format buddy.c

This commit is contained in:
KAAAsS 2021-05-12 22:57:07 +08:00
parent fd018168a9
commit a3e56b886e
Signed by: KAAAsS
GPG Key ID: D56625F3E671882F

View File

@ -11,68 +11,66 @@
* The usable memory: [pool_start_addr, pool_start_addr + pool_mem_size). * The usable memory: [pool_start_addr, pool_start_addr + pool_mem_size).
*/ */
void init_buddy(struct phys_mem_pool *pool, struct page *start_page, void init_buddy(struct phys_mem_pool *pool, struct page *start_page,
vaddr_t start_addr, u64 page_num) vaddr_t start_addr, u64 page_num) {
{ int order;
int order; int page_idx;
int page_idx; struct page *page;
struct page *page;
/* Init the physical memory pool. */ /* Init the physical memory pool. */
pool->pool_start_addr = start_addr; pool->pool_start_addr = start_addr;
pool->page_metadata = start_page; pool->page_metadata = start_page;
pool->pool_mem_size = page_num * BUDDY_PAGE_SIZE; pool->pool_mem_size = page_num * BUDDY_PAGE_SIZE;
/* This field is for unit test only. */ /* This field is for unit test only. */
pool->pool_phys_page_num = page_num; pool->pool_phys_page_num = page_num;
/* Init the free lists */ /* Init the free lists */
for (order = 0; order < BUDDY_MAX_ORDER; ++order) { for (order = 0; order < BUDDY_MAX_ORDER; ++order) {
pool->free_lists[order].nr_free = 0; pool->free_lists[order].nr_free = 0;
init_list_head(&(pool->free_lists[order].free_list)); init_list_head(&(pool->free_lists[order].free_list));
} }
/* Clear the page_metadata area. */ /* Clear the page_metadata area. */
memset((char *)start_page, 0, page_num * sizeof(struct page)); memset((char *) start_page, 0, page_num * sizeof(struct page));
/* Init the page_metadata area. */ /* Init the page_metadata area. */
for (page_idx = 0; page_idx < page_num; ++page_idx) { for (page_idx = 0; page_idx < page_num; ++page_idx) {
page = start_page + page_idx; page = start_page + page_idx;
page->allocated = 1; page->allocated = 1;
page->order = 0; page->order = 0;
} }
/* Put each physical memory page into the free lists. */ /* Put each physical memory page into the free lists. */
for (page_idx = 0; page_idx < page_num; ++page_idx) { for (page_idx = 0; page_idx < page_num; ++page_idx) {
page = start_page + page_idx; page = start_page + page_idx;
buddy_free_pages(pool, page); buddy_free_pages(pool, page);
} }
} }
static struct page *get_buddy_chunk(struct phys_mem_pool *pool, static struct page *get_buddy_chunk(struct phys_mem_pool *pool,
struct page *chunk) struct page *chunk) {
{ u64 chunk_addr;
u64 chunk_addr; u64 buddy_chunk_addr;
u64 buddy_chunk_addr; int order;
int order;
/* Get the address of the chunk. */ /* Get the address of the chunk. */
chunk_addr = (u64) page_to_virt(pool, chunk); chunk_addr = (u64) page_to_virt(pool, chunk);
order = chunk->order; order = chunk->order;
/* /*
* Calculate the address of the buddy chunk according to the address * Calculate the address of the buddy chunk according to the address
* relationship between buddies. * relationship between buddies.
*/ */
#define BUDDY_PAGE_SIZE_ORDER (12) #define BUDDY_PAGE_SIZE_ORDER (12)
buddy_chunk_addr = chunk_addr ^ buddy_chunk_addr = chunk_addr ^
(1UL << (order + BUDDY_PAGE_SIZE_ORDER)); (1UL << (order + BUDDY_PAGE_SIZE_ORDER));
/* Check whether the buddy_chunk_addr belongs to pool. */ /* Check whether the buddy_chunk_addr belongs to pool. */
if ((buddy_chunk_addr < pool->pool_start_addr) || if ((buddy_chunk_addr < pool->pool_start_addr) ||
(buddy_chunk_addr >= (pool->pool_start_addr + (buddy_chunk_addr >= (pool->pool_start_addr +
pool->pool_mem_size))) { pool->pool_mem_size))) {
return NULL; return NULL;
} }
return virt_to_page(pool, (void *)buddy_chunk_addr); return virt_to_page(pool, (void *) buddy_chunk_addr);
} }
/* /*
@ -81,104 +79,97 @@ static struct page *get_buddy_chunk(struct phys_mem_pool *pool,
* pool @ physical memory structure reserved in the kernel * pool @ physical memory structure reserved in the kernel
* order @ order for origin page block * order @ order for origin page block
* page @ splitted page * page @ splitted page
* *
* Hints: don't forget to substract the free page number for the corresponding free_list. * Hints: don't forget to substract the free page number for the corresponding free_list.
* you can invoke split_page recursively until the given page can not be splitted into two * you can invoke split_page recursively until the given page can not be splitted into two
* smaller sub-pages. * smaller sub-pages.
*/ */
static struct page *split_page(struct phys_mem_pool *pool, u64 order, static struct page *split_page(struct phys_mem_pool *pool, u64 order,
struct page *page) struct page *page) {
{ // <lab2>
// <lab2> struct page *split_page = NULL;
struct page *split_page = NULL; return split_page;
return split_page; // </lab2>
// </lab2>
} }
/* /*
* buddy_get_pages: get free page from buddy system. * buddy_get_pages: get free page from buddy system.
* pool @ physical memory structure reserved in the kernel * pool @ physical memory structure reserved in the kernel
* order @ get the (1<<order) continous pages from the buddy system * order @ get the (1<<order) continous pages from the buddy system
* *
* Hints: Find the corresonding free_list which can allocate 1<<order * Hints: Find the corresonding free_list which can allocate 1<<order
* continuous pages and don't forget to split the list node after allocation * continuous pages and don't forget to split the list node after allocation
*/ */
struct page *buddy_get_pages(struct phys_mem_pool *pool, u64 order) struct page *buddy_get_pages(struct phys_mem_pool *pool, u64 order) {
{ // <lab2>
// <lab2> struct page *page = NULL;
struct page *page = NULL;
return page; return page;
// </lab2> // </lab2>
} }
/* /*
* merge_page: merge the given page with the buddy page * merge_page: merge the given page with the buddy page
* pool @ physical memory structure reserved in the kernel * pool @ physical memory structure reserved in the kernel
* page @ merged page (attempted) * page @ merged page (attempted)
* *
* Hints: you can invoke the merge_page recursively until * Hints: you can invoke the merge_page recursively until
* there is not corresponding buddy page. get_buddy_chunk * there is not corresponding buddy page. get_buddy_chunk
* is helpful in this function. * is helpful in this function.
*/ */
static struct page *merge_page(struct phys_mem_pool *pool, struct page *page) static struct page *merge_page(struct phys_mem_pool *pool, struct page *page) {
{ // <lab2>
// <lab2>
struct page *merge_page = NULL; struct page *merge_page = NULL;
return merge_page; return merge_page;
// </lab2> // </lab2>
} }
/* /*
* buddy_free_pages: give back the pages to buddy system * buddy_free_pages: give back the pages to buddy system
* pool @ physical memory structure reserved in the kernel * pool @ physical memory structure reserved in the kernel
* page @ free page structure * page @ free page structure
* *
* Hints: you can invoke merge_page. * Hints: you can invoke merge_page.
*/ */
void buddy_free_pages(struct phys_mem_pool *pool, struct page *page) void buddy_free_pages(struct phys_mem_pool *pool, struct page *page) {
{ // <lab2>
// <lab2>
// </lab2> // </lab2>
} }
void *page_to_virt(struct phys_mem_pool *pool, struct page *page) void *page_to_virt(struct phys_mem_pool *pool, struct page *page) {
{ u64 addr;
u64 addr;
/* page_idx * BUDDY_PAGE_SIZE + start_addr */ /* page_idx * BUDDY_PAGE_SIZE + start_addr */
addr = (page - pool->page_metadata) * BUDDY_PAGE_SIZE + addr = (page - pool->page_metadata) * BUDDY_PAGE_SIZE +
pool->pool_start_addr; pool->pool_start_addr;
return (void *)addr; return (void *) addr;
} }
struct page *virt_to_page(struct phys_mem_pool *pool, void *addr) struct page *virt_to_page(struct phys_mem_pool *pool, void *addr) {
{ struct page *page;
struct page *page;
page = pool->page_metadata + page = pool->page_metadata +
(((u64) addr - pool->pool_start_addr) / BUDDY_PAGE_SIZE); (((u64) addr - pool->pool_start_addr) / BUDDY_PAGE_SIZE);
return page; return page;
} }
u64 get_free_mem_size_from_buddy(struct phys_mem_pool * pool) u64 get_free_mem_size_from_buddy(struct phys_mem_pool *pool) {
{ int order;
int order; struct free_list *list;
struct free_list *list; u64 current_order_size;
u64 current_order_size; u64 total_size = 0;
u64 total_size = 0;
for (order = 0; order < BUDDY_MAX_ORDER; order++) { for (order = 0; order < BUDDY_MAX_ORDER; order++) {
/* 2^order * 4K */ /* 2^order * 4K */
current_order_size = BUDDY_PAGE_SIZE * (1 << order); current_order_size = BUDDY_PAGE_SIZE * (1 << order);
list = pool->free_lists + order; list = pool->free_lists + order;
total_size += list->nr_free * current_order_size; total_size += list->nr_free * current_order_size;
/* debug : print info about current order */ /* debug : print info about current order */
kdebug("buddy memory chunk order: %d, size: 0x%lx, num: %d\n", kdebug("buddy memory chunk order: %d, size: 0x%lx, num: %d\n",
order, current_order_size, list->nr_free); order, current_order_size, list->nr_free);
} }
return total_size; return total_size;
} }