// calculate size
unsigned long size = cache->objsize;
unsigned long align = cache->align;
+
align = KMALLOC_MIN_ALIGN > align ? KMALLOC_MIN_ALIGN : align;
+
size = ALIGN(size, align);
size = ALIGN(size, sizeof(void *));
+
cache->size = size;
+ cache->align = align;
- // calculate order
- unsigned long order;
- for (order = 1; order < MAX_ORDER; ++order) {
+ // 允许从buddy system最小分配一页
+ unsigned long order = ~0UL;
+ for (order = 0; order < MAX_ORDER; ++order) {
if ((PAGE_SIZE << order) / cache->size >= 4) {
cache->order = order;
break;
}
}
- if (0 == cache->order) {
- printk("can not find a valid order\n");
+ // 如果没有找到合适的从buddy system分配的大小则失败
+ if (~0UL == cache->order) {
+ panic("can not find a valid order\n");
return false;
}
cache->objects = (PAGE_SIZE << cache->order) / cache->size;
- if (0 == cache->objects) {
- return false;
- }
-
return true;
}
+////////////////////////////////////////////////////////////////////////////////////////////////////////
+
bool kmem_cache_init(kmem_cache_t *cache, const char *name, size_t size, size_t align) {
memset(cache, 0, sizeof(kmem_cache_t));
slub_free(cache, page, addr);
}
+kmem_cache_t *kmem_cache_create(const char *name, size_t size, size_t align) {
+ kmem_cache_t *cache = kmalloc(sizeof(kmem_cache_t), 0);
+ if (cache == 0) {
+ return 0;
+ }
+
+ kmem_cache_init(cache, name, size, align);
+
+ unsigned long flags;
+ irq_save(flags);
+
+ list_add(&(cache->list), &slub_caches);
+
+ irq_restore(flags);
+
+ return cache;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////
+
void *kmalloc(size_t size, gfp_t gfpflags) {
unsigned int i;
kmem_cache_t *cache = 0;
void *addr = 0;
- unsigned long flags;
- irq_save(flags);
-
for (i = 0; i < SLUB_INIT_CACHE_SIZE; ++i) {
kmem_cache_t *p = kmalloc_caches + i;
if (p->objsize >= size) {
}
}
- // 如果没找到支持的cache则分配失败
- if (0 == cache) {
- goto err;
+ if (0 != cache) {
+ addr = kmem_cache_alloc(cache, gfpflags);
}
- addr = kmem_cache_alloc(cache, gfpflags);
-
-err:
- irq_restore(flags);
-
return addr;
}
void kfree(void *addr) {
- unsigned long flags;
- irq_save(flags);
-
page_t *page = get_head_page(va2page((unsigned long)addr));
kmem_cache_t *cache = page->cache;
slub_free(cache, page, addr);
-
- irq_restore(flags);
}
-kmem_cache_t *kmem_cache_create(const char *name, size_t size, size_t align) {
- kmem_cache_t *cache = kmalloc(sizeof(kmem_cache_t), 0);
- if (cache == 0) return 0;
-
- unsigned long flags;
- irq_save(flags);
-
- kmem_cache_init(cache, name, size, align);
-
- list_add(&(cache->list), &slub_caches);
+////////////////////////////////////////////////////////////////////////////////////////////////////////
- irq_restore(flags);
-
- return cache;
-}
-
-void init_slub_system() {
+void init_kmem_caches() {
unsigned int i;
kmem_cache_t *cache;
for (i = SLUB_MIN_SHIFT; i < SLUB_MAX_SHIFT; ++i) {
cache = kmalloc_caches + i - SLUB_MIN_SHIFT;
+
kmem_cache_init(cache, "kmalloc", 1UL << i, KMALLOC_MIN_ALIGN);
list_add(&(cache->list), &slub_caches);
- // printk("kmem objsize %d\tsize %d \n", cache->objsize, cache->size);
}
}
#include <types.h>
extern char etext, edata, end;
-extern void init_buddy_system();
-extern void init_slub_system();
-extern void init_bootmem();
pde_t __initdata init_pgd[PDECNT_PER_PAGE] __attribute__((__aligned__(PAGE_SIZE)));
pte_t __initdata init_pgt[PTECNT_PER_PAGE * BOOT_INIT_PAGETBL_CNT] __attribute__((__aligned__(PAGE_SIZE)));
void init_mm() {
printk("init bootmem alloc...\n");
+ extern void init_bootmem();
init_bootmem();
printk("init global paging...\n");
-
init_paging();
printk("init buddy system...\n");
+ extern void init_buddy_system();
init_buddy_system();
- printk("init slub system...\n");
- init_slub_system();
+ printk("init kmem caches...\n");
+ extern void init_kmem_caches();
+ init_kmem_caches();
printk("memory init finished...\n");
}
return page;
}
+// 从伙伴系统批发页,并将之初始化成一个链表
page_t *new_slub(kmem_cache_t *cache, gfp_t gfpflags) {
// alloc pages from buddy system
unsigned long bgn = alloc_pages(gfpflags, cache->order);
unsigned long end = 0;
+
+ // 找到该页的管理结构
page_t *page = va2page(bgn);
- if (0 == page) return 0;
+ //
+ if (0 == page) {
+ return 0;
+ }
end = bgn + cache->objects * cache->size;
+#if 1
unsigned long last = bgn;
unsigned long addr;
+
+ // 第一遍会将 bgn[0]的地址赋值给bgn[0],也就是 bgn[0] = bgn + 0
+ // 第二遍开始就是 bgn[n-1] = bgn + n
for (addr = bgn; addr < end; addr += cache->size) {
*((void **)last) = (void *)addr;
last = addr;
}
+ // 最后一个赋值为0
*((void **)last) = 0;
+#else
+ unsigned long addr;
+ for (addr = bgn; addr < end; addr += cache->size) {
+ *(unsigned long *)addr = addr + cache->size;
+ }
+
+ addr = end - cache->size;
+ *(unsigned long *)addr = 0;
+#endif
page->freelist = (void **)bgn;
page->inuse = 0;
if (cache->page == 0) {
page = get_partial(cache, gfpflags);
+ // 如果partial为空,则上伙伴系统申请
+ // 否则直接从partial上直接拿一个页来用
if (page == 0) {
- page = new_slub(cache, gfpflags);
- if (page != 0) {
- cache->page = page;
- }
+ cache->page = new_slub(cache, gfpflags);
} else {
cache->page = page;
}
}
+ // 从partial和伙伴系统里没申请到页
if (cache->page == 0) {
return 0;
}
object = cache->page->freelist;
- if (object == 0) {
- cache->page = 0;
- } else {
- cache->page->freelist = object[0];
- cache->page->inuse++;
- }
+ assert(0 != object);
+
+ cache->page->freelist = object[0];
+ cache->page->inuse++;
return object;
}
void *slub_alloc(kmem_cache_t *cache, gfp_t gfpflags) {
void **object = 0;
- if (cache == 0) return 0;
+ if (cache == 0) {
+ return 0;
+ }
unsigned long flags;
irq_save(flags);
if (cache->page == 0 || cache->page->freelist == 0) {
+ // 如果cache还没上buddy system批发页
+ // 或者批发的页已经分配完了
+ // 则需要换新的页: 1. 如果partial里有,就用partial的;2. 如果partial为空则上buddy system批发
cache->page = 0;
object = __slub_alloc(cache, gfpflags);
} else {
+ // 否则分配一个
object = cache->page->freelist;
cache->page->freelist = object[0];
cache->page->inuse++;
if (page->inuse == 0) {
list_del(&page->lru);
free_pages((unsigned long)page2va(page));
- }
-
- if (prior == 0) {
- list_add(&page->lru, &cache->partial);
+ } else {
+ if (prior == 0) {
+ list_add(&page->lru, &cache->partial);
+ }
}
}