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