static void check_n_pages(void) { struct Page* pp, *pp0; char* addr; int i; pp = pp0 = 0; // Allocate two single pages pp = page_alloc(0); pp0 = page_alloc(0); assert(pp != 0); assert(pp0 != 0); assert(pp != pp0); //cprintf("1"); // Free pp and assign four continuous pages page_free(pp); pp = page_alloc_npages(0, 4); //cprintf("1"); assert(check_continuous(pp, 4)); // //pps = page_realloc_npages(pps, 4, 6); //assert(check_continuous(pps, 6)); //cprintf("s"); // Free four continuous pages // assert(!page_free_npages(pp, 4)); //cprintf("1"); // //assert(!page_free_npages(pps, 6)); //cprintf("s"); // Free pp and assign eight continuous pages pp = page_alloc_npages(0, 8); //cprintf("1"); assert(check_continuous(pp, 8)); //cprintf("1"); // Free four continuous pages assert(!page_free_npages(pp, 8)); //cprintf("1"); // Free pp0 and assign four continuous zero pages page_free(pp0); //cprintf("1"); pp0 = page_alloc_npages(ALLOC_ZERO, 4); //cprintf("1"); addr = (char*)page2kva(pp0); //cprintf("1"); // Check Zero for( i = 0; i < 4 * PGSIZE; i++ ){ assert(addr[i] == 0); } //cprintf("1"); // Free pages assert(!page_free_npages(pp0, 4)); cprintf("check_n_pages() succeeded!\n"); /*stone: if you want to test page_realloc_pages() function, please use this*/ //check_realloc(); }
static void check_n_pages(void) { struct Page* pp, *pp0; char* addr; int i; pp = pp0 = 0; // Allocate two single pages pp = page_alloc(0); pp0 = page_alloc(0); assert(pp != 0); assert(pp0 != 0); assert(pp != pp0); // Free pp and assign four continuous pages page_free(pp); pp = page_alloc_npages(0, 4); assert(check_continuous(pp, 4)); // Free four continuous pages assert(!page_free_npages(pp, 4)); // Free pp and assign eight continuous pages pp = page_alloc_npages(0, 8); assert(check_continuous(pp, 8)); // Free four continuous pages assert(!page_free_npages(pp, 8)); // Free pp0 and assign four continuous zero pages page_free(pp0); pp0 = page_alloc_npages(ALLOC_ZERO, 4); addr = (char*)page2kva(pp0); // Check Zero for( i = 0; i < 4 * PGSIZE; i++ ){ assert(addr[i] == 0); } // Free pages assert(!page_free_npages(pp0, 4)); cprintf("check_n_pages() succeeded!\n"); }
// // Return new_n continuous pages based on the allocated old_n pages. // You can man realloc for better understanding. // (Try to reuse the allocated pages as many as possible.) // struct Page * page_realloc_npages(struct Page *pp, int old_n, int new_n) { if (old_n == new_n) return pp; if (old_n > new_n) { page_free_npages(pp+new_n,old_n-new_n); pp[new_n-1].pp_link = NULL; return pp; } int i; bool p = 1; for (i = old_n; i < new_n; i++) { if (pp[i].pp_ref != 0) { p = 0; break; } } if (p == 0) { struct Page *newpp = page_alloc_npages(ALLOC_ZERO,new_n); memmove(page2kva(newpp),page2kva(pp),old_n*PGSIZE); page_free_npages(pp,old_n); pp = newpp; }else { pp[old_n-1].pp_link = pp+old_n; struct Page *iter = page_free_list; struct Page *lst = iter; while (iter != NULL) { if (iter >= pp+old_n && iter <= pp+new_n) { if (iter == page_free_list) page_free_list = iter->pp_link; else{ lst->pp_link = iter->pp_link; } }else{ lst = iter; } iter = iter->pp_link; } for (i = old_n; i < new_n; i++) { pp[i].pp_link = pp+i+1; } memset(page2kva(pp+old_n),0,(new_n-old_n)*PGSIZE); } return pp; }
/*stone's check-test for lab2*/ static void check_realloc(void) { struct Page* pps; pps = page_alloc_npages(0, 12); assert(check_continuous(pps, 12)); pps = page_realloc_npages(pps, 12, 16); assert(check_continuous(pps, 16)); assert(!page_free_npages(pps, 16)); pps = page_alloc_npages(0, 12); pps = page_realloc_npages(pps, 12, 4); assert(check_continuous(pps, 4)); assert(!page_free_npages(pps, 4)); pps = page_alloc_npages(0, 12); pps = page_realloc_npages(pps, 12, 12); assert(check_continuous(pps, 12)); assert(!page_free_npages(pps, 12)); cprintf("check_realloc() succeed!"); }
struct Page * page_realloc_npages(struct Page *pp, int old_n, int new_n) { // Fill this function //stone's solution for lab2 if (new_n <= 0) return NULL; if (old_n <= 0) return NULL; if (check_continuous(pp, old_n) == 0) return NULL; if (new_n == old_n) return pp; if (new_n < old_n){ page_free_npages(pp+new_n, old_n-new_n); return pp; } //stone: when new_n > old_n ,if the tail pages is continuous, then link them directly, o.w alloc new pages. struct Page* tmp = pp + old_n; size_t i; int flag = 0; for (i = 0; i < new_n - old_n; i++){ if (tmp->pp_ref != 0){ flag = 1; break; } else tmp++; } struct Page* result; if (flag == 0){ result = pp + old_n - 1; for (i = 0; i < new_n - old_n; i++){ result->pp_link = result + 1; result++; } return pp; } else{ result = page_alloc_npages(ALLOC_ZERO, new_n); memmove(page2kva(result), page2kva(pp), old_n*PGSIZE); page_free_npages(pp, old_n); pp = result; return pp; } //return NULL; }
static void check_realloc_npages(void) { struct Page* pp, *pp0; char* addr; int i; pp = pp0 = 0; // Allocate two single pages pp = page_alloc(0); pp0 = page_alloc(0); assert(pp != 0); assert(pp0 != 0); assert(pp != pp0); // Free pp and pp0 page_free(pp); page_free(pp0); // Assign eight continuous pages pp = page_alloc_npages(0, 8); assert(check_continuous(pp, 8)); // Realloc to 4 pages pp0 = page_realloc_npages(pp, 8, 4); assert(pp0 == pp); assert(check_continuous(pp, 4)); // Realloc to 6 pages pp = page_realloc_npages(pp, 4, 6); assert(pp0 == pp); assert(check_continuous(pp, 6)); // Realloc to 12 pages pp0 = page_realloc_npages(pp, 6, 12); assert(check_continuous(pp0, 12)); // Free 12 continuous pages assert(!page_free_npages(pp0, 12)); cprintf("check_realloc_npages() succeeded!\n"); }
// // Return new_n continuous pages based on the allocated old_n pages. // You can man realloc for better understanding. // (Try to reuse the allocated pages as many as possible.) // struct Page * page_realloc_npages(struct Page *pp, int old_n, int new_n) { // Fill this function if (new_n == 0) { page_free_npages(pp, old_n); return NULL; } // assume pp_ref will be added by caller // need more physical pages if (old_n < new_n) { uint32_t more_n = new_n - old_n; uint32_t can_add_flag = 1; uint32_t i = 0; // if can add to tail? for (i = old_n; i < new_n; i++){ // empty and not over limit if ((pp+i)->pp_ref == 0 && pp+i < pages+npages ) { can_add_flag = 0; break; } } // if can't add to tail, free and alloc if (can_add_flag == 0){ struct Page* new_alloc; new_alloc = page_alloc_npages(ALLOC_ZERO, new_n); memmove(page2kva(new_alloc), page2kva(pp), old_n*PGSIZE); page_free_npages(pp, old_n); return new_alloc; } // if can add // first, remove those from page_free_list struct Page* find_pp; while(page_free_list > pp && page_free_list <= pp+more_n) { page_free_list = page_free_list->pp_link; } find_pp = page_free_list; while(find_pp != NULL && find_pp->pp_link != NULL) { if (find_pp->pp_link > pp && find_pp->pp_link <= pp+more_n) { find_pp->pp_link = find_pp->pp_link->pp_link; } find_pp = find_pp->pp_link; } // second, add to old alloc page list for (i = 0; i < more_n; i++) { (pp+i)->pp_link = pp+i+1; } (pp+more_n)->pp_link = NULL; // third, init new memory memset(page2kva(pp+1), 0, more_n*PGSIZE); // fourth, return pp return pp; } else if (old_n > new_n) { // free last pages page_free_npages(pp+new_n, old_n-new_n); (pp+new_n-1)->pp_link = NULL; return pp; } else { // old_n == new_n, do nothing return pp; } return NULL; }
// // Return new_n continuous pages based on the allocated old_n pages. // You can man realloc for better understanding. // (Try to reuse the allocated pages as many as possible.) // struct Page * page_realloc_npages(struct Page *pp, int old_n, int new_n) { // Fill this function if(old_n==new_n) return pp; if(new_n<old_n) { struct Page* skip=pp; int i; for(i=0;i<new_n;i++) skip=skip->pp_link; struct Page* temp; for(i=new_n;i<old_n;i++) { temp=skip; skip=skip->pp_link; page_free(temp); } return pp; } if(new_n>old_n) { struct Page* tail=pp; int i=0; for(i=0;i<old_n-1;i++) tail=tail->pp_link; struct Page* skip=page_free_list; int found=0;int following=0; while(skip) { if(page2pa(skip)-page2pa(tail)==PGSIZE) { found=1; break; } skip=skip->pp_link; } if(found==1) { if(check_continuous(skip,new_n-old_n)==1) following=1; } if(following==1) { struct Page* prev; struct Page* after; if(skip==page_free_list) { after=skip; for(i=0;i<new_n-old_n;i++) { tail->pp_link=after; tail=after; after=after->pp_link; } tail->pp_link=NULL; page_free_list=after; } else { prev=page_free_list; while(prev->pp_link!=skip) prev=prev->pp_link; after=skip; for(i=0;i<new_n-old_n;i++) { tail->pp_link=after; tail=after; after=after->pp_link; } tail->pp_link=NULL; prev->pp_link=after; } return pp; } else { struct Page* allocPage=page_alloc_npages(1,new_n); if(allocPage==NULL) return NULL; memmove(page2kva(allocPage),page2kva(pp),old_n*PGSIZE); page_free_npages(pp,old_n); return allocPage; } } return NULL; }