4,441
社区成员
发帖
与我相关
我的任务
分享
struct mm_struct {
struct vm_area_struct * mmap; /* list of VMAs */
struct vm_area_struct * mmap_avl; /* tree of VMAs */
struct vm_area_struct * mmap_cache; /* last find_vma result */
pgd_t * pgd;
atomic_t mm_users; /* How many users with user space? */
atomic_t mm_count; /* How many references to "struct mm_struct" (users count as 1) */
int map_count; /* number of VMAs */
struct semaphore mmap_sem;
spinlock_t page_table_lock;
struct list_head mmlist; /* List of all active mm's */
unsigned long start_code, end_code, start_data, end_data;
unsigned long start_brk, brk, start_stack;
unsigned long arg_start, arg_end, env_start, env_end;
unsigned long rss, total_vm, locked_vm;
unsigned long def_flags;
unsigned long cpu_vm_mask;
unsigned long swap_cnt; /* number of pages to swap on next pass */
unsigned long swap_address;
/* Architecture-specific MM context */
mm_context_t context;
};
struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr)
{
struct vm_area_struct *vma = NULL;
if (mm) {
/* Check the cache first. */
/* (Cache hit rate is typically around 35%.) */
vma = mm->mmap_cache;
if (!(vma && vma->vm_end > addr && vma->vm_start <= addr)) {
if (!mm->mmap_avl) {
/* Go through the linear list. */
vma = mm->mmap;
while (vma && vma->vm_end <= addr)
vma = vma->vm_next;
} else {
/* Then go through the AVL tree quickly. */
struct vm_area_struct * tree = mm->mmap_avl;
vma = NULL;
for (;;) {
if (tree == vm_avl_empty)
break;
if (tree->vm_end > addr) {
vma = tree;
if (tree->vm_start <= addr)
break;
tree = tree->vm_avl_left;
} else
tree = tree->vm_avl_right;
}
}
if (vma)
mm->mmap_cache = vma;
}
}
return vma;
}
struct vm_area_struct * find_vma_prev(struct mm_struct * mm, unsigned long addr,
struct vm_area_struct **pprev)
{
if (mm) {
if (!mm->mmap_avl) {
/* Go through the linear list. */
struct vm_area_struct * prev = NULL;
struct vm_area_struct * vma = mm->mmap;
while (vma && vma->vm_end <= addr) {
prev = vma;
vma = vma->vm_next;
}
*pprev = prev;
return vma;
} else {
/* Go through the AVL tree quickly. */
struct vm_area_struct * vma = NULL;
struct vm_area_struct * last_turn_right = NULL;
struct vm_area_struct * prev = NULL;
struct vm_area_struct * tree = mm->mmap_avl;
for (;;) {
if (tree == vm_avl_empty)
break;
if (tree->vm_end > addr) {
vma = tree;
prev = last_turn_right;
if (tree->vm_start <= addr)
break;
tree = tree->vm_avl_left;
} else {
last_turn_right = tree;
tree = tree->vm_avl_right;
}
}
if (vma) {
if (vma->vm_avl_left != vm_avl_empty) {
prev = vma->vm_avl_left;
while (prev->vm_avl_right != vm_avl_empty)
prev = prev->vm_avl_right;
}
if ((prev ? prev->vm_next : mm->mmap) != vma)
printk("find_vma_prev: tree inconsistent with list\n");
*pprev = prev;
return vma;
}
}
}
*pprev = NULL;
return NULL;
}