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