From 988331612c3b2f6203816375e3d7f0a50a8a8243 Mon Sep 17 00:00:00 2001 From: AceVest Date: Sun, 20 Apr 2014 10:35:02 +0800 Subject: [PATCH] add slub system support --- Makefile | 15 ++-- include/page.h | 15 +++- mm/buddy.c | 26 +++++-- mm/mm.c | 6 +- mm/slub.c | 188 ++++++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 224 insertions(+), 26 deletions(-) diff --git a/Makefile b/Makefile index 37ce15e..0822f74 100644 --- a/Makefile +++ b/Makefile @@ -1,23 +1,18 @@ -############################################################################ CC = gcc -CFLAGS = -c -fno-builtin +CFLAGS = -g -c -fno-builtin SYSTEMMAP = System.map KERNELBIN = KERNEL.BIN LINKSCRIPT = scripts/link.ld -############################################################################ SRC_DIRS = boot setup mm lib fs kernel drivers pci INC_DIRS = include drivers -CSOURCE_FILES := $(foreach dir, $(SRC_DIRS), $(wildcard $(dir)/*.c)) -SSOURCE_FILES := $(foreach dir, $(SRC_DIRS), $(wildcard $(dir)/*.S)) - -OBJS := $(patsubst %.c,%.c.o,$(CSOURCE_FILES)) -OBJS += $(patsubst %.S,%.S.o,$(SSOURCE_FILES)) - CFLAGS += ${INC_DIRS:%=-I%} -${KERNELBIN}: ${OBJS} $ +SOURCE_FILES := $(foreach DIR, $(SRC_DIRS), $(wildcard $(DIR)/*.[cS])) +OBJS := $(patsubst %,%.o,$(SOURCE_FILES)) + +${KERNELBIN}: ${OBJS} ld -M -T$(LINKSCRIPT) $(OBJS) -o $@ > $(SYSTEMMAP) %.S.o: %.S diff --git a/include/page.h b/include/page.h index 6d17634..b4791d0 100644 --- a/include/page.h +++ b/include/page.h @@ -27,6 +27,8 @@ #define PAGE_SIZE (1UL << PAGE_SHIFT) #define PAGE_MASK (~((1UL << PAGE_SHIFT)-1)) #define PAGE_OFFSET (0xC0000000) +#define PAGE_PDE_CNT 1024 +#define PAGE_PTE_CNT 1024 #ifndef ASM #include @@ -78,8 +80,19 @@ typedef struct page unsigned long private; unsigned long index; list_head_t lru; + + struct page *head_page; + unsigned int order; + + void **freelist; // for slub + unsigned long inuse; } page_t; +void *page2va(page_t *page); +page_t *va2page(unsigned long addr); + +static inline page_t *get_head_page(page_t *page) { return page->head_page; } + #define __GETPAGEFLAG(name) \ static inline int Page##name(page_t *page) \ {return constant_test_bit(PG_##name, &page->flags); } @@ -106,7 +119,7 @@ typedef struct free_area unsigned long alloc_pages(unsigned int gfp_mask, unsigned int order); -void free_pages(unsigned long addr, unsigned int order); +void free_pages(unsigned long addr); // TODO Remove typedef struct page_ diff --git a/mm/buddy.c b/mm/buddy.c index 62e3ad9..b59fdf5 100644 --- a/mm/buddy.c +++ b/mm/buddy.c @@ -25,8 +25,15 @@ int buddy_is_free(page_t *page, unsigned int order) return 0; } -#define va2page(addr) (buddy_system.page_map + va2pfn(addr)) -#define page2va(page) (pfn2va((page) - buddy_system.page_map)) +page_t *va2page(unsigned long addr) +{ + return buddy_system.page_map + va2pfn(addr); +} + +void *page2va(page_t *page) +{ + return pfn2va((page) - buddy_system.page_map); +} page_t *__alloc_pages(unsigned int order) { @@ -36,6 +43,7 @@ page_t *__alloc_pages(unsigned int order) free_area_t *area; unsigned long size; unsigned int select_order; + unsigned int i; for(select_order=order; select_orderhead_page = page; + p->order = order; + } + return page; } @@ -116,14 +132,16 @@ void __free_pages(page_t *page, unsigned int order) } -void free_pages(unsigned long addr, unsigned int order) +void free_pages(unsigned long addr) { if(!valid_va(addr)) { BUG_ON(!valid_va(addr)); } - __free_pages(va2page(addr), order); + page_t *page = va2page(addr); + + __free_pages(page, page->order); } void dump_buddy_system() diff --git a/mm/mm.c b/mm/mm.c index 22f02a5..2c712ec 100644 --- a/mm/mm.c +++ b/mm/mm.c @@ -299,8 +299,12 @@ void init_paging() unsigned long di, ti; unsigned long *pde, *pte; - unsigned long pde_end = (pfn2pa(bootmem_data.max_pfn) >> 22); + unsigned long max_pfn = bootmem_data.max_pfn; + unsigned long min_pfn = BOOT_INIT_PAGETBL_CNT*1024; + unsigned long pde_end = (pfn2pa(bootmem_data.max_pfn) >> 22); + if(1) // need to fix. + pde_end++; for(di=BOOT_INIT_PAGETBL_CNT; di #include -list_head_t slub_caches; +list_head_t slub_caches = LIST_HEAD_INIT(slub_caches); typedef struct kmem_cache { @@ -27,14 +27,19 @@ typedef struct kmem_cache page_t *page; - void **freelist; +// void **freelist; + + list_head_t list; } kmem_cache_t; -#define SLUB_PAGE_SHIFT PAGE_SHIFT -#define KMALLOC_MIN_SIZE 32 -#define KMALLOC_MIN_ALIGN 32 -static kmem_cache_t kmalloc_caches[SLUB_PAGE_SHIFT]; +#define SLUB_MIN_SHIFT 5 +#define SLUB_MAX_SHIFT 12 +#define SLUB_INIT_CACHE_SIZE ((SLUB_MAX_SHIFT) - (SLUB_MIN_SHIFT)) +#define KMALLOC_MIN_SIZE (1UL<<(SLUB_MIN_SHIFT)) +#define KMALLOC_MIN_ALIGN (1UL<<(SLUB_MIN_SHIFT)) + +static kmem_cache_t kmalloc_caches[SLUB_INIT_CACHE_SIZE]; typedef unsigned int gfp_t; @@ -96,28 +101,191 @@ static bool kmem_cache_init(kmem_cache_t *cache, cache->objsize = size; cache->align = align; cache->page = 0; - cache->freelist = 0; + //cache->freelist = 0; cache->partial_cnt = 0; INIT_LIST_HEAD(&(cache->partial)); if(!calculate_params(cache)) goto err; - return true; + return true; err: panic("kmem_cache_init can not create cache\n"); return false; } +static page_t *get_partial(kmem_cache_t *cache, gfp_t gfpflags) +{ + if(list_empty(&cache->partial)) + return 0; + + list_head_t *p = cache->partial.next; + list_del(p); + + page_t *page = 0; + + page = list_entry(p, page_t, lru); + + return page; +} + +static 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; + + + end = bgn + cache->objects*cache->size; + + unsigned long last = bgn; + unsigned long addr; + for(addr=bgn; addrsize) + { + *((void **)last) = (void *) addr; + last = addr; + } + + *((void **)last) = 0; + + page->freelist = (void **)bgn; + page->inuse = 0; + + return page; +} + +static void *__slub_alloc(kmem_cache_t *cache, gfp_t gfpflags) +{ + void **object = 0; + page_t *page = 0; + + if(cache->page == 0) + { + page = get_partial(cache, gfpflags); + if(page == 0) + { + page = new_slub(cache, gfpflags); + if(page != 0) + { + cache->page = page; + } + } + } + + 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++; + } + + return object; +} + +static void *slub_alloc(kmem_cache_t *cache, gfp_t gfpflags) +{ + void **object = 0; + + unsigned long objsize = cache->objsize; + + if(cache->page == 0 || cache->page->freelist == 0) + { + cache->page = 0; + object = __slub_alloc(cache, gfpflags); + } + else + { + object = cache->page->freelist; + cache->page->freelist = object[0]; + } + + return object; +} + +static void __slub_free(kmem_cache_t *cache, page_t *page, void *addr) +{ + void *prior; + void **object = addr; + + prior = object[0] = page->freelist; + page->freelist = object; + 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); + } +} + +static void slub_free(kmem_cache_t *cache, page_t *page, void *addr) +{ + void **object = addr; + + if(page == cache->page) + { + object[0] = page->freelist; + page->freelist = object; + } + else + { + __slub_free(cache, page, addr); + } +} + +void kmem_cache_free(kmem_cache_t *cache, void *addr) +{ + page_t *page = 0; + + page = get_head_page(va2page((unsigned long)addr)); + + slub_free(cache, page, addr); +} + + void init_slub_system() { unsigned int i; kmem_cache_t *cache; - for(i=5; iinx = i; + + list_add(&(cache->list), &slub_caches); + } + + list_head_t *p; + list_for_each(p, &slub_caches) + { + cache = list_entry(p, kmem_cache_t, list); + printk("cache size %d align %d \n", cache->size, cache->align); + } + + for(i=0; i<10; ++i) + { + void *addr = slub_alloc(kmalloc_caches+2, 0); + printk("slub addr %08x\n", (unsigned long)addr); } } -- 2.44.0