Skip to content

Commit ce4ef87

Browse files
committed
Handle absence of EVFILT_USER with kevent backend.
Some kqueue implementations do not have EVFILT_USER. We can work around this by creating a timer implementation with a very small timeout.[1] [1] Thanks to this post, which provided the idea for the workaround: https://lists.macosforge.org/pipermail/libdispatch-dev/2009-September/000010.html
1 parent c4814ec commit ce4ef87

File tree

1 file changed

+37
-0
lines changed

1 file changed

+37
-0
lines changed

src/event/event_kevent.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,9 @@ _evfiltstr(short filt)
104104
#ifdef EVFILT_FS
105105
_evfilt2(EVFILT_FS);
106106
#endif
107+
#ifdef EVFILT_USER
107108
_evfilt2(EVFILT_USER);
109+
#endif
108110
#ifdef EVFILT_SOCK
109111
_evfilt2(EVFILT_SOCK);
110112
#endif
@@ -532,11 +534,22 @@ _dispatch_kevent_merge_muxed(dispatch_kevent_t ke)
532534
}
533535
}
534536

537+
/*
538+
* If the kevent implementation doesn't support EVFILT_USER for
539+
* signaling, then we use EVFILT_TIMER with EV_ONESHOT with this ident
540+
* to make do.
541+
*/
542+
#define DISPATCH_KEVENT_ERSATZ_EVFILT_USER_IDENT (~0ull << 9)
543+
535544
DISPATCH_NOINLINE
536545
static void
537546
_dispatch_kevent_drain(dispatch_kevent_t ke)
538547
{
548+
#ifdef EVFILT_USER
539549
if (ke->filter == EVFILT_USER) {
550+
#else
551+
if (ke->filter == EVFILT_TIMER && ke->ident == DISPATCH_KEVENT_ERSATZ_EVFILT_USER_IDENT) {
552+
#endif
540553
_dispatch_kevent_mgr_debug("received", ke);
541554
return;
542555
}
@@ -583,10 +596,17 @@ static void
583596
_dispatch_kq_create(intptr_t *fd_ptr)
584597
{
585598
static const dispatch_kevent_s kev = {
599+
#ifdef EVFILT_USER
586600
.ident = 1,
587601
.filter = EVFILT_USER,
588602
.flags = EV_ADD|EV_CLEAR,
589603
.udata = (dispatch_kevent_udata_t)DISPATCH_WLH_MANAGER,
604+
#else
605+
.ident = DISPATCH_KEVENT_ERSATZ_EVFILT_USER_IDENT,
606+
.filter = EVFILT_TIMER,
607+
.flags = EV_ADD|EV_DISABLE|EV_ONESHOT,
608+
.data = 1,
609+
#endif
590610
};
591611
int kqfd;
592612

@@ -789,9 +809,15 @@ _dispatch_kq_drain(dispatch_wlh_t wlh, dispatch_kevent_t ke, int n,
789809

790810
#if DISPATCH_DEBUG
791811
for (r = 0; r < n; r++) {
812+
#ifdef EVFILT_USER
792813
if (ke[r].filter != EVFILT_USER || DISPATCH_MGR_QUEUE_DEBUG) {
793814
_dispatch_kevent_debug_n(NULL, ke + r, r, n);
794815
}
816+
#else
817+
if (DISPATCH_MGR_QUEUE_DEBUG) {
818+
_dispatch_kevent_debug_n(NULL, ke + r, r, n);
819+
}
820+
#endif
795821
}
796822
#endif
797823

@@ -923,9 +949,13 @@ _dispatch_kq_deferred_update(dispatch_wlh_t wlh, dispatch_kevent_t ke)
923949
ke->udata);
924950
dispatch_kevent_t dk = _dispatch_kq_deferred_reuse_slot(wlh, ddi, slot);
925951
*dk = *ke;
952+
#ifdef EVFILT_USER
926953
if (ke->filter != EVFILT_USER) {
927954
_dispatch_kevent_mgr_debug("deferred", ke);
928955
}
956+
#else
957+
_dispatch_kevent_mgr_debug("deferred", ke);
958+
#endif
929959
} else {
930960
_dispatch_kq_update_one(wlh, ke);
931961
}
@@ -1887,10 +1917,17 @@ _dispatch_event_loop_poke(dispatch_wlh_t wlh, uint64_t dq_state, uint32_t flags)
18871917
{
18881918
if (wlh == DISPATCH_WLH_MANAGER) {
18891919
dispatch_kevent_s ke = (dispatch_kevent_s){
1920+
#ifdef EVFILT_USER
18901921
.ident = 1,
18911922
.filter = EVFILT_USER,
18921923
.fflags = NOTE_TRIGGER,
18931924
.udata = (dispatch_kevent_udata_t)DISPATCH_WLH_MANAGER,
1925+
#else
1926+
.ident = DISPATCH_KEVENT_ERSATZ_EVFILT_USER_IDENT,
1927+
.filter = EVFILT_TIMER,
1928+
.flags = EV_ADD|EV_ENABLE|EV_ONESHOT,
1929+
.data = 1
1930+
#endif
18941931
};
18951932
return _dispatch_kq_deferred_update(DISPATCH_WLH_ANON, &ke);
18961933
} else if (wlh && wlh != DISPATCH_WLH_ANON) {

0 commit comments

Comments
 (0)