// mm_destroy - free mm and mm internal fields void mm_destroy(struct mm_struct *mm) { if (mm->mmap_tree != NULL) { rb_tree_destroy(mm->mmap_tree); } while (!list_empty(&(mm->mmap_list))) { list_entry_t *le = list_next(&(mm->mmap_list)); list_del(le); vma_destroy(le2vma(le, list_link)); } kfree(mm); }
// mm_destroy - free mm and mm internal fields void mm_destroy(struct mm_struct *mm) { assert(mm_count(mm) == 0); if (mm->mmap_tree != NULL) { rb_tree_destroy(mm->mmap_tree); } list_entry_t *list = &(mm->mmap_list), *le; while ((le = list_next(list)) != list) { list_del(le); vma_destroy(le2vma(le, list_link)); } kfree(mm); }
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; }
static int dreg_remove (dreg_entry *r) { vma_t *vma; vma = vma_search (DREG_BEGIN (r)); if (vma == NULL) /* no such region in database */ return -1; while (vma != &vma_list && vma->start <= DREG_END (r)) { remove_entry (vma, r); if (vma->list == NULL) { vma_t *next = vma->next; vma_remove (vma); vma->prev->next = vma->next; vma->next->prev = vma->prev; vma_destroy (vma); vma = next; } else { int merged; do { merged = 0; if (vma->start == vma->prev->end + 1 && compare_lists (vma, vma->prev)) { vma_t *t = vma; vma = vma->prev; vma->end = t->end; vma->next = t->next; vma->next->prev = vma; vma_remove (t); vma_destroy (t); merged = 1; } if (vma->end + 1 == vma->next->start && compare_lists (vma, vma->next)) { vma_t *t = vma->next; vma->end = t->end; vma->next = t->next; vma->next->prev = vma; vma_remove (t); vma_destroy (t); merged = 1; } } while (merged); vma = vma->next; } } return 0; }