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