[launchd-changes] [22851] trunk/launchd/src

source_changes at macosforge.org source_changes at macosforge.org
Tue Sep 12 15:46:18 PDT 2006


Revision: 22851
Author:   zarzycki at apple.com
Date:     2006-09-12 15:46:16 -0700 (Tue, 12 Sep 2006)

Log Message:
-----------
Part two of the new runtime system.

Modified Paths:
--------------
    trunk/launchd/src/launchd_core_logic.c
    trunk/launchd/src/launchd_mach_ipc.c
    trunk/launchd/src/launchd_runtime.c
    trunk/launchd/src/launchd_runtime.h

Modified: trunk/launchd/src/launchd_core_logic.c
===================================================================
--- trunk/launchd/src/launchd_core_logic.c	2006-09-11 21:08:28 UTC (rev 22850)
+++ trunk/launchd/src/launchd_core_logic.c	2006-09-12 22:46:16 UTC (rev 22851)
@@ -293,7 +293,7 @@
 		watchpath_ignore(j, wp);
 
 	SLIST_FOREACH(ms, &j->machservices, sle)
-		job_assumes(j, launchd_mport_request_callback(ms->port, NULL, false) == KERN_SUCCESS);
+		job_assumes(j, runtime_remove_mport(ms->port) == KERN_SUCCESS);
 }
 
 void
@@ -310,7 +310,7 @@
 		watchpath_watch(j, wp);
 
 	SLIST_FOREACH(ms, &j->machservices, sle)
-		job_assumes(j, launchd_mport_request_callback(ms->port, j, false) == KERN_SUCCESS);
+		job_assumes(j, runtime_add_mport(ms->port, NULL, 0) == KERN_SUCCESS);
 }
 
 void
@@ -572,10 +572,17 @@
 bool
 job_setup_machport(job_t j)
 {
+	mach_msg_size_t mxmsgsz;
+
 	if (!job_assumes(j, launchd_mport_create_recv(&j->bs_port) == KERN_SUCCESS))
 		goto out_bad;
 
-	if (!job_assumes(j, launchd_mport_request_callback(j->bs_port, j, true) == KERN_SUCCESS))
+	/* Sigh... at the moment, MIG has maxsize == sizeof(reply union) */
+	mxmsgsz = sizeof(union __RequestUnion__x_bootstrap_subsystem);
+	if (x_bootstrap_subsystem.maxsize > mxmsgsz)
+		mxmsgsz = x_bootstrap_subsystem.maxsize;
+
+	if (!job_assumes(j, runtime_add_mport(j->bs_port, bootstrap_server, mxmsgsz) == KERN_SUCCESS))
 		goto out_bad2;
 
 	return true;
@@ -2641,6 +2648,7 @@
 job_new_bootstrap(job_t p, mach_port_t requestorport, mach_port_t checkin_port)
 {
 	char bslabel[1024] = "100000";
+	mach_msg_size_t mxmsgsz;
 	job_t j;
 
 	if (requestorport == MACH_PORT_NULL) {
@@ -2663,7 +2671,12 @@
 
 	sprintf(j->label, "%d", MACH_PORT_INDEX(j->bs_port));
 
-	if (!job_assumes(j, launchd_mport_request_callback(j->bs_port, j, true) == KERN_SUCCESS))
+	/* Sigh... at the moment, MIG has maxsize == sizeof(reply union) */
+	mxmsgsz = sizeof(union __RequestUnion__x_bootstrap_subsystem);
+	if (x_bootstrap_subsystem.maxsize > mxmsgsz)
+		mxmsgsz = x_bootstrap_subsystem.maxsize;
+
+	if (!job_assumes(j, runtime_add_mport(j->bs_port, bootstrap_server, mxmsgsz) == KERN_SUCCESS))
 		goto out_bad;
 
 	if (p) {

Modified: trunk/launchd/src/launchd_mach_ipc.c
===================================================================
--- trunk/launchd/src/launchd_mach_ipc.c	2006-09-11 21:08:28 UTC (rev 22850)
+++ trunk/launchd/src/launchd_mach_ipc.c	2006-09-12 22:46:16 UTC (rev 22851)
@@ -57,7 +57,6 @@
 #include "bootstrap_private.h"
 #include "bootstrap.h"
 #include "bootstrapServer.h"
-#include "launchd_internal.h"
 #include "launchd.h"
 #include "launchd_runtime.h"
 #include "launchd_core_logic.h"
@@ -448,7 +447,7 @@
 	*reqport = job_get_reqport(j);
 	*rcvright = job_get_bsport(j);
 
-	launchd_assumes(launchd_mport_request_callback(*rcvright, NULL, true) == KERN_SUCCESS);
+	launchd_assumes(runtime_remove_mport(*rcvright) == KERN_SUCCESS);
 
 	launchd_assumes(launchd_mport_make_send(*rcvright) == KERN_SUCCESS);
 

Modified: trunk/launchd/src/launchd_runtime.c
===================================================================
--- trunk/launchd/src/launchd_runtime.c	2006-09-11 21:08:28 UTC (rev 22850)
+++ trunk/launchd/src/launchd_runtime.c	2006-09-12 22:46:16 UTC (rev 22851)
@@ -57,7 +57,6 @@
 #include "launch.h"
 #include "launchd.h"
 #include "launchd_core_logic.h"
-#include "bootstrapServer.h"
 
 static mach_port_t ipc_port_set = MACH_PORT_NULL;
 static mach_port_t demand_port_set = MACH_PORT_NULL;
@@ -66,7 +65,7 @@
 static int asynckq = -1;
 
 static pthread_t kqueue_demand_thread;
-static pthread_t demand_thread;;
+static pthread_t demand_thread;
 
 static void *mport_demand_loop(void *arg);
 static void *kqueue_demand_loop(void *arg);
@@ -74,9 +73,17 @@
 static void async_callback(void);
 static kq_callback kqasync_callback = (kq_callback)async_callback;
 
+static void launchd_runtime2(mach_msg_size_t msg_size, mig_reply_error_t *bufRequest, mig_reply_error_t *bufReply);
+static mach_msg_size_t max_msg_size;
+static mig_callback *mig_cb_table;
+static size_t mig_cb_table_sz;
+static timeout_callback runtime_idle_callback;
+static mach_msg_timeout_t runtime_idle_timeout;
+
 void
 launchd_runtime_init(void)
 {
+	mach_msg_size_t mxmsgsz;
 	pthread_attr_t attr;
 
 	launchd_assert((mainkq = kqueue()) != -1);
@@ -89,8 +96,14 @@
 
 	launchd_assert(launchd_mport_create_recv(&launchd_internal_port) == KERN_SUCCESS);
 	launchd_assert(launchd_mport_make_send(launchd_internal_port) == KERN_SUCCESS);
-	launchd_assert((errno = mach_port_move_member(mach_task_self(), launchd_internal_port, ipc_port_set)) == KERN_SUCCESS);
 
+	/* Sigh... at the moment, MIG has maxsize == sizeof(reply union) */
+	mxmsgsz = sizeof(union __RequestUnion__x_launchd_internal_subsystem);
+	if (x_launchd_internal_subsystem.maxsize > mxmsgsz)
+		mxmsgsz = x_launchd_internal_subsystem.maxsize;
+
+	launchd_assert(runtime_add_mport(launchd_internal_port, launchd_internal_demux, mxmsgsz) == KERN_SUCCESS);
+
 	pthread_attr_init(&attr);
 	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 	pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);
@@ -193,14 +206,33 @@
 void
 launchd_runtime(void)
 {
-	mach_msg_return_t msgr;
+	mig_reply_error_t *req = NULL, *rep = NULL;
+	mach_msg_size_t mz = max_msg_size;
+	kern_return_t kr;
 
 	for (;;) {
-		msgr = mach_msg_server(launchd_internal_demux, 10*1024, ipc_port_set,
-				MACH_RCV_LARGE |
-				MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT) |
-				MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0));
-		launchd_assumes(msgr == MACH_MSG_SUCCESS);
+		kr = vm_allocate(mach_task_self(), (vm_address_t *)&req, mz, VM_MAKE_TAG(VM_MEMORY_MACH_MSG)|TRUE);
+		if (!launchd_assumes(kr == KERN_SUCCESS)) {
+			goto free_path;
+		}
+
+		kr = vm_allocate(mach_task_self(), (vm_address_t *)&rep, mz, VM_MAKE_TAG(VM_MEMORY_MACH_MSG)|TRUE);
+		if (!launchd_assumes(kr == KERN_SUCCESS)) {
+			goto free_path;
+		}
+
+		/* max_msg_size might change, thus phase two... */
+		launchd_runtime2(mz, req, rep);
+
+free_path:
+		if (req) {
+			launchd_assumes(vm_deallocate(mach_task_self(), (vm_address_t)req, mz) == KERN_SUCCESS);
+			req = NULL;
+		}
+		if (rep) {
+			launchd_assumes(vm_deallocate(mach_task_self(), (vm_address_t)rep, mz) == KERN_SUCCESS);
+			rep = NULL;
+		}
 	}
 }
 
@@ -238,19 +270,55 @@
 	return errno;
 }
 
+void
+runtime_set_timeout(timeout_callback to_cb, mach_msg_timeout_t to)
+{
+	if (to == 0 || to_cb == NULL) {
+		runtime_idle_callback = NULL;
+		runtime_idle_timeout = 0;
+	}
+
+	runtime_idle_callback = to_cb;
+	runtime_idle_timeout = to;
+}
+
 kern_return_t
-launchd_mport_request_callback(mach_port_t name, void *obj, bool readmsg)
+runtime_add_mport(mach_port_t name, mig_callback demux, mach_msg_size_t msg_size)
 {
-	mach_port_t target_set = MACH_PORT_NULL;
+	size_t needed_table_sz = MACH_PORT_INDEX(name) * 2 * sizeof(mig_callback);
+	mach_port_t target_set = demux ? ipc_port_set : demand_port_set;
 
-	if (obj) {
-		target_set = readmsg ? ipc_port_set : demand_port_set;
+	msg_size = round_page(msg_size + MAX_TRAILER_SIZE);
+
+	if (needed_table_sz > mig_cb_table_sz) {
+		mig_callback *new_table = malloc(needed_table_sz);
+
+		if (!launchd_assumes(new_table != NULL))
+			return KERN_RESOURCE_SHORTAGE;
+
+		memcpy(new_table, mig_cb_table, mig_cb_table_sz);
+		memset(new_table + mig_cb_table_sz, 0, needed_table_sz - mig_cb_table_sz);
+
+		mig_cb_table_sz = needed_table_sz;
+		mig_cb_table = new_table;
 	}
 
+	mig_cb_table[MACH_PORT_INDEX(name)] = demux;
+
+	if (msg_size > max_msg_size) {
+		max_msg_size = msg_size;
+	}
+
 	return errno = mach_port_move_member(mach_task_self(), name, target_set);
 }
 
 kern_return_t
+runtime_remove_mport(mach_port_t name)
+{
+	return errno = mach_port_move_member(mach_task_self(), name, MACH_PORT_NULL);
+}
+
+kern_return_t
 launchd_mport_make_send(mach_port_t name)
 {
 	return errno = mach_port_insert_right(mach_task_self(), name, name, MACH_MSG_TYPE_MAKE_SEND);
@@ -313,19 +381,10 @@
 boolean_t
 launchd_internal_demux(mach_msg_header_t *Request, mach_msg_header_t *Reply)
 {
-	if (gc_this_job) {
-		job_remove(gc_this_job);
-		gc_this_job = NULL;
+	if (launchd_internal_server_routine(Request)) {
+		return launchd_internal_server(Request, Reply);
 	}
 
-	if (Request->msgh_local_port == launchd_internal_port) {
-		if (launchd_internal_server_routine(Request))
-			return launchd_internal_server(Request, Reply);
-	} else {
-		if (bootstrap_server_routine(Request))
-			return bootstrap_server(Request, Reply);
-	}
-
 	return notify_server(Request, Reply);
 }
 
@@ -402,3 +461,105 @@
 
 	return KERN_SUCCESS;
 }
+
+void
+launchd_runtime2(mach_msg_size_t msg_size, mig_reply_error_t *bufRequest, mig_reply_error_t *bufReply)
+{
+	mach_msg_options_t options, tmp_options;
+	mig_reply_error_t *bufTemp;
+	mig_callback the_demux;
+	mach_msg_timeout_t to;
+	mach_msg_return_t mr;
+
+	options = MACH_RCV_MSG|MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT) |
+		MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0);
+
+	tmp_options = options;
+
+	for (;;) {
+		to = MACH_MSG_TIMEOUT_NONE;
+
+		if (msg_size != max_msg_size) {
+			/* The buffer isn't big enougth to receive messages anymore... */
+			tmp_options &= ~MACH_RCV_MSG;
+			options &= ~MACH_RCV_MSG;
+			if (!(tmp_options & MACH_SEND_MSG)) {
+				return;
+			}
+		}
+
+		if ((tmp_options & MACH_RCV_MSG) && runtime_idle_callback) {
+			tmp_options |= MACH_RCV_TIMEOUT;
+
+			if (!(tmp_options & MACH_SEND_TIMEOUT)) {
+				to = runtime_idle_timeout;
+			}
+		}
+
+		mr = mach_msg(&bufReply->Head, tmp_options, bufReply->Head.msgh_size,
+				msg_size, ipc_port_set, to, MACH_PORT_NULL);
+
+		tmp_options = options;
+
+		if (mr == MACH_SEND_INVALID_DEST || mr == MACH_SEND_TIMED_OUT) {
+			/* We need to clean up and start over. */
+			if (bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) {
+				mach_msg_destroy(&bufReply->Head);
+			}
+			continue;
+		} else if (mr == MACH_RCV_TIMED_OUT) {
+			if (to == MACH_MSG_TIMEOUT_NONE) {
+				continue;
+			}
+			runtime_idle_callback();
+		} else if (!launchd_assumes(mr == MACH_MSG_SUCCESS)) {
+			continue;
+		}
+
+		bufTemp = bufRequest;
+		bufRequest = bufReply;
+		bufReply = bufTemp;
+
+		/* XXX - So very gross */
+		if (gc_this_job) {
+			job_remove(gc_this_job);
+			gc_this_job = NULL;
+		}
+
+		if (!(tmp_options & MACH_RCV_MSG)) {
+			continue;
+		}
+
+		/* we have another request message */
+		the_demux = mig_cb_table[MACH_PORT_INDEX(bufRequest->Head.msgh_local_port)];
+
+		if (!launchd_assumes(the_demux != NULL)) {
+			break;
+		}
+
+		if (the_demux(&bufRequest->Head, &bufReply->Head) == FALSE) {
+			/* XXX - also gross */
+			if (bufRequest->Head.msgh_id == MACH_NOTIFY_NO_SENDERS) {
+				notify_server(&bufRequest->Head, &bufReply->Head);
+			}
+		}
+
+		if (!(bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX)) {
+			if (bufReply->RetCode == MIG_NO_REPLY) {
+				bufReply->Head.msgh_remote_port = MACH_PORT_NULL;
+			} else if ((bufReply->RetCode != KERN_SUCCESS) && (bufRequest->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX)) {
+				/* destroy the request - but not the reply port */
+				bufRequest->Head.msgh_remote_port = MACH_PORT_NULL;
+				mach_msg_destroy(&bufRequest->Head);
+			}
+		}
+
+		if (bufReply->Head.msgh_remote_port != MACH_PORT_NULL) {
+			tmp_options |= MACH_SEND_MSG;
+
+			if (MACH_MSGH_BITS_REMOTE(bufReply->Head.msgh_bits) != MACH_MSG_TYPE_MOVE_SEND_ONCE) {
+				tmp_options |= MACH_SEND_TIMEOUT;
+			}
+		}
+	}
+}

Modified: trunk/launchd/src/launchd_runtime.h
===================================================================
--- trunk/launchd/src/launchd_runtime.h	2006-09-11 21:08:28 UTC (rev 22850)
+++ trunk/launchd/src/launchd_runtime.h	2006-09-12 22:46:16 UTC (rev 22851)
@@ -38,6 +38,8 @@
 void _log_launchd_bug(const char *rcs_rev, const char *path, unsigned int line, const char *test);
 
 typedef void (*kq_callback)(void *, struct kevent *);
+typedef boolean_t (*mig_callback)(mach_msg_header_t *, mach_msg_header_t *);
+typedef void (*timeout_callback)(void);
 
 boolean_t launchd_internal_demux(mach_msg_header_t *Request, mach_msg_header_t *Reply);
 
@@ -45,6 +47,9 @@
 void launchd_runtime(void) __attribute__((noreturn));
 
 void runtime_force_on_demand(bool);
+void runtime_set_timeout(timeout_callback to_cb, mach_msg_timeout_t to);
+kern_return_t runtime_add_mport(mach_port_t name, mig_callback demux, mach_msg_size_t msg_size);
+kern_return_t runtime_remove_mport(mach_port_t name);
 
 int kevent_mod(uintptr_t ident, short filter, u_short flags, u_int fflags, intptr_t data, void *udata);
 
@@ -52,7 +57,6 @@
 kern_return_t launchd_get_bport(mach_port_t *name);
 kern_return_t launchd_mport_notify_req(mach_port_t name, mach_msg_id_t which);
 kern_return_t launchd_mport_notify_cancel(mach_port_t name, mach_msg_id_t which);
-kern_return_t launchd_mport_request_callback(mach_port_t name, void *obj, bool readmsg);
 kern_return_t launchd_mport_create_recv(mach_port_t *name);
 kern_return_t launchd_mport_deallocate(mach_port_t name);
 kern_return_t launchd_mport_make_send(mach_port_t name);

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/launchd-changes/attachments/20060912/27a8c118/attachment.html


More information about the launchd-changes mailing list