diff --git a/lab2/kernel/mm/buddy.c b/lab2/kernel/mm/buddy.c
index 88b680b..c8cac33 100644
--- a/lab2/kernel/mm/buddy.c
+++ b/lab2/kernel/mm/buddy.c
@@ -26,7 +26,7 @@ void init_buddy(struct phys_mem_pool *pool, struct page *start_page,
/* Init the free lists */
for (order = 0; order < BUDDY_MAX_ORDER; ++order) {
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. */
@@ -35,17 +35,20 @@ void init_buddy(struct phys_mem_pool *pool, struct page *start_page,
/* Init the page_metadata area. */
for (page_idx = 0; page_idx < page_num; ++page_idx) {
page = start_page + page_idx;
- page->allocated = 1;
+ page->allocated = 1; // 所有页面初始化为已分配
page->order = 0;
}
/* Put each physical memory page into the free lists. */
for (page_idx = 0; page_idx < page_num; ++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,
struct page *chunk) {
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,
struct page *page) {
//
- struct page *split_page = NULL;
- return split_page;
+ struct page *buddy = NULL;
+
+ // 我理解的这个函数:把 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);
//
}
@@ -97,12 +123,29 @@ static struct page *split_page(struct phys_mem_pool *pool, u64 order,
* pool @ physical memory structure reserved in the kernel
* order @ get the (1<
- 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;
//
@@ -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) {
//
- struct page *merge_page = NULL;
- return merge_page;
+ struct page *try_merge = NULL, *buddy = get_buddy_chunk(pool, 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;
+
//
}
@@ -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) {
//
+ 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);
+
//
}
diff --git a/note.org b/note.org
index 86cdb27..b0c6817 100644
--- a/note.org
+++ b/note.org
@@ -94,4 +94,16 @@ LR
** Lab 2
+*** 问题1:哪个文件或代码段中指定了 ChCore 物理内存布局
+**** 编译阶段
+
+编译时配置镜像格式的文件为 scripts/linker-aarch64.lds.in
+
+**** 运行阶段
+
+运行阶段在 kernel/mm.c:L70 的 mm_init 设置各个地址
+
+*** 练习1
+
+基本思路就是回收的时候一路尝试向上合并,分配的时候找一个更大的块然后一路向下分裂。