123384Smckusick /* 237728Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337728Smckusick * All rights reserved. 423384Smckusick * 537728Smckusick * Redistribution and use in source and binary forms are permitted 637728Smckusick * provided that the above copyright notice and this paragraph are 737728Smckusick * duplicated in all such forms and that any documentation, 837728Smckusick * advertising materials, and other materials related to such 937728Smckusick * distribution and use acknowledge that the software was developed 1037728Smckusick * by the University of California, Berkeley. The name of the 1137728Smckusick * University may not be used to endorse or promote products derived 1237728Smckusick * from this software without specific prior written permission. 1337728Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1437728Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1537728Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1637728Smckusick * 17*41990Smckusick * @(#)sys_generic.c 7.16 (Berkeley) 05/15/90 1823384Smckusick */ 197423Sroot 2017094Sbloom #include "param.h" 2117094Sbloom #include "systm.h" 2237728Smckusick #include "syscontext.h" 2317094Sbloom #include "ioctl.h" 2417094Sbloom #include "file.h" 2517094Sbloom #include "proc.h" 2617094Sbloom #include "uio.h" 2717094Sbloom #include "kernel.h" 2817094Sbloom #include "stat.h" 2931653Smckusick #include "malloc.h" 3037127Skarels #ifdef KTRACE 3137127Skarels #include "ktrace.h" 3237127Skarels #endif 337423Sroot 347423Sroot /* 357423Sroot * Read system call. 367423Sroot */ 377423Sroot read() 387423Sroot { 397423Sroot register struct a { 407423Sroot int fdes; 417423Sroot char *cbuf; 427423Sroot unsigned count; 437820Sroot } *uap = (struct a *)u.u_ap; 4437728Smckusick register struct file *fp; 457746Sroot struct uio auio; 467746Sroot struct iovec aiov; 4737728Smckusick long cnt, error = 0; 4837728Smckusick #ifdef KTRACE 4937728Smckusick struct iovec ktriov; 5037728Smckusick #endif 517423Sroot 5237728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 5337728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 5437728Smckusick (fp->f_flag & FREAD) == 0) 5537728Smckusick RETURN (EBADF); 567820Sroot aiov.iov_base = (caddr_t)uap->cbuf; 577820Sroot aiov.iov_len = uap->count; 587820Sroot auio.uio_iov = &aiov; 597820Sroot auio.uio_iovcnt = 1; 6037728Smckusick auio.uio_resid = uap->count; 6137728Smckusick auio.uio_rw = UIO_READ; 6237728Smckusick auio.uio_segflg = UIO_USERSPACE; 6337728Smckusick #ifdef KTRACE 6437728Smckusick /* 6537728Smckusick * if tracing, save a copy of iovec 6637728Smckusick */ 6737728Smckusick if (KTRPOINT(u.u_procp, KTR_GENIO)) 6837728Smckusick ktriov = aiov; 6937728Smckusick #endif 7037728Smckusick cnt = uap->count; 7140703Skarels if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) 7240703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 7340703Skarels error == EINTR || error == EWOULDBLOCK)) 7440703Skarels error = 0; 7537728Smckusick cnt -= auio.uio_resid; 7637728Smckusick #ifdef KTRACE 7741178Smarc if (KTRPOINT(u.u_procp, KTR_GENIO) && error == 0) 7838591Smarc ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt); 7937728Smckusick #endif 8037728Smckusick u.u_r.r_val1 = cnt; 8137728Smckusick RETURN (error); 827820Sroot } 837820Sroot 847820Sroot readv() 857820Sroot { 867820Sroot register struct a { 877820Sroot int fdes; 887820Sroot struct iovec *iovp; 8926474Skarels unsigned iovcnt; 907820Sroot } *uap = (struct a *)u.u_ap; 9137728Smckusick register struct file *fp; 927820Sroot struct uio auio; 9337728Smckusick register struct iovec *iov; 9437728Smckusick struct iovec aiov[UIO_SMALLIOV]; 9537728Smckusick long i, cnt, error = 0; 9637728Smckusick #ifdef KTRACE 9737728Smckusick struct iovec *ktriov = NULL; 9837728Smckusick #endif 997820Sroot 10037728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 10137728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 10237728Smckusick (fp->f_flag & FREAD) == 0) 10337728Smckusick RETURN (EBADF); 10437127Skarels if (uap->iovcnt > UIO_SMALLIOV) { 10537728Smckusick if (uap->iovcnt > UIO_MAXIOV) 10637728Smckusick RETURN (EINVAL); 10737127Skarels MALLOC(iov, struct iovec *, 10837127Skarels sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK); 10937127Skarels } else 11037127Skarels iov = aiov; 11137127Skarels auio.uio_iov = iov; 1127820Sroot auio.uio_iovcnt = uap->iovcnt; 11337728Smckusick auio.uio_rw = UIO_READ; 11437728Smckusick auio.uio_segflg = UIO_USERSPACE; 11537728Smckusick if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, 11637728Smckusick uap->iovcnt * sizeof (struct iovec))) 11737127Skarels goto done; 11837728Smckusick auio.uio_resid = 0; 11937728Smckusick for (i = 0; i < uap->iovcnt; i++) { 12037728Smckusick if (iov->iov_len < 0) { 12137728Smckusick error = EINVAL; 12237728Smckusick goto done; 12337728Smckusick } 12437728Smckusick auio.uio_resid += iov->iov_len; 12537728Smckusick if (auio.uio_resid < 0) { 12637728Smckusick error = EINVAL; 12737728Smckusick goto done; 12837728Smckusick } 12937728Smckusick iov++; 13037728Smckusick } 13137728Smckusick #ifdef KTRACE 13237728Smckusick /* 13337728Smckusick * if tracing, save a copy of iovec 13437728Smckusick */ 13537728Smckusick if (KTRPOINT(u.u_procp, KTR_GENIO)) { 136*41990Smckusick unsigned iovlen = auio.uio_iovcnt * sizeof (struct iovec); 13737728Smckusick 13837728Smckusick MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 13937728Smckusick bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 14037728Smckusick } 14137728Smckusick #endif 14237728Smckusick cnt = auio.uio_resid; 14340703Skarels if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) 14440703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 14540703Skarels error == EINTR || error == EWOULDBLOCK)) 14640703Skarels error = 0; 14737728Smckusick cnt -= auio.uio_resid; 14837728Smckusick #ifdef KTRACE 14937728Smckusick if (ktriov != NULL) { 15041178Smarc if (error == 0) 15141178Smarc ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_READ, 15241178Smarc ktriov, cnt); 15337728Smckusick FREE(ktriov, M_TEMP); 15437728Smckusick } 15537728Smckusick #endif 15637728Smckusick u.u_r.r_val1 = cnt; 15737127Skarels done: 15837728Smckusick if (uap->iovcnt > UIO_SMALLIOV) 15937127Skarels FREE(iov, M_IOV); 16037728Smckusick RETURN (error); 1617423Sroot } 1627423Sroot 1637423Sroot /* 1647423Sroot * Write system call 1657423Sroot */ 1667423Sroot write() 1677423Sroot { 1687423Sroot register struct a { 1697423Sroot int fdes; 1707423Sroot char *cbuf; 17126474Skarels unsigned count; 1727820Sroot } *uap = (struct a *)u.u_ap; 17337728Smckusick register struct file *fp; 1747820Sroot struct uio auio; 1757820Sroot struct iovec aiov; 17637728Smckusick long cnt, error = 0; 17737728Smckusick #ifdef KTRACE 17837728Smckusick struct iovec ktriov; 17937728Smckusick #endif 1807423Sroot 18137728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 18237728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 18337728Smckusick (fp->f_flag & FWRITE) == 0) 18437728Smckusick RETURN (EBADF); 18537728Smckusick aiov.iov_base = (caddr_t)uap->cbuf; 18637728Smckusick aiov.iov_len = uap->count; 1877820Sroot auio.uio_iov = &aiov; 1887820Sroot auio.uio_iovcnt = 1; 18937728Smckusick auio.uio_resid = uap->count; 19037728Smckusick auio.uio_rw = UIO_WRITE; 19137728Smckusick auio.uio_segflg = UIO_USERSPACE; 19237728Smckusick #ifdef KTRACE 19337728Smckusick /* 19437728Smckusick * if tracing, save a copy of iovec 19537728Smckusick */ 19637728Smckusick if (KTRPOINT(u.u_procp, KTR_GENIO)) 19737728Smckusick ktriov = aiov; 19837728Smckusick #endif 19937728Smckusick cnt = uap->count; 20040703Skarels if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 20140703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 20240703Skarels error == EINTR || error == EWOULDBLOCK)) 20340703Skarels error = 0; 20440703Skarels if (error == EPIPE) 20540703Skarels psignal(u.u_procp, SIGPIPE); 20640703Skarels } 20737728Smckusick cnt -= auio.uio_resid; 20837728Smckusick #ifdef KTRACE 20941178Smarc if (KTRPOINT(u.u_procp, KTR_GENIO) && error == 0) 21037728Smckusick ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_WRITE, 21138591Smarc &ktriov, cnt); 21237728Smckusick #endif 21337728Smckusick u.u_r.r_val1 = cnt; 21437728Smckusick RETURN (error); 2157820Sroot } 2167820Sroot 2177820Sroot writev() 2187820Sroot { 2197820Sroot register struct a { 2207820Sroot int fdes; 2217820Sroot struct iovec *iovp; 22226474Skarels unsigned iovcnt; 2237820Sroot } *uap = (struct a *)u.u_ap; 22437728Smckusick register struct file *fp; 2257820Sroot struct uio auio; 22637728Smckusick register struct iovec *iov; 22737728Smckusick struct iovec aiov[UIO_SMALLIOV]; 22837728Smckusick long i, cnt, error = 0; 22937728Smckusick #ifdef KTRACE 23037728Smckusick struct iovec *ktriov = NULL; 23137728Smckusick #endif 2327820Sroot 23337728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 23437728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 23537728Smckusick (fp->f_flag & FWRITE) == 0) 23637728Smckusick RETURN (EBADF); 23737127Skarels if (uap->iovcnt > UIO_SMALLIOV) { 23837728Smckusick if (uap->iovcnt > UIO_MAXIOV) 23937728Smckusick RETURN (EINVAL); 24037127Skarels MALLOC(iov, struct iovec *, 24137127Skarels sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK); 24237127Skarels } else 24337127Skarels iov = aiov; 24437127Skarels auio.uio_iov = iov; 2457820Sroot auio.uio_iovcnt = uap->iovcnt; 24637728Smckusick auio.uio_rw = UIO_WRITE; 24737728Smckusick auio.uio_segflg = UIO_USERSPACE; 24837728Smckusick if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, 24937728Smckusick uap->iovcnt * sizeof (struct iovec))) 25037127Skarels goto done; 25137728Smckusick auio.uio_resid = 0; 25237728Smckusick for (i = 0; i < uap->iovcnt; i++) { 2537820Sroot if (iov->iov_len < 0) { 25437728Smckusick error = EINVAL; 25537728Smckusick goto done; 2567820Sroot } 25737728Smckusick auio.uio_resid += iov->iov_len; 25837728Smckusick if (auio.uio_resid < 0) { 25937728Smckusick error = EINVAL; 26037728Smckusick goto done; 2617820Sroot } 26213270Ssam iov++; 2637820Sroot } 26437127Skarels #ifdef KTRACE 26537728Smckusick /* 26637728Smckusick * if tracing, save a copy of iovec 26737728Smckusick */ 26837127Skarels if (KTRPOINT(u.u_procp, KTR_GENIO)) { 269*41990Smckusick unsigned iovlen = auio.uio_iovcnt * sizeof (struct iovec); 27037127Skarels 27137127Skarels MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 27237728Smckusick bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 27337127Skarels } 27437127Skarels #endif 27537728Smckusick cnt = auio.uio_resid; 27640703Skarels if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 27740703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 27840703Skarels error == EINTR || error == EWOULDBLOCK)) 27940703Skarels error = 0; 28040703Skarels if (error == EPIPE) 28140703Skarels psignal(u.u_procp, SIGPIPE); 28240703Skarels } 28337728Smckusick cnt -= auio.uio_resid; 28437127Skarels #ifdef KTRACE 28537127Skarels if (ktriov != NULL) { 28641178Smarc if (error == 0) 28741178Smarc ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_WRITE, 28841178Smarc ktriov, cnt); 28937127Skarels FREE(ktriov, M_TEMP); 29037127Skarels } 29137127Skarels #endif 29237728Smckusick u.u_r.r_val1 = cnt; 29337728Smckusick done: 29437728Smckusick if (uap->iovcnt > UIO_SMALLIOV) 29537728Smckusick FREE(iov, M_IOV); 29637728Smckusick RETURN (error); 2977423Sroot } 2987423Sroot 2997423Sroot /* 3007423Sroot * Ioctl system call 3017423Sroot */ 3027423Sroot ioctl() 3037423Sroot { 3047423Sroot register struct file *fp; 3057624Ssam struct a { 3067423Sroot int fdes; 3077423Sroot int cmd; 3087423Sroot caddr_t cmarg; 30937728Smckusick } *uap = (struct a *)u.u_ap; 31040703Skarels register int com, error; 3117820Sroot register u_int size; 31231653Smckusick caddr_t memp = 0; 31330530Skarels #define STK_PARAMS 128 31433480Skarels char stkbuf[STK_PARAMS]; 31533480Skarels caddr_t data = stkbuf; 3167423Sroot 31737728Smckusick if ((unsigned)uap->fdes >= NOFILE || 31837728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) 31937728Smckusick RETURN (EBADF); 32040703Skarels if ((fp->f_flag & (FREAD|FWRITE)) == 0) 32140703Skarels RETURN (EBADF); 3227624Ssam com = uap->cmd; 3237624Ssam 3247624Ssam if (com == FIOCLEX) { 3259592Ssam u.u_pofile[uap->fdes] |= UF_EXCLOSE; 3267423Sroot return; 3277423Sroot } 3287624Ssam if (com == FIONCLEX) { 3299592Ssam u.u_pofile[uap->fdes] &= ~UF_EXCLOSE; 33040703Skarels RETURN (0); 3317423Sroot } 3327624Ssam 3337624Ssam /* 3347624Ssam * Interpret high order word to find 3357624Ssam * amount of data to be copied to/from the 3367624Ssam * user's address space. 3377624Ssam */ 33830530Skarels size = IOCPARM_LEN(com); 33940703Skarels if (size > IOCPARM_MAX) 34040703Skarels RETURN (ENOTTY); 34133480Skarels if (size > sizeof (stkbuf)) { 34237127Skarels memp = (caddr_t)malloc((u_long)IOCPARM_LEN(com), M_IOCTLOPS, 34334473Smckusick M_WAITOK); 34431653Smckusick data = memp; 34530530Skarels } 34610601Ssam if (com&IOC_IN) { 34710601Ssam if (size) { 34840703Skarels error = copyin(uap->cmarg, data, (u_int)size); 34940703Skarels if (error) { 35031653Smckusick if (memp) 35131653Smckusick free(memp, M_IOCTLOPS); 35240703Skarels RETURN (error); 35331653Smckusick } 35410601Ssam } else 35510601Ssam *(caddr_t *)data = uap->cmarg; 35610601Ssam } else if ((com&IOC_OUT) && size) 35710601Ssam /* 35837127Skarels * Zero the buffer so the user always 35937127Skarels * gets back something deterministic. 36010601Ssam */ 36130530Skarels bzero(data, size); 36211284Ssam else if (com&IOC_VOID) 36311284Ssam *(caddr_t *)data = uap->cmarg; 3647423Sroot 36512751Ssam switch (com) { 3667624Ssam 36712751Ssam case FIONBIO: 36840703Skarels error = fset(fp, FNDELAY, *(int *)data); 36930530Skarels break; 37012751Ssam 37112751Ssam case FIOASYNC: 37240703Skarels error = fset(fp, FASYNC, *(int *)data); 37330530Skarels break; 37412751Ssam 37512751Ssam case FIOSETOWN: 37640703Skarels error = fsetown(fp, *(int *)data); 37730530Skarels break; 37812751Ssam 37912751Ssam case FIOGETOWN: 38040703Skarels error = fgetown(fp, (int *)data); 38130530Skarels break; 38230530Skarels default: 38340703Skarels error = (*fp->f_ops->fo_ioctl)(fp, com, data); 38430530Skarels /* 38530530Skarels * Copy any data to user, size was 38630530Skarels * already set and checked above. 38730530Skarels */ 38840703Skarels if (error == 0 && (com&IOC_OUT) && size) 38940703Skarels error = copyout(data, uap->cmarg, (u_int)size); 39030530Skarels break; 3917423Sroot } 39231653Smckusick if (memp) 39331653Smckusick free(memp, M_IOCTLOPS); 39440703Skarels RETURN (error); 3957423Sroot } 3967423Sroot 39712751Ssam int nselcoll; 39817593Skarels 3997423Sroot /* 40012751Ssam * Select system call. 4017423Sroot */ 40212751Ssam select() 40312751Ssam { 40412751Ssam register struct uap { 40512751Ssam int nd; 40623523Skarels fd_set *in, *ou, *ex; 40712751Ssam struct timeval *tv; 40812751Ssam } *uap = (struct uap *)u.u_ap; 40923523Skarels fd_set ibits[3], obits[3]; 41012751Ssam struct timeval atv; 41140703Skarels int s, ncoll, ni, error = 0, timo; 41212751Ssam 41326277Skarels bzero((caddr_t)ibits, sizeof(ibits)); 41426277Skarels bzero((caddr_t)obits, sizeof(obits)); 41512751Ssam if (uap->nd > NOFILE) 41612751Ssam uap->nd = NOFILE; /* forgiving, if slightly wrong */ 41723523Skarels ni = howmany(uap->nd, NFDBITS); 41812751Ssam 41912751Ssam #define getbits(name, x) \ 42012751Ssam if (uap->name) { \ 42140703Skarels error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 42226277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 42340703Skarels if (error) \ 42412751Ssam goto done; \ 42517593Skarels } 42612751Ssam getbits(in, 0); 42712751Ssam getbits(ou, 1); 42812751Ssam getbits(ex, 2); 42912751Ssam #undef getbits 43012751Ssam 43112751Ssam if (uap->tv) { 43240703Skarels error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 43312751Ssam sizeof (atv)); 43440703Skarels if (error) 43512751Ssam goto done; 43612751Ssam if (itimerfix(&atv)) { 43740703Skarels error = EINVAL; 43812751Ssam goto done; 43912751Ssam } 44017934Skarels s = splhigh(); timevaladd(&atv, &time); splx(s); 44140703Skarels timo = hzto(&atv); 44240703Skarels } else 44340703Skarels timo = 0; 44412751Ssam retry: 44512751Ssam ncoll = nselcoll; 44612751Ssam u.u_procp->p_flag |= SSEL; 44740703Skarels u.u_r.r_val1 = selscan(ibits, obits, uap->nd, &error); 44840703Skarels if (error == 0) 44940703Skarels error = u.u_error; /* XXX */ 45040703Skarels if (error || u.u_r.r_val1) 45112751Ssam goto done; 45217934Skarels s = splhigh(); 45312971Ssam /* this should be timercmp(&time, &atv, >=) */ 45412971Ssam if (uap->tv && (time.tv_sec > atv.tv_sec || 45512971Ssam time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 45612751Ssam splx(s); 45712751Ssam goto done; 45812751Ssam } 45912751Ssam if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 46012751Ssam splx(s); 46112751Ssam goto retry; 46212751Ssam } 46312751Ssam u.u_procp->p_flag &= ~SSEL; 46440703Skarels error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); 46512751Ssam splx(s); 46640703Skarels if (error == 0) 46740703Skarels goto retry; 46812751Ssam done: 46933712Skarels u.u_procp->p_flag &= ~SSEL; 47040703Skarels /* select is not restarted after signals... */ 47140703Skarels if (error == ERESTART) 47240703Skarels error = EINTR; 47340703Skarels if (error == EWOULDBLOCK) 47440703Skarels error = 0; 47512751Ssam #define putbits(name, x) \ 47612751Ssam if (uap->name) { \ 47740703Skarels int error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 47826277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 47940703Skarels if (error2) \ 48040703Skarels error = error2; \ 48112751Ssam } 48240703Skarels if (error == 0) { 48321106Skarels putbits(in, 0); 48421106Skarels putbits(ou, 1); 48521106Skarels putbits(ex, 2); 48612751Ssam #undef putbits 48721106Skarels } 48840703Skarels RETURN (error); 48912751Ssam } 49012751Ssam 49140703Skarels selscan(ibits, obits, nfd, errp) 49223523Skarels fd_set *ibits, *obits; 49340703Skarels int nfd, *errp; 49412751Ssam { 49523523Skarels register int which, i, j; 49623523Skarels register fd_mask bits; 49712751Ssam int flag; 49812751Ssam struct file *fp; 49912751Ssam int n = 0; 50012751Ssam 50112751Ssam for (which = 0; which < 3; which++) { 50212751Ssam switch (which) { 50312751Ssam 50412751Ssam case 0: 50512751Ssam flag = FREAD; break; 50612751Ssam 50712751Ssam case 1: 50812751Ssam flag = FWRITE; break; 50912751Ssam 51012751Ssam case 2: 51112751Ssam flag = 0; break; 51212751Ssam } 51323523Skarels for (i = 0; i < nfd; i += NFDBITS) { 51423523Skarels bits = ibits[which].fds_bits[i/NFDBITS]; 51517593Skarels while ((j = ffs(bits)) && i + --j < nfd) { 51617593Skarels bits &= ~(1 << j); 51717593Skarels fp = u.u_ofile[i + j]; 51817593Skarels if (fp == NULL) { 51940703Skarels *errp = EBADF; 52017593Skarels break; 52117593Skarels } 52217593Skarels if ((*fp->f_ops->fo_select)(fp, flag)) { 52323523Skarels FD_SET(i + j, &obits[which]); 52417593Skarels n++; 52517593Skarels } 52612751Ssam } 52712751Ssam } 52812751Ssam } 52912751Ssam return (n); 53012751Ssam } 53112751Ssam 5327423Sroot /*ARGSUSED*/ 53312751Ssam seltrue(dev, flag) 53412751Ssam dev_t dev; 53512751Ssam int flag; 5367423Sroot { 5377423Sroot 53812751Ssam return (1); 5397423Sroot } 5408103Sroot 54112751Ssam selwakeup(p, coll) 54212751Ssam register struct proc *p; 54312751Ssam int coll; 5448103Sroot { 5458103Sroot 54612751Ssam if (coll) { 54712751Ssam nselcoll++; 54812751Ssam wakeup((caddr_t)&selwait); 54912751Ssam } 55012751Ssam if (p) { 55117934Skarels int s = splhigh(); 55217270Skarels if (p->p_wchan == (caddr_t)&selwait) { 55317270Skarels if (p->p_stat == SSLEEP) 55417270Skarels setrun(p); 55517270Skarels else 55617270Skarels unsleep(p); 55717270Skarels } else if (p->p_flag & SSEL) 55812751Ssam p->p_flag &= ~SSEL; 55912751Ssam splx(s); 56012751Ssam } 5618103Sroot } 562