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$ 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 /* 531 * The magic 2048 here is chosen to be just enough for FD_SETSIZE 532 * infds with the new FD_SETSIZE of 1024, and more than enough for 533 * FD_SETSIZE infds, outfds and exceptfds with the old FD_SETSIZE 534 * of 256. 535 */ 536 fd_mask s_selbits[howmany(2048, NFDBITS)]; 537 fd_mask *ibits[3], *obits[3], *selbits, *sbp; 538 struct timeval atv; 539 int s, ncoll, error, timo; 540 u_int nbufbytes, ncpbytes, nfdbits; 541 542 if (uap->nd < 0) 543 return (EINVAL); 544 if (uap->nd > p->p_fd->fd_nfiles) 545 uap->nd = p->p_fd->fd_nfiles; /* forgiving; slightly wrong */ 546 547 /* 548 * Allocate just enough bits for the non-null fd_sets. Use the 549 * preallocated auto buffer if possible. 550 */ 551 nfdbits = roundup(uap->nd, NFDBITS); 552 ncpbytes = nfdbits / NBBY; 553 nbufbytes = 0; 554 if (uap->in != NULL) 555 nbufbytes += 2 * ncpbytes; 556 if (uap->ou != NULL) 557 nbufbytes += 2 * ncpbytes; 558 if (uap->ex != NULL) 559 nbufbytes += 2 * ncpbytes; 560 if (nbufbytes <= sizeof s_selbits) 561 selbits = &s_selbits[0]; 562 else 563 selbits = malloc(nbufbytes, M_SELECT, M_WAITOK); 564 565 /* 566 * Assign pointers into the bit buffers and fetch the input bits. 567 * Put the output buffers together so that they can be bzeroed 568 * together. 569 */ 570 sbp = selbits; 571 #define getbits(name, x) \ 572 do { \ 573 if (uap->name == NULL) \ 574 ibits[x] = NULL; \ 575 else { \ 576 ibits[x] = sbp + nbufbytes / 2 / sizeof *sbp; \ 577 obits[x] = sbp; \ 578 sbp += ncpbytes / sizeof *sbp; \ 579 error = copyin(uap->name, ibits[x], ncpbytes); \ 580 if (error != 0) \ 581 goto done; \ 582 } \ 583 } while (0) 584 getbits(in, 0); 585 getbits(ou, 1); 586 getbits(ex, 2); 587 #undef getbits 588 if (nbufbytes != 0) 589 bzero(selbits, nbufbytes / 2); 590 591 if (uap->tv) { 592 error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 593 sizeof (atv)); 594 if (error) 595 goto done; 596 if (itimerfix(&atv)) { 597 error = EINVAL; 598 goto done; 599 } 600 s = splclock(); 601 timevaladd(&atv, (struct timeval *)&time); 602 timo = hzto(&atv); 603 /* 604 * Avoid inadvertently sleeping forever. 605 */ 606 if (timo == 0) 607 timo = 1; 608 splx(s); 609 } else 610 timo = 0; 611 retry: 612 ncoll = nselcoll; 613 p->p_flag |= P_SELECT; 614 error = selscan(p, ibits, obits, uap->nd, retval); 615 if (error || *retval) 616 goto done; 617 s = splhigh(); 618 /* this should be timercmp(&time, &atv, >=) */ 619 if (uap->tv && (time.tv_sec > atv.tv_sec || 620 (time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec))) { 621 splx(s); 622 goto done; 623 } 624 if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) { 625 splx(s); 626 goto retry; 627 } 628 p->p_flag &= ~P_SELECT; 629 error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); 630 splx(s); 631 if (error == 0) 632 goto retry; 633 done: 634 p->p_flag &= ~P_SELECT; 635 /* select is not restarted after signals... */ 636 if (error == ERESTART) 637 error = EINTR; 638 if (error == EWOULDBLOCK) 639 error = 0; 640 #define putbits(name, x) \ 641 if (uap->name && (error2 = copyout(obits[x], uap->name, ncpbytes))) \ 642 error = error2; 643 if (error == 0) { 644 int error2; 645 646 putbits(in, 0); 647 putbits(ou, 1); 648 putbits(ex, 2); 649 #undef putbits 650 } 651 if (selbits != &s_selbits[0]) 652 free(selbits, M_SELECT); 653 return (error); 654 } 655 656 static int 657 selscan(p, ibits, obits, nfd, retval) 658 struct proc *p; 659 fd_mask **ibits, **obits; 660 int nfd, *retval; 661 { 662 register struct filedesc *fdp = p->p_fd; 663 register int msk, i, j, fd; 664 register fd_mask bits; 665 struct file *fp; 666 int n = 0; 667 static int flag[3] = { FREAD, FWRITE, 0 }; 668 669 for (msk = 0; msk < 3; msk++) { 670 if (ibits[msk] == NULL) 671 continue; 672 for (i = 0; i < nfd; i += NFDBITS) { 673 bits = ibits[msk][i/NFDBITS]; 674 while ((j = ffs(bits)) && (fd = i + --j) < nfd) { 675 bits &= ~(1 << j); 676 fp = fdp->fd_ofiles[fd]; 677 if (fp == NULL) 678 return (EBADF); 679 if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) { 680 obits[msk][(fd)/NFDBITS] |= 681 (1 << ((fd) % NFDBITS)); 682 n++; 683 } 684 } 685 } 686 } 687 *retval = n; 688 return (0); 689 } 690 691 /*ARGSUSED*/ 692 int 693 seltrue(dev, flag, p) 694 dev_t dev; 695 int flag; 696 struct proc *p; 697 { 698 699 return (1); 700 } 701 702 /* 703 * Record a select request. 704 */ 705 void 706 selrecord(selector, sip) 707 struct proc *selector; 708 struct selinfo *sip; 709 { 710 struct proc *p; 711 pid_t mypid; 712 713 mypid = selector->p_pid; 714 if (sip->si_pid == mypid) 715 return; 716 if (sip->si_pid && (p = pfind(sip->si_pid)) && 717 p->p_wchan == (caddr_t)&selwait) 718 sip->si_flags |= SI_COLL; 719 else 720 sip->si_pid = mypid; 721 } 722 723 /* 724 * Do a wakeup when a selectable event occurs. 725 */ 726 void 727 selwakeup(sip) 728 register struct selinfo *sip; 729 { 730 register struct proc *p; 731 int s; 732 733 if (sip->si_pid == 0) 734 return; 735 if (sip->si_flags & SI_COLL) { 736 nselcoll++; 737 sip->si_flags &= ~SI_COLL; 738 wakeup((caddr_t)&selwait); 739 } 740 p = pfind(sip->si_pid); 741 sip->si_pid = 0; 742 if (p != NULL) { 743 s = splhigh(); 744 if (p->p_wchan == (caddr_t)&selwait) { 745 if (p->p_stat == SSLEEP) 746 setrunnable(p); 747 else 748 unsleep(p); 749 } else if (p->p_flag & P_SELECT) 750 p->p_flag &= ~P_SELECT; 751 splx(s); 752 } 753 } 754