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; }
pmd_t * get_pmd(pgd_t *pgdir, uintptr_t la, bool create) { #if PMXSHIFT == PUXSHIFT return get_pud(pgdir, la, create); #else /* PMXSHIFT == PUXSHIFT */ pud_t *pudp; if ((pudp = get_pud(pgdir, la, create)) == NULL) { return NULL; } if (! ptep_present(pudp)) { struct Page *page; if (!create || (page = alloc_page()) == NULL) { return NULL; } set_page_ref(page, 1); uintptr_t pa = page2pa(page); memset(KADDR(pa), 0, PGSIZE); ptep_map(pudp, pa); ptep_set_u_write(pudp); ptep_set_accessed(pudp); ptep_set_dirty(pudp); } return &((pmd_t *)KADDR(PUD_ADDR(*pudp)))[PMX(la)]; #endif /* PMXSHIFT == PUXSHIFT */ }
pte_t * get_pte(pgd_t *pgdir, uintptr_t la, bool create) { #if PTXSHIFT == PMXSHIFT return get_pmd(pgdir, la, create); #else /* PTXSHIFT == PMXSHIFT */ pmd_t *pmdp; if ((pmdp = get_pmd(pgdir, la, create)) == NULL) { return NULL; } if (! ptep_present(pmdp)) { struct Page *page; if (!create || (page = alloc_page()) == NULL) { return NULL; } set_page_ref(page, 1); uintptr_t pa = page2pa(page); memset(KADDR(pa), 0, PGSIZE); #ifdef ARCH_ARM pdep_map(pmdp, pa); #else ptep_map(pmdp, pa); #endif #ifndef ARCH_ARM ptep_set_u_write(pmdp); ptep_set_accessed(pmdp); ptep_set_dirty(pmdp); #else #warning ARM9 PDE does not have access field #endif } return &((pte_t *)KADDR(PMD_ADDR(*pmdp)))[PTX(la)]; #endif /* PTXSHIFT == PMXSHIFT */ }
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 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)); }
//buddy_init_memmap - build free_list for Page base follow n continuing pages. static void buddy_init_memmap(struct numa_mem_zone *zone) { static int zone_num = 0; size_t n = zone->n; assert(n > 0 && zone_num < MAX_NUMA_MEM_ZONES); zone_num ++; struct Page *base = zone->page; struct Page *p = base; for (; p != base + n; p++) { assert(PageReserved(p)); p->flags = p->property = 0; p->zone_num = zone->id; set_page_ref(p, 0); } //p = zones[zone_num++].mem_base = base; p = base; size_t order = MAX_ORDER, order_size = (1 << order); uint32_t numa_id = zone->node->id; assert(numa_id < sysconf.lnuma_count); while (n != 0) { while (n >= order_size) { p->property = order; SetPageProperty(p); list_add(&free_list(numa_id, order), &(p->page_link)); n -= order_size, p += order_size; nr_free(numa_id, order)++; } order--; order_size >>= 1; } }
//buddy_init_memmap - build free_list for Page base follow n continuous pages. static void buddy_init_memmap(struct Page *base, size_t n) { static int zone_num = 0; assert(n > 0 && zone_num < MAX_ZONE_NUM); struct Page *p = base; for (; p != base + n; p ++) { assert(PageReserved(p)); p->flags = p->property = 0; p->zone_num = zone_num; set_page_ref(p, 0); } p = zones[zone_num ++].mem_base = base; size_t order = MAX_ORDER, order_size = (1 << order); while (n != 0) { while (n >= order_size) { p->property = order; SetPageProperty(p); list_add(&free_list(order), &(p->page_link)); n -= order_size, p += order_size; nr_free(order) ++; } order --; order_size >>= 1; } }
//get_pte - get pte and return the kernel virtual address of this pte for la // - if the PT contians this pte didn't exist, alloc a page for PT // parameter: // pgdir: the kernel virtual base address of PDT // la: the linear address need to map // create: a logical value to decide if alloc a page for PT // return vaule: the kernel virtual address of this pte pte_t * get_pte(pde_t *pgdir, uintptr_t la, bool create) { /* LAB2 EXERCISE 2: YOUR CODE * * If you need to visit a physical address, please use KADDR() * please read pmm.h for useful macros * * Maybe you want help comment, BELOW comments can help you finish the code * * Some Useful MACROs and DEFINEs, you can use them in below implementation. * MACROs or Functions: * PDX(la) = the index of page directory entry of VIRTUAL ADDRESS la. * KADDR(pa) : takes a physical address and returns the corresponding kernel virtual address. * set_page_ref(page,1) : means the page be referenced by one time * page2pa(page): get the physical address of memory which this (struct Page *) page manages * struct Page * alloc_page() : allocation a page * memset(void *s, char c, size_t n) : sets the first n bytes of the memory area pointed by s * to the specified value c. * DEFINEs: * PTE_V 0x001 // page table/directory entry flags bit : Present * PTE_W 0x002 // page table/directory entry flags bit : Writeable * PTE_U 0x004 // page table/directory entry flags bit : User can access */ #if 0 pde_t *pdep = NULL; // (1) find page directory entry if (0) { // (2) check if entry is not present // (3) check if creating is needed, then alloc page for page table // CAUTION: this page is used for page table, not for common data page // (4) set page reference uintptr_t pa = 0; // (5) get linear address of page // (6) clear page content using memset // (7) set page directory entry's permission } return NULL; // (8) return page table entry #endif pde_t *pdep = &pgdir[PDX(la)]; //right!!! // if(la==0x50000000) // cprintf("pdep=%08x\n",pdep); if (!(*pdep & PTE_V)) { struct Page *page; // cprintf("haha\n"); // cprintf("create=%d\n",create); if (!create || (page = alloc_page()) == NULL) { return NULL; } //cprintf("hahapaget_pte\n"); set_page_ref(page, 1); uintptr_t pa = page2pa(page); memset(KADDR(pa), 0, PGSIZE); *pdep = pa | PTE_TYPE_TABLE | PTE_V | PTE_R; } //cprintf("%08x\n",&((pte_t *)KADDR(PDE_ADDR(*pdep)))[PTX(la)]); // if(la==0x50000000) // cprintf("get_pte return=%08x\n",&((pte_t *)KADDR(PDE_ADDR(*pdep)))[PTX(la)]); return &((pte_t *)KADDR(PDE_ADDR(*pdep)))[PTX(la)]; }
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)); }
static void default_init_memmap(struct Page *base, size_t n) { 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)); }
//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; }
static void default_init_memmap(struct Page *base, size_t n) { assert(n > 0); struct Page *p = base; for (; p != base + n; p ++) { assert(PageReserved(p)); p->flags = 0; // init p->flags as 0 SetPageProperty(p); // p->flags should be set bit PG_property p->property = 0; // p->property should be set to 0 set_page_ref(p, 0); // p->ref should be 0, because now p is free and no reference list_add_before(&free_list, &(p->page_link)); // link this page to free_list } base->property = n; // for the first page of free block, its property should be set to total num of block nr_free += n; // sum the number of free mem block }
static void default_init_memmap(struct Page *base, size_t n) { assert(n > 0); struct Page *p = base +1; for (; p < base + n; ++ p) { assert(PageReserved(p)); ClearPageReserved(p); ClearPageProperty(p); p->property = 0; set_page_ref(p, 0); list_init(&(p->page_link)); } assert(PageReserved(base)); ClearPageReserved(base); SetPageProperty(base); base->property = n; set_page_ref(base, 0); list_add_before(&free_list, &(base -> page_link)); nr_free += n; }
static void default_init_memmap(struct Page *base, size_t n) { assert(n > 0); struct Page *p = base; for (; p != base + n; p ++) { assert(PageReserved(p)); p->flags = 0; // Clears the flags. p->property = 0; // Not the first page of free block. set_page_ref(p, 0); // Free and no reference. } SetPageProperty(base); // Valid page. list_add(&free_list, &(base->page_link)); // Links this page to free_list base->property = n; // First page of n free blocks. 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 * 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_init_memmap(struct Page *base, size_t n) { assert(n > 0); struct Page *p = base; for (; p != base + n; p ++) { assert(PageReserved(p)); p->flags = 0; SetPageProperty(p); p->property = 0; set_page_ref(p, 0); list_add_before(&free_list, &(p->page_link)); } nr_free += n; //first block base->property = n; }
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); 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); 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; }
static void default_free_pages(struct Page *base, size_t n) { assert(n > 0); // (5.1) list_entry_t *le = &free_list; while ((le = list_next(le)) != &free_list) { if (le2page(le, page_link) > base) { // the first position higher than base break; } } struct Page *p; for (p = base; p < base + n; p++) { // insert these pages p->property = 0; list_add_before(le, &(p->page_link)); } // (5.2) mark base as free page base->flags = 0; SetPageProperty(base); base->property = n; set_page_ref(base, 0); // (5.3) p = le2page(le, page_link); if (p == base + n) { // merge forward base->property += p->property; // merge p into base p->property = 0; } le = list_prev(&(base->page_link)); p = le2page(le, page_link); // prev of base if (p == base - 1) { // merge backward for (; le != &free_list; le = list_prev(le)) { p = le2page(le, page_link); if (p->property > 0) { // find property, merge base into p p->property += base->property; base->property = 0; break; } } } nr_free += n; }
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 void default_free_pages(struct Page *base, size_t n) { assert(n > 0); list_entry_t *le = &free_list; list_entry_t *bef; struct Page* p; while ((le = list_next(le)) != &free_list){ p = le2page(le, page_link); if (p > base) break; } for (p = base; p< base+n; p++){ list_add_before(le, &(p->page_link)); } base ->flags = 0; set_page_ref(base, 0); ClearPageReserved(base); // SetPageProperty(base); base->property = n; p = le2page(le, page_link); if (base + n == p){ base->property += p->property; p->property = 0; } bef = list_prev(&(base->page_link)); p = le2page(bef, page_link); if (bef != &free_list && p == base-1){ while (bef != &free_list){ if (p -> property != 0){ p->property += base->property; base->property = 0; break; } bef = list_prev(bef); p = le2page(bef, page_link); } } nr_free += n; return; }
static void default_init_memmap(struct Page *base, size_t n) { assert(n > 0); //首先需要初始化该空闲块中的每个页 struct Page *p = base; for (; p != base + n; p++) { assert(PageReserved(p)); p->flags = 0; SetPageProperty(p); //设置p->flags p->property = 0; //设置p->property set_page_ref(p, 0); //设置 p->ref list_add_before(&free_list, &(p->page_link)); } //base是该空闲块中的第一个page,并且是free的,故property赋值为n base->property = n; //最后更新nf_free的值 nr_free += n; }
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_init_memmap(struct Page *base, size_t n) { 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)); list_entry_t *le = &free_list; while ((le = list_next(le)) != &free_list) { struct Page *p = le2page(le, page_link); cprintf("iiiiiiii %d \n",p->flags); } }
static void default_init_memmap(struct Page *base, size_t n) { assert(n > 0); // n是页数 struct Page *p = base; for (; p != base + n; p ++) { assert(PageReserved(p)); p->flags = p->property = 0; SetPageProperty(p); set_page_ref(p, 0); // 引用计数设置为0 // 也就是在free_list的前面插入,不过考虑到这是一个双向链表,所以实际的意思是,插到链表的尾部 list_add_before(&free_list, &(p->page_link)); } // 因为base是头表 // property这个玩意只有在free block首地址对应的Page有用,其余都被设置为了0 // 用于指示这个free block一共有多少个free page base->property = n; // 可用的页面数是n SetPageProperty(base); // base所在的页面为头表 nr_free += n; // 空闲的页面数目增加了n //list_add(&free_list, &(base->page_link)); // 添加到free_list的头部 }
pmd_t * get_pmd(pgd_t *pgdir, uintptr_t la, bool create) { #if PMXSHIFT == PUXSHIFT return get_pud(pgdir, la, create); #else /* PMXSHIFT == PUXSHIFT */ pud_t *pudp; if ((pudp = get_pud(pgdir, la, create)) == NULL) { return NULL; } if (!(*pudp & PTE_P)) { struct Page *page; if (!create || (page = alloc_page()) == NULL) { return NULL; } set_page_ref(page, 1); uintptr_t pa = page2pa(page); memset(VADDR_DIRECT(pa), 0, PGSIZE); *pudp = pa | PTE_U | PTE_W | PTE_P; } return &((pmd_t *)VADDR_DIRECT(PUD_ADDR(*pudp)))[PMX(la)]; #endif /* PMXSHIFT == PUXSHIFT */ }
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; }