xref: /freebsd/sys/kern/sys_generic.c (revision 89b716473e1ac88b5f94df80a6df1005249a363d)
1df8bae1dSRodney W. Grimes /*
2df8bae1dSRodney W. Grimes  * Copyright (c) 1982, 1986, 1989, 1993
3df8bae1dSRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
4df8bae1dSRodney W. Grimes  * (c) UNIX System Laboratories, Inc.
5df8bae1dSRodney W. Grimes  * All or some portions of this file are derived from material licensed
6df8bae1dSRodney W. Grimes  * to the University of California by American Telephone and Telegraph
7df8bae1dSRodney W. Grimes  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8df8bae1dSRodney W. Grimes  * the permission of UNIX System Laboratories, Inc.
9df8bae1dSRodney W. Grimes  *
10df8bae1dSRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
11df8bae1dSRodney W. Grimes  * modification, are permitted provided that the following conditions
12df8bae1dSRodney W. Grimes  * are met:
13df8bae1dSRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
14df8bae1dSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
15df8bae1dSRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
16df8bae1dSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
17df8bae1dSRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
18df8bae1dSRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
19df8bae1dSRodney W. Grimes  *    must display the following acknowledgement:
20df8bae1dSRodney W. Grimes  *	This product includes software developed by the University of
21df8bae1dSRodney W. Grimes  *	California, Berkeley and its contributors.
22df8bae1dSRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
23df8bae1dSRodney W. Grimes  *    may be used to endorse or promote products derived from this software
24df8bae1dSRodney W. Grimes  *    without specific prior written permission.
25df8bae1dSRodney W. Grimes  *
26df8bae1dSRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27df8bae1dSRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28df8bae1dSRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29df8bae1dSRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30df8bae1dSRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31df8bae1dSRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32df8bae1dSRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33df8bae1dSRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34df8bae1dSRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35df8bae1dSRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36df8bae1dSRodney W. Grimes  * SUCH DAMAGE.
37df8bae1dSRodney W. Grimes  *
38df8bae1dSRodney W. Grimes  *	@(#)sys_generic.c	8.5 (Berkeley) 1/21/94
39c3aac50fSPeter Wemm  * $FreeBSD$
40df8bae1dSRodney W. Grimes  */
41df8bae1dSRodney W. Grimes 
42db6a20e2SGarrett Wollman #include "opt_ktrace.h"
43db6a20e2SGarrett Wollman 
44df8bae1dSRodney W. Grimes #include <sys/param.h>
45df8bae1dSRodney W. Grimes #include <sys/systm.h>
46d2d3e875SBruce Evans #include <sys/sysproto.h>
47df8bae1dSRodney W. Grimes #include <sys/filedesc.h>
4820982410SBruce Evans #include <sys/filio.h>
493ac4d1efSBruce Evans #include <sys/fcntl.h>
50df8bae1dSRodney W. Grimes #include <sys/file.h>
51df8bae1dSRodney W. Grimes #include <sys/proc.h>
52797f2d22SPoul-Henning Kamp #include <sys/signalvar.h>
53df8bae1dSRodney W. Grimes #include <sys/socketvar.h>
54df8bae1dSRodney W. Grimes #include <sys/uio.h>
55df8bae1dSRodney W. Grimes #include <sys/kernel.h>
56df8bae1dSRodney W. Grimes #include <sys/malloc.h>
5742d11757SPeter Wemm #include <sys/poll.h>
5889b71647SPeter Wemm #include <sys/resourcevar.h>
590a2c3d48SGarrett Wollman #include <sys/selinfo.h>
608cb96f20SPeter Wemm #include <sys/sysctl.h>
6142d11757SPeter Wemm #include <sys/sysent.h>
62279d7226SMatthew Dillon #include <sys/bio.h>
63279d7226SMatthew Dillon #include <sys/buf.h>
64df8bae1dSRodney W. Grimes #ifdef KTRACE
65df8bae1dSRodney W. Grimes #include <sys/ktrace.h>
66df8bae1dSRodney W. Grimes #endif
67279d7226SMatthew Dillon #include <vm/vm.h>
68279d7226SMatthew Dillon #include <vm/vm_page.h>
69df8bae1dSRodney W. Grimes 
70069e9bc1SDoug Rabson #include <machine/limits.h>
71069e9bc1SDoug Rabson 
72a1c995b6SPoul-Henning Kamp static MALLOC_DEFINE(M_IOCTLOPS, "ioctlops", "ioctl data buffer");
73a1c995b6SPoul-Henning Kamp static MALLOC_DEFINE(M_SELECT, "select", "select() buffer");
74a1c995b6SPoul-Henning Kamp MALLOC_DEFINE(M_IOV, "iov", "large iov's");
7555166637SPoul-Henning Kamp 
76cb226aaaSPoul-Henning Kamp static int	pollscan __P((struct proc *, struct pollfd *, int));
772087c896SBruce Evans static int	selscan __P((struct proc *, fd_mask **, fd_mask **, int));
788fe387abSDmitrij Tejblum static int	dofileread __P((struct proc *, struct file *, int, void *,
798fe387abSDmitrij Tejblum 		    size_t, off_t, int));
808fe387abSDmitrij Tejblum static int	dofilewrite __P((struct proc *, struct file *, int,
818fe387abSDmitrij Tejblum 		    const void *, size_t, off_t, int));
828fe387abSDmitrij Tejblum 
838757e5bbSAlfred Perlstein struct file*
84279d7226SMatthew Dillon holdfp(fdp, fd, flag)
858fe387abSDmitrij Tejblum 	struct filedesc* fdp;
868fe387abSDmitrij Tejblum 	int fd, flag;
878fe387abSDmitrij Tejblum {
888fe387abSDmitrij Tejblum 	struct file* fp;
898fe387abSDmitrij Tejblum 
908fe387abSDmitrij Tejblum 	if (((u_int)fd) >= fdp->fd_nfiles ||
918fe387abSDmitrij Tejblum 	    (fp = fdp->fd_ofiles[fd]) == NULL ||
92279d7226SMatthew Dillon 	    (fp->f_flag & flag) == 0) {
938fe387abSDmitrij Tejblum 		return (NULL);
94279d7226SMatthew Dillon 	}
95279d7226SMatthew Dillon 	fhold(fp);
968fe387abSDmitrij Tejblum 	return (fp);
978fe387abSDmitrij Tejblum }
98d93f860cSPoul-Henning Kamp 
99df8bae1dSRodney W. Grimes /*
100df8bae1dSRodney W. Grimes  * Read system call.
101df8bae1dSRodney W. Grimes  */
102d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
103df8bae1dSRodney W. Grimes struct read_args {
104df8bae1dSRodney W. Grimes 	int	fd;
105134e06feSBruce Evans 	void	*buf;
106134e06feSBruce Evans 	size_t	nbyte;
107df8bae1dSRodney W. Grimes };
108d2d3e875SBruce Evans #endif
10926f9a767SRodney W. Grimes int
110cb226aaaSPoul-Henning Kamp read(p, uap)
111df8bae1dSRodney W. Grimes 	struct proc *p;
112df8bae1dSRodney W. Grimes 	register struct read_args *uap;
113df8bae1dSRodney W. Grimes {
114df8bae1dSRodney W. Grimes 	register struct file *fp;
115279d7226SMatthew Dillon 	int error;
116df8bae1dSRodney W. Grimes 
117279d7226SMatthew Dillon 	if ((fp = holdfp(p->p_fd, uap->fd, FREAD)) == NULL)
118df8bae1dSRodney W. Grimes 		return (EBADF);
119279d7226SMatthew Dillon 	error = dofileread(p, fp, uap->fd, uap->buf, uap->nbyte, (off_t)-1, 0);
120279d7226SMatthew Dillon 	fdrop(fp, p);
121279d7226SMatthew Dillon 	return(error);
122df8bae1dSRodney W. Grimes }
123df8bae1dSRodney W. Grimes 
124df8bae1dSRodney W. Grimes /*
1258fe387abSDmitrij Tejblum  * Pread system call
1264160ccd9SAlan Cox  */
1274160ccd9SAlan Cox #ifndef _SYS_SYSPROTO_H_
1284160ccd9SAlan Cox struct pread_args {
1294160ccd9SAlan Cox 	int	fd;
1304160ccd9SAlan Cox 	void	*buf;
1314160ccd9SAlan Cox 	size_t	nbyte;
1328fe387abSDmitrij Tejblum 	int	pad;
1334160ccd9SAlan Cox 	off_t	offset;
1344160ccd9SAlan Cox };
1354160ccd9SAlan Cox #endif
1364160ccd9SAlan Cox int
1374160ccd9SAlan Cox pread(p, uap)
1384160ccd9SAlan Cox 	struct proc *p;
1394160ccd9SAlan Cox 	register struct pread_args *uap;
1404160ccd9SAlan Cox {
1414160ccd9SAlan Cox 	register struct file *fp;
142279d7226SMatthew Dillon 	int error;
1438fe387abSDmitrij Tejblum 
144279d7226SMatthew Dillon 	if ((fp = holdfp(p->p_fd, uap->fd, FREAD)) == NULL)
1458fe387abSDmitrij Tejblum 		return (EBADF);
146279d7226SMatthew Dillon 	if (fp->f_type != DTYPE_VNODE) {
147279d7226SMatthew Dillon 		error = ESPIPE;
148279d7226SMatthew Dillon 	} else {
149279d7226SMatthew Dillon 	    error = dofileread(p, fp, uap->fd, uap->buf, uap->nbyte,
150279d7226SMatthew Dillon 		uap->offset, FOF_OFFSET);
151279d7226SMatthew Dillon 	}
152279d7226SMatthew Dillon 	fdrop(fp, p);
153279d7226SMatthew Dillon 	return(error);
1548fe387abSDmitrij Tejblum }
1558fe387abSDmitrij Tejblum 
1568fe387abSDmitrij Tejblum /*
1578fe387abSDmitrij Tejblum  * Code common for read and pread
1588fe387abSDmitrij Tejblum  */
1598fe387abSDmitrij Tejblum int
1608fe387abSDmitrij Tejblum dofileread(p, fp, fd, buf, nbyte, offset, flags)
1618fe387abSDmitrij Tejblum 	struct proc *p;
1628fe387abSDmitrij Tejblum 	struct file *fp;
1638fe387abSDmitrij Tejblum 	int fd, flags;
1648fe387abSDmitrij Tejblum 	void *buf;
1658fe387abSDmitrij Tejblum 	size_t nbyte;
1668fe387abSDmitrij Tejblum 	off_t offset;
1678fe387abSDmitrij Tejblum {
1684160ccd9SAlan Cox 	struct uio auio;
1694160ccd9SAlan Cox 	struct iovec aiov;
1704160ccd9SAlan Cox 	long cnt, error = 0;
1714160ccd9SAlan Cox #ifdef KTRACE
1724160ccd9SAlan Cox 	struct iovec ktriov;
17342ebfbf2SBrian Feldman 	struct uio ktruio;
1743c89e357SBrian Feldman 	int didktr = 0;
1754160ccd9SAlan Cox #endif
1764160ccd9SAlan Cox 
1778fe387abSDmitrij Tejblum 	aiov.iov_base = (caddr_t)buf;
1788fe387abSDmitrij Tejblum 	aiov.iov_len = nbyte;
1794160ccd9SAlan Cox 	auio.uio_iov = &aiov;
1804160ccd9SAlan Cox 	auio.uio_iovcnt = 1;
1818fe387abSDmitrij Tejblum 	auio.uio_offset = offset;
1828fe387abSDmitrij Tejblum 	if (nbyte > INT_MAX)
1834160ccd9SAlan Cox 		return (EINVAL);
1848fe387abSDmitrij Tejblum 	auio.uio_resid = nbyte;
1854160ccd9SAlan Cox 	auio.uio_rw = UIO_READ;
1864160ccd9SAlan Cox 	auio.uio_segflg = UIO_USERSPACE;
1874160ccd9SAlan Cox 	auio.uio_procp = p;
1884160ccd9SAlan Cox #ifdef KTRACE
1894160ccd9SAlan Cox 	/*
1904160ccd9SAlan Cox 	 * if tracing, save a copy of iovec
1914160ccd9SAlan Cox 	 */
19242ebfbf2SBrian Feldman 	if (KTRPOINT(p, KTR_GENIO)) {
1934160ccd9SAlan Cox 		ktriov = aiov;
19442ebfbf2SBrian Feldman 		ktruio = auio;
1953c89e357SBrian Feldman 		didktr = 1;
19642ebfbf2SBrian Feldman 	}
1974160ccd9SAlan Cox #endif
1988fe387abSDmitrij Tejblum 	cnt = nbyte;
199279d7226SMatthew Dillon 
200279d7226SMatthew Dillon 	if ((error = fo_read(fp, &auio, fp->f_cred, flags, p))) {
2014160ccd9SAlan Cox 		if (auio.uio_resid != cnt && (error == ERESTART ||
2024160ccd9SAlan Cox 		    error == EINTR || error == EWOULDBLOCK))
2034160ccd9SAlan Cox 			error = 0;
204279d7226SMatthew Dillon 	}
2054160ccd9SAlan Cox 	cnt -= auio.uio_resid;
2064160ccd9SAlan Cox #ifdef KTRACE
2073c89e357SBrian Feldman 	if (didktr && error == 0) {
20842ebfbf2SBrian Feldman 		ktruio.uio_iov = &ktriov;
20942ebfbf2SBrian Feldman 		ktruio.uio_resid = cnt;
21042ebfbf2SBrian Feldman 		ktrgenio(p->p_tracep, fd, UIO_READ, &ktruio, error);
21142ebfbf2SBrian Feldman 	}
2124160ccd9SAlan Cox #endif
2134160ccd9SAlan Cox 	p->p_retval[0] = cnt;
2144160ccd9SAlan Cox 	return (error);
2154160ccd9SAlan Cox }
2164160ccd9SAlan Cox 
2174160ccd9SAlan Cox /*
218df8bae1dSRodney W. Grimes  * Scatter read system call.
219df8bae1dSRodney W. Grimes  */
220d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
221df8bae1dSRodney W. Grimes struct readv_args {
2227147b19dSBruce Evans 	int	fd;
223df8bae1dSRodney W. Grimes 	struct	iovec *iovp;
224df8bae1dSRodney W. Grimes 	u_int	iovcnt;
225df8bae1dSRodney W. Grimes };
226d2d3e875SBruce Evans #endif
22726f9a767SRodney W. Grimes int
228cb226aaaSPoul-Henning Kamp readv(p, uap)
229df8bae1dSRodney W. Grimes 	struct proc *p;
230df8bae1dSRodney W. Grimes 	register struct readv_args *uap;
231df8bae1dSRodney W. Grimes {
232df8bae1dSRodney W. Grimes 	register struct file *fp;
233df8bae1dSRodney W. Grimes 	register struct filedesc *fdp = p->p_fd;
234df8bae1dSRodney W. Grimes 	struct uio auio;
235df8bae1dSRodney W. Grimes 	register struct iovec *iov;
236df8bae1dSRodney W. Grimes 	struct iovec *needfree;
237df8bae1dSRodney W. Grimes 	struct iovec aiov[UIO_SMALLIOV];
238df8bae1dSRodney W. Grimes 	long i, cnt, error = 0;
239df8bae1dSRodney W. Grimes 	u_int iovlen;
240df8bae1dSRodney W. Grimes #ifdef KTRACE
241df8bae1dSRodney W. Grimes 	struct iovec *ktriov = NULL;
24242ebfbf2SBrian Feldman 	struct uio ktruio;
243df8bae1dSRodney W. Grimes #endif
244df8bae1dSRodney W. Grimes 
245279d7226SMatthew Dillon 	if ((fp = holdfp(fdp, uap->fd, FREAD)) == NULL)
246df8bae1dSRodney W. Grimes 		return (EBADF);
247df8bae1dSRodney W. Grimes 	/* note: can't use iovlen until iovcnt is validated */
248df8bae1dSRodney W. Grimes 	iovlen = uap->iovcnt * sizeof (struct iovec);
249df8bae1dSRodney W. Grimes 	if (uap->iovcnt > UIO_SMALLIOV) {
250df8bae1dSRodney W. Grimes 		if (uap->iovcnt > UIO_MAXIOV)
251df8bae1dSRodney W. Grimes 			return (EINVAL);
252df8bae1dSRodney W. Grimes 		MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
253df8bae1dSRodney W. Grimes 		needfree = iov;
254df8bae1dSRodney W. Grimes 	} else {
255df8bae1dSRodney W. Grimes 		iov = aiov;
256df8bae1dSRodney W. Grimes 		needfree = NULL;
257df8bae1dSRodney W. Grimes 	}
258df8bae1dSRodney W. Grimes 	auio.uio_iov = iov;
259df8bae1dSRodney W. Grimes 	auio.uio_iovcnt = uap->iovcnt;
260df8bae1dSRodney W. Grimes 	auio.uio_rw = UIO_READ;
261df8bae1dSRodney W. Grimes 	auio.uio_segflg = UIO_USERSPACE;
262df8bae1dSRodney W. Grimes 	auio.uio_procp = p;
2632c1011f7SJohn Dyson 	auio.uio_offset = -1;
264bb56ec4aSPoul-Henning Kamp 	if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)))
265df8bae1dSRodney W. Grimes 		goto done;
266df8bae1dSRodney W. Grimes 	auio.uio_resid = 0;
267df8bae1dSRodney W. Grimes 	for (i = 0; i < uap->iovcnt; i++) {
268069e9bc1SDoug Rabson 		if (iov->iov_len > INT_MAX - auio.uio_resid) {
269df8bae1dSRodney W. Grimes 			error = EINVAL;
270df8bae1dSRodney W. Grimes 			goto done;
271df8bae1dSRodney W. Grimes 		}
272069e9bc1SDoug Rabson 		auio.uio_resid += iov->iov_len;
273df8bae1dSRodney W. Grimes 		iov++;
274df8bae1dSRodney W. Grimes 	}
275df8bae1dSRodney W. Grimes #ifdef KTRACE
276df8bae1dSRodney W. Grimes 	/*
277df8bae1dSRodney W. Grimes 	 * if tracing, save a copy of iovec
278df8bae1dSRodney W. Grimes 	 */
279df8bae1dSRodney W. Grimes 	if (KTRPOINT(p, KTR_GENIO))  {
280df8bae1dSRodney W. Grimes 		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
281df8bae1dSRodney W. Grimes 		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
28242ebfbf2SBrian Feldman 		ktruio = auio;
283df8bae1dSRodney W. Grimes 	}
284df8bae1dSRodney W. Grimes #endif
285df8bae1dSRodney W. Grimes 	cnt = auio.uio_resid;
286279d7226SMatthew Dillon 	if ((error = fo_read(fp, &auio, fp->f_cred, 0, p))) {
287df8bae1dSRodney W. Grimes 		if (auio.uio_resid != cnt && (error == ERESTART ||
288df8bae1dSRodney W. Grimes 		    error == EINTR || error == EWOULDBLOCK))
289df8bae1dSRodney W. Grimes 			error = 0;
290279d7226SMatthew Dillon 	}
291df8bae1dSRodney W. Grimes 	cnt -= auio.uio_resid;
292df8bae1dSRodney W. Grimes #ifdef KTRACE
293df8bae1dSRodney W. Grimes 	if (ktriov != NULL) {
29442ebfbf2SBrian Feldman 		if (error == 0) {
29542ebfbf2SBrian Feldman 			ktruio.uio_iov = ktriov;
29642ebfbf2SBrian Feldman 			ktruio.uio_resid = cnt;
29742ebfbf2SBrian Feldman 			ktrgenio(p->p_tracep, uap->fd, UIO_READ, &ktruio,
29842ebfbf2SBrian Feldman 			    error);
29942ebfbf2SBrian Feldman 		}
300df8bae1dSRodney W. Grimes 		FREE(ktriov, M_TEMP);
301df8bae1dSRodney W. Grimes 	}
302df8bae1dSRodney W. Grimes #endif
303cb226aaaSPoul-Henning Kamp 	p->p_retval[0] = cnt;
304df8bae1dSRodney W. Grimes done:
305279d7226SMatthew Dillon 	fdrop(fp, p);
306df8bae1dSRodney W. Grimes 	if (needfree)
307df8bae1dSRodney W. Grimes 		FREE(needfree, M_IOV);
308df8bae1dSRodney W. Grimes 	return (error);
309df8bae1dSRodney W. Grimes }
310df8bae1dSRodney W. Grimes 
311df8bae1dSRodney W. Grimes /*
312df8bae1dSRodney W. Grimes  * Write system call
313df8bae1dSRodney W. Grimes  */
314d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
315df8bae1dSRodney W. Grimes struct write_args {
316df8bae1dSRodney W. Grimes 	int	fd;
317134e06feSBruce Evans 	const void *buf;
318134e06feSBruce Evans 	size_t	nbyte;
319df8bae1dSRodney W. Grimes };
320d2d3e875SBruce Evans #endif
32126f9a767SRodney W. Grimes int
322cb226aaaSPoul-Henning Kamp write(p, uap)
323df8bae1dSRodney W. Grimes 	struct proc *p;
324df8bae1dSRodney W. Grimes 	register struct write_args *uap;
325df8bae1dSRodney W. Grimes {
326df8bae1dSRodney W. Grimes 	register struct file *fp;
327279d7226SMatthew Dillon 	int error;
328df8bae1dSRodney W. Grimes 
329279d7226SMatthew Dillon 	if ((fp = holdfp(p->p_fd, uap->fd, FWRITE)) == NULL)
330df8bae1dSRodney W. Grimes 		return (EBADF);
331279d7226SMatthew Dillon 	error = dofilewrite(p, fp, uap->fd, uap->buf, uap->nbyte, (off_t)-1, 0);
332279d7226SMatthew Dillon 	fdrop(fp, p);
333279d7226SMatthew Dillon 	return(error);
334df8bae1dSRodney W. Grimes }
335df8bae1dSRodney W. Grimes 
336df8bae1dSRodney W. Grimes /*
3378fe387abSDmitrij Tejblum  * Pwrite system call
3384160ccd9SAlan Cox  */
3394160ccd9SAlan Cox #ifndef _SYS_SYSPROTO_H_
3404160ccd9SAlan Cox struct pwrite_args {
3414160ccd9SAlan Cox 	int	fd;
3424160ccd9SAlan Cox 	const void *buf;
3434160ccd9SAlan Cox 	size_t	nbyte;
3448fe387abSDmitrij Tejblum 	int	pad;
3454160ccd9SAlan Cox 	off_t	offset;
3464160ccd9SAlan Cox };
3474160ccd9SAlan Cox #endif
3484160ccd9SAlan Cox int
3494160ccd9SAlan Cox pwrite(p, uap)
3504160ccd9SAlan Cox 	struct proc *p;
3514160ccd9SAlan Cox 	register struct pwrite_args *uap;
3524160ccd9SAlan Cox {
3534160ccd9SAlan Cox 	register struct file *fp;
354279d7226SMatthew Dillon 	int error;
3558fe387abSDmitrij Tejblum 
356279d7226SMatthew Dillon 	if ((fp = holdfp(p->p_fd, uap->fd, FWRITE)) == NULL)
3578fe387abSDmitrij Tejblum 		return (EBADF);
358279d7226SMatthew Dillon 	if (fp->f_type != DTYPE_VNODE) {
359279d7226SMatthew Dillon 		error = ESPIPE;
360279d7226SMatthew Dillon 	} else {
361279d7226SMatthew Dillon 	    error = dofilewrite(p, fp, uap->fd, uap->buf, uap->nbyte,
362279d7226SMatthew Dillon 		uap->offset, FOF_OFFSET);
363279d7226SMatthew Dillon 	}
364279d7226SMatthew Dillon 	fdrop(fp, p);
365279d7226SMatthew Dillon 	return(error);
3668fe387abSDmitrij Tejblum }
3678fe387abSDmitrij Tejblum 
3688fe387abSDmitrij Tejblum static int
3698fe387abSDmitrij Tejblum dofilewrite(p, fp, fd, buf, nbyte, offset, flags)
3708fe387abSDmitrij Tejblum 	struct proc *p;
3718fe387abSDmitrij Tejblum 	struct file *fp;
3728fe387abSDmitrij Tejblum 	int fd, flags;
3738fe387abSDmitrij Tejblum 	const void *buf;
3748fe387abSDmitrij Tejblum 	size_t nbyte;
3758fe387abSDmitrij Tejblum 	off_t offset;
3768fe387abSDmitrij Tejblum {
3774160ccd9SAlan Cox 	struct uio auio;
3784160ccd9SAlan Cox 	struct iovec aiov;
3794160ccd9SAlan Cox 	long cnt, error = 0;
3804160ccd9SAlan Cox #ifdef KTRACE
3814160ccd9SAlan Cox 	struct iovec ktriov;
38242ebfbf2SBrian Feldman 	struct uio ktruio;
3833c89e357SBrian Feldman 	int didktr = 0;
3844160ccd9SAlan Cox #endif
3854160ccd9SAlan Cox 
386b31ae1adSPeter Wemm 	aiov.iov_base = (void *)(uintptr_t)buf;
3878fe387abSDmitrij Tejblum 	aiov.iov_len = nbyte;
3884160ccd9SAlan Cox 	auio.uio_iov = &aiov;
3894160ccd9SAlan Cox 	auio.uio_iovcnt = 1;
3908fe387abSDmitrij Tejblum 	auio.uio_offset = offset;
3918fe387abSDmitrij Tejblum 	if (nbyte > INT_MAX)
3924160ccd9SAlan Cox 		return (EINVAL);
3938fe387abSDmitrij Tejblum 	auio.uio_resid = nbyte;
3944160ccd9SAlan Cox 	auio.uio_rw = UIO_WRITE;
3954160ccd9SAlan Cox 	auio.uio_segflg = UIO_USERSPACE;
3964160ccd9SAlan Cox 	auio.uio_procp = p;
3974160ccd9SAlan Cox #ifdef KTRACE
3984160ccd9SAlan Cox 	/*
39942ebfbf2SBrian Feldman 	 * if tracing, save a copy of iovec and uio
4004160ccd9SAlan Cox 	 */
40142ebfbf2SBrian Feldman 	if (KTRPOINT(p, KTR_GENIO)) {
4024160ccd9SAlan Cox 		ktriov = aiov;
40342ebfbf2SBrian Feldman 		ktruio = auio;
4043c89e357SBrian Feldman 		didktr = 1;
40542ebfbf2SBrian Feldman 	}
4064160ccd9SAlan Cox #endif
4078fe387abSDmitrij Tejblum 	cnt = nbyte;
408c6ab5768SAlfred Perlstein 	if (fp->f_type == DTYPE_VNODE)
409279d7226SMatthew Dillon 		bwillwrite();
41013ccadd4SBrian Feldman 	if ((error = fo_write(fp, &auio, fp->f_cred, flags, p))) {
4114160ccd9SAlan Cox 		if (auio.uio_resid != cnt && (error == ERESTART ||
4124160ccd9SAlan Cox 		    error == EINTR || error == EWOULDBLOCK))
4134160ccd9SAlan Cox 			error = 0;
4144160ccd9SAlan Cox 		if (error == EPIPE)
4154160ccd9SAlan Cox 			psignal(p, SIGPIPE);
4164160ccd9SAlan Cox 	}
4174160ccd9SAlan Cox 	cnt -= auio.uio_resid;
4184160ccd9SAlan Cox #ifdef KTRACE
4193c89e357SBrian Feldman 	if (didktr && error == 0) {
42042ebfbf2SBrian Feldman 		ktruio.uio_iov = &ktriov;
42142ebfbf2SBrian Feldman 		ktruio.uio_resid = cnt;
42242ebfbf2SBrian Feldman 		ktrgenio(p->p_tracep, fd, UIO_WRITE, &ktruio, error);
42342ebfbf2SBrian Feldman 	}
4244160ccd9SAlan Cox #endif
4254160ccd9SAlan Cox 	p->p_retval[0] = cnt;
4264160ccd9SAlan Cox 	return (error);
4274160ccd9SAlan Cox }
4284160ccd9SAlan Cox 
4294160ccd9SAlan Cox /*
430df8bae1dSRodney W. Grimes  * Gather write system call
431df8bae1dSRodney W. Grimes  */
432d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
433df8bae1dSRodney W. Grimes struct writev_args {
434df8bae1dSRodney W. Grimes 	int	fd;
435df8bae1dSRodney W. Grimes 	struct	iovec *iovp;
436df8bae1dSRodney W. Grimes 	u_int	iovcnt;
437df8bae1dSRodney W. Grimes };
438d2d3e875SBruce Evans #endif
43926f9a767SRodney W. Grimes int
440cb226aaaSPoul-Henning Kamp writev(p, uap)
441df8bae1dSRodney W. Grimes 	struct proc *p;
442df8bae1dSRodney W. Grimes 	register struct writev_args *uap;
443df8bae1dSRodney W. Grimes {
444df8bae1dSRodney W. Grimes 	register struct file *fp;
445df8bae1dSRodney W. Grimes 	register struct filedesc *fdp = p->p_fd;
446df8bae1dSRodney W. Grimes 	struct uio auio;
447df8bae1dSRodney W. Grimes 	register struct iovec *iov;
448df8bae1dSRodney W. Grimes 	struct iovec *needfree;
449df8bae1dSRodney W. Grimes 	struct iovec aiov[UIO_SMALLIOV];
450df8bae1dSRodney W. Grimes 	long i, cnt, error = 0;
451df8bae1dSRodney W. Grimes 	u_int iovlen;
452df8bae1dSRodney W. Grimes #ifdef KTRACE
453df8bae1dSRodney W. Grimes 	struct iovec *ktriov = NULL;
45442ebfbf2SBrian Feldman 	struct uio ktruio;
455df8bae1dSRodney W. Grimes #endif
456df8bae1dSRodney W. Grimes 
457279d7226SMatthew Dillon 	if ((fp = holdfp(fdp, uap->fd, FWRITE)) == NULL)
458df8bae1dSRodney W. Grimes 		return (EBADF);
459df8bae1dSRodney W. Grimes 	/* note: can't use iovlen until iovcnt is validated */
460df8bae1dSRodney W. Grimes 	iovlen = uap->iovcnt * sizeof (struct iovec);
461df8bae1dSRodney W. Grimes 	if (uap->iovcnt > UIO_SMALLIOV) {
4621aa3e7ddSBrian Feldman 		if (uap->iovcnt > UIO_MAXIOV) {
4631aa3e7ddSBrian Feldman 			needfree = NULL;
4641aa3e7ddSBrian Feldman 			error = EINVAL;
4651aa3e7ddSBrian Feldman 			goto done;
4661aa3e7ddSBrian Feldman 		}
467df8bae1dSRodney W. Grimes 		MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
468df8bae1dSRodney W. Grimes 		needfree = iov;
469df8bae1dSRodney W. Grimes 	} else {
470df8bae1dSRodney W. Grimes 		iov = aiov;
471df8bae1dSRodney W. Grimes 		needfree = NULL;
472df8bae1dSRodney W. Grimes 	}
473df8bae1dSRodney W. Grimes 	auio.uio_iov = iov;
474df8bae1dSRodney W. Grimes 	auio.uio_iovcnt = uap->iovcnt;
475df8bae1dSRodney W. Grimes 	auio.uio_rw = UIO_WRITE;
476df8bae1dSRodney W. Grimes 	auio.uio_segflg = UIO_USERSPACE;
477df8bae1dSRodney W. Grimes 	auio.uio_procp = p;
4782c1011f7SJohn Dyson 	auio.uio_offset = -1;
479bb56ec4aSPoul-Henning Kamp 	if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)))
480df8bae1dSRodney W. Grimes 		goto done;
481df8bae1dSRodney W. Grimes 	auio.uio_resid = 0;
482df8bae1dSRodney W. Grimes 	for (i = 0; i < uap->iovcnt; i++) {
483069e9bc1SDoug Rabson 		if (iov->iov_len > INT_MAX - auio.uio_resid) {
484df8bae1dSRodney W. Grimes 			error = EINVAL;
485df8bae1dSRodney W. Grimes 			goto done;
486df8bae1dSRodney W. Grimes 		}
487069e9bc1SDoug Rabson 		auio.uio_resid += iov->iov_len;
488df8bae1dSRodney W. Grimes 		iov++;
489df8bae1dSRodney W. Grimes 	}
490df8bae1dSRodney W. Grimes #ifdef KTRACE
491df8bae1dSRodney W. Grimes 	/*
49242ebfbf2SBrian Feldman 	 * if tracing, save a copy of iovec and uio
493df8bae1dSRodney W. Grimes 	 */
494df8bae1dSRodney W. Grimes 	if (KTRPOINT(p, KTR_GENIO))  {
495df8bae1dSRodney W. Grimes 		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
496df8bae1dSRodney W. Grimes 		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
49742ebfbf2SBrian Feldman 		ktruio = auio;
498df8bae1dSRodney W. Grimes 	}
499df8bae1dSRodney W. Grimes #endif
500df8bae1dSRodney W. Grimes 	cnt = auio.uio_resid;
501a41ce5d3SMatthew Dillon 	if (fp->f_type == DTYPE_VNODE)
5029440653dSMatthew Dillon 		bwillwrite();
50313ccadd4SBrian Feldman 	if ((error = fo_write(fp, &auio, fp->f_cred, 0, p))) {
504df8bae1dSRodney W. Grimes 		if (auio.uio_resid != cnt && (error == ERESTART ||
505df8bae1dSRodney W. Grimes 		    error == EINTR || error == EWOULDBLOCK))
506df8bae1dSRodney W. Grimes 			error = 0;
507df8bae1dSRodney W. Grimes 		if (error == EPIPE)
508df8bae1dSRodney W. Grimes 			psignal(p, SIGPIPE);
509df8bae1dSRodney W. Grimes 	}
510df8bae1dSRodney W. Grimes 	cnt -= auio.uio_resid;
511df8bae1dSRodney W. Grimes #ifdef KTRACE
512df8bae1dSRodney W. Grimes 	if (ktriov != NULL) {
51342ebfbf2SBrian Feldman 		if (error == 0) {
51442ebfbf2SBrian Feldman 			ktruio.uio_iov = ktriov;
51542ebfbf2SBrian Feldman 			ktruio.uio_resid = cnt;
51642ebfbf2SBrian Feldman 			ktrgenio(p->p_tracep, uap->fd, UIO_WRITE, &ktruio,
51742ebfbf2SBrian Feldman 			    error);
51842ebfbf2SBrian Feldman 		}
519df8bae1dSRodney W. Grimes 		FREE(ktriov, M_TEMP);
520df8bae1dSRodney W. Grimes 	}
521df8bae1dSRodney W. Grimes #endif
522cb226aaaSPoul-Henning Kamp 	p->p_retval[0] = cnt;
523df8bae1dSRodney W. Grimes done:
524d8177437SBrian Feldman 	fdrop(fp, p);
525df8bae1dSRodney W. Grimes 	if (needfree)
526df8bae1dSRodney W. Grimes 		FREE(needfree, M_IOV);
527df8bae1dSRodney W. Grimes 	return (error);
528df8bae1dSRodney W. Grimes }
529df8bae1dSRodney W. Grimes 
530df8bae1dSRodney W. Grimes /*
531df8bae1dSRodney W. Grimes  * Ioctl system call
532df8bae1dSRodney W. Grimes  */
533d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
534df8bae1dSRodney W. Grimes struct ioctl_args {
535df8bae1dSRodney W. Grimes 	int	fd;
536069e9bc1SDoug Rabson 	u_long	com;
537df8bae1dSRodney W. Grimes 	caddr_t	data;
538df8bae1dSRodney W. Grimes };
539d2d3e875SBruce Evans #endif
540df8bae1dSRodney W. Grimes /* ARGSUSED */
54126f9a767SRodney W. Grimes int
542cb226aaaSPoul-Henning Kamp ioctl(p, uap)
543df8bae1dSRodney W. Grimes 	struct proc *p;
544df8bae1dSRodney W. Grimes 	register struct ioctl_args *uap;
545df8bae1dSRodney W. Grimes {
546df8bae1dSRodney W. Grimes 	register struct file *fp;
547df8bae1dSRodney W. Grimes 	register struct filedesc *fdp;
548831b9ef2SDoug Rabson 	register u_long com;
549831b9ef2SDoug Rabson 	int error;
550df8bae1dSRodney W. Grimes 	register u_int size;
551df8bae1dSRodney W. Grimes 	caddr_t data, memp;
552df8bae1dSRodney W. Grimes 	int tmp;
553df8bae1dSRodney W. Grimes #define STK_PARAMS	128
554d2ba455cSMatthew Dillon 	union {
555df8bae1dSRodney W. Grimes 	    char stkbuf[STK_PARAMS];
556d2ba455cSMatthew Dillon 	    long align;
557d2ba455cSMatthew Dillon 	} ubuf;
558df8bae1dSRodney W. Grimes 
559df8bae1dSRodney W. Grimes 	fdp = p->p_fd;
560df8bae1dSRodney W. Grimes 	if ((u_int)uap->fd >= fdp->fd_nfiles ||
561df8bae1dSRodney W. Grimes 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
562df8bae1dSRodney W. Grimes 		return (EBADF);
563df8bae1dSRodney W. Grimes 
564df8bae1dSRodney W. Grimes 	if ((fp->f_flag & (FREAD | FWRITE)) == 0)
565df8bae1dSRodney W. Grimes 		return (EBADF);
566df8bae1dSRodney W. Grimes 
567df8bae1dSRodney W. Grimes 	switch (com = uap->com) {
568df8bae1dSRodney W. Grimes 	case FIONCLEX:
569df8bae1dSRodney W. Grimes 		fdp->fd_ofileflags[uap->fd] &= ~UF_EXCLOSE;
570df8bae1dSRodney W. Grimes 		return (0);
571df8bae1dSRodney W. Grimes 	case FIOCLEX:
572df8bae1dSRodney W. Grimes 		fdp->fd_ofileflags[uap->fd] |= UF_EXCLOSE;
573df8bae1dSRodney W. Grimes 		return (0);
574df8bae1dSRodney W. Grimes 	}
575df8bae1dSRodney W. Grimes 
576df8bae1dSRodney W. Grimes 	/*
577df8bae1dSRodney W. Grimes 	 * Interpret high order word to find amount of data to be
578df8bae1dSRodney W. Grimes 	 * copied to/from the user's address space.
579df8bae1dSRodney W. Grimes 	 */
580df8bae1dSRodney W. Grimes 	size = IOCPARM_LEN(com);
581df8bae1dSRodney W. Grimes 	if (size > IOCPARM_MAX)
582df8bae1dSRodney W. Grimes 		return (ENOTTY);
583279d7226SMatthew Dillon 
584279d7226SMatthew Dillon 	fhold(fp);
585279d7226SMatthew Dillon 
586df8bae1dSRodney W. Grimes 	memp = NULL;
587d2ba455cSMatthew Dillon 	if (size > sizeof (ubuf.stkbuf)) {
588df8bae1dSRodney W. Grimes 		memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
589df8bae1dSRodney W. Grimes 		data = memp;
590279d7226SMatthew Dillon 	} else {
591d2ba455cSMatthew Dillon 		data = ubuf.stkbuf;
592279d7226SMatthew Dillon 	}
593df8bae1dSRodney W. Grimes 	if (com&IOC_IN) {
594df8bae1dSRodney W. Grimes 		if (size) {
595df8bae1dSRodney W. Grimes 			error = copyin(uap->data, data, (u_int)size);
596df8bae1dSRodney W. Grimes 			if (error) {
597df8bae1dSRodney W. Grimes 				if (memp)
598df8bae1dSRodney W. Grimes 					free(memp, M_IOCTLOPS);
599279d7226SMatthew Dillon 				fdrop(fp, p);
600df8bae1dSRodney W. Grimes 				return (error);
601df8bae1dSRodney W. Grimes 			}
602279d7226SMatthew Dillon 		} else {
603df8bae1dSRodney W. Grimes 			*(caddr_t *)data = uap->data;
604279d7226SMatthew Dillon 		}
605279d7226SMatthew Dillon 	} else if ((com&IOC_OUT) && size) {
606df8bae1dSRodney W. Grimes 		/*
607df8bae1dSRodney W. Grimes 		 * Zero the buffer so the user always
608df8bae1dSRodney W. Grimes 		 * gets back something deterministic.
609df8bae1dSRodney W. Grimes 		 */
610df8bae1dSRodney W. Grimes 		bzero(data, size);
611279d7226SMatthew Dillon 	} else if (com&IOC_VOID) {
612df8bae1dSRodney W. Grimes 		*(caddr_t *)data = uap->data;
613279d7226SMatthew Dillon 	}
614df8bae1dSRodney W. Grimes 
615df8bae1dSRodney W. Grimes 	switch (com) {
616df8bae1dSRodney W. Grimes 
617df8bae1dSRodney W. Grimes 	case FIONBIO:
618bb56ec4aSPoul-Henning Kamp 		if ((tmp = *(int *)data))
619df8bae1dSRodney W. Grimes 			fp->f_flag |= FNONBLOCK;
620df8bae1dSRodney W. Grimes 		else
621df8bae1dSRodney W. Grimes 			fp->f_flag &= ~FNONBLOCK;
62213ccadd4SBrian Feldman 		error = fo_ioctl(fp, FIONBIO, (caddr_t)&tmp, p);
623df8bae1dSRodney W. Grimes 		break;
624df8bae1dSRodney W. Grimes 
625df8bae1dSRodney W. Grimes 	case FIOASYNC:
626bb56ec4aSPoul-Henning Kamp 		if ((tmp = *(int *)data))
627df8bae1dSRodney W. Grimes 			fp->f_flag |= FASYNC;
628df8bae1dSRodney W. Grimes 		else
629df8bae1dSRodney W. Grimes 			fp->f_flag &= ~FASYNC;
63013ccadd4SBrian Feldman 		error = fo_ioctl(fp, FIOASYNC, (caddr_t)&tmp, p);
631df8bae1dSRodney W. Grimes 		break;
632df8bae1dSRodney W. Grimes 
633df8bae1dSRodney W. Grimes 	default:
63413ccadd4SBrian Feldman 		error = fo_ioctl(fp, com, data, p);
635df8bae1dSRodney W. Grimes 		/*
636df8bae1dSRodney W. Grimes 		 * Copy any data to user, size was
637df8bae1dSRodney W. Grimes 		 * already set and checked above.
638df8bae1dSRodney W. Grimes 		 */
639df8bae1dSRodney W. Grimes 		if (error == 0 && (com&IOC_OUT) && size)
640df8bae1dSRodney W. Grimes 			error = copyout(data, uap->data, (u_int)size);
641df8bae1dSRodney W. Grimes 		break;
642df8bae1dSRodney W. Grimes 	}
643df8bae1dSRodney W. Grimes 	if (memp)
644df8bae1dSRodney W. Grimes 		free(memp, M_IOCTLOPS);
645279d7226SMatthew Dillon 	fdrop(fp, p);
646df8bae1dSRodney W. Grimes 	return (error);
647df8bae1dSRodney W. Grimes }
648df8bae1dSRodney W. Grimes 
6498cb96f20SPeter Wemm static int	nselcoll;	/* Select collisions since boot */
65087b6de2bSPoul-Henning Kamp int	selwait;
6518cb96f20SPeter Wemm SYSCTL_INT(_kern, OID_AUTO, nselcoll, CTLFLAG_RD, &nselcoll, 0, "");
652df8bae1dSRodney W. Grimes 
653df8bae1dSRodney W. Grimes /*
654df8bae1dSRodney W. Grimes  * Select system call.
655df8bae1dSRodney W. Grimes  */
656d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_
657df8bae1dSRodney W. Grimes struct select_args {
658b08f7993SSujal Patel 	int	nd;
659df8bae1dSRodney W. Grimes 	fd_set	*in, *ou, *ex;
660df8bae1dSRodney W. Grimes 	struct	timeval *tv;
661df8bae1dSRodney W. Grimes };
662d2d3e875SBruce Evans #endif
66326f9a767SRodney W. Grimes int
664cb226aaaSPoul-Henning Kamp select(p, uap)
665df8bae1dSRodney W. Grimes 	register struct proc *p;
666df8bae1dSRodney W. Grimes 	register struct select_args *uap;
667df8bae1dSRodney W. Grimes {
668d5e4d7e1SBruce Evans 	/*
669d5e4d7e1SBruce Evans 	 * The magic 2048 here is chosen to be just enough for FD_SETSIZE
670d5e4d7e1SBruce Evans 	 * infds with the new FD_SETSIZE of 1024, and more than enough for
671d5e4d7e1SBruce Evans 	 * FD_SETSIZE infds, outfds and exceptfds with the old FD_SETSIZE
672d5e4d7e1SBruce Evans 	 * of 256.
673d5e4d7e1SBruce Evans 	 */
674d5e4d7e1SBruce Evans 	fd_mask s_selbits[howmany(2048, NFDBITS)];
675d5e4d7e1SBruce Evans 	fd_mask *ibits[3], *obits[3], *selbits, *sbp;
67600af9731SPoul-Henning Kamp 	struct timeval atv, rtv, ttv;
67700af9731SPoul-Henning Kamp 	int s, ncoll, error, timo;
678d5e4d7e1SBruce Evans 	u_int nbufbytes, ncpbytes, nfdbits;
679df8bae1dSRodney W. Grimes 
680b08f7993SSujal Patel 	if (uap->nd < 0)
681acbfbfeaSSujal Patel 		return (EINVAL);
682df8bae1dSRodney W. Grimes 	if (uap->nd > p->p_fd->fd_nfiles)
683df8bae1dSRodney W. Grimes 		uap->nd = p->p_fd->fd_nfiles;   /* forgiving; slightly wrong */
684b08f7993SSujal Patel 
685d5e4d7e1SBruce Evans 	/*
686d5e4d7e1SBruce Evans 	 * Allocate just enough bits for the non-null fd_sets.  Use the
687d5e4d7e1SBruce Evans 	 * preallocated auto buffer if possible.
688d5e4d7e1SBruce Evans 	 */
689d5e4d7e1SBruce Evans 	nfdbits = roundup(uap->nd, NFDBITS);
690d5e4d7e1SBruce Evans 	ncpbytes = nfdbits / NBBY;
691d5e4d7e1SBruce Evans 	nbufbytes = 0;
692d5e4d7e1SBruce Evans 	if (uap->in != NULL)
693d5e4d7e1SBruce Evans 		nbufbytes += 2 * ncpbytes;
694d5e4d7e1SBruce Evans 	if (uap->ou != NULL)
695d5e4d7e1SBruce Evans 		nbufbytes += 2 * ncpbytes;
696d5e4d7e1SBruce Evans 	if (uap->ex != NULL)
697d5e4d7e1SBruce Evans 		nbufbytes += 2 * ncpbytes;
698d5e4d7e1SBruce Evans 	if (nbufbytes <= sizeof s_selbits)
699d5e4d7e1SBruce Evans 		selbits = &s_selbits[0];
700d5e4d7e1SBruce Evans 	else
701d5e4d7e1SBruce Evans 		selbits = malloc(nbufbytes, M_SELECT, M_WAITOK);
702b08f7993SSujal Patel 
703b08f7993SSujal Patel 	/*
704d5e4d7e1SBruce Evans 	 * Assign pointers into the bit buffers and fetch the input bits.
705d5e4d7e1SBruce Evans 	 * Put the output buffers together so that they can be bzeroed
706d5e4d7e1SBruce Evans 	 * together.
707b08f7993SSujal Patel 	 */
708d5e4d7e1SBruce Evans 	sbp = selbits;
709df8bae1dSRodney W. Grimes #define	getbits(name, x) \
710d5e4d7e1SBruce Evans 	do {								\
711d5e4d7e1SBruce Evans 		if (uap->name == NULL)					\
712d5e4d7e1SBruce Evans 			ibits[x] = NULL;				\
713d5e4d7e1SBruce Evans 		else {							\
714d5e4d7e1SBruce Evans 			ibits[x] = sbp + nbufbytes / 2 / sizeof *sbp;	\
715d5e4d7e1SBruce Evans 			obits[x] = sbp;					\
716d5e4d7e1SBruce Evans 			sbp += ncpbytes / sizeof *sbp;			\
717d5e4d7e1SBruce Evans 			error = copyin(uap->name, ibits[x], ncpbytes);	\
718e04ac2feSJohn Baldwin 			if (error != 0)	{				\
719e04ac2feSJohn Baldwin 				PROC_LOCK(p);				\
720d5e4d7e1SBruce Evans 				goto done;				\
721d5e4d7e1SBruce Evans 			}						\
722e04ac2feSJohn Baldwin 		}							\
723d5e4d7e1SBruce Evans 	} while (0)
724df8bae1dSRodney W. Grimes 	getbits(in, 0);
725df8bae1dSRodney W. Grimes 	getbits(ou, 1);
726df8bae1dSRodney W. Grimes 	getbits(ex, 2);
727df8bae1dSRodney W. Grimes #undef	getbits
728d5e4d7e1SBruce Evans 	if (nbufbytes != 0)
729d5e4d7e1SBruce Evans 		bzero(selbits, nbufbytes / 2);
730df8bae1dSRodney W. Grimes 
731df8bae1dSRodney W. Grimes 	if (uap->tv) {
732df8bae1dSRodney W. Grimes 		error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
733df8bae1dSRodney W. Grimes 			sizeof (atv));
734e04ac2feSJohn Baldwin 		if (error) {
735e04ac2feSJohn Baldwin 			PROC_LOCK(p);
736df8bae1dSRodney W. Grimes 			goto done;
737e04ac2feSJohn Baldwin 		}
738df8bae1dSRodney W. Grimes 		if (itimerfix(&atv)) {
739df8bae1dSRodney W. Grimes 			error = EINVAL;
740e04ac2feSJohn Baldwin 			PROC_LOCK(p);
741df8bae1dSRodney W. Grimes 			goto done;
742df8bae1dSRodney W. Grimes 		}
743c21410e1SPoul-Henning Kamp 		getmicrouptime(&rtv);
74400af9731SPoul-Henning Kamp 		timevaladd(&atv, &rtv);
7459c386f6bSJohn Baldwin 	} else {
74600af9731SPoul-Henning Kamp 		atv.tv_sec = 0;
7479c386f6bSJohn Baldwin 		atv.tv_usec = 0;
7489c386f6bSJohn Baldwin 	}
74900af9731SPoul-Henning Kamp 	timo = 0;
750e04ac2feSJohn Baldwin 	PROC_LOCK(p);
751df8bae1dSRodney W. Grimes retry:
752df8bae1dSRodney W. Grimes 	ncoll = nselcoll;
753df8bae1dSRodney W. Grimes 	p->p_flag |= P_SELECT;
754e04ac2feSJohn Baldwin 	PROC_UNLOCK(p);
755cb226aaaSPoul-Henning Kamp 	error = selscan(p, ibits, obits, uap->nd);
756e04ac2feSJohn Baldwin 	PROC_LOCK(p);
757cb226aaaSPoul-Henning Kamp 	if (error || p->p_retval[0])
758df8bae1dSRodney W. Grimes 		goto done;
7594da144c0SJohn Baldwin 	if (atv.tv_sec || atv.tv_usec) {
760c21410e1SPoul-Henning Kamp 		getmicrouptime(&rtv);
76100af9731SPoul-Henning Kamp 		if (timevalcmp(&rtv, &atv, >=))
762df8bae1dSRodney W. Grimes 			goto done;
76300af9731SPoul-Henning Kamp 		ttv = atv;
76400af9731SPoul-Henning Kamp 		timevalsub(&ttv, &rtv);
76500af9731SPoul-Henning Kamp 		timo = ttv.tv_sec > 24 * 60 * 60 ?
76600af9731SPoul-Henning Kamp 		    24 * 60 * 60 * hz : tvtohz(&ttv);
767df8bae1dSRodney W. Grimes 	}
76800af9731SPoul-Henning Kamp 	s = splhigh();
769df8bae1dSRodney W. Grimes 	if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
770df8bae1dSRodney W. Grimes 		splx(s);
771df8bae1dSRodney W. Grimes 		goto retry;
772df8bae1dSRodney W. Grimes 	}
773df8bae1dSRodney W. Grimes 	p->p_flag &= ~P_SELECT;
774bfbbc4aaSJason Evans 
775e04ac2feSJohn Baldwin 	error = msleep((caddr_t)&selwait, &p->p_mtx, PSOCK | PCATCH, "select",
776e04ac2feSJohn Baldwin 	    timo);
777bfbbc4aaSJason Evans 
778df8bae1dSRodney W. Grimes 	splx(s);
779df8bae1dSRodney W. Grimes 	if (error == 0)
780df8bae1dSRodney W. Grimes 		goto retry;
781df8bae1dSRodney W. Grimes done:
782df8bae1dSRodney W. Grimes 	p->p_flag &= ~P_SELECT;
783e04ac2feSJohn Baldwin 	PROC_UNLOCK(p);
784df8bae1dSRodney W. Grimes 	/* select is not restarted after signals... */
785df8bae1dSRodney W. Grimes 	if (error == ERESTART)
786df8bae1dSRodney W. Grimes 		error = EINTR;
787df8bae1dSRodney W. Grimes 	if (error == EWOULDBLOCK)
788df8bae1dSRodney W. Grimes 		error = 0;
789df8bae1dSRodney W. Grimes #define	putbits(name, x) \
790d5e4d7e1SBruce Evans 	if (uap->name && (error2 = copyout(obits[x], uap->name, ncpbytes))) \
791df8bae1dSRodney W. Grimes 		error = error2;
792df8bae1dSRodney W. Grimes 	if (error == 0) {
793df8bae1dSRodney W. Grimes 		int error2;
794df8bae1dSRodney W. Grimes 
795df8bae1dSRodney W. Grimes 		putbits(in, 0);
796df8bae1dSRodney W. Grimes 		putbits(ou, 1);
797df8bae1dSRodney W. Grimes 		putbits(ex, 2);
798df8bae1dSRodney W. Grimes #undef putbits
799df8bae1dSRodney W. Grimes 	}
800d5e4d7e1SBruce Evans 	if (selbits != &s_selbits[0])
801d5e4d7e1SBruce Evans 		free(selbits, M_SELECT);
802df8bae1dSRodney W. Grimes 	return (error);
803df8bae1dSRodney W. Grimes }
804df8bae1dSRodney W. Grimes 
80587b6de2bSPoul-Henning Kamp static int
806cb226aaaSPoul-Henning Kamp selscan(p, ibits, obits, nfd)
807df8bae1dSRodney W. Grimes 	struct proc *p;
808b08f7993SSujal Patel 	fd_mask **ibits, **obits;
809cb226aaaSPoul-Henning Kamp 	int nfd;
810df8bae1dSRodney W. Grimes {
811f082218cSPeter Wemm 	struct filedesc *fdp = p->p_fd;
812f082218cSPeter Wemm 	int msk, i, fd;
813f082218cSPeter Wemm 	fd_mask bits;
814df8bae1dSRodney W. Grimes 	struct file *fp;
815df8bae1dSRodney W. Grimes 	int n = 0;
8162087c896SBruce Evans 	/* Note: backend also returns POLLHUP/POLLERR if appropriate. */
81742d11757SPeter Wemm 	static int flag[3] = { POLLRDNORM, POLLWRNORM, POLLRDBAND };
818df8bae1dSRodney W. Grimes 
819df8bae1dSRodney W. Grimes 	for (msk = 0; msk < 3; msk++) {
820d5e4d7e1SBruce Evans 		if (ibits[msk] == NULL)
821d5e4d7e1SBruce Evans 			continue;
822df8bae1dSRodney W. Grimes 		for (i = 0; i < nfd; i += NFDBITS) {
823b08f7993SSujal Patel 			bits = ibits[msk][i/NFDBITS];
824f082218cSPeter Wemm 			/* ffs(int mask) not portable, fd_mask is long */
825f082218cSPeter Wemm 			for (fd = i; bits && fd < nfd; fd++, bits >>= 1) {
826f082218cSPeter Wemm 				if (!(bits & 1))
827f082218cSPeter Wemm 					continue;
828df8bae1dSRodney W. Grimes 				fp = fdp->fd_ofiles[fd];
829df8bae1dSRodney W. Grimes 				if (fp == NULL)
830df8bae1dSRodney W. Grimes 					return (EBADF);
83113ccadd4SBrian Feldman 				if (fo_poll(fp, flag[msk], fp->f_cred, p)) {
832b08f7993SSujal Patel 					obits[msk][(fd)/NFDBITS] |=
833f082218cSPeter Wemm 					    ((fd_mask)1 << ((fd) % NFDBITS));
834df8bae1dSRodney W. Grimes 					n++;
835df8bae1dSRodney W. Grimes 				}
836df8bae1dSRodney W. Grimes 			}
837df8bae1dSRodney W. Grimes 		}
838df8bae1dSRodney W. Grimes 	}
839cb226aaaSPoul-Henning Kamp 	p->p_retval[0] = n;
840df8bae1dSRodney W. Grimes 	return (0);
841df8bae1dSRodney W. Grimes }
842df8bae1dSRodney W. Grimes 
84342d11757SPeter Wemm /*
84442d11757SPeter Wemm  * Poll system call.
84542d11757SPeter Wemm  */
84642d11757SPeter Wemm #ifndef _SYS_SYSPROTO_H_
84742d11757SPeter Wemm struct poll_args {
84842d11757SPeter Wemm 	struct pollfd *fds;
84942d11757SPeter Wemm 	u_int	nfds;
85042d11757SPeter Wemm 	int	timeout;
85142d11757SPeter Wemm };
85242d11757SPeter Wemm #endif
85342d11757SPeter Wemm int
854cb226aaaSPoul-Henning Kamp poll(p, uap)
85542d11757SPeter Wemm 	register struct proc *p;
85642d11757SPeter Wemm 	register struct poll_args *uap;
85742d11757SPeter Wemm {
85842d11757SPeter Wemm 	caddr_t bits;
85942d11757SPeter Wemm 	char smallbits[32 * sizeof(struct pollfd)];
86000af9731SPoul-Henning Kamp 	struct timeval atv, rtv, ttv;
86189b71647SPeter Wemm 	int s, ncoll, error = 0, timo, lim, nfds;
86242d11757SPeter Wemm 	size_t ni;
86342d11757SPeter Wemm 
86489b71647SPeter Wemm 	nfds = SCARG(uap, nfds);
86589b71647SPeter Wemm 	/*
86689b71647SPeter Wemm 	 * This is kinda bogus.  We have fd limits, but that doesn't
86789b71647SPeter Wemm 	 * map too well to the size of the pfd[] array.  Make sure
86889b71647SPeter Wemm 	 * we let the process use at least FD_SETSIZE entries.
86989b71647SPeter Wemm 	 * The specs say we only have to support OPEN_MAX entries (64).
87089b71647SPeter Wemm 	 */
87189b71647SPeter Wemm 	lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfilesperproc);
87289b71647SPeter Wemm 	lim = min(lim, FD_SETSIZE);
87389b71647SPeter Wemm 	if (nfds > lim)
87489b71647SPeter Wemm 		return (EINVAL);
87589b71647SPeter Wemm 	ni = nfds * sizeof(struct pollfd);
87642d11757SPeter Wemm 	if (ni > sizeof(smallbits))
87742d11757SPeter Wemm 		bits = malloc(ni, M_TEMP, M_WAITOK);
87842d11757SPeter Wemm 	else
87942d11757SPeter Wemm 		bits = smallbits;
88042d11757SPeter Wemm 	error = copyin(SCARG(uap, fds), bits, ni);
881e04ac2feSJohn Baldwin 	PROC_LOCK(p);
88242d11757SPeter Wemm 	if (error)
88342d11757SPeter Wemm 		goto done;
88442d11757SPeter Wemm 	if (SCARG(uap, timeout) != INFTIM) {
88542d11757SPeter Wemm 		atv.tv_sec = SCARG(uap, timeout) / 1000;
88642d11757SPeter Wemm 		atv.tv_usec = (SCARG(uap, timeout) % 1000) * 1000;
88742d11757SPeter Wemm 		if (itimerfix(&atv)) {
88842d11757SPeter Wemm 			error = EINVAL;
88942d11757SPeter Wemm 			goto done;
89042d11757SPeter Wemm 		}
891c21410e1SPoul-Henning Kamp 		getmicrouptime(&rtv);
89200af9731SPoul-Henning Kamp 		timevaladd(&atv, &rtv);
8939c386f6bSJohn Baldwin 	} else {
89400af9731SPoul-Henning Kamp 		atv.tv_sec = 0;
8959c386f6bSJohn Baldwin 		atv.tv_usec = 0;
8969c386f6bSJohn Baldwin 	}
89700af9731SPoul-Henning Kamp 	timo = 0;
89842d11757SPeter Wemm retry:
89942d11757SPeter Wemm 	ncoll = nselcoll;
90042d11757SPeter Wemm 	p->p_flag |= P_SELECT;
901e04ac2feSJohn Baldwin 	PROC_UNLOCK(p);
90289b71647SPeter Wemm 	error = pollscan(p, (struct pollfd *)bits, nfds);
903e04ac2feSJohn Baldwin 	PROC_LOCK(p);
904cb226aaaSPoul-Henning Kamp 	if (error || p->p_retval[0])
90542d11757SPeter Wemm 		goto done;
9064da144c0SJohn Baldwin 	if (atv.tv_sec || atv.tv_usec) {
907c21410e1SPoul-Henning Kamp 		getmicrouptime(&rtv);
90800af9731SPoul-Henning Kamp 		if (timevalcmp(&rtv, &atv, >=))
90942d11757SPeter Wemm 			goto done;
91000af9731SPoul-Henning Kamp 		ttv = atv;
91100af9731SPoul-Henning Kamp 		timevalsub(&ttv, &rtv);
91200af9731SPoul-Henning Kamp 		timo = ttv.tv_sec > 24 * 60 * 60 ?
91300af9731SPoul-Henning Kamp 		    24 * 60 * 60 * hz : tvtohz(&ttv);
91442d11757SPeter Wemm 	}
91500af9731SPoul-Henning Kamp 	s = splhigh();
91642d11757SPeter Wemm 	if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
91742d11757SPeter Wemm 		splx(s);
91842d11757SPeter Wemm 		goto retry;
91942d11757SPeter Wemm 	}
92042d11757SPeter Wemm 	p->p_flag &= ~P_SELECT;
921e04ac2feSJohn Baldwin 	error = msleep((caddr_t)&selwait, &p->p_mtx, PSOCK | PCATCH, "poll",
922e04ac2feSJohn Baldwin 	    timo);
92342d11757SPeter Wemm 	splx(s);
92442d11757SPeter Wemm 	if (error == 0)
92542d11757SPeter Wemm 		goto retry;
92642d11757SPeter Wemm done:
92742d11757SPeter Wemm 	p->p_flag &= ~P_SELECT;
928e04ac2feSJohn Baldwin 	PROC_UNLOCK(p);
92942d11757SPeter Wemm 	/* poll is not restarted after signals... */
93042d11757SPeter Wemm 	if (error == ERESTART)
93142d11757SPeter Wemm 		error = EINTR;
93242d11757SPeter Wemm 	if (error == EWOULDBLOCK)
93342d11757SPeter Wemm 		error = 0;
93442d11757SPeter Wemm 	if (error == 0) {
93542d11757SPeter Wemm 		error = copyout(bits, SCARG(uap, fds), ni);
93642d11757SPeter Wemm 		if (error)
93742d11757SPeter Wemm 			goto out;
93842d11757SPeter Wemm 	}
93942d11757SPeter Wemm out:
94042d11757SPeter Wemm 	if (ni > sizeof(smallbits))
94142d11757SPeter Wemm 		free(bits, M_TEMP);
94242d11757SPeter Wemm 	return (error);
94342d11757SPeter Wemm }
94442d11757SPeter Wemm 
94542d11757SPeter Wemm static int
946cb226aaaSPoul-Henning Kamp pollscan(p, fds, nfd)
94742d11757SPeter Wemm 	struct proc *p;
94842d11757SPeter Wemm 	struct pollfd *fds;
94942d11757SPeter Wemm 	int nfd;
95042d11757SPeter Wemm {
95142d11757SPeter Wemm 	register struct filedesc *fdp = p->p_fd;
95242d11757SPeter Wemm 	int i;
95342d11757SPeter Wemm 	struct file *fp;
95442d11757SPeter Wemm 	int n = 0;
95542d11757SPeter Wemm 
95642d11757SPeter Wemm 	for (i = 0; i < nfd; i++, fds++) {
957337c9691SJordan K. Hubbard 		if (fds->fd >= fdp->fd_nfiles) {
95842d11757SPeter Wemm 			fds->revents = POLLNVAL;
95942d11757SPeter Wemm 			n++;
960337c9691SJordan K. Hubbard 		} else if (fds->fd < 0) {
961337c9691SJordan K. Hubbard 			fds->revents = 0;
96242d11757SPeter Wemm 		} else {
96342d11757SPeter Wemm 			fp = fdp->fd_ofiles[fds->fd];
964279d7226SMatthew Dillon 			if (fp == NULL) {
96542d11757SPeter Wemm 				fds->revents = POLLNVAL;
96642d11757SPeter Wemm 				n++;
96742d11757SPeter Wemm 			} else {
9682087c896SBruce Evans 				/*
9692087c896SBruce Evans 				 * Note: backend also returns POLLHUP and
9702087c896SBruce Evans 				 * POLLERR if appropriate.
9712087c896SBruce Evans 				 */
97213ccadd4SBrian Feldman 				fds->revents = fo_poll(fp, fds->events,
97313ccadd4SBrian Feldman 				    fp->f_cred, p);
97442d11757SPeter Wemm 				if (fds->revents != 0)
97542d11757SPeter Wemm 					n++;
97642d11757SPeter Wemm 			}
97742d11757SPeter Wemm 		}
97842d11757SPeter Wemm 	}
979cb226aaaSPoul-Henning Kamp 	p->p_retval[0] = n;
98042d11757SPeter Wemm 	return (0);
98142d11757SPeter Wemm }
98242d11757SPeter Wemm 
98342d11757SPeter Wemm /*
98442d11757SPeter Wemm  * OpenBSD poll system call.
98542d11757SPeter Wemm  * XXX this isn't quite a true representation..  OpenBSD uses select ops.
98642d11757SPeter Wemm  */
98742d11757SPeter Wemm #ifndef _SYS_SYSPROTO_H_
98842d11757SPeter Wemm struct openbsd_poll_args {
98942d11757SPeter Wemm 	struct pollfd *fds;
99042d11757SPeter Wemm 	u_int	nfds;
99142d11757SPeter Wemm 	int	timeout;
99242d11757SPeter Wemm };
99342d11757SPeter Wemm #endif
99442d11757SPeter Wemm int
995cb226aaaSPoul-Henning Kamp openbsd_poll(p, uap)
99642d11757SPeter Wemm 	register struct proc *p;
99742d11757SPeter Wemm 	register struct openbsd_poll_args *uap;
99842d11757SPeter Wemm {
999cb226aaaSPoul-Henning Kamp 	return (poll(p, (struct poll_args *)uap));
100042d11757SPeter Wemm }
100142d11757SPeter Wemm 
1002df8bae1dSRodney W. Grimes /*ARGSUSED*/
100326f9a767SRodney W. Grimes int
100442d11757SPeter Wemm seltrue(dev, events, p)
1005df8bae1dSRodney W. Grimes 	dev_t dev;
100642d11757SPeter Wemm 	int events;
1007df8bae1dSRodney W. Grimes 	struct proc *p;
1008df8bae1dSRodney W. Grimes {
1009df8bae1dSRodney W. Grimes 
101042d11757SPeter Wemm 	return (events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
1011df8bae1dSRodney W. Grimes }
1012df8bae1dSRodney W. Grimes 
1013df8bae1dSRodney W. Grimes /*
1014df8bae1dSRodney W. Grimes  * Record a select request.
1015df8bae1dSRodney W. Grimes  */
1016df8bae1dSRodney W. Grimes void
1017df8bae1dSRodney W. Grimes selrecord(selector, sip)
1018df8bae1dSRodney W. Grimes 	struct proc *selector;
1019df8bae1dSRodney W. Grimes 	struct selinfo *sip;
1020df8bae1dSRodney W. Grimes {
1021df8bae1dSRodney W. Grimes 	struct proc *p;
1022df8bae1dSRodney W. Grimes 	pid_t mypid;
1023df8bae1dSRodney W. Grimes 
1024df8bae1dSRodney W. Grimes 	mypid = selector->p_pid;
1025df8bae1dSRodney W. Grimes 	if (sip->si_pid == mypid)
1026df8bae1dSRodney W. Grimes 		return;
1027e04ac2feSJohn Baldwin 	if (sip->si_pid && (p = pfind(sip->si_pid))) {
1028e04ac2feSJohn Baldwin 		mtx_enter(&sched_lock, MTX_SPIN);
1029e04ac2feSJohn Baldwin 	    	if (p->p_wchan == (caddr_t)&selwait) {
1030e04ac2feSJohn Baldwin 			mtx_exit(&sched_lock, MTX_SPIN);
1031df8bae1dSRodney W. Grimes 			sip->si_flags |= SI_COLL;
1032e04ac2feSJohn Baldwin 			return;
1033e04ac2feSJohn Baldwin 		}
1034e04ac2feSJohn Baldwin 		mtx_exit(&sched_lock, MTX_SPIN);
1035e04ac2feSJohn Baldwin 	}
1036df8bae1dSRodney W. Grimes 	sip->si_pid = mypid;
1037df8bae1dSRodney W. Grimes }
1038df8bae1dSRodney W. Grimes 
1039df8bae1dSRodney W. Grimes /*
1040df8bae1dSRodney W. Grimes  * Do a wakeup when a selectable event occurs.
1041df8bae1dSRodney W. Grimes  */
1042df8bae1dSRodney W. Grimes void
1043df8bae1dSRodney W. Grimes selwakeup(sip)
1044df8bae1dSRodney W. Grimes 	register struct selinfo *sip;
1045df8bae1dSRodney W. Grimes {
1046df8bae1dSRodney W. Grimes 	register struct proc *p;
1047df8bae1dSRodney W. Grimes 
1048df8bae1dSRodney W. Grimes 	if (sip->si_pid == 0)
1049df8bae1dSRodney W. Grimes 		return;
1050df8bae1dSRodney W. Grimes 	if (sip->si_flags & SI_COLL) {
1051df8bae1dSRodney W. Grimes 		nselcoll++;
1052df8bae1dSRodney W. Grimes 		sip->si_flags &= ~SI_COLL;
1053df8bae1dSRodney W. Grimes 		wakeup((caddr_t)&selwait);
1054df8bae1dSRodney W. Grimes 	}
1055df8bae1dSRodney W. Grimes 	p = pfind(sip->si_pid);
1056df8bae1dSRodney W. Grimes 	sip->si_pid = 0;
1057df8bae1dSRodney W. Grimes 	if (p != NULL) {
10584a476efaSJonathan Lemon 		mtx_enter(&sched_lock, MTX_SPIN);
1059df8bae1dSRodney W. Grimes 		if (p->p_wchan == (caddr_t)&selwait) {
1060df8bae1dSRodney W. Grimes 			if (p->p_stat == SSLEEP)
1061df8bae1dSRodney W. Grimes 				setrunnable(p);
1062df8bae1dSRodney W. Grimes 			else
1063df8bae1dSRodney W. Grimes 				unsleep(p);
10644a476efaSJonathan Lemon 			mtx_exit(&sched_lock, MTX_SPIN);
1065e04ac2feSJohn Baldwin 		} else {
1066e04ac2feSJohn Baldwin 			mtx_exit(&sched_lock, MTX_SPIN);
1067e04ac2feSJohn Baldwin 			PROC_LOCK(p);
1068e04ac2feSJohn Baldwin 			p->p_flag &= ~P_SELECT;
1069e04ac2feSJohn Baldwin 			PROC_UNLOCK(p);
1070e04ac2feSJohn Baldwin 		}
1071df8bae1dSRodney W. Grimes 	}
1072df8bae1dSRodney W. Grimes }
1073