xref: /netbsd-src/sys/kern/sys_generic.c (revision 6ea46cb5e46c49111a6ecf3bcbe3c7e2730fe9f6)
1 /*	$NetBSD: sys_generic.c,v 1.15 1994/06/29 06:33:05 cgd Exp $	*/
2 
3 /*
4  * Copyright (c) 1982, 1986, 1989, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  * (c) UNIX System Laboratories, Inc.
7  * All or some portions of this file are derived from material licensed
8  * to the University of California by American Telephone and Telegraph
9  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10  * the permission of UNIX System Laboratories, Inc.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:
22  *	This product includes software developed by the University of
23  *	California, Berkeley and its contributors.
24  * 4. Neither the name of the University nor the names of its contributors
25  *    may be used to endorse or promote products derived from this software
26  *    without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38  * SUCH DAMAGE.
39  *
40  *	@(#)sys_generic.c	8.5 (Berkeley) 1/21/94
41  */
42 
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/filedesc.h>
46 #include <sys/ioctl.h>
47 #include <sys/file.h>
48 #include <sys/proc.h>
49 #include <sys/socketvar.h>
50 #include <sys/uio.h>
51 #include <sys/kernel.h>
52 #include <sys/stat.h>
53 #include <sys/malloc.h>
54 #ifdef KTRACE
55 #include <sys/ktrace.h>
56 #endif
57 
58 /*
59  * Read system call.
60  */
61 struct read_args {
62 	int	fd;
63 	char	*buf;
64 	u_int	nbyte;
65 };
66 /* ARGSUSED */
67 read(p, uap, retval)
68 	struct proc *p;
69 	register struct read_args *uap;
70 	int *retval;
71 {
72 	register struct file *fp;
73 	register struct filedesc *fdp = p->p_fd;
74 	struct uio auio;
75 	struct iovec aiov;
76 	long cnt, error = 0;
77 #ifdef KTRACE
78 	struct iovec ktriov;
79 #endif
80 
81 	if (((u_int)uap->fd) >= fdp->fd_nfiles ||
82 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL ||
83 	    (fp->f_flag & FREAD) == 0)
84 		return (EBADF);
85 	aiov.iov_base = (caddr_t)uap->buf;
86 	aiov.iov_len = uap->nbyte;
87 	auio.uio_iov = &aiov;
88 	auio.uio_iovcnt = 1;
89 	auio.uio_resid = uap->nbyte;
90 	auio.uio_rw = UIO_READ;
91 	auio.uio_segflg = UIO_USERSPACE;
92 	auio.uio_procp = p;
93 	if (auio.uio_resid < 0)
94 		return EINVAL;
95 #ifdef KTRACE
96 	/*
97 	 * if tracing, save a copy of iovec
98 	 */
99 	if (KTRPOINT(p, KTR_GENIO))
100 		ktriov = aiov;
101 #endif
102 	cnt = uap->nbyte;
103 	if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
104 		if (auio.uio_resid != cnt && (error == ERESTART ||
105 		    error == EINTR || error == EWOULDBLOCK))
106 			error = 0;
107 	cnt -= auio.uio_resid;
108 #ifdef KTRACE
109 	if (KTRPOINT(p, KTR_GENIO) && error == 0)
110 		ktrgenio(p->p_tracep, uap->fd, UIO_READ, &ktriov, cnt, error);
111 #endif
112 	*retval = cnt;
113 	return (error);
114 }
115 
116 /*
117  * Scatter read system call.
118  */
119 struct readv_args {
120 	int	fdes;
121 	struct	iovec *iovp;
122 	u_int	iovcnt;
123 };
124 readv(p, uap, retval)
125 	struct proc *p;
126 	register struct readv_args *uap;
127 	int *retval;
128 {
129 	register struct file *fp;
130 	register struct filedesc *fdp = p->p_fd;
131 	struct uio auio;
132 	register struct iovec *iov;
133 	struct iovec *needfree;
134 	struct iovec aiov[UIO_SMALLIOV];
135 	long i, cnt, error = 0;
136 	u_int iovlen;
137 #ifdef KTRACE
138 	struct iovec *ktriov = NULL;
139 #endif
140 
141 	if (((u_int)uap->fdes) >= fdp->fd_nfiles ||
142 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
143 	    (fp->f_flag & FREAD) == 0)
144 		return (EBADF);
145 	/* note: can't use iovlen until iovcnt is validated */
146 	iovlen = uap->iovcnt * sizeof (struct iovec);
147 	if (uap->iovcnt > UIO_SMALLIOV) {
148 		if (uap->iovcnt > UIO_MAXIOV)
149 			return (EINVAL);
150 		MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
151 		needfree = iov;
152 	} else {
153 		iov = aiov;
154 		needfree = NULL;
155 	}
156 	auio.uio_iov = iov;
157 	auio.uio_iovcnt = uap->iovcnt;
158 	auio.uio_rw = UIO_READ;
159 	auio.uio_segflg = UIO_USERSPACE;
160 	auio.uio_procp = p;
161 	if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))
162 		goto done;
163 	auio.uio_resid = 0;
164 	for (i = 0; i < uap->iovcnt; i++) {
165 		if (iov->iov_len < 0) {
166 			error = EINVAL;
167 			goto done;
168 		}
169 		auio.uio_resid += iov->iov_len;
170 		if (auio.uio_resid < 0) {
171 			error = EINVAL;
172 			goto done;
173 		}
174 		iov++;
175 	}
176 #ifdef KTRACE
177 	/*
178 	 * if tracing, save a copy of iovec
179 	 */
180 	if (KTRPOINT(p, KTR_GENIO))  {
181 		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
182 		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
183 	}
184 #endif
185 	cnt = auio.uio_resid;
186 	if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
187 		if (auio.uio_resid != cnt && (error == ERESTART ||
188 		    error == EINTR || error == EWOULDBLOCK))
189 			error = 0;
190 	cnt -= auio.uio_resid;
191 #ifdef KTRACE
192 	if (ktriov != NULL) {
193 		if (error == 0)
194 			ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov,
195 			    cnt, error);
196 		FREE(ktriov, M_TEMP);
197 	}
198 #endif
199 	*retval = cnt;
200 done:
201 	if (needfree)
202 		FREE(needfree, M_IOV);
203 	return (error);
204 }
205 
206 /*
207  * Write system call
208  */
209 struct write_args {
210 	int	fd;
211 	char	*buf;
212 	u_int	nbyte;
213 };
214 write(p, uap, retval)
215 	struct proc *p;
216 	register struct write_args *uap;
217 	int *retval;
218 {
219 	register struct file *fp;
220 	register struct filedesc *fdp = p->p_fd;
221 	struct uio auio;
222 	struct iovec aiov;
223 	long cnt, error = 0;
224 #ifdef KTRACE
225 	struct iovec ktriov;
226 #endif
227 
228 	if (((u_int)uap->fd) >= fdp->fd_nfiles ||
229 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL ||
230 	    (fp->f_flag & FWRITE) == 0)
231 		return (EBADF);
232 	aiov.iov_base = (caddr_t)uap->buf;
233 	aiov.iov_len = uap->nbyte;
234 	auio.uio_iov = &aiov;
235 	auio.uio_iovcnt = 1;
236 	auio.uio_resid = uap->nbyte;
237 	auio.uio_rw = UIO_WRITE;
238 	auio.uio_segflg = UIO_USERSPACE;
239 	auio.uio_procp = p;
240 	if (auio.uio_resid < 0)
241 		return EINVAL;
242 #ifdef KTRACE
243 	/*
244 	 * if tracing, save a copy of iovec
245 	 */
246 	if (KTRPOINT(p, KTR_GENIO))
247 		ktriov = aiov;
248 #endif
249 	cnt = uap->nbyte;
250 	if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
251 		if (auio.uio_resid != cnt && (error == ERESTART ||
252 		    error == EINTR || error == EWOULDBLOCK))
253 			error = 0;
254 		if (error == EPIPE)
255 			psignal(p, SIGPIPE);
256 	}
257 	cnt -= auio.uio_resid;
258 #ifdef KTRACE
259 	if (KTRPOINT(p, KTR_GENIO) && error == 0)
260 		ktrgenio(p->p_tracep, uap->fd, UIO_WRITE,
261 		    &ktriov, cnt, error);
262 #endif
263 	*retval = cnt;
264 	return (error);
265 }
266 
267 /*
268  * Gather write system call
269  */
270 struct writev_args {
271 	int	fd;
272 	struct	iovec *iovp;
273 	u_int	iovcnt;
274 };
275 writev(p, uap, retval)
276 	struct proc *p;
277 	register struct writev_args *uap;
278 	int *retval;
279 {
280 	register struct file *fp;
281 	register struct filedesc *fdp = p->p_fd;
282 	struct uio auio;
283 	register struct iovec *iov;
284 	struct iovec *needfree;
285 	struct iovec aiov[UIO_SMALLIOV];
286 	long i, cnt, error = 0;
287 	u_int iovlen;
288 #ifdef KTRACE
289 	struct iovec *ktriov = NULL;
290 #endif
291 
292 	if (((u_int)uap->fd) >= fdp->fd_nfiles ||
293 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL ||
294 	    (fp->f_flag & FWRITE) == 0)
295 		return (EBADF);
296 	/* note: can't use iovlen until iovcnt is validated */
297 	iovlen = uap->iovcnt * sizeof (struct iovec);
298 	if (uap->iovcnt > UIO_SMALLIOV) {
299 		if (uap->iovcnt > UIO_MAXIOV)
300 			return (EINVAL);
301 		MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
302 		needfree = iov;
303 	} else {
304 		iov = aiov;
305 		needfree = NULL;
306 	}
307 	auio.uio_iov = iov;
308 	auio.uio_iovcnt = uap->iovcnt;
309 	auio.uio_rw = UIO_WRITE;
310 	auio.uio_segflg = UIO_USERSPACE;
311 	auio.uio_procp = p;
312 	if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen))
313 		goto done;
314 	auio.uio_resid = 0;
315 	for (i = 0; i < uap->iovcnt; i++) {
316 		if (iov->iov_len < 0) {
317 			error = EINVAL;
318 			goto done;
319 		}
320 		auio.uio_resid += iov->iov_len;
321 		if (auio.uio_resid < 0) {
322 			error = EINVAL;
323 			goto done;
324 		}
325 		iov++;
326 	}
327 #ifdef KTRACE
328 	/*
329 	 * if tracing, save a copy of iovec
330 	 */
331 	if (KTRPOINT(p, KTR_GENIO))  {
332 		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
333 		bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
334 	}
335 #endif
336 	cnt = auio.uio_resid;
337 	if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
338 		if (auio.uio_resid != cnt && (error == ERESTART ||
339 		    error == EINTR || error == EWOULDBLOCK))
340 			error = 0;
341 		if (error == EPIPE)
342 			psignal(p, SIGPIPE);
343 	}
344 	cnt -= auio.uio_resid;
345 #ifdef KTRACE
346 	if (ktriov != NULL) {
347 		if (error == 0)
348 			ktrgenio(p->p_tracep, uap->fd, UIO_WRITE,
349 				ktriov, cnt, error);
350 		FREE(ktriov, M_TEMP);
351 	}
352 #endif
353 	*retval = cnt;
354 done:
355 	if (needfree)
356 		FREE(needfree, M_IOV);
357 	return (error);
358 }
359 
360 /*
361  * Ioctl system call
362  */
363 struct ioctl_args {
364 	int	fd;
365 	int	com;
366 	caddr_t	data;
367 };
368 /* ARGSUSED */
369 ioctl(p, uap, retval)
370 	struct proc *p;
371 	register struct ioctl_args *uap;
372 	int *retval;
373 {
374 	register struct file *fp;
375 	register struct filedesc *fdp;
376 	register int com, error;
377 	register u_int size;
378 	caddr_t data, memp;
379 	int tmp;
380 #define STK_PARAMS	128
381 	char stkbuf[STK_PARAMS];
382 
383 	fdp = p->p_fd;
384 	if ((u_int)uap->fd >= fdp->fd_nfiles ||
385 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
386 		return (EBADF);
387 
388 	if ((fp->f_flag & (FREAD | FWRITE)) == 0)
389 		return (EBADF);
390 
391 	switch (com = uap->com) {
392 	case FIONCLEX:
393 		fdp->fd_ofileflags[uap->fd] &= ~UF_EXCLOSE;
394 		return (0);
395 	case FIOCLEX:
396 		fdp->fd_ofileflags[uap->fd] |= UF_EXCLOSE;
397 		return (0);
398 	}
399 
400 	/*
401 	 * Interpret high order word to find amount of data to be
402 	 * copied to/from the user's address space.
403 	 */
404 	size = IOCPARM_LEN(com);
405 	if (size > IOCPARM_MAX)
406 		return (ENOTTY);
407 	memp = NULL;
408 	if (size > sizeof (stkbuf)) {
409 		memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
410 		data = memp;
411 	} else
412 		data = stkbuf;
413 	if (com&IOC_IN) {
414 		if (size) {
415 			error = copyin(uap->data, data, (u_int)size);
416 			if (error) {
417 				if (memp)
418 					free(memp, M_IOCTLOPS);
419 				return (error);
420 			}
421 		} else
422 			*(caddr_t *)data = uap->data;
423 	} else if ((com&IOC_OUT) && size)
424 		/*
425 		 * Zero the buffer so the user always
426 		 * gets back something deterministic.
427 		 */
428 		bzero(data, size);
429 	else if (com&IOC_VOID)
430 		*(caddr_t *)data = uap->data;
431 
432 	switch (com) {
433 
434 	case FIONBIO:
435 		if (tmp = *(int *)data)
436 			fp->f_flag |= FNONBLOCK;
437 		else
438 			fp->f_flag &= ~FNONBLOCK;
439 		error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
440 		break;
441 
442 	case FIOASYNC:
443 		if (tmp = *(int *)data)
444 			fp->f_flag |= FASYNC;
445 		else
446 			fp->f_flag &= ~FASYNC;
447 		error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
448 		break;
449 
450 	case FIOSETOWN:
451 		tmp = *(int *)data;
452 		if (fp->f_type == DTYPE_SOCKET) {
453 			((struct socket *)fp->f_data)->so_pgid = tmp;
454 			error = 0;
455 			break;
456 		}
457 		if (tmp <= 0) {
458 			tmp = -tmp;
459 		} else {
460 			struct proc *p1 = pfind(tmp);
461 			if (p1 == 0) {
462 				error = ESRCH;
463 				break;
464 			}
465 			tmp = p1->p_pgrp->pg_id;
466 		}
467 		error = (*fp->f_ops->fo_ioctl)
468 			(fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
469 		break;
470 
471 	case FIOGETOWN:
472 		if (fp->f_type == DTYPE_SOCKET) {
473 			error = 0;
474 			*(int *)data = ((struct socket *)fp->f_data)->so_pgid;
475 			break;
476 		}
477 		error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p);
478 		*(int *)data = -*(int *)data;
479 		break;
480 
481 	default:
482 		error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
483 		/*
484 		 * Copy any data to user, size was
485 		 * already set and checked above.
486 		 */
487 		if (error == 0 && (com&IOC_OUT) && size)
488 			error = copyout(data, uap->data, (u_int)size);
489 		break;
490 	}
491 	if (memp)
492 		free(memp, M_IOCTLOPS);
493 	return (error);
494 }
495 
496 int	selwait, nselcoll;
497 
498 /*
499  * Select system call.
500  */
501 struct select_args {
502 	u_int	nd;
503 	fd_set	*in, *ou, *ex;
504 	struct	timeval *tv;
505 };
506 select(p, uap, retval)
507 	register struct proc *p;
508 	register struct select_args *uap;
509 	int *retval;
510 {
511 	fd_set ibits[3], obits[3];
512 	struct timeval atv;
513 	int s, ncoll, error = 0, timo;
514 	u_int ni;
515 
516 	bzero((caddr_t)ibits, sizeof(ibits));
517 	bzero((caddr_t)obits, sizeof(obits));
518 	if (uap->nd > FD_SETSIZE)
519 		return (EINVAL);
520 	if (uap->nd > p->p_fd->fd_nfiles)
521 		uap->nd = p->p_fd->fd_nfiles;	/* forgiving; slightly wrong */
522 	ni = howmany(uap->nd, NFDBITS) * sizeof(fd_mask);
523 
524 #define	getbits(name, x) \
525 	if (uap->name && \
526 	    (error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], ni))) \
527 		goto done;
528 	getbits(in, 0);
529 	getbits(ou, 1);
530 	getbits(ex, 2);
531 #undef	getbits
532 
533 	if (uap->tv) {
534 		error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
535 			sizeof (atv));
536 		if (error)
537 			goto done;
538 		if (itimerfix(&atv)) {
539 			error = EINVAL;
540 			goto done;
541 		}
542 		s = splclock();
543 		timevaladd(&atv, (struct timeval *)&time);
544 		timo = hzto(&atv);
545 		/*
546 		 * Avoid inadvertently sleeping forever.
547 		 */
548 		if (timo == 0)
549 			timo = 1;
550 		splx(s);
551 	} else
552 		timo = 0;
553 retry:
554 	ncoll = nselcoll;
555 	p->p_flag |= P_SELECT;
556 	error = selscan(p, ibits, obits, uap->nd, retval);
557 	if (error || *retval)
558 		goto done;
559 	s = splhigh();
560 	/* this should be timercmp(&time, &atv, >=) */
561 	if (uap->tv && (time.tv_sec > atv.tv_sec ||
562 	    time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
563 		splx(s);
564 		goto done;
565 	}
566 	if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
567 		splx(s);
568 		goto retry;
569 	}
570 	p->p_flag &= ~P_SELECT;
571 	error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
572 	splx(s);
573 	if (error == 0)
574 		goto retry;
575 done:
576 	p->p_flag &= ~P_SELECT;
577 	/* select is not restarted after signals... */
578 	if (error == ERESTART)
579 		error = EINTR;
580 	if (error == EWOULDBLOCK)
581 		error = 0;
582 #define	putbits(name, x) \
583 	if (uap->name && \
584 	    (error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, ni))) \
585 		error = error2;
586 	if (error == 0) {
587 		int error2;
588 
589 		putbits(in, 0);
590 		putbits(ou, 1);
591 		putbits(ex, 2);
592 #undef putbits
593 	}
594 	return (error);
595 }
596 
597 selscan(p, ibits, obits, nfd, retval)
598 	struct proc *p;
599 	fd_set *ibits, *obits;
600 	int nfd, *retval;
601 {
602 	register struct filedesc *fdp = p->p_fd;
603 	register int msk, i, j, fd;
604 	register fd_mask bits;
605 	struct file *fp;
606 	int n = 0;
607 	static int flag[3] = { FREAD, FWRITE, 0 };
608 
609 	for (msk = 0; msk < 3; msk++) {
610 		for (i = 0; i < nfd; i += NFDBITS) {
611 			bits = ibits[msk].fds_bits[i/NFDBITS];
612 			while ((j = ffs(bits)) && (fd = i + --j) < nfd) {
613 				bits &= ~(1 << j);
614 				fp = fdp->fd_ofiles[fd];
615 				if (fp == NULL)
616 					return (EBADF);
617 				if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) {
618 					FD_SET(fd, &obits[msk]);
619 					n++;
620 				}
621 			}
622 		}
623 	}
624 	*retval = n;
625 	return (0);
626 }
627 
628 /*ARGSUSED*/
629 seltrue(dev, flag, p)
630 	dev_t dev;
631 	int flag;
632 	struct proc *p;
633 {
634 
635 	return (1);
636 }
637 
638 /*
639  * Record a select request.
640  */
641 void
642 selrecord(selector, sip)
643 	struct proc *selector;
644 	struct selinfo *sip;
645 {
646 	struct proc *p;
647 	pid_t mypid;
648 
649 	mypid = selector->p_pid;
650 	if (sip->si_pid == mypid)
651 		return;
652 	if (sip->si_pid && (p = pfind(sip->si_pid)) &&
653 	    p->p_wchan == (caddr_t)&selwait)
654 		sip->si_flags |= SI_COLL;
655 	else
656 		sip->si_pid = mypid;
657 }
658 
659 /*
660  * Do a wakeup when a selectable event occurs.
661  */
662 void
663 selwakeup(sip)
664 	register struct selinfo *sip;
665 {
666 	register struct proc *p;
667 	int s;
668 
669 	if (sip->si_pid == 0)
670 		return;
671 	if (sip->si_flags & SI_COLL) {
672 		nselcoll++;
673 		sip->si_flags &= ~SI_COLL;
674 		wakeup((caddr_t)&selwait);
675 	}
676 	p = pfind(sip->si_pid);
677 	sip->si_pid = 0;
678 	if (p != NULL) {
679 		s = splhigh();
680 		if (p->p_wchan == (caddr_t)&selwait) {
681 			if (p->p_stat == SSLEEP)
682 				setrunnable(p);
683 			else
684 				unsleep(p);
685 		} else if (p->p_flag & P_SELECT)
686 			p->p_flag &= ~P_SELECT;
687 		splx(s);
688 	}
689 }
690