static struct Page * default_alloc_pages(size_t n) { // 我们来仔细分析一下究竟是如何来实现页面的分配的吧!n是请求的页面数 assert(n > 0); if (n > nr_free) { // nr_free是空闲页面的总数 return NULL; } struct Page *page = NULL; list_entry_t *le = &free_list; list_entry_t *len; while ((le = list_next(le)) != &free_list) { // 从现在开始遍历 struct Page *p = le2page(le, page_link); if (p->property >= n) { // 如果空闲块的个数大于请求的个数n,这其实就是首次适应算法,是吧! //page = p; //break; int i; for (i = 0; i < n; ++i) { len = list_next(le); // list entry next struct Page *pp = le2page(le, page_link); SetPageReserved(pp); // setPageReserved主要是设置这个页面已经被占用了 ClearPageProperty(pp); // 表示这个页面已经不是头表了 list_del(le); le = len; } // 一共分配n块嘛 if (p->property > n) { (le2page(le, page_link))->property = p->property - n; } ClearPageProperty(p); SetPageReserved(p); nr_free -= n; return p; } } return NULL; }
static void default_free_pages(struct Page *base, size_t n) { assert(n > 0); struct Page *p = base; for (; p != base + n; p++) { assert(!PageReserved(p) && !PageProperty(p)); p->flags = 0; set_page_ref(p, 0); } base->property = n; SetPageProperty(base); list_entry_t *le = list_next(&free_list); while (le != &free_list) { p = le2page(le, page_link); le = list_next(le); if (base + base->property == p) { base->property += p->property; ClearPageProperty(p); list_del(&(p->page_link)); } else if (p + p->property == base) { p->property += base->property; ClearPageProperty(base); base = p; list_del(&(p->page_link)); } } nr_free += n; le = &free_list; while ((le = list_next(le)) != &free_list) { if (le2page(le, page_link) > base) { break; } } list_add_before(le, &(base->page_link)); }
static struct Page * default_alloc_pages(size_t n) { assert(n > 0); if (n > nr_free) { return NULL; } list_entry_t *le, *len; le = &free_list; while((le=list_next(le)) != &free_list) { struct Page *p = le2page(le, page_link); if(p->property >= n){ int i; for(i=0;i<n;i++){ len = list_next(le); struct Page *pp = le2page(le, page_link); SetPageReserved(pp); ClearPageProperty(pp); list_del(le); le = len; } if(p->property>n){ (le2page(le,page_link))->property = p->property - n; } ClearPageProperty(p); SetPageReserved(p); nr_free -= n; return p; } } return NULL; }
static void default_free_pages(struct Page *base, size_t n) { assert(n > 0); struct Page *p = base; for (; p != base + n; p ++) { assert(!PageReserved(p) && !PageProperty(p)); p->flags = 0; set_page_ref(p, 0); } base->property = n; SetPageProperty(base); list_entry_t *le = list_next(&free_list); // Given Code // while (le != &free_list) { // p = le2page(le, page_link); // le = list_next(le); // if (base + base->property == p) { // base->property += p->property; // ClearPageProperty(p); // list_del(&(p->page_link)); // } // else if (p + p->property == base) { // p->property += base->property; // ClearPageProperty(base); // base = p; // list_del(&(p->page_link)); // } // } // nr_free += n; // list_add(&free_list, &(base->page_link)); while (le != &free_list) { p = le2page(le, page_link); if (base + base->property < p) //已经遍历到第一个地址大于base且无法合并的块,跳出循环 break; le = list_next(le); if (p + p->property == base) { //检查是否是base之前的能合并的块 p->property += base->property; base->flags = base->property = 0; ClearPageProperty(base); base = p; list_del(&(p->page_link)); } else if (base + base->property == p) { //检查是否是base之后能合并的块 base->property += p->property; p->flags = p->property = 0; ClearPageProperty(p); list_del(&(p->page_link)); } } nr_free += n; //空闲空间增加 SetPageProperty(base); //property = 1 list_add_before(le, &(base->page_link)); //插入在第一个第一个地址大于base且无法合并的块之前 }
static void default_free_pages(struct Page *base, size_t n) { assert(n > 0); struct Page *p = base; for (; p != base + n; p ++) { assert(!PageReserved(p) && !PageProperty(p)); p->flags = 0; set_page_ref(p, 0); } base->property = n; SetPageProperty(base); list_entry_t *le = &free_list; while (1) { //TODO: set reserve bits and could be faster le = list_next(le); p = le2page(le, page_link); if (le == &free_list || p > base) { list_add_before(&(p->page_link), &(base->page_link)); break; } } int flag = 1; //cprintf("Now check merge\n"); while (flag == 1) { flag = 0; p = le2page((base->page_link.next), page_link); //cprintf("base = %08x p = %08x size = %d\n", base, p, base->property); //cprintf(" plus = %08x\n", base + base->property); if (base->page_link.next != &free_list && base+base->property==p) { base->property += p->property; //cprintf("merge on the back: %d\n", p->property); ClearPageProperty(p); list_del(&(p->page_link)); //cprintf("flag = %d %d\n", base->flags, p->flags); flag = 1; } p = le2page((base->page_link.prev), page_link); //cprintf("base = %08x p = %08x size = %d\n", base, p, base->property); if (base->page_link.prev != &free_list && p+p->property==base) { p->property += base->property; //cprintf("merge on the front: %d\n", p->property); ClearPageProperty(base); list_del(&(base->page_link)); //cprintf("flag = %d %d\n", base->flags, p->flags); base = p; flag = 1; } } nr_free += n; //list_add(&free_list, &(base->page_link)); }
//buddy_alloc_pages_sub - the actual allocation implimentation, return a page whose size >=n, // - the remaining free parts insert to other free list static inline struct Page *buddy_alloc_pages_sub(uint32_t numa_id, size_t order) { assert(order <= MAX_ORDER); size_t cur_order; for (cur_order = order; cur_order <= MAX_ORDER; cur_order++) { if (!list_empty(&free_list(numa_id, cur_order))) { list_entry_t *le = list_next(&free_list(numa_id, cur_order)); struct Page *page = le2page(le, page_link); nr_free(numa_id, cur_order)--; list_del(le); size_t size = 1 << cur_order; while (cur_order > order) { cur_order--; size >>= 1; struct Page *buddy = page + size; buddy->property = cur_order; SetPageProperty(buddy); nr_free(numa_id, cur_order)++; list_add(&free_list(numa_id, cur_order), &(buddy->page_link)); } ClearPageProperty(page); return page; } }
static struct Page * default_alloc_pages(size_t n) { assert(n > 0); if (n > nr_free) { return NULL; } struct Page *page = NULL; list_entry_t *le = &free_list; while ((le = list_next(le)) != &free_list) { struct Page *p = le2page(le, page_link); if (p->property >= n) { page = p; break; } } if (page != NULL) { list_entry_t *next_le = list_next(&(page->page_link)); list_del(&(page->page_link)); if (page->property > n) { struct Page *p = page + n; p->property = page->property - n; SetPageProperty(p); if(list_empty(&free_list)) list_add(&free_list, &(p->page_link)); else list_add_before(next_le, &(p->page_link)); } nr_free -= n; ClearPageProperty(page); } return page; }
static struct Page* default_alloc_pages(size_t n) { assert(0 < n); if (nr_free < n) { return 0; } struct Page* page = 0; list_entry_t* le = &free_list; while ((le = list_next(le)) != &free_list) { struct Page* p = le2page(le, page_link); if (n <= p->property) { page = p; break; } } if (page) { list_entry_t* prevLe = list_prev(&(page->page_link)); list_del_init(&(page->page_link)); if (n < page->property) { struct Page* p = page + n; p->property = page->property - n; SetPageProperty(p); list_add(prevLe, &(p->page_link)); } nr_free -= n; ClearPageProperty(page); } return page; }
//static struct Page * //default_alloc_pages(size_t n) { // assert(n > 0); // if (n > nr_free) { // return NULL; // } // struct Page *page = NULL; // list_entry_t *le = &free_list; // while ((le = list_next(le)) != &free_list) { // struct Page *p = le2page(le,page_link); // if (p->property >= n) { // page = p; // break; // } // } // if (page != NULL) { // le = list_prev(&(page->page_link)); // list_del(&(page->page_link)); // if (page->property > n) { // struct Page *p = page + n; // p->property = page->property-n; // list_add(le, &(p->page_link)); // } // nr_free-= n; // ClearPageProperty(page); // } // return page; //} //static void //default_free_pages(struct Page *base, size_t n) { // assert(n > 0); // struct Page *p = base, *p1; // for (; p != base + n; p ++) { // assert(!PageReserved(p) && !PageProperty(p)); // p->flags = 0; // set_page_ref(p, 0); // } // base->property = n; // SetPageProperty(base); // list_entry_t *le = list_next(&free_list), *pre, *cur; // /* // while (le != &free_list) { // // 算法大致分析: // p = le2page(le, page_link); // // 遍历双向链表中的 page,如果该 page 可以和 // // base+n 合并的话,就将这两个空闲快合并。 // // 否则插入头指针后面。 // le = list_next(le); // // 评价: // if (base + base>property == p) { // // 1.没有维护双向链表的有序性。 // base>property += p>property; // // 2.实现了空闲块的合并。 // ClearPageProperty(p); // list_del(&(p>page_link)); // } // else if (p + p>property == base) { // p>property += base>property; // ClearPageProperty(base); // base = p; // list_del(&(p>page_link)); // } // } // nr_free += n; // list_add(&free_list, &(base>page_link)); // */ // // MY CODE // while (1){ // // 实现空闲页的插入 // if(le == &free_list){ // list_add_before(le, &(base->page_link)); break; // } // p = le2page(le, page_link); // if(&(p->page_link) > &(base->page_link)){ // list_add_before(le, &(base->page_link)); break; // } // le = list_next(le); // } // pre = list_next(&free_list); // cur = list_next(pre); // // 遍历链表,合并连续的空闲块 // while (cur != &free_list && pre != &free_list){ // p = le2page(pre, page_link); // p1 =le2page(cur, page_link); // if(p + p->property == p1){ // p->property += p1->property; // ClearPageProperty(p1); // list_del(&(p1->page_link)); // } // else{ // pre = cur; // } // cur = list_next(cur); // } // nr_free += n; //} static struct Page * default_alloc_pages(size_t n) { assert(n > 0); if (n > nr_free) { return NULL; } struct Page *page = NULL; list_entry_t *le = &free_list; while ((le = list_next(le)) != &free_list) { struct Page *p = le2page(le, page_link); if (p->property >= n) { page = p; break; } } if (page != NULL) { list_entry_t* pr=list_prev(&page->page_link);//增添代码 list_del(&(page->page_link)); if (page->property > n) { struct Page *p = page + n; p->property = page->property - n; list_add(pr,&(p->page_link));//增添代码 //list_add(&free_list, &(p->page_link)); } nr_free -= n; ClearPageProperty(page); } return page; }
static struct Page * default_alloc_pages(size_t n) { assert(n > 0); if (n > nr_free) { return NULL; } struct Page *found = NULL; list_entry_t *e; for(e = list_next(&free_list); e != &free_list; e = list_next(e)) { struct Page *p = le2page(e, page_link); if(p->property >= n) { found = p; break; } } if(found != NULL) { if(found->property > n) { struct Page *more = found + n; more->property = found->property - n; SetPageProperty(more); list_add_after(&found->page_link, &more->page_link); } list_del(&found->page_link); found->property = 0; ClearPageProperty(found); nr_free -= n; } return found; }
static struct Page * default_alloc_pages(size_t n) { assert(n > 0); if (n > nr_free) { return NULL; } struct Page *page = NULL; list_entry_t *le = &free_list; // (4.1) list_entry_t *le1; while ((le = list_next(le)) != &free_list) { struct Page *p = le2page(le, page_link); // (4.1.1) if (p->property >= n) { // (4.1.2) find int i; for (i = 0, le1 = le; i < n; i++, le1 = list_next(le1)) { // allocate page from p until p + n struct Page *p1 = le2page(le1, page_link); SetPageReserved(p1); // (4.1.2) set PG_reserved ClearPageProperty(p1); // (4.1.2) clear PG_property list_del(le1); // (4.1.2) unlink this page from free_list } page = p; break; } } if (page != NULL) { if (page->property > n) { (le2page(le1, page_link))->property = page->property - n; // (4.1.2.1) } nr_free -= n; // (4.1.3) } return page; // (4.1.4) or (4.2) }
static struct Page * default_alloc_pages(size_t n) { assert(n > 0); if (n > nr_free) { return NULL; } struct Page *page = NULL; list_entry_t *le = &free_list; while ((le = list_next(le)) != &free_list) { struct Page *p = le2page(le, page_link); if (p->property >= n) { page = p; break; } } if (page != NULL) { if (page->property > n) { //TODO: set property and reserve bits struct Page *p = page + n; p->property = page->property - n; list_add(le, &(p->page_link)); SetPageProperty(p); } list_del(&(page->page_link)); nr_free -= n; ClearPageProperty(page); } return page; }
static struct Page * default_alloc_pages(size_t n) { assert(n > 0); if (n > nr_free) { return NULL; } struct Page *page = NULL; list_entry_t *le = &free_list; while ((le = list_next(le)) != &free_list) { struct Page *p = le2page(le, page_link); // cprintf("%d ", (unsigned int)p / sizeof(struct Page)); if (p->property >= n) { page = p; break; } } // cprintf("\n"); if (page != NULL) { list_del(&(page->page_link)); if (page->property > n) { struct Page *p = page + n; p->property = page->property - n; SetPageProperty(p); list_add(&free_list, &(p->page_link)); } nr_free -= n; ClearPageProperty(page); } return page; }
static struct Page * default_alloc_pages(size_t n) { assert(n > 0); if (n > nr_free) { return NULL; } list_entry_t *le = &free_list; while ((le = list_next(le)) != &free_list) { struct Page *page = le2page(le, page_link); // Finds a free block. if (page->property >= n) { // Malloc the first n pages. ClearPageProperty(page); SetPageReserved(page); list_del(le); if (page->property > n) { // Updates the remained space size. struct Page* new_page = page + n; new_page->property = page->property - n; list_add_before(list_next(le), &(new_page->page_link)); } page->property = 0; nr_free -= n; return page; } } return NULL; }
// implement the buddy system strategy for freeing page frames void free_pages_bulk(struct Page * page, int order) { int size = 1 << order; unsigned long page_idx = page - mem_map, buddy_idx; struct Page * buddy, * coalesced; while (order < 10) { // calculate the buddy index, by xor operation // if 1 << order bit was previously zero, buddy // index is equal to page_idx + size, conversely, // if the bit was previously one, buddy index is // equal to page_idx - size buddy_idx = page_idx ^ size; buddy = &mem_map[buddy_idx]; if (!page_is_buddy(buddy, order)) break; LIST_REMOVE(buddy, lru); free_area[order].nr_free --; buddy->property = 0; ClearPageProperty(buddy); page_idx &= buddy_idx; order ++; } coalesced = &mem_map[page_idx]; dbmsg("free order %x, page %x\n", order, coalesced - pages); coalesced->property = order; SetPageProperty(coalesced); LIST_INSERT_HEAD(&(free_area[order].free_list), coalesced, lru); free_area[order].nr_free ++; }
static void default_init_memmap(struct Page *base, size_t n) { // Given Code // assert(n > 0); // struct Page *p = base; // for (; p != base + n; p ++) { // assert(PageReserved(p)); // p->flags = p->property = 0; // set_page_ref(p, 0); // } // base->property = n; // SetPageProperty(base); // nr_free += n; // list_add(&free_list, &(base->page_link)); assert(n > 0); struct Page *p = base; for (; p != base + n; p ++) { assert(PageReserved(p)); p->flags = p->property = 0; ClearPageProperty(p); set_page_ref(p, 0); } base->property = n; SetPageProperty(base); nr_free += n; list_add(&free_list, &(base->page_link)); }
static void default_free_pages(struct Page *base, size_t n) { assert(n > 0); struct Page *p = base; for (; p != base + n; p ++) { assert(!PageReserved(p) && !PageProperty(p)); p->flags = 0; set_page_ref(p, 0); } base->property = n; SetPageProperty(base); list_entry_t *le = list_next(&free_list); while (le != &free_list) { p = le2page(le, page_link); le = list_next(le); if (base + base->property == p) { base->property += p->property; ClearPageProperty(p); list_del(&(p->page_link)); } else if (p + p->property == base) { p->property += base->property; ClearPageProperty(base); base = p; list_del(&(p->page_link)); }else{ if(base + base->property < p && p->page_link.prev == &free_list){ list_add(&free_list , &base->page_link); nr_free += n; return ; }else if(le == &free_list && p+p->property < base){ list_add_before(&free_list , &base->page_link); nr_free += n; return ; }else { struct Page *page_next = le2page(le , page_link); if(p+p->property < base && base+base->property<page_next){ list_add(p , &base->page_link); nr_free += n; return ; } } } } nr_free += n; list_add(&free_list, &(base->page_link)); }
static void default_free_pages(struct Page *base, size_t n) { assert(n > 0); struct Page *p = base; for (; p != base + n; p ++) { assert(!PageReserved(p) && !PageProperty(p)); p->flags = 0; set_page_ref(p, 0); } base->property = n; SetPageProperty(base); list_entry_t *le = list_next(&free_list); while(1) { p = le2page(le, page_link); if (le == &free_list || p >= base) { list_add_before(le, &(base->page_link)); break; } le = list_next(le); } // Search Next le = list_next(&(base->page_link)); if(le != &free_list) { p = le2page(le, page_link); if(base + n == p) { // Link them base->property += p->property; ClearPageProperty(p); list_del(&(p->page_link)); } } // Search Prev le = list_prev(&(base->page_link)); if(le != &free_list) { p = le2page(le, page_link); if(p + p->property == base) { // Link them p->property += base->property; ClearPageProperty(base); list_del(&(base->page_link)); } } nr_free += n; }
/*buddy_free_pages - Free continous pages start with page.The header page's property flag should be unset, and the property field should assign to zero. */ void buddy_free_pages(struct Page* page){ assert(!PageReserved(page) && PageProperty(page)); uint32_t i = page2buddy(page, get_ord(page->property * MIN_BLOCK)); set_rht(mem[i], ord(mem[i])-1); set_lft(mem[i], ord(mem[i])-1); update(i); nr_free += page->property; ClearPageProperty(page); page->property = 0; }
static void default_free_pages(struct Page *base, size_t n) { assert(n > 0); // Frees the pages; base->flags = 0; // Clears the flags. base->property = 0; // Not the first page of free block. set_page_ref(base, 0); // Free and no reference. SetPageProperty(base); base->property = n; // First page of n free blocks. // Finds the insertion position. list_entry_t *le = &free_list; struct Page *prev_page = NULL; struct Page *next_page = NULL; while ((le = list_next(le)) != &free_list) { next_page = le2page(le, page_link); if (next_page > base) { break; } prev_page = next_page; } // Adds freed space to list. list_add_before(le, &(base->page_link)); // If next_p is adjacent, combine them. if (next_page && base + base->property == next_page) { base->property += next_page->property; ClearPageProperty(next_page); next_page->property = 0; list_del(&(next_page->page_link)); } // If prev_page is adjacent, combine them. if (prev_page && prev_page + prev_page->property == base) { prev_page->property += base->property; ClearPageProperty(base); base->property = 0; list_del(&(base->page_link)); } nr_free += n; }
static void default_free_pages(struct Page *base, size_t n) { assert(n > 0); list_entry_t *le = &free_list; struct Page * p; while (p <= base && (le = list_next(le)) != &free_list) p = le2page(le, page_link); for(p=base;p<base+n;p++) { list_add_before(le, &(p->page_link)); p->flags = 0; set_page_ref(p, 0); } base->flags = 0; set_page_ref(base, 0); ClearPageProperty(base); SetPageProperty(base); base->property = n; while (1) { p = le2page(le, page_link); if (base->page_link.next != &free_list && base+base->property==p) { base->property += p->property; p->property = 0; } else break; } le = list_prev(&(base->page_link)); p = le2page(le, page_link); if(le != &free_list && p == base-1) { while (1) { if (p->property) { p->property += base->property; base->property = 0; break; } if (le != &free_list) { le = list_prev(le); p = le2page(le,page_link); } else break; } } nr_free += n; }
static void default_free_pages(struct Page* base, size_t n) { assert(0 < n); struct Page* p = base; for (; p != base + n; ++p) { assert(!PageReserved(p) && !PageProperty(p)); p->flags = 0; set_page_ref(p, 0); } base->property = n; SetPageProperty(base); list_entry_t* le = list_next(&free_list); // Find insertion position while (le2page(le, page_link) < base && le != &free_list) { le = list_next(le); } le = list_prev(le); // Insert into list list_add(le, &(base->page_link)); // Merge previous one p = le2page(le, page_link); if (p + p->property == base) { p->property += base->property; ClearPageProperty(base); base->property = 0; list_del(&(base->page_link)); base = p; } // Merge next one if (list_next(&(base->page_link)) != &free_list) { p = le2page(list_next(&(base->page_link)), page_link); if (base + base->property == p) { base->property += p->property; ClearPageProperty(p); p->property = 0; list_del(&(p->page_link)); } } nr_free += n; }
//static void default_free_pages(struct Page *base, size_t n) { assert(n > 0); assert(PageReserved(base)); //遍历空闲块链表,找到合适的位置插入回收的地址块 list_entry_t *le = &free_list; struct Page *page = NULL; //寻找第一个空闲块 while ((le = list_next(le)) != &free_list) { page = le2page(le, page_link); if (page > base) { break; } } //插入回收的空闲块:按页插入 for (page=base; page<(base+n); page++) { list_add_before(le, &(page->page_link)); } //重置该块的字段 base->flags = 0; base->property = n; set_page_ref(base, 0); ClearPageProperty(base); SetPageProperty(base); //尝试合并地址相连的空闲地址块 //先查看后一个空闲块 page = le2page(le, page_link); //得到后一个空闲块起始地址 if ((base+n) == page) { base->property += page->property; page->property = 0; } //后查看前一个空闲块 le = list_prev(&(base->page_link)); page = le2page(le, page_link); //此时并不是前一个空闲块,而是前一个page if ((le!= &free_list) && page == (base-1)) { while (le!= &free_list) { if (page->property > 0) { page->property += base->property; base->property =0; break; } le = list_prev(le); page = le2page(le, page_link); } } nr_free += n; return; }
//在free_list中寻找第一个空闲块(要求块大小>=n),调整该空闲块的大小,并返回分配的内存块的地址 static struct Page * default_alloc_pages(size_t n) { assert(n > 0); if (n > nr_free) { //如果所有空闲块的大小都不能满足分配要求,则返回 return NULL; } list_entry_t *le = &free_list; list_entry_t *pageList; //寻找第一个空闲块 while ((le = list_next(le)) != &free_list) { struct Page *block = le2page(le, page_link); if (block->property >= n) { int index=0; //如果找到了合适的空闲块,说明该块的前n个页可以被分配出去,此时需要做一些设置 for (index=0; index<n; index++) { pageList = list_next(le); struct Page *singlePage = le2page(le, page_link); SetPageReserved(singlePage); //PG_reserved =1 ClearPageProperty(singlePage); //PG_property =0 list_del(le); //unlink the pages from free_list le = pageList; } //如果该空闲块过大,需要再重新计算大小 if (block->property > n) { (le2page(le,page_link))->property = block->property - n; } ClearPageProperty(block); SetPageReserved(block); nr_free -= n; return block; } } //如果没有找到返回NULL return NULL; }
static void default_free_pages(struct Page *base, size_t n) { assert(n > 0); assert(PageReserved(base)); list_entry_t *le = &free_list; struct Page * p; while((le=list_next(le)) != &free_list) { p = le2page(le, page_link); if(p>base){ break; } } // 每个page都加入freelist for(p=base;p<base+n;p++){ list_add_before(le, &(p->page_link)); } // 首个page进行设置 base->flags = 0; set_page_ref(base, 0); ClearPageProperty(base); SetPageProperty(base); base->property = n; p = le2page(le,page_link); // 如果后面需要合并 if( base+n == p ){ base->property += p->property; p->property = 0; } le = list_prev(&(base->page_link)); p = le2page(le, page_link); // 如果前面需要合并 if(le!=&free_list && p==base-1){ while(le!=&free_list){ if(p->property){ p->property += base->property; base->property = 0; break; } le = list_prev(le); p = le2page(le,page_link); } } nr_free += n; return ; }
static void default_free_pages(struct Page *base, size_t n) { // 用于释放页 // 我们来仔细看一下释放page的函数吧! assert(n > 0); assert(PageReserved(base)); list_entry_t *le = &free_list; // le指向空闲段链表的头部 struct Page *p; while ((le = list_next(le)) != &free_list) { // 开始遍历 p = le2page(le, page_link); if (p > base) { // free_list里面的数据都是按照地址从小到大排列的吧! break; } } // le现在指向一个恰好在base页面之后的page for (p = base; p < base + n; p++) { // 不断地在前面插入 list_add_before(le, &(p->page_link)); } base->flags = 0; set_page_ref(base, 0); // 引用计数变为了0 ClearPageProperty(base); // SetPageProperty(base); // 只需要这句就行了吧! base->property = n; p = le2page(le, page_link); if (base + n == p) { // 也就是说,前后可以连接起来 base->property += p->property; p->property = 0; } le = list_prev(&(base->page_link)); p = le2page(le, page_link); // 找到free_list中base之前的那个free page if (le != &free_list && p == base - 1) { // 如果两个也可以连起来 while (le != &free_list) { if (p->property) { p->property += base->property; base->property = 0; break; } le = list_prev(le); p = le2page(le, page_link); } } nr_free += n; // 空闲页的计数加n return; }
static void default_free_pages(struct Page *base, size_t n) { assert(n > 0); assert(PageReserved(base)); list_entry_t *le = &free_list; //获取空闲内存页的起始地址 struct Page *p; while((le = list_next(le))!= &free_list){ p = le2page(le, page_link); if( p > base){ //说明base应该接到p的前面,也就是le的前面 break; } } for( p = base; p<base+n; p++){ list_add_before(le, &(p->page_link)); } base->flags = 0; set_page_ref(base, 0); ClearPageProperty(base); SetPageProperty(base); base->property = n; //下面是块的合并 //向后 p = le2page(le, page_link); if(base+n == p){ base->property += p->property; p->property = 0; } //向前 le = list_prev(&(base->page_link)); p = le2page(le, page_link); if(le!=&free_list && p == base-1){ while(le!=&free_list){ if(p->property){ p->property += base->property; base->property = 0; break; } le = list_prev(le); p = le2page(le, page_link); } } nr_free += n; return ; }
static void default_free_pages(struct Page *base, size_t n) { assert(n > 0); assert(PageReserved(base)); struct Page *p = base; struct Page * q = NULL; list_entry_t * le = &free_list; while((le = list_next(le)) != &free_list) { q = le2page(le,page_link); if(q > base) break; } //struct Page * q = for(;p < base + n;p++){ list_add_before(le,&(p -> page_link)); } base -> flags = 0; set_page_ref(base,0); ClearPageProperty(base); SetPageProperty(base); base->property = n; if(q == base + n){ base -> property += q -> property; q -> property = 0; } le = list_prev(&(base -> page_link)); q = le2page(le,page_link); if(le != &free_list && q == base -1) { while(le != &free_list){ if(q -> property) { q -> property += base -> property; base -> property = 0; break; } le = list_prev(le); q = le2page(le,page_link); } } nr_free += n; return; }
static struct Page * default_alloc_pages(size_t n) { assert(n > 0); if (n > nr_free) { return NULL; } struct Page *page = NULL; list_entry_t *le = &free_list; while ((le = list_next(le)) != &free_list) { struct Page *p = le2page(le, page_link); if (p->property >= n) { page = p; break; } } if (page != NULL) { struct Page *p = page; for(; p != page + n; p++) { ClearPageProperty(p); SetPageReserved(p); } if (page->property > n) { p = page + n; //get pointer of left space p->property = page->property - n; SetPageProperty(p); // set size of left space page->property = n; list_add(&page->page_link, &(p->page_link)); } list_del(&(page->page_link)); nr_free -= n; /** list_del(&(page->page_link)); if (page->property > n) { struct Page *p = page + n; p->property = page->property - n; list_add(&free_list, &(p->page_link)); } nr_free -= n; ClearPageProperty(page); */ } return page; }
static struct Page * default_alloc_pages(size_t n) { assert(n > 0); if (n > nr_free) { return NULL; } struct Page *page = NULL; list_entry_t *le = &free_list; while ((le = list_next(le)) != &free_list) { struct Page *p = le2page(le, page_link); if (p->property >= n) { page = p; break; } } // Given Code // if (page != NULL) { // list_del(&(page->page_link)); // if (page->property > n) { // struct Page *p = page + n; // p->property = page->property - n; // list_add(&free_list, &(p->page_link)); // } // nr_free -= n; // ClearPageProperty(page); // } if (page != NULL) { //如果找到了足够大的块 list_entry_t *pre_page = list_prev(&(page->page_link)); //获得链表前一块 list_del(&(page->page_link)); //链表删除当前块 if (page->property > n) { //如果当前块比需要大则分裂 struct Page *p = page + n; p->property = page->property - n; SetPageProperty(p); list_add(pre_page, &(p->page_link)); //分裂出来的块插在前一块之后,保证按地址排序 } nr_free -= n; //空闲页数减少 ClearPageProperty(page); //property = 0 // SetPageReserved(page); } return page; }