diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2014-07-15 19:57:03 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2014-07-15 19:57:03 +0000 |
commit | a62eb1398a98d7f5e8829817819221f022709000 (patch) | |
tree | 32b516152e2e8ccd469be90e4f34d3cf7299f0c1 /sys/kern/kern_proc.c | |
parent | 3760e341ca1375f1726d42e3d53764d964ccb954 (diff) | |
download | src-a62eb1398a98d7f5e8829817819221f022709000.tar.gz src-a62eb1398a98d7f5e8829817819221f022709000.zip |
Followup to r268466.
- Move the code to calculate resident count into separate function.
It reduces the indent level and makes the operation of
vmmap_skip_res_cnt tunable more clear.
- Optimize the calculation of the resident page count for map entry.
Skip directly to the next lowest available index and page among the
whole shadow chain.
- Restore the use of pmap_incore(9), only to verify that current
mapping is indeed superpage.
- Note the issue with the invalid pages.
Suggested and reviewed by: alc
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Notes
Notes:
svn path=/head/; revision=268712
Diffstat (limited to 'sys/kern/kern_proc.c')
-rw-r--r-- | sys/kern/kern_proc.c | 90 |
1 files changed, 62 insertions, 28 deletions
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 4d72ffba2b66..6d3c732f0b3c 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -2133,6 +2133,66 @@ sysctl_kern_proc_ovmmap(SYSCTL_HANDLER_ARGS) CTASSERT(sizeof(struct kinfo_vmentry) == KINFO_VMENTRY_SIZE); #endif +static void +kern_proc_vmmap_resident(vm_map_t map, vm_map_entry_t entry, + struct kinfo_vmentry *kve) +{ + vm_object_t obj, tobj; + vm_page_t m, m_adv; + vm_offset_t addr; + vm_paddr_t locked_pa; + vm_pindex_t pi, pi_adv, pindex; + + locked_pa = 0; + obj = entry->object.vm_object; + addr = entry->start; + m_adv = NULL; + pi = OFF_TO_IDX(entry->offset + addr - entry->start); + for (; addr < entry->end; addr += IDX_TO_OFF(pi_adv), pi += pi_adv) { + if (m_adv != NULL) { + m = m_adv; + } else { + pi_adv = OFF_TO_IDX(entry->end - addr); + pindex = pi; + for (tobj = obj;; tobj = tobj->backing_object) { + m = vm_page_find_least(tobj, pindex); + if (m != NULL) { + if (m->pindex == pindex) + break; + if (pi_adv > m->pindex - pindex) { + pi_adv = m->pindex - pindex; + m_adv = m; + } + } + if (tobj->backing_object == NULL) + goto next; + pindex += OFF_TO_IDX(tobj-> + backing_object_offset); + } + } + m_adv = NULL; + if (m->psind != 0 && addr + pagesizes[1] <= entry->end && + (addr & (pagesizes[1] - 1)) == 0 && + (pmap_mincore(map->pmap, addr, &locked_pa) & + MINCORE_SUPER) != 0) { + kve->kve_flags |= KVME_FLAG_SUPER; + pi_adv = OFF_TO_IDX(pagesizes[1]); + } else { + /* + * We do not test the found page on validity. + * Either the page is busy and being paged in, + * or it was invalidated. The first case + * should be counted as resident, the second + * is not so clear; we do account both. + */ + pi_adv = 1; + } + kve->kve_resident += pi_adv; +next:; + } + PA_UNLOCK_COND(locked_pa); +} + /* * Must be called with the process locked and will return unlocked. */ @@ -2142,14 +2202,12 @@ kern_proc_vmmap_out(struct proc *p, struct sbuf *sb) vm_map_entry_t entry, tmp_entry; struct vattr va; vm_map_t map; - vm_page_t m; vm_object_t obj, tobj, lobj; char *fullpath, *freepath; struct kinfo_vmentry *kve; struct ucred *cred; struct vnode *vp; struct vmspace *vm; - vm_pindex_t pindex; vm_offset_t addr; unsigned int last_timestamp; int error; @@ -2185,32 +2243,8 @@ kern_proc_vmmap_out(struct proc *p, struct sbuf *sb) if (obj->backing_object == NULL) kve->kve_private_resident = obj->resident_page_count; - if (vmmap_skip_res_cnt) - goto skip_resident_count; - for (addr = entry->start; addr < entry->end; - addr += PAGE_SIZE) { - pindex = OFF_TO_IDX(entry->offset + addr - - entry->start); - for (tobj = obj;;) { - m = vm_page_lookup(tobj, pindex); - if (m != NULL) - break; - if (tobj->backing_object == NULL) - break; - pindex += OFF_TO_IDX( - tobj->backing_object_offset); - tobj = tobj->backing_object; - } - if (m != NULL) { - if (m->psind != 0 && addr + - pagesizes[1] <= entry->end) { - kve->kve_flags |= - KVME_FLAG_SUPER; - } - kve->kve_resident += 1; - } - } -skip_resident_count: + if (!vmmap_skip_res_cnt) + kern_proc_vmmap_resident(map, entry, kve); for (tobj = obj; tobj != NULL; tobj = tobj->backing_object) { if (tobj != obj && tobj != lobj) |