summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_event.c
diff options
context:
space:
mode:
authorjeff <jeff@FreeBSD.org>2007-12-16 06:21:20 +0000
committerjeff <jeff@FreeBSD.org>2007-12-16 06:21:20 +0000
commit4ec9caf00c407884fc51ff18adb8ff16a5eb75c0 (patch)
treee3b97a4fccf98fcc3311ea54b086b57edb1abb4d /sys/kern/kern_event.c
parent436e8270ebc964cc1f1effe79ac5c10e92e78f7b (diff)
downloadFreeBSD-src-4ec9caf00c407884fc51ff18adb8ff16a5eb75c0.zip
FreeBSD-src-4ec9caf00c407884fc51ff18adb8ff16a5eb75c0.tar.gz
Refactor select to reduce contention and hide internal implementation
details from consumers. - Track individual selecters on a per-descriptor basis such that there are no longer collisions and after sleeping for events only those descriptors which triggered events must be rescaned. - Protect the selinfo (per descriptor) structure with a mtx pool mutex. mtx pool mutexes were chosen to preserve api compatibility with existing code which does nothing but bzero() to setup selinfo structures. - Use a per-thread wait channel rather than a global wait channel. - Hide select implementation details in a seltd structure which is opaque to the rest of the kernel. - Provide a 'selsocket' interface for those kernel consumers who wish to select on a socket when they have no fd so they no longer have to be aware of select implementation details. Tested by: kris Reviewed on: arch
Diffstat (limited to 'sys/kern/kern_event.c')
-rw-r--r--sys/kern/kern_event.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index aa446b6..4d75822 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -1400,7 +1400,8 @@ kqueue_poll(struct file *fp, int events, struct ucred *active_cred,
revents |= events & (POLLIN | POLLRDNORM);
} else {
selrecord(td, &kq->kq_sel);
- kq->kq_state |= KQ_SEL;
+ if (SEL_WAITING(&kq->kq_sel))
+ kq->kq_state |= KQ_SEL;
}
}
kqueue_release(kq, 1);
@@ -1486,8 +1487,9 @@ kqueue_close(struct file *fp, struct thread *td)
}
if ((kq->kq_state & KQ_SEL) == KQ_SEL) {
- kq->kq_state &= ~KQ_SEL;
selwakeuppri(&kq->kq_sel, PSOCK);
+ if (!SEL_WAITING(&kq->kq_sel))
+ kq->kq_state &= ~KQ_SEL;
}
KQ_UNLOCK(kq);
@@ -1522,8 +1524,9 @@ kqueue_wakeup(struct kqueue *kq)
wakeup(kq);
}
if ((kq->kq_state & KQ_SEL) == KQ_SEL) {
- kq->kq_state &= ~KQ_SEL;
selwakeuppri(&kq->kq_sel, PSOCK);
+ if (!SEL_WAITING(&kq->kq_sel))
+ kq->kq_state &= ~KQ_SEL;
}
if (!knlist_empty(&kq->kq_sel.si_note))
kqueue_schedtask(kq);
OpenPOWER on IntegriCloud