static int proc_usynch_get_requested_thread_qos(struct uthread *uth) { thread_t thread = uth ? uth->uu_thread : current_thread(); int requested_qos; requested_qos = proc_get_thread_policy(thread, TASK_POLICY_ATTRIBUTE, TASK_POLICY_QOS); /* * For the purposes of userspace synchronization, it doesn't make sense to * place an override of UNSPECIFIED on another thread, if the current thread * doesn't have any QoS set. In these cases, upgrade to * THREAD_QOS_USER_INTERACTIVE. */ if (requested_qos == THREAD_QOS_UNSPECIFIED) { requested_qos = THREAD_QOS_USER_INTERACTIVE; } return requested_qos; }
kern_return_t thread_policy_get( thread_t thread, thread_policy_flavor_t flavor, thread_policy_t policy_info, mach_msg_type_number_t *count, boolean_t *get_default) { kern_return_t result = KERN_SUCCESS; spl_t s; if (thread == THREAD_NULL) return (KERN_INVALID_ARGUMENT); thread_mtx_lock(thread); if (!thread->active) { thread_mtx_unlock(thread); return (KERN_TERMINATED); } switch (flavor) { case THREAD_EXTENDED_POLICY: { boolean_t timeshare = TRUE; if (!(*get_default)) { s = splsched(); thread_lock(thread); if ( (thread->sched_mode != TH_MODE_REALTIME) && (thread->saved_mode != TH_MODE_REALTIME) ) { if (!(thread->sched_flags & TH_SFLAG_DEMOTED_MASK)) timeshare = (thread->sched_mode == TH_MODE_TIMESHARE) != 0; else timeshare = (thread->saved_mode == TH_MODE_TIMESHARE) != 0; } else *get_default = TRUE; thread_unlock(thread); splx(s); } if (*count >= THREAD_EXTENDED_POLICY_COUNT) { thread_extended_policy_t info; info = (thread_extended_policy_t)policy_info; info->timeshare = timeshare; } break; } case THREAD_TIME_CONSTRAINT_POLICY: { thread_time_constraint_policy_t info; if (*count < THREAD_TIME_CONSTRAINT_POLICY_COUNT) { result = KERN_INVALID_ARGUMENT; break; } info = (thread_time_constraint_policy_t)policy_info; if (!(*get_default)) { s = splsched(); thread_lock(thread); if ( (thread->sched_mode == TH_MODE_REALTIME) || (thread->saved_mode == TH_MODE_REALTIME) ) { info->period = thread->realtime.period; info->computation = thread->realtime.computation; info->constraint = thread->realtime.constraint; info->preemptible = thread->realtime.preemptible; } else *get_default = TRUE; thread_unlock(thread); splx(s); } if (*get_default) { info->period = 0; info->computation = default_timeshare_computation; info->constraint = default_timeshare_constraint; info->preemptible = TRUE; } break; } case THREAD_PRECEDENCE_POLICY: { thread_precedence_policy_t info; if (*count < THREAD_PRECEDENCE_POLICY_COUNT) { result = KERN_INVALID_ARGUMENT; break; } info = (thread_precedence_policy_t)policy_info; if (!(*get_default)) { s = splsched(); thread_lock(thread); info->importance = thread->importance; thread_unlock(thread); splx(s); } else info->importance = 0; break; } case THREAD_AFFINITY_POLICY: { thread_affinity_policy_t info; if (!thread_affinity_is_supported()) { result = KERN_NOT_SUPPORTED; break; } if (*count < THREAD_AFFINITY_POLICY_COUNT) { result = KERN_INVALID_ARGUMENT; break; } info = (thread_affinity_policy_t)policy_info; if (!(*get_default)) info->affinity_tag = thread_affinity_get(thread); else info->affinity_tag = THREAD_AFFINITY_TAG_NULL; break; } case THREAD_POLICY_STATE: { thread_policy_state_t info; if (*count < THREAD_POLICY_STATE_COUNT) { result = KERN_INVALID_ARGUMENT; break; } /* Only root can get this info */ if (current_task()->sec_token.val[0] != 0) { result = KERN_PROTECTION_FAILURE; break; } info = (thread_policy_state_t)policy_info; if (!(*get_default)) { info->flags = 0; info->flags |= (thread->static_param ? THREAD_POLICY_STATE_FLAG_STATIC_PARAM : 0); /* * Unlock the thread mutex and directly return. * This is necessary because proc_get_thread_policy() * takes the task lock. */ thread_mtx_unlock(thread); proc_get_thread_policy(thread, info); return (result); } else { info->requested = 0; info->effective = 0; info->pending = 0; } break; } case THREAD_LATENCY_QOS_POLICY: { thread_latency_qos_policy_t info = (thread_latency_qos_policy_t) policy_info; uint32_t plqos; if (*count < THREAD_LATENCY_QOS_POLICY_COUNT) { result = KERN_INVALID_ARGUMENT; break; } if (*get_default) { plqos = 0; } else { plqos = thread->effective_policy.t_latency_qos; } info->thread_latency_qos_tier = qos_latency_policy_package(plqos); } break; case THREAD_THROUGHPUT_QOS_POLICY: { thread_throughput_qos_policy_t info = (thread_throughput_qos_policy_t) policy_info; uint32_t ptqos; if (*count < THREAD_THROUGHPUT_QOS_POLICY_COUNT) { result = KERN_INVALID_ARGUMENT; break; } if (*get_default) { ptqos = 0; } else { ptqos = thread->effective_policy.t_through_qos; } info->thread_throughput_qos_tier = qos_throughput_policy_package(ptqos); } break; case THREAD_QOS_POLICY: case THREAD_QOS_POLICY_OVERRIDE: { thread_qos_policy_t info = (thread_qos_policy_t)policy_info; if (*count < THREAD_QOS_POLICY_COUNT) { result = KERN_INVALID_ARGUMENT; break; } if (!(*get_default)) { if (flavor == THREAD_QOS_POLICY_OVERRIDE) { info->qos_tier = thread->requested_policy.thrp_qos_override; /* TODO: handle importance overrides */ info->tier_importance = 0; } else { info->qos_tier = thread->requested_policy.thrp_qos; info->tier_importance = thread->importance; } } else { info->qos_tier = THREAD_QOS_UNSPECIFIED; info->tier_importance = 0; } break; } default: result = KERN_INVALID_ARGUMENT; break; } thread_mtx_unlock(thread); return (result); }