sys_generic.c revision 1.27 1 /* $NetBSD: sys_generic.c,v 1.27 1996/09/05 15:32:52 mycroft 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/signalvar.h>
51 #include <sys/uio.h>
52 #include <sys/kernel.h>
53 #include <sys/stat.h>
54 #include <sys/malloc.h>
55 #ifdef KTRACE
56 #include <sys/ktrace.h>
57 #endif
58
59 #include <sys/mount.h>
60 #include <sys/syscallargs.h>
61
62 int selscan __P((struct proc *, fd_mask *, fd_mask *, int, register_t *));
63
64 /*
65 * Read system call.
66 */
67 /* ARGSUSED */
68 int
69 sys_read(p, v, retval)
70 struct proc *p;
71 void *v;
72 register_t *retval;
73 {
74 register struct sys_read_args /* {
75 syscallarg(int) fd;
76 syscallarg(char *) buf;
77 syscallarg(u_int) nbyte;
78 } */ *uap = v;
79 register struct file *fp;
80 register struct filedesc *fdp = p->p_fd;
81 struct uio auio;
82 struct iovec aiov;
83 long cnt, error = 0;
84 #ifdef KTRACE
85 struct iovec ktriov;
86 #endif
87
88 if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
89 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
90 (fp->f_flag & FREAD) == 0)
91 return (EBADF);
92 aiov.iov_base = (caddr_t)SCARG(uap, buf);
93 aiov.iov_len = SCARG(uap, nbyte);
94 auio.uio_iov = &aiov;
95 auio.uio_iovcnt = 1;
96 auio.uio_resid = SCARG(uap, nbyte);
97 auio.uio_rw = UIO_READ;
98 auio.uio_segflg = UIO_USERSPACE;
99 auio.uio_procp = p;
100 if (auio.uio_resid < 0)
101 return EINVAL;
102 #ifdef KTRACE
103 /*
104 * if tracing, save a copy of iovec
105 */
106 if (KTRPOINT(p, KTR_GENIO))
107 ktriov = aiov;
108 #endif
109 cnt = SCARG(uap, nbyte);
110 error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred);
111 if (error)
112 if (auio.uio_resid != cnt && (error == ERESTART ||
113 error == EINTR || error == EWOULDBLOCK))
114 error = 0;
115 cnt -= auio.uio_resid;
116 #ifdef KTRACE
117 if (KTRPOINT(p, KTR_GENIO) && error == 0)
118 ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_READ, &ktriov,
119 cnt, error);
120 #endif
121 *retval = cnt;
122 return (error);
123 }
124
125 /*
126 * Scatter read system call.
127 */
128 int
129 sys_readv(p, v, retval)
130 struct proc *p;
131 void *v;
132 register_t *retval;
133 {
134 register struct sys_readv_args /* {
135 syscallarg(int) fd;
136 syscallarg(struct iovec *) iovp;
137 syscallarg(u_int) iovcnt;
138 } */ *uap = v;
139 register struct file *fp;
140 register struct filedesc *fdp = p->p_fd;
141 struct uio auio;
142 register struct iovec *iov;
143 struct iovec *needfree;
144 struct iovec aiov[UIO_SMALLIOV];
145 long i, cnt, error = 0;
146 u_int iovlen;
147 #ifdef KTRACE
148 struct iovec *ktriov = NULL;
149 #endif
150
151 if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
152 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
153 (fp->f_flag & FREAD) == 0)
154 return (EBADF);
155 /* note: can't use iovlen until iovcnt is validated */
156 iovlen = SCARG(uap, iovcnt) * sizeof (struct iovec);
157 if (SCARG(uap, iovcnt) > UIO_SMALLIOV) {
158 if (SCARG(uap, iovcnt) > UIO_MAXIOV)
159 return (EINVAL);
160 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
161 needfree = iov;
162 } else {
163 iov = aiov;
164 needfree = NULL;
165 }
166 auio.uio_iov = iov;
167 auio.uio_iovcnt = SCARG(uap, iovcnt);
168 auio.uio_rw = UIO_READ;
169 auio.uio_segflg = UIO_USERSPACE;
170 auio.uio_procp = p;
171 error = copyin((caddr_t)SCARG(uap, iovp), (caddr_t)iov, iovlen);
172 if (error)
173 goto done;
174 auio.uio_resid = 0;
175 for (i = 0; i < SCARG(uap, iovcnt); i++) {
176 #if 0
177 /* Cannot happen iov_len is unsigned */
178 if (iov->iov_len < 0) {
179 error = EINVAL;
180 goto done;
181 }
182 #endif
183 auio.uio_resid += iov->iov_len;
184 if (auio.uio_resid < 0) {
185 error = EINVAL;
186 goto done;
187 }
188 iov++;
189 }
190 #ifdef KTRACE
191 /*
192 * if tracing, save a copy of iovec
193 */
194 if (KTRPOINT(p, KTR_GENIO)) {
195 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
196 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
197 }
198 #endif
199 cnt = auio.uio_resid;
200 error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred);
201 if (error)
202 if (auio.uio_resid != cnt && (error == ERESTART ||
203 error == EINTR || error == EWOULDBLOCK))
204 error = 0;
205 cnt -= auio.uio_resid;
206 #ifdef KTRACE
207 if (ktriov != NULL) {
208 if (error == 0)
209 ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_READ, ktriov,
210 cnt, error);
211 FREE(ktriov, M_TEMP);
212 }
213 #endif
214 *retval = cnt;
215 done:
216 if (needfree)
217 FREE(needfree, M_IOV);
218 return (error);
219 }
220
221 /*
222 * Write system call
223 */
224 int
225 sys_write(p, v, retval)
226 struct proc *p;
227 void *v;
228 register_t *retval;
229 {
230 register struct sys_write_args /* {
231 syscallarg(int) fd;
232 syscallarg(char *) buf;
233 syscallarg(u_int) nbyte;
234 } */ *uap = v;
235 register struct file *fp;
236 register struct filedesc *fdp = p->p_fd;
237 struct uio auio;
238 struct iovec aiov;
239 long cnt, error = 0;
240 #ifdef KTRACE
241 struct iovec ktriov;
242 #endif
243
244 if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
245 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
246 (fp->f_flag & FWRITE) == 0)
247 return (EBADF);
248 aiov.iov_base = (caddr_t)SCARG(uap, buf);
249 aiov.iov_len = SCARG(uap, nbyte);
250 auio.uio_iov = &aiov;
251 auio.uio_iovcnt = 1;
252 auio.uio_resid = SCARG(uap, nbyte);
253 auio.uio_rw = UIO_WRITE;
254 auio.uio_segflg = UIO_USERSPACE;
255 auio.uio_procp = p;
256 if (auio.uio_resid < 0)
257 return EINVAL;
258 #ifdef KTRACE
259 /*
260 * if tracing, save a copy of iovec
261 */
262 if (KTRPOINT(p, KTR_GENIO))
263 ktriov = aiov;
264 #endif
265 cnt = SCARG(uap, nbyte);
266 error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred);
267 if (error) {
268 if (auio.uio_resid != cnt && (error == ERESTART ||
269 error == EINTR || error == EWOULDBLOCK))
270 error = 0;
271 if (error == EPIPE)
272 psignal(p, SIGPIPE);
273 }
274 cnt -= auio.uio_resid;
275 #ifdef KTRACE
276 if (KTRPOINT(p, KTR_GENIO) && error == 0)
277 ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_WRITE,
278 &ktriov, cnt, error);
279 #endif
280 *retval = cnt;
281 return (error);
282 }
283
284 /*
285 * Gather write system call
286 */
287 int
288 sys_writev(p, v, retval)
289 struct proc *p;
290 void *v;
291 register_t *retval;
292 {
293 register struct sys_writev_args /* {
294 syscallarg(int) fd;
295 syscallarg(struct iovec *) iovp;
296 syscallarg(u_int) iovcnt;
297 } */ *uap = v;
298 register struct file *fp;
299 register struct filedesc *fdp = p->p_fd;
300 struct uio auio;
301 register struct iovec *iov;
302 struct iovec *needfree;
303 struct iovec aiov[UIO_SMALLIOV];
304 long i, cnt, error = 0;
305 u_int iovlen;
306 #ifdef KTRACE
307 struct iovec *ktriov = NULL;
308 #endif
309
310 if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
311 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
312 (fp->f_flag & FWRITE) == 0)
313 return (EBADF);
314 /* note: can't use iovlen until iovcnt is validated */
315 iovlen = SCARG(uap, iovcnt) * sizeof (struct iovec);
316 if (SCARG(uap, iovcnt) > UIO_SMALLIOV) {
317 if (SCARG(uap, iovcnt) > UIO_MAXIOV)
318 return (EINVAL);
319 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
320 needfree = iov;
321 } else {
322 iov = aiov;
323 needfree = NULL;
324 }
325 auio.uio_iov = iov;
326 auio.uio_iovcnt = SCARG(uap, iovcnt);
327 auio.uio_rw = UIO_WRITE;
328 auio.uio_segflg = UIO_USERSPACE;
329 auio.uio_procp = p;
330 error = copyin((caddr_t)SCARG(uap, iovp), (caddr_t)iov, iovlen);
331 if (error)
332 goto done;
333 auio.uio_resid = 0;
334 for (i = 0; i < SCARG(uap, iovcnt); i++) {
335 #if 0
336 /* Cannot happen iov_len is unsigned */
337 if (iov->iov_len < 0) {
338 error = EINVAL;
339 goto done;
340 }
341 #endif
342 auio.uio_resid += iov->iov_len;
343 if (auio.uio_resid < 0) {
344 error = EINVAL;
345 goto done;
346 }
347 iov++;
348 }
349 #ifdef KTRACE
350 /*
351 * if tracing, save a copy of iovec
352 */
353 if (KTRPOINT(p, KTR_GENIO)) {
354 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
355 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
356 }
357 #endif
358 cnt = auio.uio_resid;
359 error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred);
360 if (error) {
361 if (auio.uio_resid != cnt && (error == ERESTART ||
362 error == EINTR || error == EWOULDBLOCK))
363 error = 0;
364 if (error == EPIPE)
365 psignal(p, SIGPIPE);
366 }
367 cnt -= auio.uio_resid;
368 #ifdef KTRACE
369 if (ktriov != NULL) {
370 if (error == 0)
371 ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_WRITE,
372 ktriov, cnt, error);
373 FREE(ktriov, M_TEMP);
374 }
375 #endif
376 *retval = cnt;
377 done:
378 if (needfree)
379 FREE(needfree, M_IOV);
380 return (error);
381 }
382
383 /*
384 * Ioctl system call
385 */
386 /* ARGSUSED */
387 int
388 sys_ioctl(p, v, retval)
389 struct proc *p;
390 void *v;
391 register_t *retval;
392 {
393 register struct sys_ioctl_args /* {
394 syscallarg(int) fd;
395 syscallarg(u_long) com;
396 syscallarg(caddr_t) data;
397 } */ *uap = v;
398 register struct file *fp;
399 register struct filedesc *fdp;
400 register u_long com;
401 register int error;
402 register u_int size;
403 caddr_t data, memp;
404 int tmp;
405 #define STK_PARAMS 128
406 char stkbuf[STK_PARAMS];
407
408 fdp = p->p_fd;
409 if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
410 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
411 return (EBADF);
412
413 if ((fp->f_flag & (FREAD | FWRITE)) == 0)
414 return (EBADF);
415
416 switch (com = SCARG(uap, com)) {
417 case FIONCLEX:
418 fdp->fd_ofileflags[SCARG(uap, fd)] &= ~UF_EXCLOSE;
419 return (0);
420 case FIOCLEX:
421 fdp->fd_ofileflags[SCARG(uap, fd)] |= UF_EXCLOSE;
422 return (0);
423 }
424
425 /*
426 * Interpret high order word to find amount of data to be
427 * copied to/from the user's address space.
428 */
429 size = IOCPARM_LEN(com);
430 if (size > IOCPARM_MAX)
431 return (ENOTTY);
432 memp = NULL;
433 if (size > sizeof (stkbuf)) {
434 memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
435 data = memp;
436 } else
437 data = stkbuf;
438 if (com&IOC_IN) {
439 if (size) {
440 error = copyin(SCARG(uap, data), data, (u_int)size);
441 if (error) {
442 if (memp)
443 free(memp, M_IOCTLOPS);
444 return (error);
445 }
446 } else
447 *(caddr_t *)data = SCARG(uap, data);
448 } else if ((com&IOC_OUT) && size)
449 /*
450 * Zero the buffer so the user always
451 * gets back something deterministic.
452 */
453 bzero(data, size);
454 else if (com&IOC_VOID)
455 *(caddr_t *)data = SCARG(uap, data);
456
457 switch (com) {
458
459 case FIONBIO:
460 if ((tmp = *(int *)data) != 0)
461 fp->f_flag |= FNONBLOCK;
462 else
463 fp->f_flag &= ~FNONBLOCK;
464 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
465 break;
466
467 case FIOASYNC:
468 if ((tmp = *(int *)data) != 0)
469 fp->f_flag |= FASYNC;
470 else
471 fp->f_flag &= ~FASYNC;
472 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
473 break;
474
475 case FIOSETOWN:
476 tmp = *(int *)data;
477 if (fp->f_type == DTYPE_SOCKET) {
478 ((struct socket *)fp->f_data)->so_pgid = tmp;
479 error = 0;
480 break;
481 }
482 if (tmp <= 0) {
483 tmp = -tmp;
484 } else {
485 struct proc *p1 = pfind(tmp);
486 if (p1 == 0) {
487 error = ESRCH;
488 break;
489 }
490 tmp = p1->p_pgrp->pg_id;
491 }
492 error = (*fp->f_ops->fo_ioctl)
493 (fp, TIOCSPGRP, (caddr_t)&tmp, p);
494 break;
495
496 case FIOGETOWN:
497 if (fp->f_type == DTYPE_SOCKET) {
498 error = 0;
499 *(int *)data = ((struct socket *)fp->f_data)->so_pgid;
500 break;
501 }
502 error = (*fp->f_ops->fo_ioctl)(fp, TIOCGPGRP, data, p);
503 *(int *)data = -*(int *)data;
504 break;
505
506 default:
507 error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
508 /*
509 * Copy any data to user, size was
510 * already set and checked above.
511 */
512 if (error == 0 && (com&IOC_OUT) && size)
513 error = copyout(data, SCARG(uap, data), (u_int)size);
514 break;
515 }
516 if (memp)
517 free(memp, M_IOCTLOPS);
518 return (error);
519 }
520
521 int selwait, nselcoll;
522
523 /*
524 * Select system call.
525 */
526 int
527 sys_select(p, v, retval)
528 register struct proc *p;
529 void *v;
530 register_t *retval;
531 {
532 register struct sys_select_args /* {
533 syscallarg(u_int) nd;
534 syscallarg(fd_set *) in;
535 syscallarg(fd_set *) ou;
536 syscallarg(fd_set *) ex;
537 syscallarg(struct timeval *) tv;
538 } */ *uap = v;
539 caddr_t bits;
540 char smallbits[howmany(FD_SETSIZE, NFDBITS) * sizeof(fd_mask) * 6];
541 struct timeval atv;
542 int s, ncoll, error = 0, timo;
543 size_t ni;
544
545 if (SCARG(uap, nd) > p->p_fd->fd_nfiles) {
546 /* forgiving; slightly wrong */
547 SCARG(uap, nd) = p->p_fd->fd_nfiles;
548 }
549 ni = howmany(SCARG(uap, nd), NFDBITS) * sizeof(fd_mask);
550 if (ni * 6 > sizeof(smallbits))
551 bits = malloc(ni * 6, M_TEMP, M_WAITOK);
552 else
553 bits = smallbits;
554
555 #define getbits(name, x) \
556 if (SCARG(uap, name)) { \
557 error = copyin((caddr_t)SCARG(uap, name), bits + ni * x, ni); \
558 if (error) \
559 goto done; \
560 } else \
561 bzero(bits + ni * x, ni);
562 getbits(in, 0);
563 getbits(ou, 1);
564 getbits(ex, 2);
565 #undef getbits
566
567 if (SCARG(uap, tv)) {
568 error = copyin((caddr_t)SCARG(uap, tv), (caddr_t)&atv,
569 sizeof (atv));
570 if (error)
571 goto done;
572 if (itimerfix(&atv)) {
573 error = EINVAL;
574 goto done;
575 }
576 s = splclock();
577 timeradd(&atv, &time, &atv);
578 timo = hzto(&atv);
579 /*
580 * Avoid inadvertently sleeping forever.
581 */
582 if (timo == 0)
583 timo = 1;
584 splx(s);
585 } else
586 timo = 0;
587 retry:
588 ncoll = nselcoll;
589 p->p_flag |= P_SELECT;
590 error = selscan(p, (fd_mask *)(bits + ni * 0),
591 (fd_mask *)(bits + ni * 3), SCARG(uap, nd), retval);
592 if (error || *retval)
593 goto done;
594 s = splhigh();
595 if (timo && timercmp(&time, &atv, >=)) {
596 splx(s);
597 goto done;
598 }
599 if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
600 splx(s);
601 goto retry;
602 }
603 p->p_flag &= ~P_SELECT;
604 error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
605 splx(s);
606 if (error == 0)
607 goto retry;
608 done:
609 p->p_flag &= ~P_SELECT;
610 /* select is not restarted after signals... */
611 if (error == ERESTART)
612 error = EINTR;
613 if (error == EWOULDBLOCK)
614 error = 0;
615 if (error == 0) {
616 #define putbits(name, x) \
617 if (SCARG(uap, name)) { \
618 error = copyout(bits + ni * x, (caddr_t)SCARG(uap, name), ni); \
619 if (error) \
620 goto out; \
621 }
622 putbits(in, 3);
623 putbits(ou, 4);
624 putbits(ex, 5);
625 #undef putbits
626 }
627 out:
628 if (ni * 6 > sizeof(smallbits))
629 free(bits, M_TEMP);
630 return (error);
631 }
632
633 int
634 selscan(p, ibitp, obitp, nfd, retval)
635 struct proc *p;
636 fd_mask *ibitp, *obitp;
637 int nfd;
638 register_t *retval;
639 {
640 register struct filedesc *fdp = p->p_fd;
641 register int msk, i, j, fd;
642 register fd_mask ibits, obits;
643 struct file *fp;
644 int n = 0;
645 static int flag[3] = { FREAD, FWRITE, 0 };
646
647 for (msk = 0; msk < 3; msk++) {
648 for (i = 0; i < nfd; i += NFDBITS) {
649 ibits = *ibitp++;
650 obits = 0;
651 while ((j = ffs(ibits)) && (fd = i + --j) < nfd) {
652 ibits &= ~(1 << j);
653 fp = fdp->fd_ofiles[fd];
654 if (fp == NULL)
655 return (EBADF);
656 if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) {
657 obits |= (1 << j);
658 n++;
659 }
660 }
661 *obitp++ = obits;
662 }
663 }
664 *retval = n;
665 return (0);
666 }
667
668 /*ARGSUSED*/
669 int
670 seltrue(dev, flag, p)
671 dev_t dev;
672 int flag;
673 struct proc *p;
674 {
675
676 return (1);
677 }
678
679 /*
680 * Record a select request.
681 */
682 void
683 selrecord(selector, sip)
684 struct proc *selector;
685 struct selinfo *sip;
686 {
687 struct proc *p;
688 pid_t mypid;
689
690 mypid = selector->p_pid;
691 if (sip->si_pid == mypid)
692 return;
693 if (sip->si_pid && (p = pfind(sip->si_pid)) &&
694 p->p_wchan == (caddr_t)&selwait)
695 sip->si_flags |= SI_COLL;
696 else
697 sip->si_pid = mypid;
698 }
699
700 /*
701 * Do a wakeup when a selectable event occurs.
702 */
703 void
704 selwakeup(sip)
705 register struct selinfo *sip;
706 {
707 register struct proc *p;
708 int s;
709
710 if (sip->si_pid == 0)
711 return;
712 if (sip->si_flags & SI_COLL) {
713 nselcoll++;
714 sip->si_flags &= ~SI_COLL;
715 wakeup((caddr_t)&selwait);
716 }
717 p = pfind(sip->si_pid);
718 sip->si_pid = 0;
719 if (p != NULL) {
720 s = splhigh();
721 if (p->p_wchan == (caddr_t)&selwait) {
722 if (p->p_stat == SSLEEP)
723 setrunnable(p);
724 else
725 unsleep(p);
726 } else if (p->p_flag & P_SELECT)
727 p->p_flag &= ~P_SELECT;
728 splx(s);
729 }
730 }
731