+ port = semaphore->port;
+
+ if (!IP_VALID(port)) {
+ port = ipc_port_alloc_kernel();
+ assert(IP_VALID(port));
+ ipc_kobject_set_atomically(port, (ipc_kobject_t) semaphore, IKOT_SEMAPHORE);
+
+ /* If we lose the race, deallocate and pick up the other guy's port */
+ if (!OSCompareAndSwapPtr(IP_NULL, port, &semaphore->port)) {
+ ipc_port_dealloc_kernel(port);
+ port = semaphore->port;
+ assert(ip_kotype(port) == IKOT_SEMAPHORE);
+ assert(port->ip_kobject == (ipc_kobject_t)semaphore);
+ }
+ }
+
+ ip_lock(port);
+ assert(ip_active(port));
+ send = ipc_port_make_send_locked(port);
+
+ if (1 == port->ip_srights) {
+ ipc_port_t old_notify;
+
+ /* transfer our ref to the port, and arm the no-senders notification */
+ assert(IP_NULL == port->ip_nsrequest);
+ ipc_port_nsrequest(port, port->ip_mscount, ipc_port_make_sonce_locked(port), &old_notify);
+ /* port unlocked */
+ assert(IP_NULL == old_notify);
+ } else {
+ /* piggyback on the existing port reference, so consume ours */
+ ip_unlock(port);
+ semaphore_dereference(semaphore);
+ }
+ return (send);
+}
+
+/*
+ * Routine: semaphore_notify
+ * Purpose:
+ * Called whenever the Mach port system detects no-senders
+ * on the semaphore port.
+ *
+ * When a send-right is first created, a no-senders
+ * notification is armed (and a semaphore reference is donated).
+ *
+ * A no-senders notification will be posted when no one else holds a
+ * send-right (reference) to the semaphore's port. This notification function
+ * will consume the semaphore reference donated to the extant collection of
+ * send-rights.
+ */
+void
+semaphore_notify(mach_msg_header_t *msg)
+{
+ mach_no_senders_notification_t *notification = (void *)msg;
+ ipc_port_t port = notification->not_header.msgh_remote_port;
+ semaphore_t semaphore;
+
+ assert(ip_active(port));
+ assert(IKOT_SEMAPHORE == ip_kotype(port));
+ semaphore = (semaphore_t)port->ip_kobject;
+