|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986, 1989 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * 1. Redistributions of source code must retain the above copyright ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. Neither the name of the University nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: * ! 33: * @(#)sys_generic.c 7.30 (Berkeley) 5/30/91 ! 34: */ ! 35: ! 36: #include "param.h" ! 37: #include "systm.h" ! 38: #include "filedesc.h" ! 39: #include "ioctl.h" ! 40: #include "file.h" ! 41: #include "socketvar.h" ! 42: #include "proc.h" ! 43: #include "uio.h" ! 44: #include "kernel.h" ! 45: #include "stat.h" ! 46: #include "malloc.h" ! 47: #ifdef KTRACE ! 48: #include "ktrace.h" ! 49: #endif ! 50: ! 51: /* ! 52: * Read system call. ! 53: */ ! 54: /* ARGSUSED */ ! 55: read(p, uap, retval) ! 56: struct proc *p; ! 57: register struct args { ! 58: int fdes; ! 59: char *cbuf; ! 60: unsigned count; ! 61: } *uap; ! 62: int *retval; ! 63: { ! 64: register struct file *fp; ! 65: register struct filedesc *fdp = p->p_fd; ! 66: struct uio auio; ! 67: struct iovec aiov; ! 68: long cnt, error = 0; ! 69: #ifdef KTRACE ! 70: struct iovec ktriov; ! 71: #endif ! 72: ! 73: if (((unsigned)uap->fdes) >= fdp->fd_nfiles || ! 74: (fp = fdp->fd_ofiles[uap->fdes]) == NULL || ! 75: (fp->f_flag & FREAD) == 0) ! 76: return (EBADF); ! 77: aiov.iov_base = (caddr_t)uap->cbuf; ! 78: aiov.iov_len = uap->count; ! 79: auio.uio_iov = &aiov; ! 80: auio.uio_iovcnt = 1; ! 81: auio.uio_resid = uap->count; ! 82: auio.uio_rw = UIO_READ; ! 83: auio.uio_segflg = UIO_USERSPACE; ! 84: auio.uio_procp = p; ! 85: #ifdef KTRACE ! 86: /* ! 87: * if tracing, save a copy of iovec ! 88: */ ! 89: if (KTRPOINT(p, KTR_GENIO)) ! 90: ktriov = aiov; ! 91: #endif ! 92: cnt = uap->count; ! 93: if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) ! 94: if (auio.uio_resid != cnt && (error == ERESTART || ! 95: error == EINTR || error == EWOULDBLOCK)) ! 96: error = 0; ! 97: cnt -= auio.uio_resid; ! 98: #ifdef KTRACE ! 99: if (KTRPOINT(p, KTR_GENIO) && error == 0) ! 100: ktrgenio(p->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt, error); ! 101: #endif ! 102: *retval = cnt; ! 103: return (error); ! 104: } ! 105: ! 106: /* ! 107: * Scatter read system call. ! 108: */ ! 109: /* ARGSUSED */ ! 110: readv(p, uap, retval) ! 111: struct proc *p; ! 112: register struct args { ! 113: int fdes; ! 114: struct iovec *iovp; ! 115: unsigned iovcnt; ! 116: } *uap; ! 117: int *retval; ! 118: { ! 119: register struct file *fp; ! 120: register struct filedesc *fdp = p->p_fd; ! 121: struct uio auio; ! 122: register struct iovec *iov; ! 123: struct iovec *saveiov; ! 124: struct iovec aiov[UIO_SMALLIOV]; ! 125: long i, cnt, error = 0; ! 126: unsigned iovlen; ! 127: #ifdef KTRACE ! 128: struct iovec *ktriov = NULL; ! 129: #endif ! 130: ! 131: if (((unsigned)uap->fdes) >= fdp->fd_nfiles || ! 132: (fp = fdp->fd_ofiles[uap->fdes]) == NULL || ! 133: (fp->f_flag & FREAD) == 0) ! 134: return (EBADF); ! 135: /* note: can't use iovlen until iovcnt is validated */ ! 136: iovlen = uap->iovcnt * sizeof (struct iovec); ! 137: if (uap->iovcnt > UIO_SMALLIOV) { ! 138: if (uap->iovcnt > UIO_MAXIOV) ! 139: return (EINVAL); ! 140: MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); ! 141: saveiov = iov; ! 142: } else ! 143: iov = aiov; ! 144: auio.uio_iov = iov; ! 145: auio.uio_iovcnt = uap->iovcnt; ! 146: auio.uio_rw = UIO_READ; ! 147: auio.uio_segflg = UIO_USERSPACE; ! 148: auio.uio_procp = p; ! 149: if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)) ! 150: goto done; ! 151: auio.uio_resid = 0; ! 152: for (i = 0; i < uap->iovcnt; i++) { ! 153: if (iov->iov_len < 0) { ! 154: error = EINVAL; ! 155: goto done; ! 156: } ! 157: auio.uio_resid += iov->iov_len; ! 158: if (auio.uio_resid < 0) { ! 159: error = EINVAL; ! 160: goto done; ! 161: } ! 162: iov++; ! 163: } ! 164: #ifdef KTRACE ! 165: /* ! 166: * if tracing, save a copy of iovec ! 167: */ ! 168: if (KTRPOINT(p, KTR_GENIO)) { ! 169: MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); ! 170: bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); ! 171: } ! 172: #endif ! 173: cnt = auio.uio_resid; ! 174: if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) ! 175: if (auio.uio_resid != cnt && (error == ERESTART || ! 176: error == EINTR || error == EWOULDBLOCK)) ! 177: error = 0; ! 178: cnt -= auio.uio_resid; ! 179: #ifdef KTRACE ! 180: if (ktriov != NULL) { ! 181: if (error == 0) ! 182: ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov, ! 183: cnt, error); ! 184: FREE(ktriov, M_TEMP); ! 185: } ! 186: #endif ! 187: *retval = cnt; ! 188: done: ! 189: if (uap->iovcnt > UIO_SMALLIOV) ! 190: FREE(saveiov, M_IOV); ! 191: return (error); ! 192: } ! 193: ! 194: /* ! 195: * Write system call ! 196: */ ! 197: write(p, uap, retval) ! 198: struct proc *p; ! 199: register struct args { ! 200: int fdes; ! 201: char *cbuf; ! 202: unsigned count; ! 203: } *uap; ! 204: int *retval; ! 205: { ! 206: register struct file *fp; ! 207: register struct filedesc *fdp = p->p_fd; ! 208: struct uio auio; ! 209: struct iovec aiov; ! 210: long cnt, error = 0; ! 211: #ifdef KTRACE ! 212: struct iovec ktriov; ! 213: #endif ! 214: ! 215: if (((unsigned)uap->fdes) >= fdp->fd_nfiles || ! 216: (fp = fdp->fd_ofiles[uap->fdes]) == NULL || ! 217: (fp->f_flag & FWRITE) == 0) ! 218: return (EBADF); ! 219: aiov.iov_base = (caddr_t)uap->cbuf; ! 220: aiov.iov_len = uap->count; ! 221: auio.uio_iov = &aiov; ! 222: auio.uio_iovcnt = 1; ! 223: auio.uio_resid = uap->count; ! 224: auio.uio_rw = UIO_WRITE; ! 225: auio.uio_segflg = UIO_USERSPACE; ! 226: auio.uio_procp = p; ! 227: #ifdef KTRACE ! 228: /* ! 229: * if tracing, save a copy of iovec ! 230: */ ! 231: if (KTRPOINT(p, KTR_GENIO)) ! 232: ktriov = aiov; ! 233: #endif ! 234: cnt = uap->count; ! 235: if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { ! 236: if (auio.uio_resid != cnt && (error == ERESTART || ! 237: error == EINTR || error == EWOULDBLOCK)) ! 238: error = 0; ! 239: if (error == EPIPE) ! 240: psignal(p, SIGPIPE); ! 241: } ! 242: cnt -= auio.uio_resid; ! 243: #ifdef KTRACE ! 244: if (KTRPOINT(p, KTR_GENIO) && error == 0) ! 245: ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE, ! 246: &ktriov, cnt, error); ! 247: #endif ! 248: *retval = cnt; ! 249: return (error); ! 250: } ! 251: ! 252: /* ! 253: * Gather write system call ! 254: */ ! 255: writev(p, uap, retval) ! 256: struct proc *p; ! 257: register struct args { ! 258: int fdes; ! 259: struct iovec *iovp; ! 260: unsigned iovcnt; ! 261: } *uap; ! 262: int *retval; ! 263: { ! 264: register struct file *fp; ! 265: register struct filedesc *fdp = p->p_fd; ! 266: struct uio auio; ! 267: register struct iovec *iov; ! 268: struct iovec *saveiov; ! 269: struct iovec aiov[UIO_SMALLIOV]; ! 270: long i, cnt, error = 0; ! 271: unsigned iovlen; ! 272: #ifdef KTRACE ! 273: struct iovec *ktriov = NULL; ! 274: #endif ! 275: ! 276: if (((unsigned)uap->fdes) >= fdp->fd_nfiles || ! 277: (fp = fdp->fd_ofiles[uap->fdes]) == NULL || ! 278: (fp->f_flag & FWRITE) == 0) ! 279: return (EBADF); ! 280: /* note: can't use iovlen until iovcnt is validated */ ! 281: iovlen = uap->iovcnt * sizeof (struct iovec); ! 282: if (uap->iovcnt > UIO_SMALLIOV) { ! 283: if (uap->iovcnt > UIO_MAXIOV) ! 284: return (EINVAL); ! 285: MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); ! 286: saveiov = iov; ! 287: } else ! 288: iov = aiov; ! 289: auio.uio_iov = iov; ! 290: auio.uio_iovcnt = uap->iovcnt; ! 291: auio.uio_rw = UIO_WRITE; ! 292: auio.uio_segflg = UIO_USERSPACE; ! 293: auio.uio_procp = p; ! 294: if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)) ! 295: goto done; ! 296: auio.uio_resid = 0; ! 297: for (i = 0; i < uap->iovcnt; i++) { ! 298: if (iov->iov_len < 0) { ! 299: error = EINVAL; ! 300: goto done; ! 301: } ! 302: auio.uio_resid += iov->iov_len; ! 303: if (auio.uio_resid < 0) { ! 304: error = EINVAL; ! 305: goto done; ! 306: } ! 307: iov++; ! 308: } ! 309: #ifdef KTRACE ! 310: /* ! 311: * if tracing, save a copy of iovec ! 312: */ ! 313: if (KTRPOINT(p, KTR_GENIO)) { ! 314: MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); ! 315: bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); ! 316: } ! 317: #endif ! 318: cnt = auio.uio_resid; ! 319: if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { ! 320: if (auio.uio_resid != cnt && (error == ERESTART || ! 321: error == EINTR || error == EWOULDBLOCK)) ! 322: error = 0; ! 323: if (error == EPIPE) ! 324: psignal(p, SIGPIPE); ! 325: } ! 326: cnt -= auio.uio_resid; ! 327: #ifdef KTRACE ! 328: if (ktriov != NULL) { ! 329: if (error == 0) ! 330: ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE, ! 331: ktriov, cnt, error); ! 332: FREE(ktriov, M_TEMP); ! 333: } ! 334: #endif ! 335: *retval = cnt; ! 336: done: ! 337: if (uap->iovcnt > UIO_SMALLIOV) ! 338: FREE(saveiov, M_IOV); ! 339: return (error); ! 340: } ! 341: ! 342: /* ! 343: * Ioctl system call ! 344: */ ! 345: /* ARGSUSED */ ! 346: ioctl(p, uap, retval) ! 347: struct proc *p; ! 348: register struct args { ! 349: int fdes; ! 350: int cmd; ! 351: caddr_t cmarg; ! 352: } *uap; ! 353: int *retval; ! 354: { ! 355: register struct file *fp; ! 356: register struct filedesc *fdp = p->p_fd; ! 357: register int com, error; ! 358: register u_int size; ! 359: caddr_t memp = 0; ! 360: #define STK_PARAMS 128 ! 361: char stkbuf[STK_PARAMS]; ! 362: caddr_t data = stkbuf; ! 363: int tmp; ! 364: ! 365: if ((unsigned)uap->fdes >= fdp->fd_nfiles || ! 366: (fp = fdp->fd_ofiles[uap->fdes]) == NULL) ! 367: return (EBADF); ! 368: if ((fp->f_flag & (FREAD|FWRITE)) == 0) ! 369: return (EBADF); ! 370: com = uap->cmd; ! 371: ! 372: if (com == FIOCLEX) { ! 373: fdp->fd_ofileflags[uap->fdes] |= UF_EXCLOSE; ! 374: return (0); ! 375: } ! 376: if (com == FIONCLEX) { ! 377: fdp->fd_ofileflags[uap->fdes] &= ~UF_EXCLOSE; ! 378: return (0); ! 379: } ! 380: ! 381: /* ! 382: * Interpret high order word to find ! 383: * amount of data to be copied to/from the ! 384: * user's address space. ! 385: */ ! 386: size = IOCPARM_LEN(com); ! 387: if (size > IOCPARM_MAX) ! 388: return (ENOTTY); ! 389: if (size > sizeof (stkbuf)) { ! 390: memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); ! 391: data = memp; ! 392: } ! 393: if (com&IOC_IN) { ! 394: if (size) { ! 395: error = copyin(uap->cmarg, data, (u_int)size); ! 396: if (error) { ! 397: if (memp) ! 398: free(memp, M_IOCTLOPS); ! 399: return (error); ! 400: } ! 401: } else ! 402: *(caddr_t *)data = uap->cmarg; ! 403: } else if ((com&IOC_OUT) && size) ! 404: /* ! 405: * Zero the buffer so the user always ! 406: * gets back something deterministic. ! 407: */ ! 408: bzero(data, size); ! 409: else if (com&IOC_VOID) ! 410: *(caddr_t *)data = uap->cmarg; ! 411: ! 412: switch (com) { ! 413: ! 414: case FIONBIO: ! 415: if (tmp = *(int *)data) ! 416: fp->f_flag |= FNONBLOCK; ! 417: else ! 418: fp->f_flag &= ~FNONBLOCK; ! 419: error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); ! 420: break; ! 421: ! 422: case FIOASYNC: ! 423: if (tmp = *(int *)data) ! 424: fp->f_flag |= FASYNC; ! 425: else ! 426: fp->f_flag &= ~FASYNC; ! 427: error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p); ! 428: break; ! 429: ! 430: case FIOSETOWN: ! 431: tmp = *(int *)data; ! 432: if (fp->f_type == DTYPE_SOCKET) { ! 433: ((struct socket *)fp->f_data)->so_pgid = tmp; ! 434: error = 0; ! 435: break; ! 436: } ! 437: if (tmp <= 0) { ! 438: tmp = -tmp; ! 439: } else { ! 440: struct proc *p1 = pfind(tmp); ! 441: if (p1 == 0) { ! 442: error = ESRCH; ! 443: break; ! 444: } ! 445: tmp = p1->p_pgrp->pg_id; ! 446: } ! 447: error = (*fp->f_ops->fo_ioctl) ! 448: (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p); ! 449: break; ! 450: ! 451: case FIOGETOWN: ! 452: if (fp->f_type == DTYPE_SOCKET) { ! 453: error = 0; ! 454: *(int *)data = ((struct socket *)fp->f_data)->so_pgid; ! 455: break; ! 456: } ! 457: error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p); ! 458: *(int *)data = -*(int *)data; ! 459: break; ! 460: ! 461: default: ! 462: error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); ! 463: /* ! 464: * Copy any data to user, size was ! 465: * already set and checked above. ! 466: */ ! 467: if (error == 0 && (com&IOC_OUT) && size) ! 468: error = copyout(data, uap->cmarg, (u_int)size); ! 469: break; ! 470: } ! 471: if (memp) ! 472: free(memp, M_IOCTLOPS); ! 473: return (error); ! 474: } ! 475: ! 476: int selwait, nselcoll; ! 477: ! 478: /* ! 479: * Select system call. ! 480: */ ! 481: select(p, uap, retval) ! 482: register struct proc *p; ! 483: register struct args { ! 484: int nd; ! 485: fd_set *in, *ou, *ex; ! 486: struct timeval *tv; ! 487: } *uap; ! 488: int *retval; ! 489: { ! 490: fd_set ibits[3], obits[3]; ! 491: struct timeval atv; ! 492: int s, ncoll, ni, error = 0, timo; ! 493: ! 494: bzero((caddr_t)ibits, sizeof(ibits)); ! 495: bzero((caddr_t)obits, sizeof(obits)); ! 496: if (uap->nd > p->p_fd->fd_nfiles) ! 497: uap->nd = p->p_fd->fd_nfiles; /* forgiving; slightly wrong */ ! 498: ni = howmany(uap->nd, NFDBITS); ! 499: ! 500: #define getbits(name, x) \ ! 501: if (uap->name) { \ ! 502: error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ ! 503: (unsigned)(ni * sizeof(fd_mask))); \ ! 504: if (error) \ ! 505: goto done; \ ! 506: } ! 507: getbits(in, 0); ! 508: getbits(ou, 1); ! 509: getbits(ex, 2); ! 510: #undef getbits ! 511: ! 512: if (uap->tv) { ! 513: error = copyin((caddr_t)uap->tv, (caddr_t)&atv, ! 514: sizeof (atv)); ! 515: if (error) ! 516: goto done; ! 517: if (itimerfix(&atv)) { ! 518: error = EINVAL; ! 519: goto done; ! 520: } ! 521: s = splhigh(); timevaladd(&atv, &time); splx(s); ! 522: timo = hzto(&atv); ! 523: } else ! 524: timo = 0; ! 525: retry: ! 526: ncoll = nselcoll; ! 527: p->p_flag |= SSEL; ! 528: error = selscan(p, ibits, obits, uap->nd, retval); ! 529: if (error || *retval) ! 530: goto done; ! 531: s = splhigh(); ! 532: /* this should be timercmp(&time, &atv, >=) */ ! 533: if (uap->tv && (time.tv_sec > atv.tv_sec || ! 534: time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { ! 535: splx(s); ! 536: goto done; ! 537: } ! 538: if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) { ! 539: splx(s); ! 540: goto retry; ! 541: } ! 542: p->p_flag &= ~SSEL; ! 543: error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); ! 544: splx(s); ! 545: if (error == 0) ! 546: goto retry; ! 547: done: ! 548: p->p_flag &= ~SSEL; ! 549: /* select is not restarted after signals... */ ! 550: if (error == ERESTART) ! 551: error = EINTR; ! 552: if (error == EWOULDBLOCK) ! 553: error = 0; ! 554: #define putbits(name, x) \ ! 555: if (uap->name) { \ ! 556: int error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ ! 557: (unsigned)(ni * sizeof(fd_mask))); \ ! 558: if (error2) \ ! 559: error = error2; \ ! 560: } ! 561: if (error == 0) { ! 562: putbits(in, 0); ! 563: putbits(ou, 1); ! 564: putbits(ex, 2); ! 565: #undef putbits ! 566: } ! 567: return (error); ! 568: } ! 569: ! 570: selscan(p, ibits, obits, nfd, retval) ! 571: struct proc *p; ! 572: fd_set *ibits, *obits; ! 573: int nfd, *retval; ! 574: { ! 575: register struct filedesc *fdp = p->p_fd; ! 576: register int which, i, j; ! 577: register fd_mask bits; ! 578: int flag; ! 579: struct file *fp; ! 580: int error = 0, n = 0; ! 581: ! 582: for (which = 0; which < 3; which++) { ! 583: switch (which) { ! 584: ! 585: case 0: ! 586: flag = FREAD; break; ! 587: ! 588: case 1: ! 589: flag = FWRITE; break; ! 590: ! 591: case 2: ! 592: flag = 0; break; ! 593: } ! 594: for (i = 0; i < nfd; i += NFDBITS) { ! 595: bits = ibits[which].fds_bits[i/NFDBITS]; ! 596: while ((j = ffs(bits)) && i + --j < nfd) { ! 597: bits &= ~(1 << j); ! 598: fp = fdp->fd_ofiles[i + j]; ! 599: if (fp == NULL) { ! 600: error = EBADF; ! 601: break; ! 602: } ! 603: if ((*fp->f_ops->fo_select)(fp, flag, p)) { ! 604: FD_SET(i + j, &obits[which]); ! 605: n++; ! 606: } ! 607: } ! 608: } ! 609: } ! 610: *retval = n; ! 611: return (error); ! 612: } ! 613: ! 614: /*ARGSUSED*/ ! 615: #ifdef __STDC__ ! 616: seltrue(dev_t dev, int which, struct proc *p) ! 617: #else ! 618: seltrue(dev, flag, p) ! 619: dev_t dev; ! 620: int flag; ! 621: struct proc *p; ! 622: #endif ! 623: { ! 624: ! 625: return (1); ! 626: } ! 627: ! 628: selwakeup(p, coll) ! 629: register struct proc *p; ! 630: int coll; ! 631: { ! 632: ! 633: if (coll) { ! 634: nselcoll++; ! 635: wakeup((caddr_t)&selwait); ! 636: } ! 637: if (p) { ! 638: int s = splhigh(); ! 639: if (p->p_wchan == (caddr_t)&selwait) { ! 640: if (p->p_stat == SSLEEP) ! 641: setrun(p); ! 642: else ! 643: unsleep(p); ! 644: } else if (p->p_flag & SSEL) ! 645: p->p_flag &= ~SSEL; ! 646: splx(s); ! 647: } ! 648: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.