diff options
author | truckman <truckman@FreeBSD.org> | 2006-01-25 01:03:34 +0000 |
---|---|---|
committer | truckman <truckman@FreeBSD.org> | 2006-01-25 01:03:34 +0000 |
commit | 9f8a407ccb300c9276aa63a86ef00e3a1d8c43ee (patch) | |
tree | aa35f34c3e4e057ece92157cdb9b46303d9f5677 /sys/kern/kern_sysctl.c | |
parent | 4730881b84dbcf19ec1fe034d784fcdddf207c96 (diff) | |
download | FreeBSD-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
Diffstat (limited to 'sys/kern/kern_sysctl.c')
-rw-r--r-- | sys/kern/kern_sysctl.c | 13 |
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; |