finish buddy
This commit is contained in:
parent
a3e56b886e
commit
5cf26522a5
@ -26,7 +26,7 @@ void init_buddy(struct phys_mem_pool *pool, struct page *start_page,
|
|||||||
/* 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)); // free lists 初始化为空链表
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear the page_metadata area. */
|
/* Clear the page_metadata area. */
|
||||||
@ -35,17 +35,20 @@ void init_buddy(struct phys_mem_pool *pool, struct page *start_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); // 逐一去配页面以初始化 free lists
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 获得页面的伙伴页面
|
||||||
|
*/
|
||||||
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;
|
||||||
@ -87,8 +90,31 @@ static struct page *get_buddy_chunk(struct phys_mem_pool *pool,
|
|||||||
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 *buddy = NULL;
|
||||||
return split_page;
|
|
||||||
|
// 我理解的这个函数:把 page 递归切成 order,返回结果。过程修改的都是未分配区域。
|
||||||
|
|
||||||
|
// 递归出口
|
||||||
|
if (page->order == order) {
|
||||||
|
return page;
|
||||||
|
} else if (page->order < order) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// 分裂
|
||||||
|
// 删除当前节点
|
||||||
|
list_del(&page->node);
|
||||||
|
pool->free_lists[page->order].nr_free--;
|
||||||
|
// 降格
|
||||||
|
page->order--;
|
||||||
|
// 找伙伴
|
||||||
|
buddy = get_buddy_chunk(pool, page);
|
||||||
|
buddy->order = page->order;
|
||||||
|
// 加入 free list
|
||||||
|
list_add(&page->node, &pool->free_lists[page->order].free_list);
|
||||||
|
list_add(&buddy->node, &pool->free_lists[page->order].free_list);
|
||||||
|
pool->free_lists[page->order].nr_free += 2;
|
||||||
|
// 递归调用
|
||||||
|
return split_page(pool, order, page);
|
||||||
// </lab2>
|
// </lab2>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,12 +123,29 @@ static struct page *split_page(struct phys_mem_pool *pool, u64 order,
|
|||||||
* 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 corresponding 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, *free_page = NULL;
|
||||||
|
|
||||||
|
// 找可分配 order
|
||||||
|
u64 free_order = order;
|
||||||
|
while (free_order < BUDDY_MAX_ORDER && pool->free_lists[free_order].nr_free == 0) {
|
||||||
|
free_order++;
|
||||||
|
}
|
||||||
|
// 当前无可分配
|
||||||
|
if (free_order == BUDDY_MAX_ORDER) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// 有可分配,取一块切分
|
||||||
|
free_page = (struct page *) pool->free_lists[free_order].free_list.next;
|
||||||
|
page = split_page(pool, order, free_page);
|
||||||
|
// 删除出 free list,分配
|
||||||
|
list_del(&page->node);
|
||||||
|
pool->free_lists[page->order].nr_free--;
|
||||||
|
page->allocated = true;
|
||||||
|
|
||||||
return page;
|
return page;
|
||||||
// </lab2>
|
// </lab2>
|
||||||
@ -120,8 +163,41 @@ struct page *buddy_get_pages(struct phys_mem_pool *pool, u64 order) {
|
|||||||
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 *try_merge = NULL, *buddy = get_buddy_chunk(pool, page);
|
||||||
return merge_page;
|
|
||||||
|
// 不存在伙伴、伙伴已分配、order 不同则无法合并
|
||||||
|
if (buddy == NULL || buddy->allocated || page->order != buddy->order) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// 如果已经最大 order,则不合并
|
||||||
|
if (page->order >= BUDDY_MAX_ORDER - 1) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 双方都未分配,可以合并一次
|
||||||
|
// 从 free 中删除两个节点
|
||||||
|
list_del(&page->node);
|
||||||
|
list_del(&buddy->node);
|
||||||
|
pool->free_lists[page->order].nr_free -= 2;
|
||||||
|
// 选择左侧 page
|
||||||
|
struct page *t;
|
||||||
|
if (buddy < page) {
|
||||||
|
t = page;
|
||||||
|
page = buddy;
|
||||||
|
}
|
||||||
|
// 增加 page 的 order
|
||||||
|
page->order++;
|
||||||
|
// 链入上一层空列表
|
||||||
|
list_add(&page->node, &pool->free_lists[page->order].free_list);
|
||||||
|
pool->free_lists[page->order].nr_free++;
|
||||||
|
// 尝试递归合并
|
||||||
|
try_merge = merge_page(pool, page);
|
||||||
|
if (try_merge != NULL) {
|
||||||
|
return try_merge;
|
||||||
|
}
|
||||||
|
|
||||||
|
return page;
|
||||||
|
|
||||||
// </lab2>
|
// </lab2>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,6 +211,17 @@ static struct page *merge_page(struct phys_mem_pool *pool, struct page *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>
|
||||||
|
|
||||||
|
if (!page->allocated)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 设置标志
|
||||||
|
page->allocated = false;
|
||||||
|
// 修改 free list
|
||||||
|
list_add(&page->node, &pool->free_lists[page->order].free_list);
|
||||||
|
pool->free_lists[page->order].nr_free++;
|
||||||
|
// 尝试合并当前页面
|
||||||
|
merge_page(pool, page);
|
||||||
|
|
||||||
// </lab2>
|
// </lab2>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user