[PATCH 2/4] complete separation
--- src/kevent_internal.h | 6 +--- src/source.c | 52 ++------------------------------- src/source_internal.h | 9 ++++- src/source_kevent.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 84 insertions(+), 60 deletions(-) diff --git a/src/kevent_internal.h b/src/kevent_internal.h index 7109439..3ad63c2 100644 --- a/src/kevent_internal.h +++ b/src/kevent_internal.h @@ -28,6 +28,7 @@ #define __DISPATCH_KEVENT_INTERNAL__ #include <internal.h> +#include <sys/event.h> struct dispatch_kevent_s { TAILQ_ENTRY(dispatch_kevent_s) dk_list; @@ -35,11 +36,6 @@ struct dispatch_kevent_s { struct kevent dk_kevent; }; -#define DISPATCH_EVFILT_TIMER (-EVFILT_SYSCOUNT - 1) -#define DISPATCH_EVFILT_CUSTOM_ADD (-EVFILT_SYSCOUNT - 2) -#define DISPATCH_EVFILT_CUSTOM_OR (-EVFILT_SYSCOUNT - 3) -#define DISPATCH_EVFILT_SYSCOUNT (EVFILT_SYSCOUNT + 3) - extern const struct dispatch_source_vtable_s _dispatch_source_kevent_vtable; #if DISPATCH_DEBUG diff --git a/src/source.c b/src/source.c index f2ccd82..01061a4 100644 --- a/src/source.c +++ b/src/source.c @@ -25,8 +25,6 @@ #endif #include <sys/mount.h> -#include "kevent_internal.h" - #ifndef DISPATCH_NO_LEGACY struct dispatch_source_attr_vtable_s { DISPATCH_VTABLE_HEADER(dispatch_source_attr_s); @@ -392,48 +390,17 @@ dispatch_source_create(dispatch_source_type_t type, unsigned long mask, dispatch_queue_t q) { - const struct kevent *proto_kev = &type->ke; dispatch_source_t ds = NULL; - dispatch_kevent_t dk = NULL; // input validation if (type == NULL || (mask & ~type->mask)) { goto out_bad; } - switch (type->ke.filter) { - case EVFILT_SIGNAL: - if (handle >= NSIG) { - goto out_bad; - } - break; - case EVFILT_FS: - case DISPATCH_EVFILT_CUSTOM_ADD: - case DISPATCH_EVFILT_CUSTOM_OR: - case DISPATCH_EVFILT_TIMER: - if (handle) { - goto out_bad; - } - break; - default: - break; - } - ds = calloc(1ul, sizeof(struct dispatch_source_s)); if (slowpath(!ds)) { goto out_bad; } - dk = calloc(1ul, sizeof(struct dispatch_kevent_s)); - if (slowpath(!dk)) { - goto out_bad; - } - - dk->dk_kevent = *proto_kev; - dk->dk_kevent.ident = handle; - dk->dk_kevent.flags |= EV_ADD|EV_ENABLE; - dk->dk_kevent.fflags |= (uint32_t)mask; - dk->dk_kevent.udata = dk; - TAILQ_INIT(&dk->dk_sources); // Initialize as a queue first, then override some settings below. _dispatch_queue_init((dispatch_queue_t)ds); @@ -446,22 +413,10 @@ dispatch_source_create(dispatch_source_type_t type, // do_targetq will be retained below, past point of no-return ds->do_targetq = q; - // Dispatch Source - ds->ds_ident_hack = dk->dk_kevent.ident; - ds->ds_dkev = dk; - ds->ds_pending_data_mask = dk->dk_kevent.fflags; - if ((EV_DISPATCH|EV_ONESHOT) & proto_kev->flags) { - ds->ds_is_level = true; - ds->ds_needs_rearm = true; - } else if (!(EV_CLEAR & proto_kev->flags)) { - // we cheat and use EV_CLEAR to mean a "flag thingy" - ds->ds_is_adder = true; - } - - // Some sources require special processing - if (type->init != NULL) { - type->init(ds, type, handle, mask, q); + if (slowpath (!type->init(ds, type, handle, mask, q))) { + goto out_bad; } + dispatch_assert(!(ds->ds_is_level && ds->ds_is_adder)); #if DISPATCH_DEBUG dispatch_debug(ds, __FUNCTION__); @@ -472,7 +427,6 @@ dispatch_source_create(dispatch_source_type_t type, out_bad: free(ds); - free(dk); return NULL; } diff --git a/src/source_internal.h b/src/source_internal.h index e247e4a..222a85d 100644 --- a/src/source_internal.h +++ b/src/source_internal.h @@ -103,17 +103,22 @@ dispatch_queue_t _dispatch_source_invoke(dispatch_source_t ds); bool _dispatch_source_probe(dispatch_source_t ds); void _dispatch_source_dispose(dispatch_source_t ds); size_t _dispatch_source_debug(dispatch_source_t ds, char* buf, size_t bufsiz); -void _dispatch_source_merge_kevent(dispatch_source_t ds, const struct kevent *ke); void _dispatch_source_kevent_resume(dispatch_source_t ds, uint32_t new_flags, uint32_t del_flags); void _dispatch_kevent_merge(dispatch_source_t ds); void _dispatch_kevent_release(dispatch_source_t ds); void _dispatch_timer_list_update(dispatch_source_t ds); +#ifdef __linux__ +/* In the future, Linux may use epoll or libevent or something like that. + For now, this lets it compile except for the kqueue bits. */ +struct kevent {}; +#endif + struct dispatch_source_type_s { struct kevent ke; uint64_t mask; - void (*init) (dispatch_source_t ds, + bool (*init) (dispatch_source_t ds, dispatch_source_type_t type, uintptr_t handle, unsigned long mask, diff --git a/src/source_kevent.c b/src/source_kevent.c index 2c5a508..0e1d34f 100644 --- a/src/source_kevent.c +++ b/src/source_kevent.c @@ -73,6 +73,7 @@ static struct dispatch_kevent_s _dispatch_kevent_data_add = { .dk_sources = TAILQ_HEAD_INITIALIZER(_dispatch_kevent_data_add.dk_sources), }; +static void _dispatch_source_merge_kevent(dispatch_source_t ds, const struct kevent *ke); static void _dispatch_kevent_resume(dispatch_kevent_t dk, uint32_t new_flags, uint32_t del_flags); #if HAVE_MACH static void _dispatch_kevent_machport_resume(dispatch_kevent_t dk, uint32_t new_flags, uint32_t del_flags); @@ -569,11 +570,63 @@ dispatch_source_merge_data(dispatch_source_t ds, unsigned long val) _dispatch_source_merge_kevent(ds, &kev); } -static void -dispatch_source_type_timer_init(dispatch_source_t ds, dispatch_source_type_t type, uintptr_t handle, unsigned long mask, dispatch_queue_t q) +static bool dispatch_source_type_kevent_init (dispatch_source_t ds, dispatch_source_type_t type, uintptr_t handle, unsigned long mask, dispatch_queue_t q) { + const struct kevent *proto_kev = &type->ke; + dispatch_kevent_t dk = NULL; + + switch (type->ke.filter) { + case EVFILT_SIGNAL: + if (handle >= NSIG) { + return false; + } + break; + case EVFILT_FS: + case DISPATCH_EVFILT_CUSTOM_ADD: + case DISPATCH_EVFILT_CUSTOM_OR: + case DISPATCH_EVFILT_TIMER: + if (handle) { + return false; + } + break; + default: + break; + } + + dk = calloc(1ul, sizeof(struct dispatch_kevent_s)); + if (slowpath(!dk)) { + return false; + } + + dk->dk_kevent = *proto_kev; + dk->dk_kevent.ident = handle; + dk->dk_kevent.flags |= EV_ADD|EV_ENABLE; + dk->dk_kevent.fflags |= (uint32_t)mask; + dk->dk_kevent.udata = dk; + TAILQ_INIT(&dk->dk_sources); + + // Dispatch Source + ds->ds_ident_hack = dk->dk_kevent.ident; + ds->ds_dkev = dk; + ds->ds_pending_data_mask = dk->dk_kevent.fflags; + if ((EV_DISPATCH|EV_ONESHOT) & proto_kev->flags) { + ds->ds_is_level = true; + ds->ds_needs_rearm = true; + } else if (!(EV_CLEAR & proto_kev->flags)) { + // we cheat and use EV_CLEAR to mean a "flag thingy" + ds->ds_is_adder = true; + } + return true; +} + +static bool dispatch_source_type_timer_init (dispatch_source_t ds, dispatch_source_type_t type, uintptr_t handle, unsigned long mask, dispatch_queue_t q) +{ + if (!dispatch_source_type_kevent_init (ds, type, handle, mask, q)) { + return false; + } ds->ds_needs_rearm = true; ds->ds_timer.flags = mask; + return true; } const struct dispatch_source_type_s _dispatch_source_type_timer = { @@ -589,6 +642,7 @@ const struct dispatch_source_type_s _dispatch_source_type_read = { .filter = EVFILT_READ, .flags = EV_DISPATCH, }, + .init = dispatch_source_type_kevent_init }; const struct dispatch_source_type_s _dispatch_source_type_write = { @@ -596,6 +650,7 @@ const struct dispatch_source_type_s _dispatch_source_type_write = { .filter = EVFILT_WRITE, .flags = EV_DISPATCH, }, + .init = dispatch_source_type_kevent_init }; const struct dispatch_source_type_s _dispatch_source_type_proc = { @@ -611,12 +666,14 @@ const struct dispatch_source_type_s _dispatch_source_type_proc = { |NOTE_REAP #endif , + .init = dispatch_source_type_kevent_init }; const struct dispatch_source_type_s _dispatch_source_type_signal = { .ke = { .filter = EVFILT_SIGNAL, }, + .init = dispatch_source_type_kevent_init }; const struct dispatch_source_type_s _dispatch_source_type_vnode = { @@ -630,6 +687,7 @@ const struct dispatch_source_type_s _dispatch_source_type_vnode = { |NOTE_NONE #endif , + .init = dispatch_source_type_kevent_init }; const struct dispatch_source_type_s _dispatch_source_type_vfs = { @@ -646,17 +704,22 @@ const struct dispatch_source_type_s _dispatch_source_type_vfs = { |VQ_VERYLOWDISK #endif , + .init = dispatch_source_type_kevent_init }; #if HAVE_MACH -static void +static bool dispatch_source_type_mach_send_init(dispatch_source_t ds, dispatch_source_type_t type, uintptr_t handle, unsigned long mask, dispatch_queue_t q) { static dispatch_once_t pred; + if (!dispatch_source_type_kevent_init (ds, type, handle, mask, q)) { + return false; + } ds->ds_is_level = false; dispatch_once_f(&pred, NULL, _dispatch_mach_notify_source_init); + return true; } const struct dispatch_source_type_s _dispatch_source_type_mach_send = { @@ -669,10 +732,14 @@ const struct dispatch_source_type_s _dispatch_source_type_mach_send = { .init = dispatch_source_type_mach_send_init, }; -static void +static bool dispatch_source_type_mach_recv_init(dispatch_source_t ds, dispatch_source_type_t type, uintptr_t handle, unsigned long mask, dispatch_queue_t q) { + if (!dispatch_source_type_kevent_init (ds, type, handle, mask, q)) { + return false; + } ds->ds_is_level = false; + return true; } const struct dispatch_source_type_s _dispatch_source_type_mach_recv = { @@ -689,6 +756,7 @@ const struct dispatch_source_type_s _dispatch_source_type_data_add = { .ke = { .filter = DISPATCH_EVFILT_CUSTOM_ADD, }, + .init = dispatch_source_type_kevent_init, }; const struct dispatch_source_type_s _dispatch_source_type_data_or = { @@ -697,6 +765,7 @@ const struct dispatch_source_type_s _dispatch_source_type_data_or = { .flags = EV_CLEAR, .fflags = ~0, }, + .init = dispatch_source_type_kevent_init }; // Updates the ordered list of timers based on next fire date for changes to ds. -- 1.6.2.5
On 11/10/2009 12:55 PM, Robert Watson wrote:
On Tue, 10 Nov 2009, Paolo Bonzini wrote:
---
I assume that there was a patch 1/4 that hasn't made it through the moderator yet due to size? If so, I'll await that before starting on the rest.
Yes. 4/4 is independent though, it is just a portability fix. Paolo
On Tue, 10 Nov 2009, Paolo Bonzini wrote:
I assume that there was a patch 1/4 that hasn't made it through the moderator yet due to size? If so, I'll await that before starting on the rest.
Yes. 4/4 is independent though, it is just a portability fix.
Merged as r147. There were conflicts as it was incremental with respect to other changes to the same function, and I also tweaked the style so it uses sizeof() in the style of a function as appears elsewhere in libdispatch. Robert
On Nov 10, 2009, at 4:39 AM, Paolo Bonzini wrote:
On 11/10/2009 12:55 PM, Robert Watson wrote:
On Tue, 10 Nov 2009, Paolo Bonzini wrote:
---
I assume that there was a patch 1/4 that hasn't made it through the moderator yet due to size? If so, I'll await that before starting on the rest.
Yes. 4/4 is independent though, it is just a portability fix.
I've bumped up the message size limit to 200K, so hopefully most patches will make it through now. -Bill
On Tue, 10 Nov 2009, Paolo Bonzini wrote:
--- src/kevent_internal.h | 6 +--- src/source.c | 52 ++------------------------------- src/source_internal.h | 9 ++++- src/source_kevent.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 84 insertions(+), 60 deletions(-)
Committed as r153 with some minor refinements, such as adopting house style (real tabs, no space between function name and parens on invocation, ',' after last entry in a C99-initialized data structure). I also removed the empty __linux__ struct kevent definition -- I'm pondering whether it's worth adding a check for struct kevent in configure.ac, but since we only support kqueue as an event source currently I'm not sure of the benefit is too concreate. If we do want to build without kqueue for build-checking purposes, then doing it via configure is probably the right way so that it also works on Linux? Thanks! Robert N M Watson Computer Laboratory University of Cambridge
participants (3)
-
Paolo Bonzini
-
Robert Watson
-
William Siegrist