[libdispatch-dev] [PATCH 2/4] complete separation
Paolo Bonzini
bonzini at gnu.org
Tue Nov 10 03:23:11 PST 2009
---
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
More information about the libdispatch-dev
mailing list