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