123384Smckusick /* 237728Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337728Smckusick * All rights reserved. 423384Smckusick * 5*44444Sbostic * %sccs.include.redist.c% 637728Smckusick * 7*44444Sbostic * @(#)sys_generic.c 7.22 (Berkeley) 06/28/90 823384Smckusick */ 97423Sroot 1017094Sbloom #include "param.h" 1117094Sbloom #include "systm.h" 1244405Skarels #include "user.h" 1317094Sbloom #include "ioctl.h" 1417094Sbloom #include "file.h" 1517094Sbloom #include "proc.h" 1617094Sbloom #include "uio.h" 1717094Sbloom #include "kernel.h" 1817094Sbloom #include "stat.h" 1931653Smckusick #include "malloc.h" 2037127Skarels #ifdef KTRACE 2137127Skarels #include "ktrace.h" 2237127Skarels #endif 237423Sroot 247423Sroot /* 257423Sroot * Read system call. 267423Sroot */ 2742922Smckusick read(p, uap, retval) 2842922Smckusick struct proc *p; 2942922Smckusick register struct args { 307423Sroot int fdes; 317423Sroot char *cbuf; 327423Sroot unsigned count; 3342922Smckusick } *uap; 3442922Smckusick int *retval; 3542922Smckusick { 3637728Smckusick register struct file *fp; 377746Sroot struct uio auio; 387746Sroot struct iovec aiov; 3937728Smckusick long cnt, error = 0; 4037728Smckusick #ifdef KTRACE 4137728Smckusick struct iovec ktriov; 4237728Smckusick #endif 437423Sroot 4437728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 4537728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 4637728Smckusick (fp->f_flag & FREAD) == 0) 4744405Skarels return (EBADF); 487820Sroot aiov.iov_base = (caddr_t)uap->cbuf; 497820Sroot aiov.iov_len = uap->count; 507820Sroot auio.uio_iov = &aiov; 517820Sroot auio.uio_iovcnt = 1; 5237728Smckusick auio.uio_resid = uap->count; 5337728Smckusick auio.uio_rw = UIO_READ; 5437728Smckusick auio.uio_segflg = UIO_USERSPACE; 5537728Smckusick #ifdef KTRACE 5637728Smckusick /* 5737728Smckusick * if tracing, save a copy of iovec 5837728Smckusick */ 5942922Smckusick if (KTRPOINT(p, KTR_GENIO)) 6037728Smckusick ktriov = aiov; 6137728Smckusick #endif 6237728Smckusick cnt = uap->count; 6340703Skarels if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) 6440703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 6540703Skarels error == EINTR || error == EWOULDBLOCK)) 6640703Skarels error = 0; 6737728Smckusick cnt -= auio.uio_resid; 6837728Smckusick #ifdef KTRACE 6942922Smckusick if (KTRPOINT(p, KTR_GENIO) && error == 0) 7043448Smckusick ktrgenio(p->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt, error); 7137728Smckusick #endif 7242922Smckusick *retval = cnt; 7344405Skarels return (error); 747820Sroot } 757820Sroot 7642922Smckusick /* 7742922Smckusick * Scatter read system call. 7842922Smckusick */ 7942922Smckusick readv(p, uap, retval) 8042922Smckusick struct proc *p; 8142922Smckusick register struct args { 827820Sroot int fdes; 837820Sroot struct iovec *iovp; 8426474Skarels unsigned iovcnt; 8542922Smckusick } *uap; 8642922Smckusick int *retval; 8742922Smckusick { 8837728Smckusick register struct file *fp; 897820Sroot struct uio auio; 9037728Smckusick register struct iovec *iov; 9137728Smckusick struct iovec aiov[UIO_SMALLIOV]; 9237728Smckusick long i, cnt, error = 0; 9337728Smckusick #ifdef KTRACE 9437728Smckusick struct iovec *ktriov = NULL; 9537728Smckusick #endif 967820Sroot 9737728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 9837728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 9937728Smckusick (fp->f_flag & FREAD) == 0) 10044405Skarels return (EBADF); 10137127Skarels if (uap->iovcnt > UIO_SMALLIOV) { 10237728Smckusick if (uap->iovcnt > UIO_MAXIOV) 10344405Skarels return (EINVAL); 10437127Skarels MALLOC(iov, struct iovec *, 10537127Skarels sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK); 10637127Skarels } else 10737127Skarels iov = aiov; 10837127Skarels auio.uio_iov = iov; 1097820Sroot auio.uio_iovcnt = uap->iovcnt; 11037728Smckusick auio.uio_rw = UIO_READ; 11137728Smckusick auio.uio_segflg = UIO_USERSPACE; 11237728Smckusick if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, 11337728Smckusick uap->iovcnt * sizeof (struct iovec))) 11437127Skarels goto done; 11537728Smckusick auio.uio_resid = 0; 11637728Smckusick for (i = 0; i < uap->iovcnt; i++) { 11737728Smckusick if (iov->iov_len < 0) { 11837728Smckusick error = EINVAL; 11937728Smckusick goto done; 12037728Smckusick } 12137728Smckusick auio.uio_resid += iov->iov_len; 12237728Smckusick if (auio.uio_resid < 0) { 12337728Smckusick error = EINVAL; 12437728Smckusick goto done; 12537728Smckusick } 12637728Smckusick iov++; 12737728Smckusick } 12837728Smckusick #ifdef KTRACE 12937728Smckusick /* 13037728Smckusick * if tracing, save a copy of iovec 13137728Smckusick */ 13242922Smckusick if (KTRPOINT(p, KTR_GENIO)) { 13341990Smckusick unsigned iovlen = auio.uio_iovcnt * sizeof (struct iovec); 13437728Smckusick 13537728Smckusick MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 13637728Smckusick bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 13737728Smckusick } 13837728Smckusick #endif 13937728Smckusick cnt = auio.uio_resid; 14040703Skarels if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) 14140703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 14240703Skarels error == EINTR || error == EWOULDBLOCK)) 14340703Skarels error = 0; 14437728Smckusick cnt -= auio.uio_resid; 14537728Smckusick #ifdef KTRACE 14637728Smckusick if (ktriov != NULL) { 14741178Smarc if (error == 0) 14843448Smckusick ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov, 14943448Smckusick cnt, error); 15037728Smckusick FREE(ktriov, M_TEMP); 15137728Smckusick } 15237728Smckusick #endif 15342922Smckusick *retval = cnt; 15437127Skarels done: 15537728Smckusick if (uap->iovcnt > UIO_SMALLIOV) 15637127Skarels FREE(iov, M_IOV); 15744405Skarels return (error); 1587423Sroot } 1597423Sroot 1607423Sroot /* 1617423Sroot * Write system call 1627423Sroot */ 16342922Smckusick write(p, uap, retval) 16442922Smckusick struct proc *p; 16542922Smckusick register struct args { 1667423Sroot int fdes; 1677423Sroot char *cbuf; 16826474Skarels unsigned count; 16942922Smckusick } *uap; 17042922Smckusick int *retval; 17142922Smckusick { 17237728Smckusick register struct file *fp; 1737820Sroot struct uio auio; 1747820Sroot struct iovec aiov; 17537728Smckusick long cnt, error = 0; 17637728Smckusick #ifdef KTRACE 17737728Smckusick struct iovec ktriov; 17837728Smckusick #endif 1797423Sroot 18037728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 18137728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 18237728Smckusick (fp->f_flag & FWRITE) == 0) 18344405Skarels return (EBADF); 18437728Smckusick aiov.iov_base = (caddr_t)uap->cbuf; 18537728Smckusick aiov.iov_len = uap->count; 1867820Sroot auio.uio_iov = &aiov; 1877820Sroot auio.uio_iovcnt = 1; 18837728Smckusick auio.uio_resid = uap->count; 18937728Smckusick auio.uio_rw = UIO_WRITE; 19037728Smckusick auio.uio_segflg = UIO_USERSPACE; 19137728Smckusick #ifdef KTRACE 19237728Smckusick /* 19337728Smckusick * if tracing, save a copy of iovec 19437728Smckusick */ 19542922Smckusick if (KTRPOINT(p, KTR_GENIO)) 19637728Smckusick ktriov = aiov; 19737728Smckusick #endif 19837728Smckusick cnt = uap->count; 19940703Skarels if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 20040703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 20140703Skarels error == EINTR || error == EWOULDBLOCK)) 20240703Skarels error = 0; 20340703Skarels if (error == EPIPE) 20442922Smckusick psignal(p, SIGPIPE); 20540703Skarels } 20637728Smckusick cnt -= auio.uio_resid; 20737728Smckusick #ifdef KTRACE 20842922Smckusick if (KTRPOINT(p, KTR_GENIO) && error == 0) 20942922Smckusick ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE, 21043448Smckusick &ktriov, cnt, error); 21137728Smckusick #endif 21242922Smckusick *retval = cnt; 21344405Skarels return (error); 2147820Sroot } 2157820Sroot 21642922Smckusick /* 21742922Smckusick * Gather write system call 21842922Smckusick */ 21942922Smckusick writev(p, uap, retval) 22042922Smckusick struct proc *p; 22142922Smckusick register struct args { 2227820Sroot int fdes; 2237820Sroot struct iovec *iovp; 22426474Skarels unsigned iovcnt; 22542922Smckusick } *uap; 22642922Smckusick int *retval; 22742922Smckusick { 22837728Smckusick register struct file *fp; 2297820Sroot struct uio auio; 23037728Smckusick register struct iovec *iov; 23137728Smckusick struct iovec aiov[UIO_SMALLIOV]; 23237728Smckusick long i, cnt, error = 0; 23337728Smckusick #ifdef KTRACE 23437728Smckusick struct iovec *ktriov = NULL; 23537728Smckusick #endif 2367820Sroot 23737728Smckusick if (((unsigned)uap->fdes) >= NOFILE || 23837728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL || 23937728Smckusick (fp->f_flag & FWRITE) == 0) 24044405Skarels return (EBADF); 24137127Skarels if (uap->iovcnt > UIO_SMALLIOV) { 24237728Smckusick if (uap->iovcnt > UIO_MAXIOV) 24344405Skarels return (EINVAL); 24437127Skarels MALLOC(iov, struct iovec *, 24537127Skarels sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK); 24637127Skarels } else 24737127Skarels iov = aiov; 24837127Skarels auio.uio_iov = iov; 2497820Sroot auio.uio_iovcnt = uap->iovcnt; 25037728Smckusick auio.uio_rw = UIO_WRITE; 25137728Smckusick auio.uio_segflg = UIO_USERSPACE; 25237728Smckusick if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, 25337728Smckusick uap->iovcnt * sizeof (struct iovec))) 25437127Skarels goto done; 25537728Smckusick auio.uio_resid = 0; 25637728Smckusick for (i = 0; i < uap->iovcnt; i++) { 2577820Sroot if (iov->iov_len < 0) { 25837728Smckusick error = EINVAL; 25937728Smckusick goto done; 2607820Sroot } 26137728Smckusick auio.uio_resid += iov->iov_len; 26237728Smckusick if (auio.uio_resid < 0) { 26337728Smckusick error = EINVAL; 26437728Smckusick goto done; 2657820Sroot } 26613270Ssam iov++; 2677820Sroot } 26837127Skarels #ifdef KTRACE 26937728Smckusick /* 27037728Smckusick * if tracing, save a copy of iovec 27137728Smckusick */ 27242922Smckusick if (KTRPOINT(p, KTR_GENIO)) { 27341990Smckusick unsigned iovlen = auio.uio_iovcnt * sizeof (struct iovec); 27437127Skarels 27537127Skarels MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 27637728Smckusick bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 27737127Skarels } 27837127Skarels #endif 27937728Smckusick cnt = auio.uio_resid; 28040703Skarels if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 28140703Skarels if (auio.uio_resid != cnt && (error == ERESTART || 28240703Skarels error == EINTR || error == EWOULDBLOCK)) 28340703Skarels error = 0; 28440703Skarels if (error == EPIPE) 28542922Smckusick psignal(p, SIGPIPE); 28640703Skarels } 28737728Smckusick cnt -= auio.uio_resid; 28837127Skarels #ifdef KTRACE 28937127Skarels if (ktriov != NULL) { 29041178Smarc if (error == 0) 29142922Smckusick ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE, 29243448Smckusick ktriov, cnt, error); 29337127Skarels FREE(ktriov, M_TEMP); 29437127Skarels } 29537127Skarels #endif 29642922Smckusick *retval = cnt; 29737728Smckusick done: 29837728Smckusick if (uap->iovcnt > UIO_SMALLIOV) 29937728Smckusick FREE(iov, M_IOV); 30044405Skarels return (error); 3017423Sroot } 3027423Sroot 3037423Sroot /* 3047423Sroot * Ioctl system call 3057423Sroot */ 30642922Smckusick /* ARGSUSED */ 30742922Smckusick ioctl(p, uap, retval) 30842922Smckusick struct proc *p; 30942922Smckusick register struct args { 3107423Sroot int fdes; 3117423Sroot int cmd; 3127423Sroot caddr_t cmarg; 31342922Smckusick } *uap; 31442922Smckusick int *retval; 31542922Smckusick { 31642922Smckusick register struct file *fp; 31740703Skarels register int com, error; 3187820Sroot register u_int size; 31931653Smckusick caddr_t memp = 0; 32030530Skarels #define STK_PARAMS 128 32133480Skarels char stkbuf[STK_PARAMS]; 32233480Skarels caddr_t data = stkbuf; 3237423Sroot 32437728Smckusick if ((unsigned)uap->fdes >= NOFILE || 32537728Smckusick (fp = u.u_ofile[uap->fdes]) == NULL) 32644405Skarels return (EBADF); 32740703Skarels if ((fp->f_flag & (FREAD|FWRITE)) == 0) 32844405Skarels return (EBADF); 3297624Ssam com = uap->cmd; 3307624Ssam 3317624Ssam if (com == FIOCLEX) { 3329592Ssam u.u_pofile[uap->fdes] |= UF_EXCLOSE; 33344405Skarels return (0); 3347423Sroot } 3357624Ssam if (com == FIONCLEX) { 3369592Ssam u.u_pofile[uap->fdes] &= ~UF_EXCLOSE; 33744405Skarels return (0); 3387423Sroot } 3397624Ssam 3407624Ssam /* 3417624Ssam * Interpret high order word to find 3427624Ssam * amount of data to be copied to/from the 3437624Ssam * user's address space. 3447624Ssam */ 34530530Skarels size = IOCPARM_LEN(com); 34640703Skarels if (size > IOCPARM_MAX) 34744405Skarels return (ENOTTY); 34833480Skarels if (size > sizeof (stkbuf)) { 34943383Smckusick memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 35031653Smckusick data = memp; 35130530Skarels } 35210601Ssam if (com&IOC_IN) { 35310601Ssam if (size) { 35440703Skarels error = copyin(uap->cmarg, data, (u_int)size); 35540703Skarels if (error) { 35631653Smckusick if (memp) 35731653Smckusick free(memp, M_IOCTLOPS); 35844405Skarels return (error); 35931653Smckusick } 36010601Ssam } else 36110601Ssam *(caddr_t *)data = uap->cmarg; 36210601Ssam } else if ((com&IOC_OUT) && size) 36310601Ssam /* 36437127Skarels * Zero the buffer so the user always 36537127Skarels * gets back something deterministic. 36610601Ssam */ 36730530Skarels bzero(data, size); 36811284Ssam else if (com&IOC_VOID) 36911284Ssam *(caddr_t *)data = uap->cmarg; 3707423Sroot 37112751Ssam switch (com) { 3727624Ssam 37312751Ssam case FIONBIO: 37440703Skarels error = fset(fp, FNDELAY, *(int *)data); 37530530Skarels break; 37612751Ssam 37712751Ssam case FIOASYNC: 37840703Skarels error = fset(fp, FASYNC, *(int *)data); 37930530Skarels break; 38012751Ssam 38112751Ssam case FIOSETOWN: 38240703Skarels error = fsetown(fp, *(int *)data); 38330530Skarels break; 38412751Ssam 38512751Ssam case FIOGETOWN: 38640703Skarels error = fgetown(fp, (int *)data); 38730530Skarels break; 38830530Skarels default: 38940703Skarels error = (*fp->f_ops->fo_ioctl)(fp, com, data); 39030530Skarels /* 39130530Skarels * Copy any data to user, size was 39230530Skarels * already set and checked above. 39330530Skarels */ 39440703Skarels if (error == 0 && (com&IOC_OUT) && size) 39540703Skarels error = copyout(data, uap->cmarg, (u_int)size); 39630530Skarels break; 3977423Sroot } 39831653Smckusick if (memp) 39931653Smckusick free(memp, M_IOCTLOPS); 40044405Skarels return (error); 4017423Sroot } 4027423Sroot 40312751Ssam int nselcoll; 40417593Skarels 4057423Sroot /* 40612751Ssam * Select system call. 4077423Sroot */ 40842922Smckusick select(p, uap, retval) 40942922Smckusick register struct proc *p; 41042922Smckusick register struct args { 41112751Ssam int nd; 41223523Skarels fd_set *in, *ou, *ex; 41312751Ssam struct timeval *tv; 41442922Smckusick } *uap; 41542922Smckusick int *retval; 41642922Smckusick { 41723523Skarels fd_set ibits[3], obits[3]; 41812751Ssam struct timeval atv; 41940703Skarels int s, ncoll, ni, error = 0, timo; 42012751Ssam 42126277Skarels bzero((caddr_t)ibits, sizeof(ibits)); 42226277Skarels bzero((caddr_t)obits, sizeof(obits)); 42312751Ssam if (uap->nd > NOFILE) 42412751Ssam uap->nd = NOFILE; /* forgiving, if slightly wrong */ 42523523Skarels ni = howmany(uap->nd, NFDBITS); 42612751Ssam 42712751Ssam #define getbits(name, x) \ 42812751Ssam if (uap->name) { \ 42940703Skarels error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 43026277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 43140703Skarels if (error) \ 43212751Ssam goto done; \ 43317593Skarels } 43412751Ssam getbits(in, 0); 43512751Ssam getbits(ou, 1); 43612751Ssam getbits(ex, 2); 43712751Ssam #undef getbits 43812751Ssam 43912751Ssam if (uap->tv) { 44040703Skarels error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 44112751Ssam sizeof (atv)); 44240703Skarels if (error) 44312751Ssam goto done; 44412751Ssam if (itimerfix(&atv)) { 44540703Skarels error = EINVAL; 44612751Ssam goto done; 44712751Ssam } 44817934Skarels s = splhigh(); timevaladd(&atv, &time); splx(s); 44940703Skarels timo = hzto(&atv); 45040703Skarels } else 45140703Skarels timo = 0; 45212751Ssam retry: 45312751Ssam ncoll = nselcoll; 45442922Smckusick p->p_flag |= SSEL; 45542922Smckusick error = selscan(ibits, obits, uap->nd, retval); 45642922Smckusick if (error || *retval) 45712751Ssam goto done; 45817934Skarels s = splhigh(); 45912971Ssam /* this should be timercmp(&time, &atv, >=) */ 46012971Ssam if (uap->tv && (time.tv_sec > atv.tv_sec || 46112971Ssam time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 46212751Ssam splx(s); 46312751Ssam goto done; 46412751Ssam } 46542922Smckusick if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) { 46612751Ssam splx(s); 46712751Ssam goto retry; 46812751Ssam } 46942922Smckusick p->p_flag &= ~SSEL; 47040703Skarels error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); 47112751Ssam splx(s); 47240703Skarels if (error == 0) 47340703Skarels goto retry; 47412751Ssam done: 47542922Smckusick p->p_flag &= ~SSEL; 47640703Skarels /* select is not restarted after signals... */ 47740703Skarels if (error == ERESTART) 47840703Skarels error = EINTR; 47940703Skarels if (error == EWOULDBLOCK) 48040703Skarels error = 0; 48112751Ssam #define putbits(name, x) \ 48212751Ssam if (uap->name) { \ 48340703Skarels int error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ 48426277Skarels (unsigned)(ni * sizeof(fd_mask))); \ 48540703Skarels if (error2) \ 48640703Skarels error = error2; \ 48712751Ssam } 48840703Skarels if (error == 0) { 48921106Skarels putbits(in, 0); 49021106Skarels putbits(ou, 1); 49121106Skarels putbits(ex, 2); 49212751Ssam #undef putbits 49321106Skarels } 49444405Skarels return (error); 49512751Ssam } 49612751Ssam 49742922Smckusick selscan(ibits, obits, nfd, retval) 49823523Skarels fd_set *ibits, *obits; 49942922Smckusick int nfd, *retval; 50012751Ssam { 50123523Skarels register int which, i, j; 50223523Skarels register fd_mask bits; 50312751Ssam int flag; 50412751Ssam struct file *fp; 50542922Smckusick int error = 0, n = 0; 50612751Ssam 50712751Ssam for (which = 0; which < 3; which++) { 50812751Ssam switch (which) { 50912751Ssam 51012751Ssam case 0: 51112751Ssam flag = FREAD; break; 51212751Ssam 51312751Ssam case 1: 51412751Ssam flag = FWRITE; break; 51512751Ssam 51612751Ssam case 2: 51712751Ssam flag = 0; break; 51812751Ssam } 51923523Skarels for (i = 0; i < nfd; i += NFDBITS) { 52023523Skarels bits = ibits[which].fds_bits[i/NFDBITS]; 52117593Skarels while ((j = ffs(bits)) && i + --j < nfd) { 52217593Skarels bits &= ~(1 << j); 52317593Skarels fp = u.u_ofile[i + j]; 52417593Skarels if (fp == NULL) { 52542922Smckusick error = EBADF; 52617593Skarels break; 52717593Skarels } 52817593Skarels if ((*fp->f_ops->fo_select)(fp, flag)) { 52923523Skarels FD_SET(i + j, &obits[which]); 53017593Skarels n++; 53117593Skarels } 53212751Ssam } 53312751Ssam } 53412751Ssam } 53542922Smckusick *retval = n; 53642922Smckusick return (error); 53712751Ssam } 53812751Ssam 5397423Sroot /*ARGSUSED*/ 54012751Ssam seltrue(dev, flag) 54112751Ssam dev_t dev; 54212751Ssam int flag; 5437423Sroot { 5447423Sroot 54512751Ssam return (1); 5467423Sroot } 5478103Sroot 54812751Ssam selwakeup(p, coll) 54912751Ssam register struct proc *p; 55012751Ssam int coll; 5518103Sroot { 5528103Sroot 55312751Ssam if (coll) { 55412751Ssam nselcoll++; 55512751Ssam wakeup((caddr_t)&selwait); 55612751Ssam } 55712751Ssam if (p) { 55817934Skarels int s = splhigh(); 55917270Skarels if (p->p_wchan == (caddr_t)&selwait) { 56017270Skarels if (p->p_stat == SSLEEP) 56117270Skarels setrun(p); 56217270Skarels else 56317270Skarels unsleep(p); 56417270Skarels } else if (p->p_flag & SSEL) 56512751Ssam p->p_flag &= ~SSEL; 56612751Ssam splx(s); 56712751Ssam } 5688103Sroot } 569