+ ip_reference(port);
+ thread->ith_special_reply_port = port;
+ port->ip_messages.imq_srp_owner_thread = thread;
+
+ ipc_special_reply_port_bits_reset(port);
+}
+
+/*
+ * Routine: ipc_port_unbind_special_reply_port
+ * Purpose:
+ * Unbind the thread's special reply port.
+ * If the special port has threads waiting on turnstile,
+ * update it's inheritor.
+ * Condition:
+ * Nothing locked.
+ * Returns:
+ * None.
+ */
+static kern_return_t
+ipc_port_unbind_special_reply_port(
+ thread_t thread,
+ boolean_t unbind_active_port)
+{
+ ipc_port_t special_reply_port = thread->ith_special_reply_port;
+
+ ip_lock(special_reply_port);
+
+ /* Return error if port active and unbind_active_port set to FALSE */
+ if (unbind_active_port == FALSE && ip_active(special_reply_port)) {
+ ip_unlock(special_reply_port);
+ return KERN_FAILURE;
+ }
+
+ thread->ith_special_reply_port = NULL;
+ ipc_port_adjust_special_reply_port_locked(special_reply_port, NULL,
+ IPC_PORT_ADJUST_UNLINK_THREAD, FALSE);
+ /* port unlocked */
+
+ ip_release(special_reply_port);
+ return KERN_SUCCESS;
+}
+
+/*
+ * Routine: thread_get_special_port [kernel call]
+ * Purpose:
+ * Clones a send right for one of the thread's
+ * special ports.
+ * Conditions:
+ * Nothing locked.
+ * Returns:
+ * KERN_SUCCESS Extracted a send right.
+ * KERN_INVALID_ARGUMENT The thread is null.
+ * KERN_FAILURE The thread is dead.
+ * KERN_INVALID_ARGUMENT Invalid special port.
+ */
+
+kern_return_t
+thread_get_special_port(
+ thread_t thread,
+ int which,
+ ipc_port_t *portp)
+{
+ kern_return_t result = KERN_SUCCESS;
+ ipc_port_t *whichp;
+
+ if (thread == THREAD_NULL) {
+ return KERN_INVALID_ARGUMENT;
+ }
+
+ switch (which) {
+ case THREAD_KERNEL_PORT:
+ whichp = &thread->ith_sself;
+ break;
+
+ default:
+ return KERN_INVALID_ARGUMENT;
+ }
+
+ thread_mtx_lock(thread);
+
+ if (thread->active) {
+ *portp = ipc_port_copy_send(*whichp);
+ } else {
+ result = KERN_FAILURE;
+ }
+
+ thread_mtx_unlock(thread);
+
+ return result;
+}
+
+/*
+ * Routine: thread_set_special_port [kernel call]
+ * Purpose:
+ * Changes one of the thread's special ports,
+ * setting it to the supplied send right.
+ * Conditions:
+ * Nothing locked. If successful, consumes
+ * the supplied send right.
+ * Returns:
+ * KERN_SUCCESS Changed the special port.
+ * KERN_INVALID_ARGUMENT The thread is null.
+ * KERN_FAILURE The thread is dead.
+ * KERN_INVALID_ARGUMENT Invalid special port.
+ */
+
+kern_return_t
+thread_set_special_port(
+ thread_t thread,
+ int which,
+ ipc_port_t port)
+{
+ kern_return_t result = KERN_SUCCESS;
+ ipc_port_t *whichp, old = IP_NULL;
+
+ if (thread == THREAD_NULL) {
+ return KERN_INVALID_ARGUMENT;
+ }
+
+ switch (which) {
+ case THREAD_KERNEL_PORT:
+ whichp = &thread->ith_sself;