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