Varied-Sized Allocator

寫一個 API 包住 Buddy System 與 Object Allocator,當想要 allocate 的 memory 超過一個 PAGE_SIZE 時,使用 Buddy System,當小於 PAGE_SIZE 時使用 Object Allocator。

在有了 kmalloc 後,一些之前使用 static allocation 的變數,可以改用 kmalloc 進行 dynamic allocation

Allocation

src/mm.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void* kmalloc(uint64_t size) {
    // size too large
    if (size >= PAGE_SIZE) {
        uart_printf("kmalloc using buddy\n");
        int order;
        for (int i = 0; i < MAX_BUDDY_ORDER; i++) {
            if (size <= (uint64_t)((1 << i) * PAGE_SIZE)) {
                order = i;
                break;
            }
        }
        return buddy_alloc(order);
    }
    else {
        uart_printf("kmalloc using object allocator\n");
        // check exist object allocator
        for (int i = 0; i < MAX_OBJ_ALLOCTOR_NUM; i++) {
            if ((uint64_t)obj_allocator[i].obj_size == size) {
                return (void*) obj_alloc_kernel(i);
            }
        }
        // register new obj allocator
        int token = obj_alloc_register(size);
        return obj_alloc_kernel(token);
    }
}

Free

src/mm.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
void kfree(void* addr) {
    for (int i = 0; i < MAX_OBJ_ALLOCTOR_NUM; i++) {
        struct pool_t pool = obj_allocator[i];
        for (int j = 0; j < pool.page_used; j++) {
            int addr_pfn = phy_to_pfn(virtual_to_physical((uint64_t)addr));
            int page_pfn = phy_to_pfn(virtual_to_physical(pool.page_addr[j]));
            if (addr_pfn == page_pfn) {
                uart_printf("free using obj allocator\n");
                obj_free(i, addr);
                return;
            }
        }
    }
    uart_printf("free using buddy\n");
    buddy_free(addr);
}
comments powered by Disqus