summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/atkbdc/psm.c2
-rw-r--r--sys/dev/bktr/bktr_core.c2
-rw-r--r--sys/dev/kbd/kbd.c2
-rw-r--r--sys/dev/snp/snp.c2
-rw-r--r--sys/dev/sound/midi/midibuf.c4
-rw-r--r--sys/dev/sound/pcm/channel.c2
-rw-r--r--sys/dev/usb/ums.c2
-rw-r--r--sys/i386/isa/asc.c5
-rw-r--r--sys/i386/isa/pcaudio.c7
-rw-r--r--sys/isa/psm.c2
-rw-r--r--sys/kern/sys_generic.c226
-rw-r--r--sys/kern/tty.c4
-rw-r--r--sys/sys/proc.h3
-rw-r--r--sys/sys/selinfo.h9
-rw-r--r--sys/sys/systm.h2
15 files changed, 135 insertions, 139 deletions
diff --git a/sys/dev/atkbdc/psm.c b/sys/dev/atkbdc/psm.c
index d43207e..6be30d4 100644
--- a/sys/dev/atkbdc/psm.c
+++ b/sys/dev/atkbdc/psm.c
@@ -1314,8 +1314,6 @@ psmopen(dev_t dev, int flag, int fmt, struct thread *td)
device_busy(devclass_get_device(psm_devclass, unit));
/* Initialize state */
- sc->rsel.si_flags = 0;
- sc->rsel.si_pid = 0;
sc->mode.level = sc->dflt_mode.level;
sc->mode.protocol = sc->dflt_mode.protocol;
sc->watchdog = FALSE;
diff --git a/sys/dev/bktr/bktr_core.c b/sys/dev/bktr/bktr_core.c
index 528f09a..1a062dd 100644
--- a/sys/dev/bktr/bktr_core.c
+++ b/sys/dev/bktr/bktr_core.c
@@ -809,7 +809,7 @@ common_bktr_intr( void *arg )
}
/* If someone has a select() on /dev/vbi, inform them */
- if (bktr->vbi_select.si_pid) {
+ if (SEL_WAITING(&bktr->vbi_select)) {
selwakeup(&bktr->vbi_select);
}
diff --git a/sys/dev/kbd/kbd.c b/sys/dev/kbd/kbd.c
index 1a1c132..6eef728 100644
--- a/sys/dev/kbd/kbd.c
+++ b/sys/dev/kbd/kbd.c
@@ -523,8 +523,6 @@ genkbdopen(dev_t dev, int mode, int flag, struct thread *td)
bzero(&sc->gkb_q, sizeof(sc->gkb_q));
#endif
clist_alloc_cblocks(&sc->gkb_q, KB_QSIZE, KB_QSIZE/2); /* XXX */
- sc->gkb_rsel.si_flags = 0;
- sc->gkb_rsel.si_pid = 0;
splx(s);
return 0;
diff --git a/sys/dev/snp/snp.c b/sys/dev/snp/snp.c
index a72940b..78d5cd3 100644
--- a/sys/dev/snp/snp.c
+++ b/sys/dev/snp/snp.c
@@ -374,7 +374,6 @@ snp_in(snp, buf, n)
wakeup((caddr_t)snp);
}
selwakeup(&snp->snp_sel);
- snp->snp_sel.si_pid = 0;
return (n);
}
@@ -449,7 +448,6 @@ snp_detach(snp)
detach_notty:
selwakeup(&snp->snp_sel);
- snp->snp_sel.si_pid = 0;
if ((snp->snp_flags & SNOOP_OPEN) == 0)
free(snp, M_SNP);
diff --git a/sys/dev/sound/midi/midibuf.c b/sys/dev/sound/midi/midibuf.c
index d764b68..8b4eda7 100644
--- a/sys/dev/sound/midi/midibuf.c
+++ b/sys/dev/sound/midi/midibuf.c
@@ -357,7 +357,7 @@ queuerawdata(midi_dbuf *dbuf, char *data, int len)
/* Wake up the processes sleeping on input data. */
cv_broadcast(&dbuf->cv_in);
- if (dbuf->sel.si_pid && dbuf->rl >= dbuf->blocksize)
+ if (SEL_WAITING(&dbuf->sel) && dbuf->rl >= dbuf->blocksize)
selwakeup(&dbuf->sel);
}
@@ -398,6 +398,6 @@ deleterawdata(midi_dbuf *dbuf, int len)
/* Wake up the processes sleeping on queueing. */
cv_broadcast(&dbuf->cv_out);
- if (dbuf->sel.si_pid && dbuf->fl >= dbuf->blocksize)
+ if (SEL_WAITING(&dbuf->sel) && dbuf->fl >= dbuf->blocksize)
selwakeup(&dbuf->sel);
}
diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c
index 3d36e10..c55229c 100644
--- a/sys/dev/sound/pcm/channel.c
+++ b/sys/dev/sound/pcm/channel.c
@@ -116,7 +116,7 @@ chn_wakeup(struct pcm_channel *c)
struct snd_dbuf *bs = c->bufsoft;
CHN_LOCKASSERT(c);
- if (sndbuf_getsel(bs)->si_pid && chn_polltrigger(c))
+ if (SEL_WAITING(sndbuf_getsel(bs)) && chn_polltrigger(c))
selwakeup(sndbuf_getsel(bs));
wakeup(bs);
}
diff --git a/sys/dev/usb/ums.c b/sys/dev/usb/ums.c
index 0fdafde..bb7193d 100644
--- a/sys/dev/usb/ums.c
+++ b/sys/dev/usb/ums.c
@@ -344,8 +344,10 @@ USB_ATTACH(ums)
sc->status.button = sc->status.obutton = 0;
sc->status.dx = sc->status.dy = sc->status.dz = 0;
+#ifndef __FreeBSD__
sc->rsel.si_flags = 0;
sc->rsel.si_pid = 0;
+#endif
sc->dev = make_dev(&ums_cdevsw, device_get_unit(self),
UID_ROOT, GID_OPERATOR,
diff --git a/sys/i386/isa/asc.c b/sys/i386/isa/asc.c
index ca90a0d..292b6d5 100644
--- a/sys/i386/isa/asc.c
+++ b/sys/i386/isa/asc.c
@@ -484,7 +484,6 @@ ascattach(struct isa_device *isdp)
scu->flags &= ~FLAG_DEBUG;
scu->selp.si_flags=0;
- scu->selp.si_pid=(pid_t)0;
#define ASC_UID 0
#define ASC_GID 13
make_dev(&asc_cdevsw, unit<<6, ASC_UID, ASC_GID, 0666, "asc%d", unit);
@@ -531,10 +530,8 @@ ascintr(int unit)
if (scu->sbuf.size - scu->sbuf.count >= scu->linesize) {
dma_restart(scu);
}
- if (scu->selp.si_pid) {
+ if (SEL_WAITING(&scu->selp)) {
selwakeup(&scu->selp);
- scu->selp.si_pid=(pid_t)0;
- scu->selp.si_flags = 0;
}
}
}
diff --git a/sys/i386/isa/pcaudio.c b/sys/i386/isa/pcaudio.c
index a4809ed..e457eed 100644
--- a/sys/i386/isa/pcaudio.c
+++ b/sys/i386/isa/pcaudio.c
@@ -542,11 +542,8 @@ pcaintr(struct clockframe *frame)
pca_status.buffer = pca_status.buf[pca_status.current];
if (pca_sleep)
wakeup(&pca_sleep);
- if (pca_status.wsel.si_pid) {
- selwakeup((struct selinfo *)&pca_status.wsel.si_pid);
- pca_status.wsel.si_pid = 0;
- pca_status.wsel.si_flags = 0;
- }
+ if (SEL_WAITING(&pca_status.wsel))
+ selwakeup(&pca_status.wsel);
}
}
diff --git a/sys/isa/psm.c b/sys/isa/psm.c
index d43207e..6be30d4 100644
--- a/sys/isa/psm.c
+++ b/sys/isa/psm.c
@@ -1314,8 +1314,6 @@ psmopen(dev_t dev, int flag, int fmt, struct thread *td)
device_busy(devclass_get_device(psm_devclass, unit));
/* Initialize state */
- sc->rsel.si_flags = 0;
- sc->rsel.si_pid = 0;
sc->mode.level = sc->dflt_mode.level;
sc->mode.protocol = sc->dflt_mode.protocol;
sc->watchdog = FALSE;
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
index 3462e6c..dff12a1 100644
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -696,8 +696,12 @@ done:
return (error);
}
-static int nselcoll; /* Select collisions since boot */
+/*
+ * sellock and selwait are initialized in selectinit() via SYSINIT.
+ */
+struct mtx sellock;
struct cv selwait;
+int nselcoll; /* Select collisions since boot */
SYSCTL_INT(_kern, OID_AUTO, nselcoll, CTLFLAG_RD, &nselcoll, 0, "");
/*
@@ -775,7 +779,7 @@ select(td, uap)
sbp += ncpbytes / sizeof *sbp; \
error = copyin(uap->name, ibits[x], ncpbytes); \
if (error != 0) \
- goto done_noproclock; \
+ goto done_nosellock; \
} \
} while (0)
getbits(in, 0);
@@ -789,10 +793,10 @@ select(td, uap)
error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
sizeof (atv));
if (error)
- goto done_noproclock;
+ goto done_nosellock;
if (itimerfix(&atv)) {
error = EINVAL;
- goto done_noproclock;
+ goto done_nosellock;
}
getmicrouptime(&rtv);
timevaladd(&atv, &rtv);
@@ -801,61 +805,59 @@ select(td, uap)
atv.tv_usec = 0;
}
timo = 0;
- PROC_LOCK(td->td_proc);
+ mtx_lock(&sellock);
retry:
ncoll = nselcoll;
mtx_lock_spin(&sched_lock);
td->td_flags |= TDF_SELECT;
mtx_unlock_spin(&sched_lock);
- PROC_UNLOCK(td->td_proc);
+ mtx_unlock(&sellock);
+
+ /* XXX Is there a better place for this? */
+ TAILQ_INIT(&td->td_selq);
error = selscan(td, ibits, obits, uap->nd);
- PROC_LOCK(td->td_proc);
+ mtx_lock(&sellock);
if (error || td->td_retval[0])
goto done;
if (atv.tv_sec || atv.tv_usec) {
getmicrouptime(&rtv);
- if (timevalcmp(&rtv, &atv, >=)) {
- /*
- * An event of our interest may occur during locking a process.
- * In order to avoid missing the event that occured during locking
- * the process, test TDF_SELECT and rescan file descriptors if
- * necessary.
- */
- mtx_lock_spin(&sched_lock);
- if ((td->td_flags & TDF_SELECT) == 0 || nselcoll != ncoll) {
- ncoll = nselcoll;
- td->td_flags |= TDF_SELECT;
- mtx_unlock_spin(&sched_lock);
- PROC_UNLOCK(td->td_proc);
- error = selscan(td, ibits, obits, uap->nd);
- PROC_LOCK(td->td_proc);
- } else
- mtx_unlock_spin(&sched_lock);
+ if (timevalcmp(&rtv, &atv, >=))
goto done;
- }
ttv = atv;
timevalsub(&ttv, &rtv);
timo = ttv.tv_sec > 24 * 60 * 60 ?
24 * 60 * 60 * hz : tvtohz(&ttv);
}
+
+ /*
+ * An event of interest may occur while we do not hold
+ * sellock, so check TDF_SELECT and the number of
+ * collisions and rescan the file descriptors if
+ * necessary.
+ */
mtx_lock_spin(&sched_lock);
- td->td_flags &= ~TDF_SELECT;
+ if ((td->td_flags & TDF_SELECT) == 0 || nselcoll != ncoll) {
+ mtx_unlock_spin(&sched_lock);
+ goto retry;
+ }
mtx_unlock_spin(&sched_lock);
if (timo > 0)
- error = cv_timedwait_sig(&selwait, &td->td_proc->p_mtx, timo);
+ error = cv_timedwait_sig(&selwait, &sellock, timo);
else
- error = cv_wait_sig(&selwait, &td->td_proc->p_mtx);
+ error = cv_wait_sig(&selwait, &sellock);
if (error == 0)
goto retry;
done:
+ clear_selinfo_list(td);
mtx_lock_spin(&sched_lock);
td->td_flags &= ~TDF_SELECT;
mtx_unlock_spin(&sched_lock);
- PROC_UNLOCK(td->td_proc);
-done_noproclock:
+ mtx_unlock(&sellock);
+
+done_nosellock:
/* select is not restarted after signals... */
if (error == ERESTART)
error = EINTR;
@@ -967,13 +969,13 @@ poll(td, uap)
bits = smallbits;
error = copyin(SCARG(uap, fds), bits, ni);
if (error)
- goto done_noproclock;
+ goto done_nosellock;
if (SCARG(uap, timeout) != INFTIM) {
atv.tv_sec = SCARG(uap, timeout) / 1000;
atv.tv_usec = (SCARG(uap, timeout) % 1000) * 1000;
if (itimerfix(&atv)) {
error = EINVAL;
- goto done_noproclock;
+ goto done_nosellock;
}
getmicrouptime(&rtv);
timevaladd(&atv, &rtv);
@@ -982,59 +984,57 @@ poll(td, uap)
atv.tv_usec = 0;
}
timo = 0;
- PROC_LOCK(td->td_proc);
+ mtx_lock(&sellock);
retry:
ncoll = nselcoll;
mtx_lock_spin(&sched_lock);
td->td_flags |= TDF_SELECT;
mtx_unlock_spin(&sched_lock);
- PROC_UNLOCK(td->td_proc);
+ mtx_unlock(&sellock);
+
+ /* XXX Is there a better place for this? */
+ TAILQ_INIT(&td->td_selq);
error = pollscan(td, (struct pollfd *)bits, nfds);
- PROC_LOCK(td->td_proc);
+ mtx_lock(&sellock);
if (error || td->td_retval[0])
goto done;
if (atv.tv_sec || atv.tv_usec) {
getmicrouptime(&rtv);
- if (timevalcmp(&rtv, &atv, >=)) {
- /*
- * An event of our interest may occur during locking a process.
- * In order to avoid missing the event that occured during locking
- * the process, test TDF_SELECT and rescan file descriptors if
- * necessary.
- */
- mtx_lock_spin(&sched_lock);
- if ((td->td_flags & TDF_SELECT) == 0 || nselcoll != ncoll) {
- ncoll = nselcoll;
- td->td_flags |= TDF_SELECT;
- mtx_unlock_spin(&sched_lock);
- PROC_UNLOCK(td->td_proc);
- error = pollscan(td, (struct pollfd *)bits, nfds);
- PROC_LOCK(td->td_proc);
- } else
- mtx_unlock_spin(&sched_lock);
+ if (timevalcmp(&rtv, &atv, >=))
goto done;
- }
ttv = atv;
timevalsub(&ttv, &rtv);
timo = ttv.tv_sec > 24 * 60 * 60 ?
24 * 60 * 60 * hz : tvtohz(&ttv);
}
+ /*
+ * An event of interest may occur while we do not hold
+ * sellock, so check TDF_SELECT and the number of collisions
+ * and rescan the file descriptors if necessary.
+ */
mtx_lock_spin(&sched_lock);
- td->td_flags &= ~TDF_SELECT;
+ if ((td->td_flags & TDF_SELECT) == 0 || nselcoll != ncoll) {
+ mtx_unlock_spin(&sched_lock);
+ goto retry;
+ }
mtx_unlock_spin(&sched_lock);
+
if (timo > 0)
- error = cv_timedwait_sig(&selwait, &td->td_proc->p_mtx, timo);
+ error = cv_timedwait_sig(&selwait, &sellock, timo);
else
- error = cv_wait_sig(&selwait, &td->td_proc->p_mtx);
+ error = cv_wait_sig(&selwait, &sellock);
+
if (error == 0)
goto retry;
done:
+ clear_selinfo_list(td);
mtx_lock_spin(&sched_lock);
td->td_flags &= ~TDF_SELECT;
mtx_unlock_spin(&sched_lock);
- PROC_UNLOCK(td->td_proc);
-done_noproclock:
+ mtx_unlock(&sellock);
+
+done_nosellock:
/* poll is not restarted after signals... */
if (error == ERESTART)
error = EINTR;
@@ -1115,6 +1115,26 @@ openbsd_poll(td, uap)
return (poll(td, (struct poll_args *)uap));
}
+/*
+ * Remove the references to the thread from all of the objects
+ * we were polling.
+ *
+ * This code assumes that the underlying owner of the selinfo
+ * structure will hold sellock before it changes it, and that
+ * it will unlink itself from our list if it goes away.
+ */
+void
+clear_selinfo_list(td)
+ struct thread *td;
+{
+ struct selinfo *si;
+
+ mtx_assert(&sellock, MA_OWNED);
+ TAILQ_FOREACH(si, &td->td_selq, si_thrlist)
+ si->si_thread = NULL;
+ TAILQ_INIT(&td->td_selq);
+}
+
/*ARGSUSED*/
int
seltrue(dev, events, td)
@@ -1126,18 +1146,6 @@ seltrue(dev, events, td)
return (events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
}
-static int
-find_thread_in_proc(struct proc *p, struct thread *td)
-{
- struct thread *td2;
- FOREACH_THREAD_IN_PROC(p, td2) {
- if (td2 == td) {
- return (1);
- }
- }
- return (0);
-}
-
/*
* Record a select request.
*/
@@ -1146,29 +1154,22 @@ selrecord(selector, sip)
struct thread *selector;
struct selinfo *sip;
{
- struct proc *p;
- pid_t mypid;
- mypid = selector->td_proc->p_pid;
- if ((sip->si_pid == mypid) &&
- (sip->si_thread == selector)) { /* XXXKSE should be an ID? */
- return;
- }
- if (sip->si_pid &&
- (p = pfind(sip->si_pid)) &&
- (find_thread_in_proc(p, sip->si_thread))) {
- mtx_lock_spin(&sched_lock);
- if (sip->si_thread->td_wchan == (caddr_t)&selwait) {
- mtx_unlock_spin(&sched_lock);
- PROC_UNLOCK(p);
- sip->si_flags |= SI_COLL;
- return;
- }
- mtx_unlock_spin(&sched_lock);
- PROC_UNLOCK(p);
+ mtx_lock(&sellock);
+ /*
+ * If the thread is NULL then take ownership of selinfo
+ * however if the thread is not NULL and the thread points to
+ * someone else, then we have a collision, otherwise leave it alone
+ * as we've owned it in a previous selrecord on this selinfo.
+ */
+ if (sip->si_thread == NULL) {
+ sip->si_thread = selector;
+ TAILQ_INSERT_TAIL(&selector->td_selq, sip, si_thrlist);
+ } else if (sip->si_thread != selector) {
+ sip->si_flags |= SI_COLL;
}
- sip->si_pid = mypid;
- sip->si_thread = selector;
+
+ mtx_unlock(&sellock);
}
/*
@@ -1176,37 +1177,33 @@ selrecord(selector, sip)
*/
void
selwakeup(sip)
- register struct selinfo *sip;
+ struct selinfo *sip;
{
struct thread *td;
- register struct proc *p;
- if (sip->si_pid == 0)
- return;
- if (sip->si_flags & SI_COLL) {
+ mtx_lock(&sellock);
+ td = sip->si_thread;
+ if ((sip->si_flags & SI_COLL) != 0) {
nselcoll++;
sip->si_flags &= ~SI_COLL;
cv_broadcast(&selwait);
}
- p = pfind(sip->si_pid);
- sip->si_pid = 0;
- td = sip->si_thread;
- if (p != NULL) {
- if (!find_thread_in_proc(p, td)) {
- PROC_UNLOCK(p); /* lock is in pfind() */;
- return;
- }
- mtx_lock_spin(&sched_lock);
- if (td->td_wchan == (caddr_t)&selwait) {
- if (td->td_proc->p_stat == SSLEEP)
- setrunnable(td);
- else
- cv_waitq_remove(td);
- } else
- td->td_flags &= ~TDF_SELECT;
- mtx_unlock_spin(&sched_lock);
- PROC_UNLOCK(p); /* Lock is in pfind() */
+ if (td == NULL) {
+ mtx_unlock(&sellock);
+ return;
}
+ TAILQ_REMOVE(&td->td_selq, sip, si_thrlist);
+ sip->si_thread = NULL;
+ mtx_lock_spin(&sched_lock);
+ if (td->td_wchan == (caddr_t)&selwait) {
+ if (td->td_proc->p_stat == SSLEEP)
+ setrunnable(td);
+ else
+ cv_waitq_remove(td);
+ } else
+ td->td_flags &= ~TDF_SELECT;
+ mtx_unlock_spin(&sched_lock);
+ mtx_unlock(&sellock);
}
static void selectinit __P((void *));
@@ -1218,4 +1215,5 @@ selectinit(dummy)
void *dummy;
{
cv_init(&selwait, "select");
+ mtx_init(&sellock, "sellck", MTX_DEF);
}
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index 923923a..89207e6 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -2273,7 +2273,7 @@ ttwakeup(tp)
register struct tty *tp;
{
- if (tp->t_rsel.si_pid != 0)
+ if (SEL_WAITING(&tp->t_rsel))
selwakeup(&tp->t_rsel);
if (ISSET(tp->t_state, TS_ASYNC) && tp->t_sigio != NULL)
pgsigio(tp->t_sigio, SIGIO, (tp->t_session != NULL));
@@ -2289,7 +2289,7 @@ ttwwakeup(tp)
register struct tty *tp;
{
- if (tp->t_wsel.si_pid != 0 && tp->t_outq.c_cc <= tp->t_olowat)
+ if (SEL_WAITING(&tp->t_wsel) && tp->t_outq.c_cc <= tp->t_olowat)
selwakeup(&tp->t_wsel);
if (ISSET(tp->t_state, TS_ASYNC) && tp->t_sigio != NULL)
pgsigio(tp->t_sigio, SIGIO, (tp->t_session != NULL));
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 02ddfe4..a458f66 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -147,6 +147,7 @@ struct pargs {
* m - Giant
* n - not locked, lazy
* o - locked by pgrpsess_lock sx
+ * p - select lock (sellock)
*
* If the locking key specifies two identifiers (for example, p_pptr) then
* either lock is sufficient for read access, but both locks must be held
@@ -260,6 +261,8 @@ struct thread {
TAILQ_ENTRY(thread) td_blkq; /* (j) Mutex queue. XXXKSE */
TAILQ_ENTRY(thread) td_runq; /* (j) Run queue(s). XXXKSE */
+ TAILQ_HEAD(, selinfo) td_selq; /* (p) List of selinfos. */
+
#define td_startzero td_flags
int td_flags; /* (j) TDF_* flags. */
int td_dupfd; /* (k) Ret value from fdopen. XXX */
diff --git a/sys/sys/selinfo.h b/sys/sys/selinfo.h
index aa1bb89..318681f 100644
--- a/sys/sys/selinfo.h
+++ b/sys/sys/selinfo.h
@@ -45,18 +45,23 @@ struct thread;
* notified when I/O becomes possible.
*/
struct selinfo {
- pid_t si_pid; /* process to be notified */
- struct thread *si_thread; /* thread in that process XXXKSE */
+ TAILQ_ENTRY(selinfo) si_thrlist; /* list hung off of thread */
+ struct thread *si_thread; /* thread waiting */
struct klist si_note; /* kernel note list */
short si_flags; /* see below */
};
#define SI_COLL 0x0001 /* collision occurred */
+#define SEL_WAITING(si) \
+ ((si)->si_thread != NULL || ((si)->si_flags & SI_COLL) != 0)
+
#ifdef _KERNEL
struct thread;
+void clear_selinfo_list(struct thread *);
void selrecord __P((struct thread *selector, struct selinfo *));
void selwakeup __P((struct selinfo *));
+
#endif
#endif /* !_SYS_SELINFO_H_ */
diff --git a/sys/sys/systm.h b/sys/sys/systm.h
index c2178f1..37eb4bf 100644
--- a/sys/sys/systm.h
+++ b/sys/sys/systm.h
@@ -57,6 +57,8 @@ extern char copyright[]; /* system copyright */
extern int nswap; /* size of swap space */
+extern int nselcoll; /* select collisions since boot */
+extern struct mtx sellock; /* select lock variable */
extern struct cv selwait; /* select conditional variable */
extern int physmem; /* physical memory */
OpenPOWER on IntegriCloud