diff options
author | truckman <truckman@FreeBSD.org> | 2002-07-22 08:25:37 +0000 |
---|---|---|
committer | truckman <truckman@FreeBSD.org> | 2002-07-22 08:25:37 +0000 |
commit | 4e1d45c7e4bcb9b58482a6b8826f24e4e80562fe (patch) | |
tree | 6e679c177d6d751fe6b7312ead26b9df68fc492e | |
parent | 7825a53069172475d61bd42a2d426f3c2be43bc8 (diff) | |
download | FreeBSD-src-4e1d45c7e4bcb9b58482a6b8826f24e4e80562fe.zip FreeBSD-src-4e1d45c7e4bcb9b58482a6b8826f24e4e80562fe.tar.gz |
Provide a way for sysctl handlers to pre-wire their output buffer before
they grab a lock so that they don't block in SYSCTL_OUT() with the lock
being held.
-rw-r--r-- | sys/kern/kern_sysctl.c | 17 | ||||
-rw-r--r-- | sys/sys/sysctl.h | 1 |
2 files changed, 18 insertions, 0 deletions
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index 8f30fed..5472cf7 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -990,6 +990,23 @@ sysctl_new_user(struct sysctl_req *req, void *p, size_t l) return (error); } +/* + * Wire the user space destination buffer. If set to a value greater than + * zero, the len parameter limits the maximum amount of wired memory. + * + * XXX - The len parameter is currently ignored due to the lack of + * a place to save it in the sysctl_req structure so that the matching + * amount of memory can be unwired in the sysctl exit code. + */ +void +sysctl_wire_old_buffer(struct sysctl_req *req, size_t len) +{ + if (req->lock == 1 && req->oldptr && req->oldfunc == sysctl_old_user) { + vslock(req->oldptr, req->oldlen); + req->lock = 2; + } +} + int sysctl_find_oid(int *name, u_int namelen, struct sysctl_oid **noid, int *nindx, struct sysctl_req *req) diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h index f9a7818..e0d47ae 100644 --- a/sys/sys/sysctl.h +++ b/sys/sys/sysctl.h @@ -595,6 +595,7 @@ int userland_sysctl(struct thread *td, int *name, u_int namelen, void *old, size_t *retval); int sysctl_find_oid(int *name, u_int namelen, struct sysctl_oid **noid, int *nindx, struct sysctl_req *req); +void sysctl_wire_old_buffer(struct sysctl_req *req, size_t len); #else /* !_KERNEL */ #include <sys/cdefs.h> |