+ * Internal helper routine to convert from a port to a locked
+ * task inspect right. Used by internal routines that try to convert from a
+ * task inspect port to a reference on some task related object.
+ * Conditions:
+ * Nothing locked, blocking OK.
+ */
+task_inspect_t
+convert_port_to_locked_task_inspect(ipc_port_t port)
+{
+ int try_failed_count = 0;
+
+ while (IP_VALID(port)) {
+ task_inspect_t task;
+
+ ip_lock(port);
+ if (!ip_active(port) || (ip_kotype(port) != IKOT_TASK)) {
+ ip_unlock(port);
+ return TASK_INSPECT_NULL;
+ }
+ task = (task_inspect_t)port->ip_kobject;
+ assert(task != TASK_INSPECT_NULL);
+ /*
+ * Normal lock ordering puts task_lock() before ip_lock().
+ * Attempt out-of-order locking here.
+ */
+ if (task_lock_try((task_t)task)) {
+ ip_unlock(port);
+ return task;
+ }
+ try_failed_count++;
+
+ ip_unlock(port);
+ mutex_pause(try_failed_count);
+ }
+ return TASK_INSPECT_NULL;
+}
+
+static task_t
+convert_port_to_task_locked(
+ ipc_port_t port,
+ uint32_t *exec_token)
+{
+ task_t task = TASK_NULL;
+
+ ip_lock_held(port);
+ require_ip_active(port);
+
+ if (ip_kotype(port) == IKOT_TASK) {
+ task_t ct = current_task();
+ task = (task_t)port->ip_kobject;
+ assert(task != TASK_NULL);
+
+ if (task_conversion_eval(ct, task)) {
+ return TASK_NULL;
+ }
+
+ if (exec_token) {
+ *exec_token = task->exec_token;
+ }
+ task_reference_internal(task);
+ }
+
+ return task;
+}
+
+/*
+ * Routine: convert_port_to_task_with_exec_token
+ * Purpose:
+ * Convert from a port to a task and return
+ * the exec token stored in the task.