[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