summaryrefslogtreecommitdiffstats
path: root/sys/ia64
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2010-04-24 17:32:52 +0000
committeralc <alc@FreeBSD.org>2010-04-24 17:32:52 +0000
commit0a905b1db997b1f231d5d442e158b5228d69937a (patch)
tree7bce54bbe68a24f0e3ffcf944e58cf38a95b99e3 /sys/ia64
parent49089e216a08f4cd346d73ab4334e75650d4aa16 (diff)
downloadFreeBSD-src-0a905b1db997b1f231d5d442e158b5228d69937a.zip
FreeBSD-src-0a905b1db997b1f231d5d442e158b5228d69937a.tar.gz
Resurrect pmap_is_referenced() and use it in mincore(). Essentially,
pmap_ts_referenced() is not always appropriate for checking whether or not pages have been referenced because it clears any reference bits that it encounters. For example, in mincore(), clearing the reference bits has two negative consequences. First, it throws off the activity count calculations performed by the page daemon. Specifically, a page on which mincore() has called pmap_ts_referenced() looks less active to the page daemon than it should. Consequently, the page could be deactivated prematurely by the page daemon. Arguably, this problem could be fixed by having mincore() duplicate the activity count calculation on the page. However, there is a second problem for which that is not a solution. In order to clear a reference on a 4KB page, it may be necessary to demote a 2/4MB page mapping. Thus, a mincore() by one process can have the side effect of demoting a superpage mapping within another process!
Diffstat (limited to 'sys/ia64')
-rw-r--r--sys/ia64/ia64/pmap.c35
1 files changed, 32 insertions, 3 deletions
diff --git a/sys/ia64/ia64/pmap.c b/sys/ia64/ia64/pmap.c
index 6fe4cdf..a7c47ef 100644
--- a/sys/ia64/ia64/pmap.c
+++ b/sys/ia64/ia64/pmap.c
@@ -2023,6 +2023,37 @@ pmap_is_prefaultable(pmap_t pmap, vm_offset_t addr)
}
/*
+ * pmap_is_referenced:
+ *
+ * Return whether or not the specified physical page was referenced
+ * in any physical maps.
+ */
+boolean_t
+pmap_is_referenced(vm_page_t m)
+{
+ struct ia64_lpte *pte;
+ pmap_t oldpmap;
+ pv_entry_t pv;
+ boolean_t rv;
+
+ rv = FALSE;
+ if (m->flags & PG_FICTITIOUS)
+ return (rv);
+ TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
+ PMAP_LOCK(pv->pv_pmap);
+ oldpmap = pmap_switch(pv->pv_pmap);
+ pte = pmap_find_vhpt(pv->pv_va);
+ pmap_switch(oldpmap);
+ KASSERT(pte != NULL, ("pte"));
+ rv = pmap_accessed(pte) ? TRUE : FALSE;
+ PMAP_UNLOCK(pv->pv_pmap);
+ if (rv)
+ break;
+ }
+ return (rv);
+}
+
+/*
* Clear the modify bits on the specified physical page.
*/
void
@@ -2197,10 +2228,8 @@ pmap_mincore(pmap_t pmap, vm_offset_t addr)
* Referenced by someone
*/
vm_page_lock_queues();
- if (pmap_ts_referenced(m)) {
+ if (pmap_is_referenced(m))
val |= MINCORE_REFERENCED_OTHER;
- vm_page_flag_set(m, PG_REFERENCED);
- }
vm_page_unlock_queues();
}
}
OpenPOWER on IntegriCloud