[libdispatch-dev] [PATCH 16/17] complete separation

Paolo Bonzini bonzini at gnu.org
Sun Oct 18 08:04:16 PDT 2009


Here I rely on the initialization hook that I created earlier,
to move the kevent-specific parts of dispatch_source_create away.
I need a small change in the interface of the hook, that didn't
make sense at the time I introduced the hook itself.  This is
needed especially because allocation of the dispatch_kevent_t
is moved to source_kevent.c (source.c sees it as opaque).

The only file left referring to struct kevent is source_internal.h.
---
 src/kevent_internal.h |    6 +---
 src/source.c          |   52 ++----------------------------
 src/source_internal.h |    3 +-
 src/source_kevent.c   |   85 +++++++++++++++++++++++++++++++++++++++++++++++--
 4 files changed, 87 insertions(+), 59 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 c071c11..5c3fbfe 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);
@@ -391,9 +389,7 @@ 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;
 	static char source_label[sizeof ds->dq_label] = "source";
 
 	// input validation
@@ -401,39 +397,10 @@ dispatch_source_create(dispatch_source_type_t type,
 		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) {
-		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 279edc3..3711649 100644
--- a/src/source_internal.h
+++ b/src/source_internal.h
@@ -103,7 +103,6 @@ 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);
@@ -113,7 +112,7 @@ void _dispatch_timer_list_update(dispatch_source_t ds);
 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 0697e9c..6554040 100644
--- a/src/source_kevent.c
+++ b/src/source_kevent.c
@@ -26,6 +26,11 @@
 #endif
 #include <sys/mount.h>
 
+#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)
+
 static struct dispatch_kevent_s _dispatch_kevent_timer[] = {
 	{
 		.dk_kevent = {
@@ -62,6 +67,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);
 #ifdef HAVE_MACH
 static void _dispatch_kevent_machport_resume(dispatch_kevent_t dk, uint32_t new_flags, uint32_t del_flags);
@@ -559,14 +565,71 @@ 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,
+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 = {
@@ -582,6 +645,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 = {
@@ -589,6 +653,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 = {
@@ -604,12 +669,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 = {
@@ -623,6 +690,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 = {
@@ -639,19 +707,24 @@ const struct dispatch_source_type_s _dispatch_source_type_vfs = {
 	    |VQ_VERYLOWDISK
 #endif
 	    ,
+	.init = dispatch_source_type_kevent_init
 };
 
 #ifdef HAVE_MACH
 
-static void dispatch_source_type_mach_send_init (dispatch_source_t ds,
+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 = {
@@ -664,13 +737,17 @@ const struct dispatch_source_type_s _dispatch_source_type_mach_send = {
 	.init = dispatch_source_type_mach_send_init
 };
 
-static void dispatch_source_type_mach_recv_init (dispatch_source_t ds,
+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 = {
@@ -687,6 +764,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 = {
@@ -695,6 +773,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