svn commit: r295786 - in head: sys/kern tests/sys/kqueue
Mark Johnston
markj at FreeBSD.org
Fri Feb 19 01:49:34 UTC 2016
Author: markj
Date: Fri Feb 19 01:49:33 2016
New Revision: 295786
URL: https://svnweb.freebsd.org/changeset/base/295786
Log:
Ensure that we test the event condition when a disabled kevent is enabled.
r274560 modified kqueue_register() to only test the event condition if the
corresponding knote is not disabled. However, this check takes place before
the EV_ENABLE flag is used to clear the KN_DISABLED flag on the knote, so
enabling a previously-disabled kevent would not result in a notification for
a triggered event. This change fixes the problem by testing for EV_ENABLED
before possibly checking the event condition.
This change also updates a kqueue regression test to exercise this case.
PR: 206368
Reviewed by: kib
Sponsored by: EMC / Isilon Storage Division
Differential Revision: https://reviews.freebsd.org/D5307
Modified:
head/sys/kern/kern_event.c
head/tests/sys/kqueue/read.c
Modified: head/sys/kern/kern_event.c
==============================================================================
--- head/sys/kern/kern_event.c Fri Feb 19 01:35:01 2016 (r295785)
+++ head/sys/kern/kern_event.c Fri Feb 19 01:49:33 2016 (r295786)
@@ -1323,27 +1323,24 @@ findkn:
* kn_knlist.
*/
done_ev_add:
- if ((kev->flags & EV_DISABLE) &&
- ((kn->kn_status & KN_DISABLED) == 0)) {
+ if ((kev->flags & EV_ENABLE) != 0)
+ kn->kn_status &= ~KN_DISABLED;
+ else if ((kev->flags & EV_DISABLE) != 0)
kn->kn_status |= KN_DISABLED;
- }
if ((kn->kn_status & KN_DISABLED) == 0)
event = kn->kn_fop->f_event(kn, 0);
else
event = 0;
+
KQ_LOCK(kq);
if (event)
- KNOTE_ACTIVATE(kn, 1);
+ kn->kn_status |= KN_ACTIVE;
+ if ((kn->kn_status & (KN_ACTIVE | KN_DISABLED | KN_QUEUED)) ==
+ KN_ACTIVE)
+ knote_enqueue(kn);
kn->kn_status &= ~(KN_INFLUX | KN_SCAN);
KN_LIST_UNLOCK(kn);
-
- if ((kev->flags & EV_ENABLE) && (kn->kn_status & KN_DISABLED)) {
- kn->kn_status &= ~KN_DISABLED;
- if ((kn->kn_status & KN_ACTIVE) &&
- ((kn->kn_status & KN_QUEUED) == 0))
- knote_enqueue(kn);
- }
KQ_UNLOCK_FLUX(kq);
done:
Modified: head/tests/sys/kqueue/read.c
==============================================================================
--- head/tests/sys/kqueue/read.c Fri Feb 19 01:35:01 2016 (r295785)
+++ head/tests/sys/kqueue/read.c Fri Feb 19 01:49:33 2016 (r295786)
@@ -124,15 +124,17 @@ test_kevent_socket_disable_and_enable(vo
test_begin(test_id);
- /* Add an event, then disable it. */
- EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]);
- if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
- err(1, "%s", test_id);
- EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DISABLE, 0, 0, &sockfd[0]);
+ /*
+ * Write to the socket before adding the event. This way we can verify that
+ * enabling a triggered kevent causes the event to be returned immediately.
+ */
+ kevent_socket_fill();
+
+ /* Add a disabled event. */
+ EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISABLE, 0, 0, &sockfd[0]);
if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
err(1, "%s", test_id);
- kevent_socket_fill();
test_no_kevents();
/* Re-enable the knote, then see if an event is generated */
More information about the svn-src-all
mailing list