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