+
+/* task Darwin BG enforcement/settings related routines */
+int
+proc_get_task_bg_policy(task_t task)
+{
+
+ int selfset = 0;
+ int val = 0;
+
+ if (current_task() == task)
+ selfset = 1;
+
+ if (selfset == 0) {
+ val = task->ext_policystate.hw_bg;
+ } else {
+ val = task->policystate.hw_bg;
+ }
+
+ return(val);
+}
+
+
+int
+proc_get_thread_bg_policy(task_t task, uint64_t tid)
+{
+ thread_t self = current_thread();
+ thread_t thread = THREAD_NULL;
+ int val = 0;
+
+ if (tid == self->thread_id) {
+ val = self->policystate.hw_bg;
+ } else {
+ task_lock(task);
+ thread = task_findtid(task, tid);
+ if (thread != NULL)
+ val = thread->ext_policystate.hw_bg;
+ task_unlock(task);
+ }
+
+ return(val);
+}
+
+int
+proc_get_self_isbackground(void)
+{
+ task_t task = current_task();;
+ thread_t thread = current_thread();
+
+ if ((task->ext_actionstate.hw_bg != TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE) ||
+ (task->actionstate.hw_bg != TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE) ||
+ (thread->ext_actionstate.hw_bg != TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE) ||
+ (thread->actionstate.hw_bg != TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE))
+ return(1);
+ else
+ return(0);
+
+}
+
+int proc_get_selfthread_isbackground(void)
+{
+ thread_t thread = current_thread();
+
+ if ((thread->ext_actionstate.hw_bg != TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE) ||
+ (thread->actionstate.hw_bg != TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE))
+ return(1);
+ else
+ return(0);
+}
+
+
+int
+proc_set_bgtaskpolicy(task_t task, int intval)
+{
+
+ int selfset = 0;
+
+ if (current_task() == task)
+ selfset = 1;
+
+ task_lock(task);
+
+ if (selfset == 0) {
+ /* allready set? */
+ if (task->ext_policystate.hw_bg != intval)
+ task->ext_policystate.hw_bg = intval;
+ } else {
+ if (task->policystate.hw_bg != intval)
+ task->policystate.hw_bg = intval;
+ }
+
+ task_unlock(task);
+ return(0);
+}
+
+/* set and apply as well */
+int proc_set1_bgtaskpolicy(task_t task, int prio)
+{
+ int error = 0;
+
+ if (prio == PRIO_DARWIN_BG) {
+ error = proc_set_bgtaskpolicy(task, TASK_POLICY_BACKGROUND_ATTRIBUTE_ALL);
+ if (error == 0)
+ error = proc_apply_bgtaskpolicy(task);
+ } else {
+ error = proc_restore_bgtaskpolicy(task);
+ }
+
+ return(error);
+}
+
+
+int
+proc_set_bgthreadpolicy(task_t task, uint64_t tid, int prio)
+{
+ thread_t self = current_thread();
+ thread_t thread = THREAD_NULL;
+ int reset;
+
+ if (prio == 0)
+ reset = 1;
+ task_lock(task);
+ if (tid == self->thread_id) {
+ self->policystate.hw_bg = prio;
+ } else {
+ thread = task_findtid(task, tid);
+ if (thread != NULL)
+ thread->ext_policystate.hw_bg = prio;
+ }
+
+ task_unlock(task);
+
+ return(0);
+}
+
+int
+proc_set1_bgthreadpolicy(task_t task, uint64_t tid, int prio)
+{
+ int error = 0;
+
+ if (prio == PRIO_DARWIN_BG) {
+ error = proc_set_bgthreadpolicy(task, tid, TASK_POLICY_BACKGROUND_ATTRIBUTE_ALL);
+ if (error == 0)
+ error = proc_apply_bgthreadpolicy(task, tid);
+ } else {
+ error = proc_restore_bgthreadpolicy(task, tid);
+ }
+
+ return(error);
+}
+
+int
+proc_add_bgtaskpolicy(task_t task, int val)
+{
+ int selfset = 0;
+
+ if (current_task() == task)
+ selfset = 1;
+
+ task_lock(task);
+
+ if (selfset == 0) {
+ task->policystate.hw_bg |= val;
+ } else {
+ task->ext_policystate.hw_bg |= val;
+ }
+
+ task_unlock(task);
+ return(0);
+}
+
+int
+proc_add_bgthreadpolicy(task_t task, uint64_t tid, int val)
+{
+ thread_t self = current_thread();
+ thread_t thread = THREAD_NULL;
+ int reset;
+
+ if (val == 0)
+ reset = 1;
+ task_lock(task);
+ if (tid == self->thread_id) {
+ self->policystate.hw_bg |= val;
+ } else {
+ thread = task_findtid(task, tid);
+ if (thread != NULL)
+ thread->ext_policystate.hw_bg |= val;
+ }
+
+ task_unlock(task);
+
+ return(val);
+}
+
+int
+proc_remove_bgtaskpolicy(task_t task, int intval)
+{
+ int selfset = 0;
+
+ if (current_task() == task)
+ selfset = 1;
+
+ task_lock(task);
+
+ if (selfset == 0) {
+ task->policystate.hw_bg &= ~intval;
+ } else {
+ task->ext_policystate.hw_bg &= ~intval;
+ }
+
+ task_unlock(task);
+ return(0);
+}
+
+int
+proc_remove_bgthreadpolicy(task_t task, uint64_t tid, int val)
+{
+ thread_t self = current_thread();
+ thread_t thread = THREAD_NULL;
+ int reset;
+
+ if (val == 0)
+ reset = 1;
+ task_lock(task);
+ if (tid == self->thread_id) {
+ self->policystate.hw_bg &= ~val;
+ } else {
+ thread = task_findtid(task, tid);
+ if (thread != NULL)
+ thread->ext_policystate.hw_bg &= ~val;
+ }
+
+ task_unlock(task);
+
+ return(val);
+}
+
+int
+proc_apply_bgtask_selfpolicy(void)
+{
+ return(proc_apply_bgtaskpolicy(current_task()));
+}
+
+int
+proc_apply_bgtaskpolicy(task_t task)
+{
+ int external = 1;
+
+ if (task == current_task())
+ external = 0;
+
+ return(proc_apply_bgtaskpolicy_locked(task, 0, external));
+}
+
+int
+proc_apply_bgtaskpolicy_external(task_t task)
+{
+ return(proc_apply_bgtaskpolicy_locked(task, 0, 1));
+
+}
+
+int
+proc_apply_bgtaskpolicy_internal(task_t task)
+{
+ return(proc_apply_bgtaskpolicy_locked(task, 0, 0));
+}
+
+
+static int
+proc_apply_bgtaskpolicy_locked(task_t task, int locked, int external)
+{
+ if (locked == 0)
+ task_lock(task);
+
+ if (external != 0) {
+ /* allready set? */
+ if (task->ext_actionstate.hw_bg != task->ext_policystate.hw_bg) {
+ task->ext_actionstate.hw_bg = task->ext_policystate.hw_bg;
+ task_priority(task, MAXPRI_THROTTLE, MAXPRI_THROTTLE);
+ /* background state applied */
+ }
+ } else {
+ if (task->actionstate.hw_bg != task->policystate.hw_bg) {
+ task->actionstate.hw_bg = task->policystate.hw_bg;
+ task_priority(task, MAXPRI_THROTTLE, MAXPRI_THROTTLE);
+ }
+ }
+ if (locked == 0)
+ task_unlock(task);
+ return(0);
+}
+
+/* apply the self backgrounding even if the thread is not current thread/task(timer threads) */
+int
+proc_apply_workq_bgthreadpolicy(thread_t thread)
+{
+ int error;
+ task_t wqtask = TASK_NULL;
+
+ if (thread != THREAD_NULL) {
+ wqtask = thread->task;
+ task_lock(wqtask);
+ /* apply the background as selfset internal one */
+ error = proc_apply_bgthreadpolicy_locked(thread, 1);
+ task_unlock(wqtask);
+ } else
+ error = ESRCH;
+
+ return(error);
+}
+
+int
+proc_apply_bgthreadpolicy(task_t task, uint64_t tid)
+{
+ thread_t self = current_thread();
+ thread_t thread = THREAD_NULL;
+ int selfset = 0, error = 0;
+ task_t localtask = TASK_NULL;
+
+ if (tid == self->thread_id) {
+ selfset = 1;
+ localtask = current_task();
+ } else {
+ localtask = task;
+ }
+
+ task_lock(localtask);
+ if (selfset != 0) {
+ thread = self;
+ } else {
+ thread = task_findtid(task, tid);
+ }
+
+ error = proc_apply_bgthreadpolicy_locked(thread, selfset);
+ task_unlock(localtask);
+
+ return(error);
+}
+
+static int
+proc_apply_bgthreadpolicy_locked(thread_t thread, int selfset)
+{
+ int set = 0;
+ thread_precedence_policy_data_t policy;
+
+ if (thread != NULL) {
+ if (selfset != 0) {
+ /* internal application */
+ if (thread->actionstate.hw_bg != thread->policystate.hw_bg) {
+ thread->actionstate.hw_bg = thread->policystate.hw_bg;
+ if (thread->ext_actionstate.hw_bg == TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE)
+ set = 1;
+
+ }
+ } else {
+ /* external application */
+ if (thread->ext_actionstate.hw_bg != thread->ext_policystate.hw_bg) {
+ thread->ext_actionstate.hw_bg = thread->ext_policystate.hw_bg;
+ if (thread->actionstate.hw_bg == TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE)
+ set = 1;
+ }
+ }
+
+ if (set != 0) {
+ /* set thread priority (we did not save previous value) */
+ policy.importance = INT_MIN;
+
+ thread_policy_set_internal(thread, THREAD_PRECEDENCE_POLICY,
+ (thread_policy_t)&policy,
+ THREAD_PRECEDENCE_POLICY_COUNT );
+
+ }
+ } else
+ return(ESRCH);
+
+ return(0);
+}
+
+int
+proc_apply_bgthread_selfpolicy(void)
+{
+ return(proc_apply_bgthreadpolicy(current_task(), current_thread()->thread_id));
+}
+
+
+int
+proc_restore_bgtaskpolicy(task_t task)
+{
+ int external = 1;
+
+ if (current_task() == task)
+ external = 0;
+ return(proc_restore_bgtaskpolicy_locked(task, 0, external, BASEPRI_DEFAULT));
+}
+
+static int
+proc_restore_bgtaskpolicy_locked(task_t task, int locked, int external, int pri)
+{
+ if (locked == 0)
+ task_lock(task);
+
+ if (external != 0) {
+ task->ext_actionstate.hw_bg = TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE;
+ /* self BG in flight? */
+ if (task->actionstate.hw_bg == TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE) {
+ task_priority(task, pri, MAXPRI_USER);
+#if CONFIG_EMBEDDED
+ /* non embedded users need role for policy reapplication */
+ task->role = TASK_DEFAULT_APPLICATION;
+#endif /* CONFIG_EMBEDDED */
+ }
+ } else {
+ task->actionstate.hw_bg = TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE;
+ /* external BG in flight? */
+ if (task->ext_actionstate.hw_bg == TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE) {
+ task_priority(task, pri, MAXPRI_USER);
+#if CONFIG_EMBEDDED
+ /* non embedded users need role for policy reapplication */
+ task->role = TASK_DEFAULT_APPLICATION;
+#endif /* CONFIG_EMBEDDED */
+ }
+ }
+
+ if (locked == 0)
+ task_unlock(task);
+
+ return(0);
+}
+
+/* restore the self backgrounding even if the thread is not current thread */
+int
+proc_restore_workq_bgthreadpolicy(thread_t thread)
+{
+ int error = 0;
+ task_t wqtask = TASK_NULL;
+
+ if (thread != THREAD_NULL) {
+ wqtask = thread->task;
+ task_lock(wqtask);
+ /* remove the background and restore default importance as self(internal) removal */
+ restore_bgthreadpolicy_locked(thread, 1);
+ task_unlock(wqtask);
+ } else
+ error = ESRCH;
+
+ return(error);
+}
+
+int proc_restore_bgthread_selfpolicy(void)
+{
+ return(proc_restore_bgthreadpolicy(current_task(), thread_tid(current_thread())));
+
+}
+
+
+int
+proc_restore_bgthreadpolicy(task_t task, uint64_t tid)
+{
+ int selfset = 0;
+ thread_t self = current_thread();
+ thread_t thread = THREAD_NULL;
+
+ task_lock(task);
+ if (tid == self->thread_id) {
+ thread = self;
+ selfset = 1;
+ } else {
+ thread = task_findtid(task, tid);
+ }
+
+ if (thread != NULL)
+ restore_bgthreadpolicy_locked(thread, selfset);
+
+ task_unlock(task);
+
+ if (thread != NULL)
+ return(0);
+ else
+ return(1);
+}
+
+static void
+restore_bgthreadpolicy_locked(thread_t thread, int selfset)
+{
+ thread_precedence_policy_data_t policy;
+ int reset = 0;
+
+ if (thread != NULL) {
+ if (selfset != 0) {
+ thread->actionstate.hw_bg = TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE;
+ /* external BG in flight? */
+ if (thread->ext_actionstate.hw_bg == TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE)
+ reset = 1;
+
+ } else {
+ thread->ext_actionstate.hw_bg = TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE;
+ /* self BG in flight? */
+ if (thread->actionstate.hw_bg == TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE)
+ reset = 1;
+ }
+
+ if (reset != 0) {
+ /* reset thread priority (we did not save previous value) */
+ policy.importance = 0;
+ thread_policy_set_internal(thread, THREAD_PRECEDENCE_POLICY,
+ (thread_policy_t)&policy,
+ THREAD_PRECEDENCE_POLICY_COUNT );
+ }
+ }
+}
+
+void
+proc_set_task_apptype(task_t task, int type)
+{
+ switch (type) {
+ case PROC_POLICY_OSX_APPTYPE_TAL:
+ task->ext_policystate.apptype = type;
+ task->policystate.apptype = type;
+ proc_apply_bgtaskpolicy_external(task);
+ /* indicate that BG is set and next foreground needs to reset */
+ task->ext_actionstate.apptype = type;
+ break;
+
+ case PROC_POLICY_OSX_APPTYPE_DBCLIENT:
+ task->ext_policystate.apptype = type;
+ task->policystate.apptype = type;
+ proc_apply_bgtaskpolicy_internal(task);
+ /* indicate that BG is set and next foreground needs to reset */
+ task->ext_actionstate.apptype = type;
+ break;
+
+ case PROC_POLICY_IOS_APPTYPE:
+ task->ext_policystate.apptype = type;
+ task->policystate.apptype = type;
+ break;
+ case PROC_POLICY_IOS_NONUITYPE:
+ task->ext_policystate.apptype = type;
+ task->policystate.apptype = type;
+ /* set to deny access to gpu */
+ task->ext_actionstate.hw_gpu = TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS;
+ task->ext_policystate.hw_gpu = TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS;
+ break;
+
+ default:
+ break;
+ }
+}
+
+/* update the darwin backdground action state in the flags field for libproc */
+#define PROC_FLAG_DARWINBG 0x8000 /* process in darwin background */
+#define PROC_FLAG_EXT_DARWINBG 0x10000 /* process in darwin background - external enforcement */
+
+int
+proc_get_darwinbgstate(task_t task, uint32_t * flagsp)
+{
+ if (task->ext_actionstate.hw_bg == TASK_POLICY_BACKGROUND_ATTRIBUTE_ALL){
+ *flagsp |= PROC_FLAG_EXT_DARWINBG;
+ }
+ if (task->actionstate.hw_bg == TASK_POLICY_BACKGROUND_ATTRIBUTE_ALL){
+ *flagsp |= PROC_FLAG_DARWINBG;
+ }
+
+ return(0);
+}
+
+/*
+ * HW disk access realted routines, they need to return
+ * IOPOL_XXX equivalents for spec_xxx/throttle updates.
+ */
+
+int
+proc_get_task_disacc(task_t task)
+{
+ if ((task->ext_actionstate.hw_bg & TASK_POLICY_BACKGROUND_ATTRIBUTE_DISKTHROTTLE) != 0)
+ return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_THROTTLE);
+ if (task->ext_actionstate.hw_disk != TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_NORMAL)
+ return(task->ext_actionstate.hw_disk);
+ if ((task->actionstate.hw_bg & TASK_POLICY_BACKGROUND_ATTRIBUTE_DISKTHROTTLE) != 0)
+ return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_THROTTLE);
+ if (task->actionstate.hw_disk != TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_NORMAL)
+ return(task->actionstate.hw_disk);
+ return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_NORMAL);
+}
+
+int
+proc_get_task_selfdiskacc(void)
+{
+ task_t task = current_task();
+ thread_t thread= current_thread();
+
+ /*
+ * As per defined iopolicysys behavior, thread trumps task.
+ * Do we need to follow that for external enforcements of BG or hw access?
+ * Status quo for now..
+ */
+ if((thread->ext_actionstate.hw_bg & TASK_POLICY_BACKGROUND_ATTRIBUTE_DISKTHROTTLE) != 0)
+ return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_THROTTLE);
+ if (thread->ext_actionstate.hw_disk != TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_NORMAL)
+ return(thread->ext_actionstate.hw_disk);
+ if((thread->actionstate.hw_bg & TASK_POLICY_BACKGROUND_ATTRIBUTE_DISKTHROTTLE) != 0)
+ return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_THROTTLE);
+ if (thread->actionstate.hw_disk != TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_NORMAL)
+ return(thread->actionstate.hw_disk);
+
+ if ((task->ext_actionstate.hw_bg & TASK_POLICY_BACKGROUND_ATTRIBUTE_DISKTHROTTLE) != 0)
+ return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_THROTTLE);
+ if (task->ext_actionstate.hw_disk != TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_NORMAL)
+ return(task->ext_actionstate.hw_disk);
+ if ((task->actionstate.hw_bg & TASK_POLICY_BACKGROUND_ATTRIBUTE_DISKTHROTTLE) != 0)
+ return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_THROTTLE);
+ if (task->actionstate.hw_disk != TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_NORMAL)
+ return(task->actionstate.hw_disk);
+ return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_NORMAL);
+}
+
+int
+proc_get_thread_selfdiskacc(void)
+{
+ thread_t thread = current_thread();
+
+ if((thread->ext_actionstate.hw_bg & TASK_POLICY_BACKGROUND_ATTRIBUTE_DISKTHROTTLE) != 0)
+ return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_THROTTLE);
+ if (thread->ext_actionstate.hw_disk != TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_NORMAL)
+ return(thread->ext_actionstate.hw_disk);
+ if((thread->actionstate.hw_bg & TASK_POLICY_BACKGROUND_ATTRIBUTE_DISKTHROTTLE) != 0)
+ return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_THROTTLE);
+ if (thread->actionstate.hw_disk != TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_NORMAL)
+ return(thread->actionstate.hw_disk);
+ return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_NORMAL);
+}
+
+int proc_apply_task_diskacc(task_t task, int policy)
+{
+ task_t self = current_task();
+
+ task_lock(task);
+ if (task == self) {
+ task->actionstate.hw_disk = policy;
+ task->policystate.hw_disk = policy;
+ } else {
+ task->ext_actionstate.hw_disk = policy;
+ task->ext_policystate.hw_disk = policy;
+ }
+ task_unlock(task);
+ return(0);
+}
+
+int proc_apply_thread_diskacc(task_t task, uint64_t tid, int policy)
+{
+ thread_t thread;
+
+ if (tid == TID_NULL) {
+ thread = current_thread();
+ proc_apply_thread_selfdiskacc(policy);
+ } else {
+ task_lock(task);
+ thread = task_findtid(task, tid);
+ if (thread != NULL) {
+ thread->ext_actionstate.hw_disk = policy;
+ thread->ext_policystate.hw_disk = policy;
+ }
+ task_unlock(task);
+ }
+ if (thread != NULL)
+ return(0);
+ else
+ return(0);
+}
+
+int
+proc_apply_thread_selfdiskacc(int policy)
+{
+ task_t task = current_task();
+ thread_t thread = current_thread();
+
+ task_lock(task);
+ thread->actionstate.hw_disk = policy;
+ thread->policystate.hw_disk = policy;
+ task_unlock(task);
+ return(0);
+}
+
+int
+proc_denyinherit_policy(__unused task_t task)
+{
+ return(0);
+}
+
+int
+proc_denyselfset_policy(__unused task_t task)
+{
+ return(0);
+}
+
+/* HW GPU access related routines */
+int
+proc_get_task_selfgpuacc_deny(void)
+{
+ task_t task = current_task();
+ thread_t thread = current_thread();
+
+ if (((task->ext_actionstate.hw_bg & TASK_POLICY_BACKGROUND_ATTRIBUTE_NOGPU) != 0) || (task->ext_actionstate.hw_gpu == TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS))
+ return(TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS);
+ if (((task->actionstate.hw_bg & TASK_POLICY_BACKGROUND_ATTRIBUTE_NOGPU) != 0) || (task->actionstate.hw_gpu == TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS))
+ return(TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS);
+ if (((thread->ext_actionstate.hw_bg & TASK_POLICY_BACKGROUND_ATTRIBUTE_NOGPU) != 0) || (thread->ext_actionstate.hw_gpu == TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS))
+ return(TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS);
+ if (((thread->actionstate.hw_bg & TASK_POLICY_BACKGROUND_ATTRIBUTE_NOGPU) != 0) || (thread->actionstate.hw_gpu == TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS))
+ return(TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS);
+
+ return(TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NORMAL);
+}
+
+int
+proc_apply_task_gpuacc(task_t task, int policy)
+{
+
+ task_t self = current_task();
+
+ task_lock(task);
+ if (task == self) {
+ task->actionstate.hw_gpu = policy;
+ task->policystate.hw_gpu = policy;
+ } else {
+ task->ext_actionstate.hw_gpu = policy;
+ task->ext_policystate.hw_gpu = policy;
+ }
+ task_unlock(task);
+
+ return(0);
+}
+
+/* Resource usage , CPU realted routines */
+int
+proc_get_task_ruse_cpu(task_t task, uint32_t * policyp, uint32_t * percentagep, uint64_t * intervalp, uint64_t * deadlinep)
+{
+
+ int error = 0;
+
+ task_lock(task);
+ if (task != current_task()) {
+ *policyp = task->ext_policystate.ru_cpu;
+ } else {
+ *policyp = task->policystate.ru_cpu;
+ }
+
+ error = task_get_cpuusage(task, percentagep, intervalp, deadlinep);
+
+ return(error);
+}
+
+int
+proc_set_task_ruse_cpu(task_t task, uint32_t policy, uint32_t percentage, uint64_t interval, uint64_t deadline)
+{
+ int error = 0;
+
+ task_lock(task);
+ if (task != current_task()) {
+ task->ext_policystate.ru_cpu = policy;
+ } else {
+ task->policystate.ru_cpu = policy;
+ }
+ error = task_set_cpuusage(task, percentage, interval, deadline);
+ task_unlock(task);
+ return(error);
+}
+
+
+/* used to apply resource limit related actions */
+static int
+task_apply_resource_actions(task_t task, int type)
+{
+ int action = TASK_POLICY_RESOURCE_ATTRIBUTE_NONE;
+ void * bsdinfo = NULL;
+
+ switch (type) {
+ case TASK_POLICY_CPU_RESOURCE_USAGE:
+ break;
+ case TASK_POLICY_WIREDMEM_RESOURCE_USAGE:
+ case TASK_POLICY_VIRTUALMEM_RESOURCE_USAGE:
+ case TASK_POLICY_DISK_RESOURCE_USAGE:
+ case TASK_POLICY_NETWORK_RESOURCE_USAGE:
+ case TASK_POLICY_POWER_RESOURCE_USAGE:
+ return(0);
+
+ default:
+ return(1);
+ };
+
+ /* only cpu actions for now */
+ task_lock(task);
+
+ if (task->ext_actionstate.ru_cpu == TASK_POLICY_RESOURCE_ATTRIBUTE_NONE) {
+ /* apply action */
+ task->ext_actionstate.ru_cpu = task->ext_policystate.ru_cpu;
+ action = task->ext_actionstate.ru_cpu;
+ }
+ if (action != TASK_POLICY_RESOURCE_ATTRIBUTE_NONE) {
+ bsdinfo = task->bsd_info;
+ task_unlock(task);
+ proc_apply_resource_actions(bsdinfo, TASK_POLICY_CPU_RESOURCE_USAGE, action);
+ } else
+ task_unlock(task);
+
+ return(0);
+}
+
+int
+task_restore_resource_actions(task_t task, int type)
+{
+ int action;
+ void * bsdinfo = NULL;
+
+ switch (type) {
+ case TASK_POLICY_CPU_RESOURCE_USAGE:
+ break;
+ case TASK_POLICY_WIREDMEM_RESOURCE_USAGE:
+ case TASK_POLICY_VIRTUALMEM_RESOURCE_USAGE:
+ case TASK_POLICY_DISK_RESOURCE_USAGE:
+ case TASK_POLICY_NETWORK_RESOURCE_USAGE:
+ case TASK_POLICY_POWER_RESOURCE_USAGE:
+ return(0);
+
+ default:
+ return(1);
+ };
+
+ /* only cpu actions for now */
+ task_lock(task);
+
+ action = task->ext_actionstate.ru_cpu;
+ if (task->ext_actionstate.ru_cpu != TASK_POLICY_RESOURCE_ATTRIBUTE_NONE) {
+ /* reset action */
+ task->ext_actionstate.ru_cpu = TASK_POLICY_RESOURCE_ATTRIBUTE_NONE;
+ }
+ if (action != TASK_POLICY_RESOURCE_ATTRIBUTE_NONE) {
+ bsdinfo = task->bsd_info;
+ task_unlock(task);
+ proc_restore_resource_actions(bsdinfo, TASK_POLICY_CPU_RESOURCE_USAGE, action);
+ } else
+ task_unlock(task);
+
+ return(0);
+
+}
+
+/* For ledger hookups */
+static int
+task_get_cpuusage(__unused task_t task, uint32_t * percentagep, uint64_t * intervalp, uint64_t * deadlinep)
+{
+ *percentagep = 0;
+ *intervalp = 0;
+ *deadlinep = 0;
+
+ return(0);
+}
+
+static int
+task_set_cpuusage(__unused task_t task, __unused uint32_t percentage, __unused uint64_t interval, __unused uint64_t deadline)
+{
+ return(0);
+}
+
+/* called by ledger unit to enforce action due to resource usage criteria being met */
+int
+task_action_cpuusage(task_t task)
+{
+ return(task_apply_resource_actions(task, TASK_POLICY_CPU_RESOURCE_USAGE));
+}
+
+int
+proc_disable_task_apptype(task_t task, int policy_subtype)
+{
+ void * bsdinfo = NULL;
+ int setbg = 0;
+ int ret = 0;
+ int maxpri = BASEPRI_DEFAULT;
+
+ task_lock(task);
+
+ if (task->ext_policystate.apptype != policy_subtype) {
+ ret = EINVAL;
+ goto out;
+ }
+
+#if !CONFIG_EMBEDDED
+ switch (task->role) {
+ case TASK_FOREGROUND_APPLICATION:
+ maxpri = BASEPRI_FOREGROUND;
+ break;
+ case TASK_BACKGROUND_APPLICATION:
+ maxpri = BASEPRI_BACKGROUND;
+ break;
+ default:
+ maxpri = BASEPRI_DEFAULT;
+ }
+#endif
+
+ if (task->ext_actionstate.apptype != PROC_POLICY_OSX_APPTYPE_NONE) {
+ switch (task->ext_actionstate.apptype) {
+ case PROC_POLICY_OSX_APPTYPE_TAL:
+ /* disable foreground/background handling */
+ task->ext_actionstate.apptype = PROC_POLICY_OSX_APPTYPE_NONE;
+ /* external BG application removal */
+ proc_restore_bgtaskpolicy_locked(task, 1, 1, maxpri);
+ bsdinfo = task->bsd_info;
+ setbg = 0;
+ break;
+
+ case PROC_POLICY_OSX_APPTYPE_DBCLIENT:
+ /* disable foreground/background handling */
+ task->ext_actionstate.apptype = PROC_POLICY_OSX_APPTYPE_NONE;
+ /* internal BG application removal */
+ proc_restore_bgtaskpolicy_locked(task, 1, 0, maxpri);
+ bsdinfo = task->bsd_info;
+ setbg = 0;
+ break;
+
+ default:
+ ret = EINVAL;
+ break;
+ }
+ } else
+ ret = EINVAL;
+
+out:
+ task_unlock(task);
+ /* if backgrounding action ... */
+ if (bsdinfo != NULL)
+ proc_set_task_networkbg(bsdinfo, setbg);
+
+ return(ret);
+}
+
+int
+proc_enable_task_apptype(task_t task, int policy_subtype)
+{
+ void * bsdinfo = NULL;
+ int setbg = 0;
+ int ret = 0;
+
+ task_lock(task);
+
+ if (task->ext_policystate.apptype != policy_subtype) {
+ ret = EINVAL;
+ goto out;
+ }
+
+ if (task->ext_actionstate.apptype == PROC_POLICY_OSX_APPTYPE_NONE) {
+ switch (task->ext_policystate.apptype) {
+ case PROC_POLICY_OSX_APPTYPE_TAL:
+ /* TAL policy is activated again */
+ task->ext_actionstate.apptype = task->ext_policystate.apptype;
+ if (task->role == TASK_BACKGROUND_APPLICATION) {
+ if (task->role == TASK_BACKGROUND_APPLICATION) {
+ proc_apply_bgtaskpolicy_locked(task, 1, 1);
+ bsdinfo = task->bsd_info;
+ setbg = 1;
+ }
+ }
+ ret = 0;
+ break;
+ default:
+ ret = EINVAL;
+ }
+ } else
+ ret = EINVAL;
+
+out:
+ task_unlock(task);
+ /* if backgrounding action ... */
+ if (bsdinfo != NULL)
+ proc_set_task_networkbg(bsdinfo, setbg);
+
+ return(ret);
+}
+