static void check_vma_struct(void) { size_t nr_free_pages_store = nr_free_pages(); struct mm_struct *mm = mm_create(); assert(mm != NULL); int step1 = 10, step2 = step1 * 10; int i; for (i = step1; i >= 1; i --) { struct vma_struct *vma = vma_create(i * 5, i * 5 + 2, 0); assert(vma != NULL); insert_vma_struct(mm, vma); } for (i = step1 + 1; i <= step2; i ++) { struct vma_struct *vma = vma_create(i * 5, i * 5 + 2, 0); assert(vma != NULL); insert_vma_struct(mm, vma); } list_entry_t *le = list_next(&(mm->mmap_list)); for (i = 1; i <= step2; i ++) { assert(le != &(mm->mmap_list)); struct vma_struct *mmap = le2vma(le, list_link); assert(mmap->vm_start == i * 5 && mmap->vm_end == i * 5 + 2); le = list_next(le); } for (i = 5; i <= 5 * step2; i +=5) { struct vma_struct *vma1 = find_vma(mm, i); assert(vma1 != NULL); struct vma_struct *vma2 = find_vma(mm, i+1); assert(vma2 != NULL); struct vma_struct *vma3 = find_vma(mm, i+2); assert(vma3 == NULL); struct vma_struct *vma4 = find_vma(mm, i+3); assert(vma4 == NULL); struct vma_struct *vma5 = find_vma(mm, i+4); assert(vma5 == NULL); assert(vma1->vm_start == i && vma1->vm_end == i + 2); assert(vma2->vm_start == i && vma2->vm_end == i + 2); } for (i =4; i>=0; i--) { struct vma_struct *vma_below_5= find_vma(mm,i); if (vma_below_5 != NULL ) { cprintf("vma_below_5: i %x, start %x, end %x\n",i, vma_below_5->vm_start, vma_below_5->vm_end); } assert(vma_below_5 == NULL); } mm_destroy(mm); assert(nr_free_pages_store == nr_free_pages()); cprintf("check_vma_struct() succeeded!\n"); }
int mm_unmap(struct mm_struct *mm, uintptr_t addr, size_t len) { uintptr_t start = ROUNDDOWN(addr, PGSIZE), end = ROUNDUP(addr + len, PGSIZE); if (!USER_ACCESS(start, end)) { return -E_INVAL; } assert(mm != NULL); struct vma_struct *vma; if ((vma = find_vma(mm, start)) == NULL || end <= vma->vm_start) { return 0; } if (vma->vm_start < start && end < vma->vm_end) { struct vma_struct *nvma; if ((nvma = vma_create(vma->vm_start, start, vma->vm_flags)) == NULL) { return -E_NO_MEM; } vma_resize(vma, end, vma->vm_end); insert_vma_struct(mm, nvma); unmap_range(mm->pgdir, start, end); return 0; } list_entry_t free_list, *le; list_init(&free_list); while (vma->vm_start < end) { le = list_next(&(vma->list_link)); remove_vma_struct(mm, vma); list_add(&free_list, &(vma->list_link)); if (le == &(mm->mmap_list)) { break; } vma = le2vma(le, list_link); } le = list_next(&free_list); while (le != &free_list) { vma = le2vma(le, list_link); le = list_next(le); uintptr_t un_start, un_end; if (vma->vm_start < start) { un_start = start, un_end = vma->vm_end; vma_resize(vma, vma->vm_start, un_start); insert_vma_struct(mm, vma); } else { un_start = vma->vm_start, un_end = vma->vm_end; if (end < un_end) { un_end = end; vma_resize(vma, un_end, vma->vm_end); insert_vma_struct(mm, vma); } else { vma_destroy(vma); } } unmap_range(mm->pgdir, un_start, un_end); } return 0; }