summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortruckman <truckman@FreeBSD.org>2002-07-22 08:25:37 +0000
committertruckman <truckman@FreeBSD.org>2002-07-22 08:25:37 +0000
commit4e1d45c7e4bcb9b58482a6b8826f24e4e80562fe (patch)
tree6e679c177d6d751fe6b7312ead26b9df68fc492e
parent7825a53069172475d61bd42a2d426f3c2be43bc8 (diff)
downloadFreeBSD-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.c17
-rw-r--r--sys/sys/sysctl.h1
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>
OpenPOWER on IntegriCloud