-int unselect();
-int nselcoll;
-/*
- * Select system call.
- */
-select()
-{
- register struct uap {
- int nd;
- long *in;
- long *ou;
- long *ex;
- struct timeval *tv;
- } *uap = (struct uap *)u.u_ap;
- int ibits[3], obits[3];
- struct timeval atv;
- int s, ncoll;
- label_t lqsave;
-
- obits[0] = obits[1] = obits[2] = 0;
- if (uap->nd > NOFILE)
- uap->nd = NOFILE; /* forgiving, if slightly wrong */
-
-#define getbits(name, x) \
- if (uap->name) { \
- u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \
- sizeof (ibits[x])); \
- if (u.u_error) \
- goto done; \
- } else \
- ibits[x] = 0;
- getbits(in, 0);
- getbits(ou, 1);
- getbits(ex, 2);
-#undef getbits
-
- if (uap->tv) {
- u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
- sizeof (atv));
- if (u.u_error)
- goto done;
- if (itimerfix(&atv)) {
- u.u_error = EINVAL;
- goto done;
- }
- s = spl7(); timevaladd(&atv, &time); splx(s);
- }
-retry:
- ncoll = nselcoll;
- u.u_procp->p_flag |= SSEL;
- u.u_r.r_val1 = selscan(ibits, obits);
- if (u.u_error || u.u_r.r_val1)
- goto done;
- s = spl6();
- if (uap->tv && timercmp(&time, &atv, >=)) {
- splx(s);
- goto done;
- }
- if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) {
- u.u_procp->p_flag &= ~SSEL;
- splx(s);
- goto retry;
- }
- u.u_procp->p_flag &= ~SSEL;
- if (uap->tv) {
- lqsave = u.u_qsave;
- if (setjmp(&u.u_qsave)) {
- untimeout(unselect, (caddr_t)u.u_procp);
- u.u_error = EINTR;
- splx(s);
- goto done;
- }
- timeout(unselect, (caddr_t)u.u_procp, hzto(&atv));
- }
- sleep((caddr_t)&selwait, PZERO+1);
- if (uap->tv) {
- u.u_qsave = lqsave;
- untimeout(unselect, (caddr_t)u.u_procp);
- }
- splx(s);
- goto retry;
-done:
-#define putbits(name, x) \
- if (uap->name) { \
- int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \
- sizeof (obits[x])); \
- if (error) \
- u.u_error = error; \
- }
- putbits(in, 0);
- putbits(ou, 1);
- putbits(ex, 2);
-#undef putbits