From 4bfab488727c5727180593be1f0b537d6cad4902 Mon Sep 17 00:00:00 2001 From: acevest Date: Sun, 14 Nov 2021 18:55:38 +0800 Subject: [PATCH] fix slub system --- .bochsrc | 2 +- include/page.h | 33 +++++++------------- include/system.h | 2 +- mm/kmem.c | 79 +++++++++++++++++++++++------------------------- mm/mm.c | 11 +++---- mm/slub.c | 56 ++++++++++++++++++++++++---------- 6 files changed, 95 insertions(+), 88 deletions(-) diff --git a/.bochsrc b/.bochsrc index 939539d..04ffc27 100644 --- a/.bochsrc +++ b/.bochsrc @@ -1313,4 +1313,4 @@ debug_symbols: file="kernel.sym" #megs: 64 #megs: 32 #megs: 16 -megs: 8 +megs: 32 diff --git a/include/page.h b/include/page.h index e8c8406..daa3dfe 100644 --- a/include/page.h +++ b/include/page.h @@ -128,42 +128,31 @@ void free_pages(unsigned long addr); struct kmem_cache { const char *name; + // 预期分配的大小 unsigned long objsize; + + // 实际分配的大小 unsigned long size; + + // 对齐 unsigned long align; + + // 从buddy system批发的页的幂数 unsigned long order; + + // unsigned long objects; + // 没有完全分配的页的链表及数量 unsigned int partial_cnt; list_head_t partial; + // 正在分配的页 page_t *page; list_head_t list; }; -// TODO Remove -typedef struct page_ { - // struct page *prev, *next; - ListHead list; - unsigned int order; - unsigned int mapNR; - unsigned int count; -} Page, *pPage; - -typedef struct free_area_ { - // struct page *prev, *next; - ListHead freeList; - unsigned char *map; - unsigned int mapSize; - unsigned int count; -} FreeArea, *pFreeArea; - -pPage old_alloc_pages(unsigned int order); -void old_free_pages(pPage page); -// void free_pages(pPage page, unsigned int order); -void disp_free_area(); - #endif // ASM #endif //_PAGE_H diff --git a/include/system.h b/include/system.h index 4c477c9..5726b37 100644 --- a/include/system.h +++ b/include/system.h @@ -147,7 +147,7 @@ typedef struct system { u64 mm_size; // Byte u32 page_count; - pPage page_map; + u32 page_bitmap; u32 *page_dir; diff --git a/mm/kmem.c b/mm/kmem.c index bc19bd6..756aebe 100644 --- a/mm/kmem.c +++ b/mm/kmem.c @@ -20,34 +20,37 @@ bool calculate_params(kmem_cache_t *cache) { // 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)); @@ -78,14 +81,31 @@ void kmem_cache_free(kmem_cache_t *cache, void *addr) { 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) { @@ -94,56 +114,31 @@ void *kmalloc(size_t size, gfp_t gfpflags) { } } - // 如果没找到支持的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); } } diff --git a/mm/mm.c b/mm/mm.c index 40cf447..0e7c1f2 100644 --- a/mm/mm.c +++ b/mm/mm.c @@ -24,9 +24,6 @@ #include 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))); @@ -124,15 +121,17 @@ void init_paging() { 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"); } diff --git a/mm/slub.c b/mm/slub.c index 393bf50..d700130 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -26,24 +26,44 @@ page_t *get_partial(kmem_cache_t *cache, gfp_t gfpflags) { 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; @@ -58,28 +78,26 @@ void *__slub_alloc(kmem_cache_t *cache, gfp_t gfpflags) { 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; } @@ -87,15 +105,21 @@ void *__slub_alloc(kmem_cache_t *cache, gfp_t gfpflags) { 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++; @@ -116,10 +140,10 @@ void __slub_free(kmem_cache_t *cache, page_t *page, void *addr) { 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); + } } } -- 2.44.0