/* * Returns remaining count of pages to be swapped out by followup call. */ static inline int swap_out_mm(struct mm_struct * mm, int count, int * mmcounter, zone_t * classzone) { unsigned long address; struct vm_area_struct* vma; /* * Find the proper vm-area after freezing the vma chain * and ptes. */ spin_lock(&mm->page_table_lock); continue_scan: address = mm->swap_address; if (address == TASK_SIZE || swap_mm != mm) { /* We raced: don't count this mm but try again */ ++*mmcounter; goto out_unlock; } vma = find_vma(mm, address); if (vma) { if (address < vma->vm_start) address = vma->vm_start; for (;;) { count = swap_out_vma(mm, vma, address, count, classzone); vma = vma->vm_next; if (!vma) break; /* we reach this with a lock depth of 1 and 2 */ #if 0 if (conditional_schedule_needed()) { break_spin_lock(&mm->page_table_lock); goto continue_scan; } #endif if (!count) goto out_unlock; address = vma->vm_start; } } /* Indicate that we reached the end of address space */ mm->swap_address = TASK_SIZE; out_unlock: spin_unlock(&mm->page_table_lock); return count; }
static int swap_out_mm(struct mm_struct * mm, int gfp_mask) { unsigned long address; struct vm_area_struct* vma; /* * Go through process' page directory. */ address = mm->swap_address; /* * Find the proper vm-area after freezing the vma chain * and ptes. */ spin_lock(&mm->page_table_lock); vma = find_vma(mm, address); if (vma) { if (address < vma->vm_start) address = vma->vm_start; for (;;) { int result = swap_out_vma(mm, vma, address, gfp_mask); if (result) return result; if (!mm->swap_cnt) goto out_unlock; vma = vma->vm_next; if (!vma) break; address = vma->vm_start; } } /* Reset to 0 when we reach the end of address space */ mm->swap_address = 0; mm->swap_cnt = 0; out_unlock: spin_unlock(&mm->page_table_lock); /* We didn't find anything for the process */ return 0; }
// swap_out_mm - call swap_out_vma to try to unmap a set of vma ('require' NUM pages). int swap_out_mm(struct mm_struct *mm, size_t require) { assert(mm != NULL); if (require == 0 || mm->map_count == 0) { return 0; } assert(!list_empty(&(mm->mmap_list))); uintptr_t addr = mm->swap_address; struct vma_struct *vma; if ((vma = find_vma(mm, addr)) == NULL) { addr = mm->swap_address = 0; vma = le2vma(list_next(&(mm->mmap_list)), list_link); } assert(vma != NULL && addr <= vma->vm_end); if (addr < vma->vm_start) { addr = vma->vm_start; } int i; size_t free_count = 0; for (i = 0; i <= mm->map_count; i ++) { int ret = swap_out_vma(mm, vma, addr, require); free_count += ret, require -= ret; if (require == 0) { break; } list_entry_t *le = list_next(&(vma->list_link)); if (le == &(mm->mmap_list)) { le = list_next(le); } vma = le2vma(le, list_link); addr = vma->vm_start; } return free_count; }