summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortruckman <truckman@FreeBSD.org>2006-01-25 01:03:34 +0000
committertruckman <truckman@FreeBSD.org>2006-01-25 01:03:34 +0000
commit9f8a407ccb300c9276aa63a86ef00e3a1d8c43ee (patch)
treeaa35f34c3e4e057ece92157cdb9b46303d9f5677
parent4730881b84dbcf19ec1fe034d784fcdddf207c96 (diff)
downloadFreeBSD-src-9f8a407ccb300c9276aa63a86ef00e3a1d8c43ee.zip
FreeBSD-src-9f8a407ccb300c9276aa63a86ef00e3a1d8c43ee.tar.gz
Touch all the pages wired by sysctl_wire_old_buffer() to avoid PTE
modified bit emulation traps on Alpha while holding locks in the sysctl handler. A better solution would be to pass a hint to the Alpha pmap code to tell mark these pages as modified when they as they are being wired, but that appears to be more difficult to implement. Suggested by: jhb MFC after: 3 days
-rw-r--r--sys/kern/kern_sysctl.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c
index 6a64a1a..38fb5dc 100644
--- a/sys/kern/kern_sysctl.c
+++ b/sys/kern/kern_sysctl.c
@@ -1118,7 +1118,8 @@ int
sysctl_wire_old_buffer(struct sysctl_req *req, size_t len)
{
int ret;
- size_t wiredlen;
+ size_t i, wiredlen;
+ char *cp, dummy;
wiredlen = (len > 0 && len < req->oldlen) ? len : req->oldlen;
ret = 0;
@@ -1131,6 +1132,16 @@ sysctl_wire_old_buffer(struct sysctl_req *req, size_t len)
return (ret);
wiredlen = 0;
}
+ /*
+ * Touch all the wired pages to avoid PTE modified
+ * bit emulation traps on Alpha while holding locks
+ * in the sysctl handler.
+ */
+ for (i = (wiredlen + PAGE_SIZE - 1) / PAGE_SIZE,
+ cp = req->oldptr; i > 0; i--, cp += PAGE_SIZE) {
+ copyin(cp, &dummy, 1);
+ copyout(&dummy, cp, 1);
+ }
}
req->lock = REQ_WIRED;
req->validlen = wiredlen;
OpenPOWER on IntegriCloud