+ return value;
+}
+
+
+/*
+ * Functions for querying effective state for relevant subsystems
+ * ONLY the relevant subsystem should query these.
+ * NEVER take a value from one of the 'effective' functions and stuff it into a setter.
+ */
+
+int
+proc_get_effective_task_policy(task_t task, int flavor)
+{
+ return proc_get_effective_policy(task, THREAD_NULL, flavor);
+}
+
+int
+proc_get_effective_thread_policy(thread_t thread, int flavor)
+{
+ return proc_get_effective_policy(thread->task, thread, flavor);
+}
+
+/*
+ * Gets what is actually in effect, for subsystems which pull policy instead of receive updates.
+ *
+ * NOTE: This accessor does not take the task lock.
+ * Notifications of state updates need to be externally synchronized with state queries.
+ * This routine *MUST* remain interrupt safe, as it is potentially invoked
+ * within the context of a timer interrupt.
+ */
+static int
+proc_get_effective_policy(task_t task,
+ thread_t thread,
+ int flavor)
+{
+ boolean_t on_task = (thread == THREAD_NULL) ? TRUE : FALSE;
+ int value = 0;
+
+ switch (flavor) {
+ case TASK_POLICY_DARWIN_BG:
+ /*
+ * This backs the KPI call proc_pidbackgrounded to find
+ * out if a pid is backgrounded,
+ * as well as proc_get_effective_thread_policy.
+ * Its main use is within the timer layer, as well as
+ * prioritizing requests to the graphics system.
+ * Returns 1 for background mode, 0 for normal mode
+ */
+ if (on_task)
+ value = task->effective_policy.darwinbg;
+ else
+ value = (task->effective_policy.darwinbg ||
+ thread->effective_policy.darwinbg) ? 1 : 0;
+ break;
+ case TASK_POLICY_IO:
+ /*
+ * The I/O system calls here to find out what throttling tier to apply to an operation.
+ * Returns THROTTLE_LEVEL_* values
+ */
+ if (on_task)
+ value = task->effective_policy.io_tier;
+ else {
+ value = MAX(task->effective_policy.io_tier,
+ thread->effective_policy.io_tier);
+ if (thread->iotier_override != THROTTLE_LEVEL_NONE)
+ value = MIN(value, thread->iotier_override);
+ }
+ break;
+ case TASK_POLICY_PASSIVE_IO:
+ /*
+ * The I/O system calls here to find out whether an operation should be passive.
+ * (i.e. not cause operations with lower throttle tiers to be throttled)
+ * Returns 1 for passive mode, 0 for normal mode
+ */
+ if (on_task)
+ value = task->effective_policy.io_passive;
+ else
+ value = (task->effective_policy.io_passive ||
+ thread->effective_policy.io_passive) ? 1 : 0;
+ break;
+ case TASK_POLICY_NEW_SOCKETS_BG:
+ /*
+ * socreate() calls this to determine if it should mark a new socket as background
+ * Returns 1 for background mode, 0 for normal mode
+ */
+ if (on_task)
+ value = task->effective_policy.new_sockets_bg;
+ else
+ value = (task->effective_policy.new_sockets_bg ||
+ thread->effective_policy.new_sockets_bg) ? 1 : 0;
+ break;
+ case TASK_POLICY_LOWPRI_CPU:
+ /*
+ * Returns 1 for low priority cpu mode, 0 for normal mode
+ */
+ if (on_task)
+ value = task->effective_policy.lowpri_cpu;
+ else
+ value = (task->effective_policy.lowpri_cpu ||
+ thread->effective_policy.lowpri_cpu) ? 1 : 0;
+ break;
+ case TASK_POLICY_SUPPRESSED_CPU:
+ /*
+ * Returns 1 for suppressed cpu mode, 0 for normal mode
+ */
+ assert(on_task);
+ value = task->effective_policy.t_suppressed_cpu;
+ break;
+ case TASK_POLICY_LATENCY_QOS:
+ /*
+ * timer arming calls into here to find out the timer coalescing level
+ * Returns a QoS tier (0-6)
+ */
+ assert(on_task);
+ value = task->effective_policy.t_latency_qos;
+ break;
+ case TASK_POLICY_THROUGH_QOS:
+ /*
+ * Returns a QoS tier (0-6)
+ */
+ assert(on_task);
+ value = task->effective_policy.t_through_qos;
+ break;
+ case TASK_POLICY_GPU_DENY:
+ /*
+ * This is where IOKit calls into task_policy to find out whether
+ * it should allow access to the GPU.
+ * Returns 1 for NOT allowed, returns 0 for allowed
+ */
+ assert(on_task);
+ value = task->effective_policy.t_gpu_deny;
+ break;
+ case TASK_POLICY_ROLE:
+ assert(on_task);
+ value = task->effective_policy.t_role;
+ break;
+ case TASK_POLICY_WATCHERS_BG:
+ assert(on_task);
+ value = task->effective_policy.t_watchers_bg;
+ break;
+ default:
+ panic("unknown policy_flavor %d", flavor);
+ break;