summaryrefslogtreecommitdiffstats
path: root/sys/kern/sys_generic.c
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2002-09-01 20:37:28 +0000
committeriedowse <iedowse@FreeBSD.org>2002-09-01 20:37:28 +0000
commitbe17b12cb696a0d3f7deed6d1b2201b472b6f85c (patch)
treeec81ad0e54c0e056c6214598679ec3e70c089905 /sys/kern/sys_generic.c
parent84a9d83087b5c82ac362ac1c686726ba0657c506 (diff)
downloadFreeBSD-src-be17b12cb696a0d3f7deed6d1b2201b472b6f85c.zip
FreeBSD-src-be17b12cb696a0d3f7deed6d1b2201b472b6f85c.tar.gz
Split out a number of mostly VFS and signal related syscalls into
a kernel-internal kern_*() version and a wrapper that is called via the syscall vector table. For paths and structure pointers, the internal version either takes a uio_seg parameter or requires the caller to copyin() the data to kernel memory as appropiate. This will permit emulation layers to use these syscalls without having to copy out translated arguments to the stack gap. Discussed on: -arch Review/suggestions: bde, jhb, peter, marcel
Diffstat (limited to 'sys/kern/sys_generic.c')
-rw-r--r--sys/kern/sys_generic.c59
1 files changed, 38 insertions, 21 deletions
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
index 54214e8..ec9958d 100644
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -57,6 +57,7 @@
#include <sys/poll.h>
#include <sys/resourcevar.h>
#include <sys/selinfo.h>
+#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
#include <sys/sysent.h>
#include <sys/bio.h>
@@ -713,6 +714,24 @@ select(td, uap)
register struct thread *td;
register struct select_args *uap;
{
+ struct timeval tv, *tvp;
+ int error;
+
+ if (uap->tv != NULL) {
+ error = copyin(uap->tv, &tv, sizeof(tv));
+ if (error)
+ return (error);
+ tvp = &tv;
+ } else
+ tvp = NULL;
+
+ return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
+}
+
+int
+kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou,
+ fd_set *fd_ex, struct timeval *tvp)
+{
struct filedesc *fdp;
/*
* The magic 2048 here is chosen to be just enough for FD_SETSIZE
@@ -726,28 +745,28 @@ select(td, uap)
int error, timo;
u_int ncoll, nbufbytes, ncpbytes, nfdbits;
- if (uap->nd < 0)
+ if (nd < 0)
return (EINVAL);
fdp = td->td_proc->p_fd;
mtx_lock(&Giant);
FILEDESC_LOCK(fdp);
- if (uap->nd > td->td_proc->p_fd->fd_nfiles)
- uap->nd = td->td_proc->p_fd->fd_nfiles; /* forgiving; slightly wrong */
+ if (nd > td->td_proc->p_fd->fd_nfiles)
+ nd = td->td_proc->p_fd->fd_nfiles; /* forgiving; slightly wrong */
FILEDESC_UNLOCK(fdp);
/*
* Allocate just enough bits for the non-null fd_sets. Use the
* preallocated auto buffer if possible.
*/
- nfdbits = roundup(uap->nd, NFDBITS);
+ nfdbits = roundup(nd, NFDBITS);
ncpbytes = nfdbits / NBBY;
nbufbytes = 0;
- if (uap->in != NULL)
+ if (fd_in != NULL)
nbufbytes += 2 * ncpbytes;
- if (uap->ou != NULL)
+ if (fd_ou != NULL)
nbufbytes += 2 * ncpbytes;
- if (uap->ex != NULL)
+ if (fd_ex != NULL)
nbufbytes += 2 * ncpbytes;
if (nbufbytes <= sizeof s_selbits)
selbits = &s_selbits[0];
@@ -762,28 +781,26 @@ select(td, uap)
sbp = selbits;
#define getbits(name, x) \
do { \
- if (uap->name == NULL) \
+ if (name == NULL) \
ibits[x] = NULL; \
else { \
ibits[x] = sbp + nbufbytes / 2 / sizeof *sbp; \
obits[x] = sbp; \
sbp += ncpbytes / sizeof *sbp; \
- error = copyin(uap->name, ibits[x], ncpbytes); \
+ error = copyin(name, ibits[x], ncpbytes); \
if (error != 0) \
goto done_nosellock; \
} \
} while (0)
- getbits(in, 0);
- getbits(ou, 1);
- getbits(ex, 2);
+ getbits(fd_in, 0);
+ getbits(fd_ou, 1);
+ getbits(fd_ex, 2);
#undef getbits
if (nbufbytes != 0)
bzero(selbits, nbufbytes / 2);
- if (uap->tv) {
- error = copyin(uap->tv, &atv, sizeof (atv));
- if (error)
- goto done_nosellock;
+ if (tvp != NULL) {
+ atv = *tvp;
if (itimerfix(&atv)) {
error = EINVAL;
goto done_nosellock;
@@ -804,7 +821,7 @@ retry:
mtx_unlock_spin(&sched_lock);
mtx_unlock(&sellock);
- error = selscan(td, ibits, obits, uap->nd);
+ error = selscan(td, ibits, obits, nd);
mtx_lock(&sellock);
if (error || td->td_retval[0])
goto done;
@@ -853,14 +870,14 @@ done_nosellock:
if (error == EWOULDBLOCK)
error = 0;
#define putbits(name, x) \
- if (uap->name && (error2 = copyout(obits[x], uap->name, ncpbytes))) \
+ if (name && (error2 = copyout(obits[x], name, ncpbytes))) \
error = error2;
if (error == 0) {
int error2;
- putbits(in, 0);
- putbits(ou, 1);
- putbits(ex, 2);
+ putbits(fd_in, 0);
+ putbits(fd_ou, 1);
+ putbits(fd_ex, 2);
#undef putbits
}
if (selbits != &s_selbits[0])
OpenPOWER on IntegriCloud