// vma_compare - compare vma1->vm_start < vma2->vm_start ? static inline int vma_compare(rb_node *node1, rb_node *node2) { struct vma_struct *vma1 = rbn2vma(node1, rb_link); struct vma_struct *vma2 = rbn2vma(node2, rb_link); uintptr_t start1 = vma1->vm_start, start2 = vma2->vm_start; return (start1 < start2) ? -1 : (start1 > start2) ? 1 : 0; }
static int vma_compare(RBNode* a, RBNode* b) { ptrdiff_t ret = rbn2vma(a, vm_link)->vm_start - rbn2vma(b, vm_link)->vm_start; if (ret > 0) return 1; else if (ret < 0) return -1; return 0; }
// find_vma_rb - find a vma (vma->vm_start <= addr < vma_vm_end) in rb tree static inline struct vma_struct *find_vma_rb(rb_tree * tree, uintptr_t addr) { rb_node *node = rb_node_root(tree); struct vma_struct *vma = NULL, *tmp; //kprintf(" find_vma_rb begin:: addr is %d\n",addr); while (node != NULL) { tmp = rbn2vma(node, rb_link); //kprintf("find_vma_rb while:: vma tmp start %d, end %d, addr %d\n",tmp->vm_start, tmp->vm_end, addr); if (tmp->vm_end > addr) { vma = tmp; if (tmp->vm_start <= addr) { break; } vma = NULL; node = rb_node_left(tree, node); } else { vma = NULL; node = rb_node_right(tree, node); } } #if 0 if (vma!=NULL) kprintf(" find_vma_rb end:: addr %d, vma %x, start %d, end %d\n",addr, vma, vma->vm_start, vma->vm_end); else kprintf(" find_vma_rb end:: vma is NULL\n"); #endif return vma; }
// insert_vma_rb - insert vma in rb tree according vma->start_addr static inline void insert_vma_rb(rb_tree *tree, struct vma_struct *vma, struct vma_struct **vma_prevp) { rb_node *node = &(vma->rb_link), *prev; rb_insert(tree, node); if (vma_prevp != NULL) { prev = rb_node_prev(tree, node); *vma_prevp = (prev != NULL) ? rbn2vma(prev, rb_link) : NULL; } }
static int vma_key_compare(RBNode* n, void* key) { ptrdiff_t ret = rbn2vma(n, vm_link)->vm_start - *(uintptr_t*)key; if (ret > 0) return 1; else if (ret < 0) return -1; return 0; }
void vm_insert_vma(ProcVM *proc, ProcVMA *vma) { kassert(vma->vm_start < vma->vm_end); rb_insert(&(proc->mmap_root), &(vma->vm_link)); #if defined(__PCORE_NO_OPTIMIZE__) // Check overlap. RBNode *x = rb_search(&(proc->mmap_root), vma_key_compare, &(vma->vm_start)); kassert(x != NULL); RBNode *y = rb_node_prev(&(proc->mmap_root), x); if (y != NULL) { vma_check_overlap(rbn2vma(y, vm_link), vma); } y = rb_node_next(&(proc->mmap_root), x); if (y != NULL) { vma_check_overlap(vma, rbn2vma(y, vm_link)); } #endif // __PCORE_NO_OPTIMIZE__ atomic_add(&(proc->map_count), 1); }
static void check_vma_struct(void) { ProcVM *mm = vm_create_proc(); assert(mm != NULL); int step1 = 10, step2 = step1 * 10; int i; for (i = step1; i >= 1; i --) { ProcVMA *vma = vm_create_vma(i * 5, i * 5 + 2, 0); assert(vma != NULL); vm_insert_vma(mm, vma); } for (i = step1 + 1; i <= step2; i ++) { ProcVMA *vma = vm_create_vma(i * 5, i * 5 + 2, 0); assert(vma != NULL); vm_insert_vma(mm, vma); } RBNode *rbn = rb_leftmost(&(mm->mmap_root)); for (i = 1; i <= step2; i ++) { assert(rbn != NULL); ProcVMA *mmap = rbn2vma(rbn, vm_link); assert(mmap->vm_start == i * 5 && mmap->vm_end == i * 5 + 2); rbn = rb_node_next(&(mm->mmap_root), rbn); } for (i = 5; i <= 5 * step2; i += 5) { ProcVMA *vma1 = vm_find_vma(mm, i); assert(vma1 != NULL); ProcVMA *vma2 = vm_find_vma(mm, i+1); assert(vma2 != NULL); ProcVMA *vma3 = vm_find_vma(mm, i+2); assert(vma3 == NULL); ProcVMA *vma4 = vm_find_vma(mm, i+3); assert(vma4 == NULL); ProcVMA *vma5 = vm_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--) { ProcVMA *vma_below_5 = vm_find_vma(mm,i); assert(vma_below_5 == NULL); } vm_destroy_proc(mm); printf("[vmm] Passes check_vma_struct test.\n"); }
static void print_vma_struct(ProcVM *proc) { // Find the left-most node. RBNode *start = rb_leftmost(&(proc->mmap_root)); // Print every node. for (; start != NULL;) { ProcVMA *vma = rbn2vma(start, vm_link); printf("VMA start=%08u, end=%08u\n", vma->vm_start, vma->vm_end); start = rb_node_next(&(proc->mmap_root), start); } kfree(proc); }
void vm_destroy_proc(ProcVM *proc) { kassert(vm_get_proc_count(proc) == 0); // Find the left-most node. RBNode *start = rb_leftmost(&(proc->mmap_root)); // Destroy every node. for (; start != NULL;) { RBNode *right = rb_node_next(&(proc->mmap_root), start); kfree(rbn2vma(start, vm_link)); start = right; } kfree(proc); }
// find_vma_rb - find a vma (vma->vm_start <= addr <= vma_vm_end) in rb tree static inline struct vma_struct * find_vma_rb(rb_tree *tree, uintptr_t addr) { rb_node *node = rb_node_root(tree); struct vma_struct *vma = NULL, *tmp; while (node != NULL) { tmp = rbn2vma(node, rb_link); if (tmp->vm_end > addr) { vma = tmp; if (tmp->vm_start <= addr) { break; } node = rb_node_left(tree, node); } else { node = rb_node_right(tree, node); } } return vma; }
ProcVMA* vm_find_vma(ProcVM *proc, uintptr_t addr) { ProcVMA *vma = NULL; if (proc != NULL) { vma = proc->mmap_cache; if (!(vma != NULL && vma->vm_start <= addr && vma->vm_end > addr)) { RBNode *ret = rb_upbound(&(proc->mmap_root), vma_key_compare, &addr); if (ret == NULL) vma = NULL; else { vma = rbn2vma(ret, vm_link); if (vma->vm_end <= addr) vma = NULL; } } if (vma != NULL) proc->mmap_cache = vma; } return vma; }