2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <mach/mach_types.h>
30 #include <mach/task_server.h>
32 #include <kern/sched.h>
33 #include <kern/task.h>
34 #include <mach/thread_policy.h>
35 #include <sys/errno.h>
36 #include <sys/resource.h>
37 #include <machine/limits.h>
38 #include <kern/ledger.h>
39 #include <kern/thread_call.h>
41 #include <kern/kalloc.h>
42 #include <sys/errno.h>
43 #endif /* CONFIG_EMBEDDED */
44 #include <sys/kdebug.h>
46 #if CONFIG_MEMORYSTATUS
47 extern void memorystatus_on_suspend(int pid
);
48 extern void memorystatus_on_resume(int pid
);
51 static int proc_apply_bgtaskpolicy_internal(task_t
, int, int);
52 static int proc_restore_bgtaskpolicy_internal(task_t
, int, int, int);
53 static int task_get_cpuusage(task_t task
, uint32_t * percentagep
, uint64_t * intervalp
, uint64_t * deadlinep
);
54 int task_set_cpuusage(task_t task
, uint64_t percentage
, uint64_t interval
, uint64_t deadline
, int scope
);
55 static int task_clear_cpuusage_locked(task_t task
);
56 static int task_apply_resource_actions(task_t task
, int type
);
57 static void task_priority(task_t task
, integer_t priority
, integer_t max_priority
);
58 static kern_return_t
task_role_default_handler(task_t task
, task_role_t role
);
59 void task_action_cpuusage(thread_call_param_t param0
, thread_call_param_t param1
);
60 static int proc_apply_bgthreadpolicy_locked(thread_t thread
, int selfset
);
61 static void restore_bgthreadpolicy_locked(thread_t thread
, int selfset
, int importance
);
62 static int proc_get_task_selfdiskacc_internal(task_t task
, thread_t thread
);
63 extern void unthrottle_thread(void * uthread
);
66 static void set_thread_appbg(thread_t thread
, int setbg
,int importance
);
67 static void apply_bgthreadpolicy_external(thread_t thread
);
68 static void add_taskwatch_locked(task_t task
, task_watch_t
* twp
);
69 static void remove_taskwatch_locked(task_t task
, task_watch_t
* twp
);
70 static void task_watch_lock(void);
71 static void task_watch_unlock(void);
72 static void apply_appstate_watchers(task_t task
, int setbg
);
73 void proc_apply_task_networkbg_internal(void *, thread_t
);
74 void proc_restore_task_networkbg_internal(void *, thread_t
);
75 int proc_pid(void * proc
);
77 typedef struct thread_watchlist
{
78 thread_t thread
; /* thread being worked on for taskwatch action */
79 int importance
; /* importance to be restored if thread is being made active */
82 #endif /* CONFIG_EMBEDDED */
85 process_policy_t default_task_proc_policy
= {0,
87 TASK_POLICY_RESOURCE_ATTRIBUTE_NONE
,
88 TASK_POLICY_RESOURCE_ATTRIBUTE_NONE
,
89 TASK_POLICY_RESOURCE_ATTRIBUTE_NONE
,
90 TASK_POLICY_RESOURCE_ATTRIBUTE_NONE
,
91 TASK_POLICY_RESOURCE_ATTRIBUTE_NONE
,
92 TASK_POLICY_RESOURCE_ATTRIBUTE_NONE
,
93 TASK_POLICY_RESOURCE_ATTRIBUTE_NONE
,
95 TASK_POLICY_HWACCESS_CPU_ATTRIBUTE_FULLACCESS
,
96 TASK_POLICY_HWACCESS_NET_ATTRIBUTE_FULLACCESS
,
97 TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_FULLACCESS
,
98 TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_NORMAL
,
99 TASK_POLICY_BACKGROUND_ATTRIBUTE_ALL
102 process_policy_t default_task_null_policy
= {0,
104 TASK_POLICY_RESOURCE_ATTRIBUTE_NONE
,
105 TASK_POLICY_RESOURCE_ATTRIBUTE_NONE
,
106 TASK_POLICY_RESOURCE_ATTRIBUTE_NONE
,
107 TASK_POLICY_RESOURCE_ATTRIBUTE_NONE
,
108 TASK_POLICY_RESOURCE_ATTRIBUTE_NONE
,
109 TASK_POLICY_RESOURCE_ATTRIBUTE_NONE
,
110 TASK_POLICY_RESOURCE_ATTRIBUTE_NONE
,
112 TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NONE
,
113 TASK_POLICY_HWACCESS_NET_ATTRIBUTE_NONE
,
114 TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NONE
,
115 TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_NORMAL
,
116 TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE
122 * This routine should always be called with the task lock held.
123 * This routine handles Default operations for TASK_FOREGROUND_APPLICATION
124 * and TASK_BACKGROUND_APPLICATION of task with no special app type.
127 task_role_default_handler(task_t task
, task_role_t role
)
129 kern_return_t result
= KERN_SUCCESS
;
131 switch (task
->role
) {
132 case TASK_FOREGROUND_APPLICATION
:
133 case TASK_BACKGROUND_APPLICATION
:
134 case TASK_UNSPECIFIED
:
135 /* if there are no process wide backgrounding ... */
136 if ((task
->ext_appliedstate
.hw_bg
== TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE
) &&
137 (task
->appliedstate
.hw_bg
== TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE
)) {
139 ((role
== TASK_FOREGROUND_APPLICATION
)?
140 BASEPRI_FOREGROUND
: BASEPRI_BACKGROUND
),
146 case TASK_CONTROL_APPLICATION
:
148 /* else fail silently */
152 result
= KERN_INVALID_ARGUMENT
;
162 task_policy_flavor_t flavor
,
163 task_policy_t policy_info
,
164 mach_msg_type_number_t count
)
166 kern_return_t result
= KERN_SUCCESS
;
167 void * bsdinfo
= NULL
;
170 if (task
== TASK_NULL
|| task
== kernel_task
)
171 return (KERN_INVALID_ARGUMENT
);
175 case TASK_CATEGORY_POLICY
:
177 task_category_policy_t info
= (task_category_policy_t
)policy_info
;
179 if (count
< TASK_CATEGORY_POLICY_COUNT
)
180 return (KERN_INVALID_ARGUMENT
);
183 if ((current_task() == task
) && (info
!= NULL
) &&
184 (info
->role
!= TASK_THROTTLE_APPLICATION
))
185 return (KERN_INVALID_ARGUMENT
);
190 case TASK_FOREGROUND_APPLICATION
: {
191 if (task
->ext_appliedstate
.apptype
== PROC_POLICY_OSX_APPTYPE_NONE
) {
192 result
= task_role_default_handler(task
, info
->role
);
194 switch (task
->ext_appliedstate
.apptype
) {
196 case PROC_POLICY_OSX_APPTYPE_TAL
:
197 /* Move the app to foreground with no DarwinBG */
198 proc_restore_bgtaskpolicy_internal(task
, 1, 1, BASEPRI_FOREGROUND
);
199 bsdinfo
= task
->bsd_info
;
203 case PROC_POLICY_OSX_APPTYPE_DBCLIENT
:
204 /* reset the apptype so enforcement on background/foregound */
205 task
->ext_appliedstate
.apptype
= PROC_POLICY_OSX_APPTYPE_NONE
;
206 /* Internal application and make it foreground pri */
207 proc_restore_bgtaskpolicy_internal(task
, 1, 0, BASEPRI_FOREGROUND
);
208 bsdinfo
= task
->bsd_info
;
211 #endif /* !CONFIG_EMBEDDED */
214 /* the app types cannot be in CONTROL, GRAPHICS STATE, so it will de default state here */
215 task_priority(task
, BASEPRI_FOREGROUND
, task
->max_priority
);
218 } /* switch (task->ext_appliedstate.apptype) */
219 task
->role
= TASK_FOREGROUND_APPLICATION
;
224 case TASK_BACKGROUND_APPLICATION
: {
225 if (task
->ext_appliedstate
.apptype
== PROC_POLICY_OSX_APPTYPE_NONE
) {
226 result
= task_role_default_handler(task
, info
->role
);
227 } else { /* apptype != PROC_POLICY_OSX_APPTYPE_NONE */
228 switch (task
->ext_appliedstate
.apptype
) {
230 case PROC_POLICY_OSX_APPTYPE_TAL
:
231 /* TAL apps will get Darwin backgrounded if not already set */
232 if (task
->ext_appliedstate
.hw_bg
== TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE
) {
233 proc_apply_bgtaskpolicy_internal(task
, 1, 1);
234 bsdinfo
= task
->bsd_info
;
238 #endif /* !CONFIG_EMBEDDED */
240 task_priority(task
, BASEPRI_BACKGROUND
, task
->max_priority
);
242 } /* switch (task->ext_appliedstate.apptype) */
243 task
->role
= TASK_BACKGROUND_APPLICATION
;
248 case TASK_CONTROL_APPLICATION
:
249 if (task
!= current_task()||
250 task
->sec_token
.val
[0] != 0)
251 result
= KERN_INVALID_ARGUMENT
;
253 task_priority(task
, BASEPRI_CONTROL
, task
->max_priority
);
254 task
->role
= info
->role
;
258 case TASK_GRAPHICS_SERVER
:
259 if (task
!= current_task() ||
260 task
->sec_token
.val
[0] != 0)
261 result
= KERN_INVALID_ARGUMENT
;
263 task_priority(task
, MAXPRI_RESERVED
- 3, MAXPRI_RESERVED
);
264 task
->role
= info
->role
;
267 case TASK_DEFAULT_APPLICATION
:
268 task_priority(task
, BASEPRI_DEFAULT
, MAXPRI_USER
);
269 task
->role
= info
->role
;
273 result
= KERN_INVALID_ARGUMENT
;
275 } /* switch (info->role) */
279 /* if backgrounding action ... */
281 proc_set_task_networkbg(bsdinfo
, setbg
);
287 result
= KERN_INVALID_ARGUMENT
;
298 integer_t max_priority
)
302 task
->max_priority
= max_priority
;
304 if (priority
> task
->max_priority
)
305 priority
= task
->max_priority
;
307 if (priority
< MINPRI
)
310 task
->priority
= priority
;
312 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
313 thread_mtx_lock(thread
);
316 thread_task_priority(thread
, priority
, max_priority
);
318 thread_mtx_unlock(thread
);
325 integer_t importance
)
327 if (task
== TASK_NULL
|| task
== kernel_task
)
328 return (KERN_INVALID_ARGUMENT
);
335 return (KERN_TERMINATED
);
338 if (task
->role
>= TASK_CONTROL_APPLICATION
) {
341 return (KERN_INVALID_ARGUMENT
);
344 task_priority(task
, importance
+ BASEPRI_DEFAULT
, task
->max_priority
);
345 task
->role
= TASK_RENICED
;
349 return (KERN_SUCCESS
);
355 task_policy_flavor_t flavor
,
356 task_policy_t policy_info
,
357 mach_msg_type_number_t
*count
,
358 boolean_t
*get_default
)
360 if (task
== TASK_NULL
|| task
== kernel_task
)
361 return (KERN_INVALID_ARGUMENT
);
365 case TASK_CATEGORY_POLICY
:
367 task_category_policy_t info
= (task_category_policy_t
)policy_info
;
369 if (*count
< TASK_CATEGORY_POLICY_COUNT
)
370 return (KERN_INVALID_ARGUMENT
);
373 info
->role
= TASK_UNSPECIFIED
;
376 info
->role
= task
->role
;
383 return (KERN_INVALID_ARGUMENT
);
386 return (KERN_SUCCESS
);
389 /* task Darwin BG enforcement/settings related routines */
391 proc_get_task_bg_policy(task_t task
)
397 if (current_task() == task
)
401 val
= task
->ext_policystate
.hw_bg
;
403 val
= task
->policystate
.hw_bg
;
411 proc_get_thread_bg_policy(task_t task
, uint64_t tid
)
414 thread_t self
= current_thread();
415 thread_t thread
= THREAD_NULL
;
418 if (tid
== self
->thread_id
)
423 thread
= task_findtid(task
, tid
);
425 val
= thread
->ext_policystate
.hw_bg
;
428 val
= self
->policystate
.hw_bg
;
435 proc_get_self_isbackground(void)
437 task_t task
= current_task();;
438 thread_t thread
= current_thread();
440 if ((task
->ext_appliedstate
.hw_bg
!= TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE
) ||
441 (task
->appliedstate
.hw_bg
!= TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE
) ||
442 (thread
->ext_appliedstate
.hw_bg
!= TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE
) ||
443 (thread
->appliedstate
.hw_bg
!= TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE
))
450 int proc_get_selfthread_isbackground(void)
452 thread_t thread
= current_thread();
454 if ((thread
->ext_appliedstate
.hw_bg
!= TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE
) ||
455 (thread
->appliedstate
.hw_bg
!= TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE
))
463 proc_set_bgtaskpolicy(task_t task
, int intval
)
468 if (current_task() == task
)
475 if (task
->ext_policystate
.hw_bg
!= intval
)
476 task
->ext_policystate
.hw_bg
= intval
;
478 if (task
->policystate
.hw_bg
!= intval
)
479 task
->policystate
.hw_bg
= intval
;
486 /* set and apply as well , handles reset of NONUI due to setprio() task app state implmn side effect */
488 proc_set_and_apply_bgtaskpolicy(task_t task
, int prio
)
492 if (prio
== PRIO_DARWIN_BG
) {
493 error
= proc_set_bgtaskpolicy(task
, TASK_POLICY_BACKGROUND_ATTRIBUTE_ALL
);
495 error
= proc_apply_bgtaskpolicy(task
);
497 /* XXX: till SB uses newer SPIs */
498 apply_appstate_watchers(task
, 1);
499 #endif /* CONFIG_EMBEDDED */
502 error
= proc_restore_bgtaskpolicy(task
);
504 /* since prior impl of non UI was overloaded with bg state, need to reset */
505 error
= proc_apply_task_gpuacc(task
, TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_DEFAULT
);
507 /* XXX: till SB uses newer SPIs */
508 apply_appstate_watchers(task
, 0);
509 #endif /* CONFIG_EMBEDDED */
519 proc_set_bgthreadpolicy(task_t task
, uint64_t tid
, int prio
)
522 thread_t self
= current_thread();
523 thread_t thread
= THREAD_NULL
;
528 if (tid
== self
->thread_id
)
533 thread
= task_findtid(task
, tid
);
535 thread
->ext_policystate
.hw_bg
= prio
;
537 self
->policystate
.hw_bg
= prio
;
546 proc_set_and_apply_bgthreadpolicy(task_t task
, uint64_t tid
, int prio
)
550 if (prio
== PRIO_DARWIN_BG
) {
551 error
= proc_set_bgthreadpolicy(task
, tid
, TASK_POLICY_BACKGROUND_ATTRIBUTE_ALL
);
553 error
= proc_apply_bgthreadpolicy(task
, tid
);
555 error
= proc_restore_bgthreadpolicy(task
, tid
);
562 proc_add_bgtaskpolicy(task_t task
, int val
)
566 if (current_task() == task
)
572 task
->policystate
.hw_bg
|= val
;
574 task
->ext_policystate
.hw_bg
|= val
;
582 proc_add_bgthreadpolicy(task_t task
, uint64_t tid
, int val
)
585 thread_t self
= current_thread();
586 thread_t thread
= THREAD_NULL
;
591 if (tid
== self
->thread_id
)
596 thread
= task_findtid(task
, tid
);
598 thread
->ext_policystate
.hw_bg
|= val
;
600 self
->policystate
.hw_bg
|= val
;
609 proc_remove_bgtaskpolicy(task_t task
, int intval
)
613 if (current_task() == task
)
619 task
->policystate
.hw_bg
&= ~intval
;
621 task
->ext_policystate
.hw_bg
&= ~intval
;
629 proc_remove_bgthreadpolicy(task_t task
, uint64_t tid
, int val
)
632 thread_t self
= current_thread();
633 thread_t thread
= THREAD_NULL
;
638 if (tid
== self
->thread_id
)
643 thread
= task_findtid(task
, tid
);
645 thread
->ext_policystate
.hw_bg
&= ~val
;
647 self
->policystate
.hw_bg
&= ~val
;
656 proc_apply_bgtask_selfpolicy(void)
658 return(proc_apply_bgtaskpolicy(current_task()));
662 proc_apply_bgtaskpolicy(task_t task
)
666 if (task
== current_task())
668 return(proc_apply_bgtaskpolicy_internal(task
, 0, external
));
672 proc_apply_bgtaskpolicy_external(task_t task
)
674 return(proc_apply_bgtaskpolicy_internal(task
, 0, 1));
678 proc_apply_bgtaskpolicy_internal(task_t task
, int locked
, int external
)
684 /* if the process is exiting, no action to be done */
685 if (task
->proc_terminate
!= 0)
690 if (task
->ext_appliedstate
.hw_bg
!= task
->ext_policystate
.hw_bg
) {
691 task
->ext_appliedstate
.hw_bg
= task
->ext_policystate
.hw_bg
;
692 task_priority(task
, MAXPRI_THROTTLE
, MAXPRI_THROTTLE
);
693 /* background state applied */
696 if (task
->appliedstate
.hw_bg
!= task
->policystate
.hw_bg
) {
697 task
->appliedstate
.hw_bg
= task
->policystate
.hw_bg
;
698 task_priority(task
, MAXPRI_THROTTLE
, MAXPRI_THROTTLE
);
707 /* apply the self backgrounding even if the thread is not current thread */
709 proc_apply_workq_bgthreadpolicy(thread_t thread
)
712 task_t wqtask
= TASK_NULL
;
714 if (thread
!= THREAD_NULL
) {
715 wqtask
= thread
->task
;
717 /* apply the background as selfset internal one */
718 error
= proc_apply_bgthreadpolicy_locked(thread
, 1);
727 proc_apply_bgthreadpolicy(task_t task
, uint64_t tid
)
729 int selfset
= 0, error
= 0;
730 thread_t self
= current_thread();
731 thread_t thread
= THREAD_NULL
;
732 task_t localtask
= TASK_NULL
;
734 if (tid
== self
->thread_id
) {
736 localtask
= current_task();
740 task_lock(localtask
);
744 thread
= task_findtid(localtask
, tid
);
747 error
= proc_apply_bgthreadpolicy_locked(thread
, selfset
);
749 task_unlock(localtask
);
755 proc_apply_bgthreadpolicy_locked(thread_t thread
, int selfset
)
758 thread_precedence_policy_data_t policy
;
761 if (thread
!= NULL
) {
762 /* if the process is exiting, no action to be done */
763 if (thread
->task
->proc_terminate
!= 0)
767 /* internal application */
768 if (thread
->appliedstate
.hw_bg
!= thread
->policystate
.hw_bg
) {
769 thread
->appliedstate
.hw_bg
= thread
->policystate
.hw_bg
;
770 if (thread
->ext_appliedstate
.hw_bg
== TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE
)
775 /* external application */
776 if (thread
->ext_appliedstate
.hw_bg
!= thread
->ext_policystate
.hw_bg
) {
777 thread
->ext_appliedstate
.hw_bg
= thread
->ext_policystate
.hw_bg
;
778 if (thread
->appliedstate
.hw_bg
== TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE
)
785 if (thread
->task
->ext_appliedstate
.apptype
== PROC_POLICY_IOS_APPLE_DAEMON
) {
786 thread
->saved_importance
= thread
->importance
;
788 #endif /* CONFIG_EMBEDDED */
789 /* set thread priority (we did not save previous value) */
790 policy
.importance
= INT_MIN
;
792 thread_policy_set_internal(thread
, THREAD_PRECEDENCE_POLICY
,
793 (thread_policy_t
)&policy
,
794 THREAD_PRECEDENCE_POLICY_COUNT
);
805 /* set external application of background */
807 apply_bgthreadpolicy_external(thread_t thread
)
810 thread_precedence_policy_data_t policy
;
812 /* if the process is exiting, no action to be done */
813 if (thread
->task
->proc_terminate
!= 0)
816 thread
->ext_policystate
.hw_bg
= TASK_POLICY_BACKGROUND_ATTRIBUTE_ALL
;
818 if (thread
->ext_appliedstate
.hw_bg
!= thread
->ext_policystate
.hw_bg
) {
819 thread
->ext_appliedstate
.hw_bg
= thread
->ext_policystate
.hw_bg
;
820 if (thread
->appliedstate
.hw_bg
== TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE
)
825 /* set thread priority (we did not save previous value) */
826 policy
.importance
= INT_MIN
;
828 thread_policy_set_internal(thread
, THREAD_PRECEDENCE_POLICY
,
829 (thread_policy_t
)&policy
,
830 THREAD_PRECEDENCE_POLICY_COUNT
);
834 #endif /* CONFIG_EMBEDDED */
837 proc_apply_bgthread_selfpolicy(void)
839 return(proc_apply_bgthreadpolicy(current_task(), current_thread()->thread_id
));
844 proc_restore_bgtaskpolicy(task_t task
)
848 if (current_task() == task
)
850 return(proc_restore_bgtaskpolicy_internal(task
, 0, external
, BASEPRI_DEFAULT
));
854 proc_restore_bgtaskpolicy_internal(task_t task
, int locked
, int external
, int pri
)
859 /* if the process is exiting, no action to be done */
860 if (task
->proc_terminate
!= 0)
864 task
->ext_appliedstate
.hw_bg
= TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE
;
865 /* self BG in flight? */
866 if (task
->appliedstate
.hw_bg
== TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE
) {
867 task_priority(task
, pri
, MAXPRI_USER
);
869 task
->role
= TASK_DEFAULT_APPLICATION
;
870 #endif /* CONFIG_EMBEDDED */
873 task
->appliedstate
.hw_bg
= TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE
;
874 /* external BG in flight? */
875 if (task
->ext_appliedstate
.hw_bg
== TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE
) {
876 task_priority(task
, pri
, MAXPRI_USER
);
878 task
->role
= TASK_DEFAULT_APPLICATION
;
879 #endif /* CONFIG_EMBEDDED */
889 /* restore the self backgrounding even if the thread is not current thread */
891 proc_restore_workq_bgthreadpolicy(thread_t thread
)
894 task_t wqtask
= TASK_NULL
;
897 if (thread
!= THREAD_NULL
) {
898 wqtask
= thread
->task
;
900 /* remove the background and restore default importance as self(internal) removal */
902 if (thread
->task
->ext_appliedstate
.apptype
== PROC_POLICY_IOS_APPLE_DAEMON
) {
903 /* restore prev set importnace */
904 importance
= thread
->saved_importance
;
905 thread
->saved_importance
= 0;
907 #endif /* CONFIG_EMBEDDED */
908 restore_bgthreadpolicy_locked(thread
, 1, importance
);
917 proc_restore_bgthread_selfpolicy(void)
919 return(proc_restore_bgthreadpolicy(current_task(), thread_tid(current_thread())));
923 proc_restore_bgthreadpolicy(task_t task
, uint64_t tid
)
927 thread_t self
= current_thread();
928 thread_t thread
= THREAD_NULL
;
931 if (tid
== self
->thread_id
)
936 thread
= task_findtid(task
, tid
);
941 if (thread
!= NULL
) {
943 if (thread
->task
->ext_appliedstate
.apptype
== PROC_POLICY_IOS_APPLE_DAEMON
) {
944 /* restore prev set importnace */
945 importance
= thread
->saved_importance
;
946 thread
->saved_importance
= 0;
948 #endif /* CONFIG_EMBEDDED */
949 restore_bgthreadpolicy_locked(thread
, selfset
, importance
);
960 restore_bgthreadpolicy_locked(thread_t thread
, int selfset
, int importance
)
962 thread_precedence_policy_data_t policy
;
965 if (thread
!= NULL
) {
966 /* if the process is exiting, no action to be done */
967 if (thread
->task
->proc_terminate
!= 0)
971 thread
->appliedstate
.hw_bg
= TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE
;
972 /* external BG in flight? */
973 if (thread
->ext_appliedstate
.hw_bg
== TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE
)
977 thread
->ext_appliedstate
.hw_bg
= TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE
;
978 /* self BG in flight? */
979 if (thread
->appliedstate
.hw_bg
== TASK_POLICY_BACKGROUND_ATTRIBUTE_NONE
)
984 /* reset thread priority (we did not save previous value) */
985 policy
.importance
= importance
;
986 thread_policy_set_internal(thread
, THREAD_PRECEDENCE_POLICY
,
987 (thread_policy_t
)&policy
,
988 THREAD_PRECEDENCE_POLICY_COUNT
);
995 proc_set_task_apptype(task_t task
, int type
, thread_t thread
)
997 proc_set_task_apptype(task_t task
, int type
, __unused thread_t thread
)
1001 thread_t th
= THREAD_NULL
;
1002 #endif /* CONFIG_EMBEDDED */
1006 case PROC_POLICY_IOS_RESV1_APPTYPE
:
1007 task
->ext_policystate
.apptype
= type
;
1008 task
->policystate
.apptype
= type
;
1009 proc_apply_bgtaskpolicy_external(task
);
1010 /* indicate that BG is set and next foreground needs to reset */
1011 task
->ext_appliedstate
.apptype
= type
;
1014 case PROC_POLICY_IOS_APPLE_DAEMON
:
1015 task
->ext_policystate
.apptype
= type
;
1016 task
->policystate
.apptype
= type
;
1017 task
->ext_appliedstate
.apptype
= type
;
1018 /* posix spawn will already have thread created, so backround it */
1020 th
= current_thread();
1023 if (th
->appliedstate
.hw_bg
!= TASK_POLICY_BACKGROUND_ATTRIBUTE_ALL
) {
1024 /* apply self backgrounding if not already set */
1025 task_lock(th
->task
);
1026 proc_apply_bgthreadpolicy_locked(th
, 1);
1027 task_unlock(th
->task
);
1031 case PROC_POLICY_IOS_APPTYPE
:
1032 task
->ext_policystate
.apptype
= type
;
1033 task
->policystate
.apptype
= type
;
1035 case PROC_POLICY_IOS_NONUITYPE
:
1036 task
->ext_policystate
.apptype
= type
;
1037 task
->policystate
.apptype
= type
;
1038 /* set to deny access to gpu */
1039 task
->ext_appliedstate
.hw_gpu
= TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS
;
1040 task
->ext_policystate
.hw_gpu
= TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS
;
1042 #else /* CONFIG_EMBEDDED */
1043 case PROC_POLICY_OSX_APPTYPE_TAL
:
1044 task
->ext_policystate
.apptype
= type
;
1045 task
->policystate
.apptype
= type
;
1046 proc_apply_bgtaskpolicy_external(task
);
1047 /* indicate that BG is set and next foreground needs to reset */
1048 task
->ext_appliedstate
.apptype
= type
;
1051 case PROC_POLICY_OSX_APPTYPE_DBCLIENT
:
1052 task
->ext_policystate
.apptype
= type
;
1053 task
->policystate
.apptype
= type
;
1054 proc_apply_bgtaskpolicy_internal(task
, 0, 0);
1057 #endif /* CONFIG_EMBEDDED */
1064 /* update the darwin backdground action state in the flags field for libproc */
1065 #define PROC_FLAG_DARWINBG 0x8000 /* process in darwin background */
1066 #define PROC_FLAG_EXT_DARWINBG 0x10000 /* process in darwin background - external enforcement */
1067 #define PROC_FLAG_IOS_APPLEDAEMON 0x20000 /* process is apple ios daemon */
1070 proc_get_darwinbgstate(task_t task
, uint32_t * flagsp
)
1072 if (task
->ext_appliedstate
.hw_bg
== TASK_POLICY_BACKGROUND_ATTRIBUTE_ALL
){
1073 *flagsp
|= PROC_FLAG_EXT_DARWINBG
;
1075 if (task
->appliedstate
.hw_bg
== TASK_POLICY_BACKGROUND_ATTRIBUTE_ALL
){
1076 *flagsp
|= PROC_FLAG_DARWINBG
;
1079 if (task
->ext_appliedstate
.apptype
== PROC_POLICY_IOS_APPLE_DAEMON
) {
1080 *flagsp
|= PROC_FLAG_IOS_APPLEDAEMON
;
1082 #endif /* CONFIG_EMBEDDED */
1088 * HW disk access realted routines, they need to return
1089 * IOPOL_XXX equivalents for spec_xxx/throttle updates.
1093 proc_get_task_disacc(task_t task
)
1096 if ((task
->ext_appliedstate
.hw_bg
& TASK_POLICY_BACKGROUND_ATTRIBUTE_DISKTHROTTLE
) != 0)
1097 return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_THROTTLE
);
1098 #else /* CONFIG_EMBEDDED */
1099 if ((task
->ext_appliedstate
.hw_bg
& TASK_POLICY_BACKGROUND_ATTRIBUTE_DISKTHROTTLE
) != 0) {
1100 /* if it is a TAL or DBClient and not self throttled, return Utility */
1101 if ((task
->ext_appliedstate
.apptype
== PROC_POLICY_OSX_APPTYPE_TAL
) || (task
->ext_appliedstate
.apptype
== PROC_POLICY_OSX_APPTYPE_DBCLIENT
)) {
1102 /* any setting for DBG, we need to honor that */
1103 if ((task
->ext_appliedstate
.hw_disk
!= TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_THROTTLE
) &&
1104 ((task
->appliedstate
.hw_bg
& TASK_POLICY_BACKGROUND_ATTRIBUTE_DISKTHROTTLE
)!= 0) &&
1105 (task
->appliedstate
.hw_disk
!= TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_THROTTLE
)) {
1106 return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_UTILITY
);
1108 return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_THROTTLE
);
1110 return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_THROTTLE
);
1112 #endif /* CONFIG_EMBEDDED */
1113 if (task
->ext_appliedstate
.hw_disk
!= TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_FULLACCESS
)
1114 return(task
->ext_appliedstate
.hw_disk
);
1115 if ((task
->appliedstate
.hw_bg
& TASK_POLICY_BACKGROUND_ATTRIBUTE_DISKTHROTTLE
) != 0)
1116 return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_THROTTLE
);
1117 if (task
->appliedstate
.hw_disk
!= TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_FULLACCESS
)
1118 return(task
->appliedstate
.hw_disk
);
1119 return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_FULLACCESS
);
1123 proc_get_task_selfdiskacc_internal(task_t task
, thread_t thread
)
1125 /* if the task is marked for proc_terminate, no throttling for it */
1126 if (task
->proc_terminate
!= 0)
1129 * As per defined iopolicysys behavior, thread trumps task.
1130 * Do we need to follow that for external enforcements of BG or hw access?
1131 * Status quo for now..
1134 if((thread
->ext_appliedstate
.hw_bg
& TASK_POLICY_BACKGROUND_ATTRIBUTE_DISKTHROTTLE
) != 0)
1135 return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_THROTTLE
);
1136 if (thread
->ext_appliedstate
.hw_disk
!= TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_FULLACCESS
)
1137 return(thread
->ext_appliedstate
.hw_disk
);
1138 if((thread
->appliedstate
.hw_bg
& TASK_POLICY_BACKGROUND_ATTRIBUTE_DISKTHROTTLE
) != 0)
1139 return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_THROTTLE
);
1140 if (thread
->appliedstate
.hw_disk
!= TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_FULLACCESS
)
1141 return(thread
->appliedstate
.hw_disk
);
1144 if ((task
->ext_appliedstate
.hw_bg
& TASK_POLICY_BACKGROUND_ATTRIBUTE_DISKTHROTTLE
) != 0)
1145 return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_THROTTLE
);
1146 #else /* CONFIG_EMBEDDED */
1147 if ((task
->ext_appliedstate
.hw_bg
& TASK_POLICY_BACKGROUND_ATTRIBUTE_DISKTHROTTLE
) != 0) {
1148 /* if it is a TAL or DBClient and not self throttled, return Utility */
1149 if ((task
->ext_appliedstate
.apptype
== PROC_POLICY_OSX_APPTYPE_TAL
) || (task
->ext_appliedstate
.apptype
== PROC_POLICY_OSX_APPTYPE_DBCLIENT
)) {
1150 /* any setting for DBG, we need to honor that */
1151 if ((task
->ext_appliedstate
.hw_disk
!= TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_THROTTLE
) &&
1152 ((task
->appliedstate
.hw_bg
& TASK_POLICY_BACKGROUND_ATTRIBUTE_DISKTHROTTLE
)!= 0) &&
1153 (task
->appliedstate
.hw_disk
!= TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_THROTTLE
)) {
1154 return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_UTILITY
);
1156 return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_THROTTLE
);
1158 return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_THROTTLE
);
1160 #endif /* CONFIG_EMBEDDED */
1161 if (task
->ext_appliedstate
.hw_disk
!= TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_FULLACCESS
)
1162 return(task
->ext_appliedstate
.hw_disk
);
1163 if ((task
->appliedstate
.hw_bg
& TASK_POLICY_BACKGROUND_ATTRIBUTE_DISKTHROTTLE
) != 0)
1164 return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_THROTTLE
);
1165 if (task
->appliedstate
.hw_disk
!= TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_FULLACCESS
)
1166 return(task
->appliedstate
.hw_disk
);
1168 return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_FULLACCESS
);
1173 proc_get_task_selfdiskacc(void)
1175 return(proc_get_task_selfdiskacc_internal(current_task(), current_thread()));
1180 proc_get_diskacc(thread_t thread
)
1182 return(proc_get_task_selfdiskacc_internal(thread
->task
, thread
));
1187 proc_get_thread_selfdiskacc(void)
1189 thread_t thread
= current_thread();
1191 if((thread
->ext_appliedstate
.hw_bg
& TASK_POLICY_BACKGROUND_ATTRIBUTE_DISKTHROTTLE
) != 0)
1192 return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_THROTTLE
);
1193 if (thread
->ext_appliedstate
.hw_disk
!= TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_FULLACCESS
)
1194 return(thread
->ext_appliedstate
.hw_disk
);
1195 if((thread
->appliedstate
.hw_bg
& TASK_POLICY_BACKGROUND_ATTRIBUTE_DISKTHROTTLE
) != 0)
1196 return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_THROTTLE
);
1197 if (thread
->appliedstate
.hw_disk
!= TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_FULLACCESS
)
1198 return(thread
->appliedstate
.hw_disk
);
1199 return(TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_FULLACCESS
);
1203 proc_apply_task_diskacc(task_t task
, int policy
)
1205 task_t self
= current_task();
1209 task
->appliedstate
.hw_disk
= policy
;
1210 task
->policystate
.hw_disk
= policy
;
1212 task
->ext_appliedstate
.hw_disk
= policy
;
1213 task
->ext_policystate
.hw_disk
= policy
;
1220 proc_apply_thread_diskacc(task_t task
, uint64_t tid
, int policy
)
1224 if (tid
== TID_NULL
) {
1225 thread
= current_thread();
1226 proc_apply_thread_selfdiskacc(policy
);
1229 thread
= task_findtid(task
, tid
);
1230 if (thread
!= NULL
) {
1231 thread
->ext_appliedstate
.hw_disk
= policy
;
1232 thread
->ext_policystate
.hw_disk
= policy
;
1243 proc_task_remove_throttle(task_t task
)
1251 /* remove processwide internal DBG applicationn */
1252 proc_restore_bgtaskpolicy_internal(task
, 1, 0, BASEPRI_DEFAULT
);
1253 /* remove processwide external DBG applicationn */
1254 proc_restore_bgtaskpolicy_internal(task
, 1, 1, BASEPRI_DEFAULT
);
1256 for (thread
= (thread_t
)queue_first(&task
->threads
);
1257 !queue_end(&task
->threads
, (queue_entry_t
)thread
); ) {
1259 if (thread
->task
->ext_appliedstate
.apptype
== PROC_POLICY_IOS_APPLE_DAEMON
) {
1260 /* restore prev set importnace */
1261 importance
= thread
->saved_importance
;
1262 thread
->saved_importance
= 0;
1264 #endif /* CONFIG_EMBEDDED */
1265 /* remove thread level internal DBG application */
1266 restore_bgthreadpolicy_locked(thread
, 1, importance
);
1267 /* remove thread level external DBG application */
1268 restore_bgthreadpolicy_locked(thread
, 0, importance
);
1269 /* reset thread io policy */
1270 thread
->ext_appliedstate
.hw_disk
= TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_FULLACCESS
;
1271 thread
->appliedstate
.hw_disk
= TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_FULLACCESS
;
1272 unthrottle_thread(thread
->uthread
);
1273 thread
= (thread_t
)queue_next(&thread
->task_threads
);
1276 /* reset task iopolicy */
1277 task
->ext_appliedstate
.hw_disk
= TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_FULLACCESS
;
1278 task
->appliedstate
.hw_disk
= TASK_POLICY_HWACCESS_DISK_ATTRIBUTE_FULLACCESS
;
1279 task
->proc_terminate
= 1;
1287 proc_apply_thread_selfdiskacc(int policy
)
1289 task_t task
= current_task();
1290 thread_t thread
= current_thread();
1293 thread
->appliedstate
.hw_disk
= policy
;
1294 thread
->policystate
.hw_disk
= policy
;
1300 proc_denyinherit_policy(__unused task_t task
)
1306 proc_denyselfset_policy(__unused task_t task
)
1311 /* HW GPU access related routines */
1313 proc_get_task_selfgpuacc_deny(void)
1315 task_t task
= current_task();
1317 thread_t thread
= current_thread();
1320 if (((task
->ext_appliedstate
.hw_bg
& TASK_POLICY_BACKGROUND_ATTRIBUTE_NOGPU
) != 0) || (task
->ext_appliedstate
.hw_gpu
== TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS
))
1321 return(TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS
);
1322 if (((task
->appliedstate
.hw_bg
& TASK_POLICY_BACKGROUND_ATTRIBUTE_NOGPU
) != 0) || (task
->appliedstate
.hw_gpu
== TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS
))
1323 return(TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS
);
1326 * Since background dispatch items run in a thread can also be
1327 * denied access, we need to make sure there are no unintended
1328 * consequences of background dispatch usage. So till this is
1329 * hashed out, disable thread level checking.
1331 if (((thread
->ext_appliedstate
.hw_bg
& TASK_POLICY_BACKGROUND_ATTRIBUTE_NOGPU
) != 0) || (thread
->ext_appliedstate
.hw_gpu
== TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS
))
1332 return(TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS
);
1333 if (((thread
->appliedstate
.hw_bg
& TASK_POLICY_BACKGROUND_ATTRIBUTE_NOGPU
) != 0) || (thread
->appliedstate
.hw_gpu
== TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS
))
1334 return(TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS
);
1337 return(TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_FULLACCESS
);
1341 proc_apply_task_gpuacc(task_t task
, int policy
)
1344 task_t self
= current_task();
1348 task
->appliedstate
.hw_gpu
= policy
;
1349 task
->policystate
.hw_gpu
= policy
;
1351 task
->ext_appliedstate
.hw_gpu
= policy
;
1352 task
->ext_policystate
.hw_gpu
= policy
;
1359 /* Resource usage , CPU realted routines */
1361 proc_get_task_ruse_cpu(task_t task
, uint32_t * policyp
, uint32_t * percentagep
, uint64_t * intervalp
, uint64_t * deadlinep
)
1367 if (task
!= current_task()) {
1368 *policyp
= task
->ext_policystate
.ru_cpu
;
1370 *policyp
= task
->policystate
.ru_cpu
;
1373 error
= task_get_cpuusage(task
, percentagep
, intervalp
, deadlinep
);
1379 * Currently supported configurations for CPU limits.
1381 * Deadline-based CPU limit Percentage-based CPU limit
1382 * PROC_POLICY_RSRCACT_THROTTLE ENOTSUP Task-wide scope only
1383 * PROC_POLICY_RSRCACT_SUSPEND Task-wide scope only ENOTSUP
1384 * PROC_POLICY_RSRCACT_TERMINATE Task-wide scope only ENOTSUP
1385 * PROC_POLICY_RSRCACT_NOTIFY_KQ Task-wide scope only ENOTSUP
1386 * PROC_POLICY_RSRCACT_NOTIFY_EXC ENOTSUP Per-thread scope only
1388 * A deadline-based CPU limit is actually a simple wallclock timer - the requested action is performed
1389 * after the specified amount of wallclock time has elapsed.
1391 * A percentage-based CPU limit performs the requested action after the specified amount of actual CPU time
1392 * has been consumed -- regardless of how much wallclock time has elapsed -- by either the task as an
1393 * aggregate entity (so-called "Task-wide" or "Proc-wide" scope, whereby the CPU time consumed by all threads
1394 * in the task are added together), or by any one thread in the task (so-called "per-thread" scope).
1396 * We support either deadline != 0 OR percentage != 0, but not both. The original intention in having them
1397 * share an API was to use actual CPU time as the basis of the deadline-based limit (as in: perform an action
1398 * after I have used some amount of CPU time; this is different than the recurring percentage/interval model)
1399 * but the potential consumer of the API at the time was insisting on wallclock time instead.
1401 * Currently, requesting notification via an exception is the only way to get per-thread scope for a
1402 * CPU limit. All other types of notifications force task-wide scope for the limit.
1405 proc_set_task_ruse_cpu(task_t task
, uint32_t policy
, uint32_t percentage
, uint64_t interval
, uint64_t deadline
)
1411 * Enforce the matrix of supported configurations for policy, percentage, and deadline.
1414 // If no policy is explicitly given, the default is to throttle.
1415 case TASK_POLICY_RESOURCE_ATTRIBUTE_NONE
:
1416 case TASK_POLICY_RESOURCE_ATTRIBUTE_THROTTLE
:
1419 scope
= TASK_RUSECPU_FLAGS_PROC_LIMIT
;
1421 case TASK_POLICY_RESOURCE_ATTRIBUTE_SUSPEND
:
1422 case TASK_POLICY_RESOURCE_ATTRIBUTE_TERMINATE
:
1423 case TASK_POLICY_RESOURCE_ATTRIBUTE_NOTIFY_KQ
:
1424 if (percentage
!= 0)
1426 scope
= TASK_RUSECPU_FLAGS_DEADLINE
;
1428 case TASK_POLICY_RESOURCE_ATTRIBUTE_NOTIFY_EXC
:
1431 scope
= TASK_RUSECPU_FLAGS_PERTHR_LIMIT
;
1438 if (task
!= current_task()) {
1439 task
->ext_policystate
.ru_cpu
= policy
;
1441 task
->policystate
.ru_cpu
= policy
;
1443 error
= task_set_cpuusage(task
, percentage
, interval
, deadline
, scope
);
1449 proc_clear_task_ruse_cpu(task_t task
)
1453 void * bsdinfo
= NULL
;
1456 if (task
!= current_task()) {
1457 task
->ext_policystate
.ru_cpu
= TASK_POLICY_RESOURCE_ATTRIBUTE_DEFAULT
;
1459 task
->policystate
.ru_cpu
= TASK_POLICY_RESOURCE_ATTRIBUTE_DEFAULT
;
1462 error
= task_clear_cpuusage_locked(task
);
1466 action
= task
->ext_appliedstate
.ru_cpu
;
1467 if (task
->ext_appliedstate
.ru_cpu
!= TASK_POLICY_RESOURCE_ATTRIBUTE_NONE
) {
1469 task
->ext_appliedstate
.ru_cpu
= TASK_POLICY_RESOURCE_ATTRIBUTE_NONE
;
1471 if (action
!= TASK_POLICY_RESOURCE_ATTRIBUTE_NONE
) {
1472 bsdinfo
= task
->bsd_info
;
1474 proc_restore_resource_actions(bsdinfo
, TASK_POLICY_CPU_RESOURCE_USAGE
, action
);
1485 /* used to apply resource limit related actions */
1487 task_apply_resource_actions(task_t task
, int type
)
1489 int action
= TASK_POLICY_RESOURCE_ATTRIBUTE_NONE
;
1490 void * bsdinfo
= NULL
;
1493 case TASK_POLICY_CPU_RESOURCE_USAGE
:
1495 case TASK_POLICY_WIREDMEM_RESOURCE_USAGE
:
1496 case TASK_POLICY_VIRTUALMEM_RESOURCE_USAGE
:
1497 case TASK_POLICY_DISK_RESOURCE_USAGE
:
1498 case TASK_POLICY_NETWORK_RESOURCE_USAGE
:
1499 case TASK_POLICY_POWER_RESOURCE_USAGE
:
1506 /* only cpu actions for now */
1509 if (task
->ext_appliedstate
.ru_cpu
== TASK_POLICY_RESOURCE_ATTRIBUTE_NONE
) {
1511 task
->ext_appliedstate
.ru_cpu
= task
->ext_policystate
.ru_cpu
;
1512 action
= task
->ext_appliedstate
.ru_cpu
;
1514 action
= task
->ext_appliedstate
.ru_cpu
;
1517 if (action
!= TASK_POLICY_RESOURCE_ATTRIBUTE_NONE
) {
1518 bsdinfo
= task
->bsd_info
;
1520 proc_apply_resource_actions(bsdinfo
, TASK_POLICY_CPU_RESOURCE_USAGE
, action
);
1527 /* For ledger hookups */
1529 task_get_cpuusage(task_t task
, uint32_t * percentagep
, uint64_t * intervalp
, uint64_t * deadlinep
)
1531 *percentagep
= task
->rusage_cpu_percentage
;
1532 *intervalp
= task
->rusage_cpu_interval
;
1533 *deadlinep
= task
->rusage_cpu_deadline
;
1539 task_set_cpuusage(task_t task
, uint64_t percentage
, uint64_t interval
, uint64_t deadline
, int scope
)
1541 uint64_t abstime
= 0;
1542 uint64_t save_abstime
= 0;
1543 uint64_t limittime
= 0;
1546 lck_mtx_assert(&task
->lock
, LCK_MTX_ASSERT_OWNED
);
1548 /* By default, refill once per second */
1550 interval
= NSEC_PER_SEC
;
1552 if (percentage
!= 0) {
1553 if (percentage
> 100)
1555 limittime
= (interval
* percentage
)/ 100;
1556 nanoseconds_to_absolutetime(limittime
, &abstime
);
1557 if (scope
== TASK_RUSECPU_FLAGS_PERTHR_LIMIT
) {
1559 * A per-thread CPU limit on a task generates an exception
1560 * (LEDGER_ACTION_EXCEPTION) if any one thread in the task
1561 * exceeds the limit.
1563 task
->rusage_cpu_flags
|= TASK_RUSECPU_FLAGS_PERTHR_LIMIT
;
1564 task
->rusage_cpu_perthr_percentage
= percentage
;
1565 task
->rusage_cpu_perthr_interval
= interval
;
1566 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
1567 set_astledger(thread
);
1569 } else if (scope
== TASK_RUSECPU_FLAGS_PROC_LIMIT
) {
1571 * Currently, a proc-wide CPU limit always blocks if the limit is
1572 * exceeded (LEDGER_ACTION_BLOCK).
1574 task
->rusage_cpu_flags
|= TASK_RUSECPU_FLAGS_PROC_LIMIT
;
1575 task
->rusage_cpu_percentage
= percentage
;
1576 task
->rusage_cpu_interval
= interval
;
1578 ledger_set_limit(task
->ledger
, task_ledgers
.cpu_time
, abstime
);
1579 ledger_set_period(task
->ledger
, task_ledgers
.cpu_time
, interval
);
1580 ledger_set_action(task
->ledger
, task_ledgers
.cpu_time
, LEDGER_ACTION_BLOCK
);
1584 if (deadline
!= 0) {
1585 assert(scope
== TASK_RUSECPU_FLAGS_DEADLINE
);
1587 /* if already in use, cancel and wait for it to cleanout */
1588 if (task
->rusage_cpu_callt
!= NULL
) {
1590 thread_call_cancel_wait(task
->rusage_cpu_callt
);
1593 if (task
->rusage_cpu_callt
== NULL
) {
1594 task
->rusage_cpu_callt
= thread_call_allocate_with_priority(task_action_cpuusage
, (thread_call_param_t
)task
, THREAD_CALL_PRIORITY_KERNEL
);
1597 if (task
->rusage_cpu_callt
!= 0) {
1598 task
->rusage_cpu_flags
|= TASK_RUSECPU_FLAGS_DEADLINE
;
1599 task
->rusage_cpu_deadline
= deadline
;
1601 nanoseconds_to_absolutetime(deadline
, &abstime
);
1602 save_abstime
= abstime
;
1603 clock_absolutetime_interval_to_deadline(save_abstime
, &abstime
);
1604 thread_call_enter_delayed(task
->rusage_cpu_callt
, abstime
);
1612 task_clear_cpuusage(task_t task
)
1617 retval
= task_clear_cpuusage_locked(task
);
1624 task_clear_cpuusage_locked(task_t task
)
1626 thread_call_t savecallt
;
1629 /* cancel percentage handling if set */
1630 if (task
->rusage_cpu_flags
& TASK_RUSECPU_FLAGS_PROC_LIMIT
) {
1631 task
->rusage_cpu_flags
&= ~TASK_RUSECPU_FLAGS_PROC_LIMIT
;
1632 ledger_set_limit(task
->ledger
, task_ledgers
.cpu_time
, LEDGER_LIMIT_INFINITY
);
1633 task
->rusage_cpu_percentage
= 0;
1634 task
->rusage_cpu_interval
= 0;
1637 if (task
->rusage_cpu_flags
& TASK_RUSECPU_FLAGS_PERTHR_LIMIT
) {
1638 task
->rusage_cpu_flags
&= ~TASK_RUSECPU_FLAGS_PERTHR_LIMIT
;
1639 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
1640 set_astledger(thread
);
1642 task
->rusage_cpu_perthr_percentage
= 0;
1643 task
->rusage_cpu_perthr_interval
= 0;
1647 /* cancel deadline handling if set */
1648 if (task
->rusage_cpu_flags
& TASK_RUSECPU_FLAGS_DEADLINE
) {
1649 task
->rusage_cpu_flags
&= ~TASK_RUSECPU_FLAGS_DEADLINE
;
1650 if (task
->rusage_cpu_callt
!= 0) {
1651 savecallt
= task
->rusage_cpu_callt
;
1652 task
->rusage_cpu_callt
= NULL
;
1653 task
->rusage_cpu_deadline
= 0;
1655 thread_call_cancel_wait(savecallt
);
1656 thread_call_free(savecallt
);
1663 /* called by ledger unit to enforce action due to resource usage criteria being met */
1665 task_action_cpuusage(thread_call_param_t param0
, __unused thread_call_param_t param1
)
1667 task_t task
= (task_t
)param0
;
1668 (void)task_apply_resource_actions(task
, TASK_POLICY_CPU_RESOURCE_USAGE
);
1673 /* return the appstate of a task */
1675 proc_lf_getappstate(task_t task
)
1677 return(task
->appstate
);
1682 /* set appstate of a task and apply approp actions */
1684 proc_lf_setappstate(task_t task
, int state
)
1686 int ret
= 0, oldstate
;
1687 kern_return_t kret
= KERN_SUCCESS
;
1688 int applywatch
= 0, setbg
= 0, setnetbg
= 0;
1689 int sethib_suspend
= 0, sethib_resume
=0;
1691 if (state
== TASK_APPSTATE_NONE
)
1696 case TASK_APPSTATE_ACTIVE
:
1697 case TASK_APPSTATE_BACKGROUND
:
1698 case TASK_APPSTATE_NONUI
:
1699 case TASK_APPSTATE_INACTIVE
:
1708 oldstate
= task
->appstate
;
1709 if (oldstate
== state
) {
1715 case TASK_APPSTATE_ACTIVE
:
1717 case TASK_APPSTATE_BACKGROUND
:
1718 /* moving from active to app background */
1719 task
->ext_policystate
.hw_bg
= TASK_POLICY_BACKGROUND_ATTRIBUTE_ALL
;
1720 proc_apply_bgtaskpolicy_internal(task
, 1, 1);
1721 /* watchers need update */
1724 /* set network part */
1728 case TASK_APPSTATE_NONUI
:
1729 /* set no graphics */
1730 task
->ext_policystate
.hw_gpu
= TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS
;
1731 task
->ext_appliedstate
.hw_gpu
= TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS
;
1734 case TASK_APPSTATE_INACTIVE
:
1735 /* suspend the process */
1736 kret
= task_pidsuspend_locked(task
);
1737 if (kret
!= KERN_SUCCESS
)
1746 case TASK_APPSTATE_BACKGROUND
:
1748 /* watchers need update */
1751 /* set network part */
1753 case TASK_APPSTATE_ACTIVE
:
1754 /* remove app background */
1755 ret
= proc_restore_bgtaskpolicy_internal(task
, 1, 1, BASEPRI_DEFAULT
);
1756 /* going from BG to active */
1759 case TASK_APPSTATE_NONUI
:
1760 /* remove app background + no graphics */
1761 task
->ext_policystate
.hw_gpu
= TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS
;
1762 task
->ext_appliedstate
.hw_gpu
= TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS
;
1763 ret
= proc_restore_bgtaskpolicy_internal(task
, 1, 1, BASEPRI_DEFAULT
);
1766 case TASK_APPSTATE_INACTIVE
:
1767 /* suspend and then remove app background */
1768 kret
= task_pidsuspend_locked(task
);
1769 if (kret
!= KERN_SUCCESS
) {
1772 ret
= proc_restore_bgtaskpolicy_internal(task
, 1, 1, BASEPRI_DEFAULT
);
1781 case TASK_APPSTATE_NONUI
:
1783 case TASK_APPSTATE_ACTIVE
:
1784 /* restore graphics access */
1785 task
->ext_policystate
.hw_gpu
= TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS
;
1786 task
->ext_appliedstate
.hw_gpu
= TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_DEFAULT
;
1789 case TASK_APPSTATE_BACKGROUND
:
1790 /* set app background */
1791 task
->ext_policystate
.hw_bg
= TASK_POLICY_BACKGROUND_ATTRIBUTE_ALL
;
1793 ret
= proc_apply_bgtaskpolicy_internal(task
, 1, 1);
1795 task
->ext_policystate
.hw_gpu
= TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_DEFAULT
;
1796 task
->ext_appliedstate
.hw_gpu
= TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_DEFAULT
;
1798 /* watchers need update */
1801 /* set network part */
1805 case TASK_APPSTATE_INACTIVE
:
1806 /* suspend & restore graphics access */
1807 kret
= task_pidsuspend_locked(task
);
1808 if (kret
!= KERN_SUCCESS
) {
1811 ret
= proc_restore_bgtaskpolicy_internal(task
, 1, 1, BASEPRI_DEFAULT
);
1812 task
->ext_policystate
.hw_gpu
= TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_DEFAULT
;
1813 task
->ext_appliedstate
.hw_gpu
= TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_DEFAULT
;
1820 case TASK_APPSTATE_INACTIVE
:
1822 case TASK_APPSTATE_ACTIVE
:
1823 /* resume process */
1824 /* going from inactive to active */
1827 case TASK_APPSTATE_BACKGROUND
:
1828 task
->ext_policystate
.hw_bg
= TASK_POLICY_BACKGROUND_ATTRIBUTE_ALL
;
1829 ret
= proc_apply_bgtaskpolicy_internal(task
, 1, 1);
1830 /* put in app background & resume process */
1831 /* watchers need update */
1834 /* set network part */
1838 case TASK_APPSTATE_NONUI
:
1839 /* remove graphics access and resume */
1840 task
->ext_policystate
.hw_gpu
= TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS
;
1841 task
->ext_appliedstate
.hw_gpu
= TASK_POLICY_HWACCESS_GPU_ATTRIBUTE_NOACCESS
;
1844 /* pidresume does drop task lock,so no need to have locked version */
1846 kret
= task_pidresume(task
);
1851 /* set the new app state on the task */
1852 task
->appstate
= state
;
1855 if (setnetbg
!= 0) {
1856 /* apply network background */
1858 proc_apply_task_networkbg_internal(task
->bsd_info
, NULL
);
1860 proc_restore_task_networkbg_internal(task
->bsd_info
, NULL
);
1862 #if CONFIG_MEMORYSTATUS
1863 if (sethib_suspend
!= 0)
1864 memorystatus_on_suspend(proc_pid(task
->bsd_info
));
1865 if (sethib_resume
!= 0)
1866 memorystatus_on_resume(proc_pid(task
->bsd_info
));
1867 #endif /* CONFIG_MEMORYSTATUS */
1868 /* if watchers need update, safe point to do that */
1869 if (applywatch
!= 0)
1870 apply_appstate_watchers(task
, setbg
);
1877 task_watch_lock(void)
1879 lck_mtx_lock(&task_watch_mtx
);
1883 task_watch_unlock(void)
1885 lck_mtx_unlock(&task_watch_mtx
);
1889 add_taskwatch_locked(task_t task
, task_watch_t
* twp
)
1891 queue_enter(&task
->task_watchers
, twp
, task_watch_t
*, tw_links
);
1892 task
->num_taskwatchers
++;
1897 remove_taskwatch_locked(task_t task
, task_watch_t
* twp
)
1899 queue_remove(&task
->task_watchers
, twp
, task_watch_t
*, tw_links
);
1900 task
->num_taskwatchers
--;
1905 proc_lf_pidbind(task_t curtask
, uint64_t tid
, task_t target_task
, int bind
)
1907 thread_t self
= current_thread();
1908 thread_t target_thread
= NULL
;
1909 int selfset
= 0, ret
= 0, setbg
= 0;
1910 task_watch_t
*twp
= NULL
;
1911 task_t task
= TASK_NULL
;
1914 if ((tid
== 0) || (tid
== self
->thread_id
)) {
1916 target_thread
= self
;
1917 thread_reference(target_thread
);
1920 target_thread
= task_findtid(curtask
, tid
);
1921 if (target_thread
!= NULL
)
1922 thread_reference(target_thread
);
1928 task_unlock(curtask
);
1932 /* task is still active ? */
1933 task_lock(target_task
);
1934 if (target_task
->active
== 0) {
1935 task_unlock(target_task
);
1939 task_unlock(target_task
);
1941 twp
= (task_watch_t
*)kalloc(sizeof(task_watch_t
));
1943 task_watch_unlock();
1948 bzero(twp
, sizeof(task_watch_t
));
1952 if (target_thread
->taskwatch
!= NULL
){
1953 /* already bound to another task */
1954 task_watch_unlock();
1956 kfree(twp
, sizeof(task_watch_t
));
1961 task_reference(target_task
);
1963 twp
->tw_task
= target_task
; /* holds the task reference */
1964 twp
->tw_thread
= target_thread
; /* holds the thread reference */
1965 twp
->tw_state
= target_task
->appstate
;
1966 twp
->tw_importance
= target_thread
->importance
;
1968 add_taskwatch_locked(target_task
, twp
);
1970 target_thread
->taskwatch
= twp
;
1972 if (target_task
->appstate
== TASK_APPSTATE_BACKGROUND
)
1975 task_watch_unlock();
1978 set_thread_appbg(target_thread
, setbg
, INT_MIN
);
1981 /* retain the thread reference as it is in twp */
1982 target_thread
= NULL
;
1986 if ((twp
= target_thread
->taskwatch
) != NULL
) {
1987 task
= twp
->tw_task
;
1988 target_thread
->taskwatch
= NULL
;
1989 remove_taskwatch_locked(task
, twp
);
1991 task_watch_unlock();
1993 task_deallocate(task
); /* drop task ref in twp */
1994 set_thread_appbg(target_thread
, 0, twp
->tw_importance
);
1995 thread_deallocate(target_thread
); /* drop thread ref in twp */
1996 kfree(twp
, sizeof(task_watch_t
));
1998 task_watch_unlock();
1999 ret
= 0; /* return success if it not alredy bound */
2004 if (target_thread
!= NULL
)
2005 thread_deallocate(target_thread
); /* drop thread ref acquired in this routine */
2010 set_thread_appbg(thread_t thread
, int setbg
,int importance
)
2012 /* TBD: ensure the proc for network is fine */
2014 restore_bgthreadpolicy_locked(thread
, 0, importance
);
2015 proc_restore_task_networkbg_internal(thread
->task
->bsd_info
, thread
);
2017 apply_bgthreadpolicy_external(thread
);
2018 proc_apply_task_networkbg_internal(thread
->task
->bsd_info
, thread
);
2023 apply_appstate_watchers(task_t task
, int setbg
)
2025 int numwatchers
= 0, i
, j
;
2026 thread_watchlist_t
* threadlist
;
2030 /* if no watchers on the list return */
2031 if ((numwatchers
= task
->num_taskwatchers
) == 0)
2034 threadlist
= (thread_watchlist_t
*)kalloc(numwatchers
*sizeof(thread_watchlist_t
));
2035 if (threadlist
== NULL
)
2038 bzero(threadlist
, numwatchers
*sizeof(thread_watchlist_t
));
2041 /*serialize application of app state changes */
2042 if (task
->watchapplying
!= 0) {
2043 lck_mtx_sleep(&task_watch_mtx
, LCK_SLEEP_DEFAULT
, &task
->watchapplying
, THREAD_UNINT
);
2044 task_watch_unlock();
2045 kfree(threadlist
, numwatchers
*sizeof(thread_watchlist_t
));
2049 if (numwatchers
!= task
->num_taskwatchers
) {
2050 task_watch_unlock();
2051 kfree(threadlist
, numwatchers
*sizeof(thread_watchlist_t
));
2055 task
->watchapplying
= 1;
2057 queue_iterate(&task
->task_watchers
, twp
, task_watch_t
*, tw_links
) {
2059 threadlist
[i
].thread
= twp
->tw_thread
;
2060 thread_reference(threadlist
[i
].thread
);
2062 twp
->tw_importance
= twp
->tw_thread
->importance
;
2063 threadlist
[i
].importance
= INT_MIN
;
2065 threadlist
[i
].importance
= twp
->tw_importance
;
2067 if (i
> numwatchers
)
2070 task_watch_unlock();
2072 for (j
= 0; j
< i
; j
++) {
2073 set_thread_appbg(threadlist
[j
].thread
, setbg
, threadlist
[j
].importance
);
2074 thread_deallocate(threadlist
[j
].thread
);
2076 kfree(threadlist
, numwatchers
*sizeof(thread_watchlist_t
));
2080 task
->watchapplying
= 0;
2081 thread_wakeup_one(&task
->watchapplying
);
2082 task_watch_unlock();
2086 thead_remove_taskwatch(thread_t thread
)
2092 if ((twp
= thread
->taskwatch
) != NULL
) {
2093 thread
->taskwatch
= NULL
;
2094 remove_taskwatch_locked(twp
->tw_task
, twp
);
2096 task_watch_unlock();
2098 thread_deallocate(twp
->tw_thread
);
2099 task_deallocate(twp
->tw_task
);
2100 importance
= twp
->tw_importance
;
2101 kfree(twp
, sizeof(task_watch_t
));
2102 /* remove the thread and networkbg */
2103 set_thread_appbg(thread
, 0, importance
);
2108 task_removewatchers(task_t task
)
2110 int numwatchers
= 0, i
, j
;
2111 task_watch_t
** twplist
= NULL
;
2112 task_watch_t
* twp
= NULL
;
2115 if ((numwatchers
= task
->num_taskwatchers
) == 0)
2118 twplist
= (task_watch_t
**)kalloc(numwatchers
*sizeof(task_watch_t
*));
2119 if (twplist
== NULL
)
2122 bzero(twplist
, numwatchers
*sizeof(task_watch_t
*));
2125 if (task
->num_taskwatchers
== 0) {
2126 task_watch_unlock();
2130 if (numwatchers
!= task
->num_taskwatchers
) {
2131 task_watch_unlock();
2132 kfree(twplist
, numwatchers
*sizeof(task_watch_t
*));
2138 while((twp
= (task_watch_t
*)dequeue_head(&task
->task_watchers
)) != NULL
)
2141 task
->num_taskwatchers
--;
2144 * Since the linkage is removed and thead state cleanup is already set up,
2145 * remove the refernce from the thread.
2147 twp
->tw_thread
->taskwatch
= NULL
; /* removed linkage, clear thread holding ref */
2149 if ((task
->num_taskwatchers
== 0) || (i
> numwatchers
))
2153 task_watch_unlock();
2155 for (j
= 0; j
< i
; j
++) {
2158 /* remove thread and network bg */
2159 set_thread_appbg(twp
->tw_thread
, 0, twp
->tw_importance
);
2160 thread_deallocate(twp
->tw_thread
);
2161 task_deallocate(twp
->tw_task
);
2162 kfree(twp
, sizeof(task_watch_t
));
2166 kfree(twplist
, numwatchers
*sizeof(task_watch_t
*));
2169 #endif /* CONFIG_EMBEDDED */
2173 proc_disable_task_apptype(task_t task
, int policy_subtype
)
2175 void * bsdinfo
= NULL
;
2178 #if !CONFIG_EMBEDDED
2179 int maxpri
= BASEPRI_DEFAULT
;
2180 #endif /* !CONFIG_EMBEDDED */
2184 if (task
->ext_policystate
.apptype
!= policy_subtype
) {
2189 #if !CONFIG_EMBEDDED
2190 switch (task
->role
) {
2191 case TASK_FOREGROUND_APPLICATION
:
2192 maxpri
= BASEPRI_FOREGROUND
;
2194 case TASK_BACKGROUND_APPLICATION
:
2195 maxpri
= BASEPRI_BACKGROUND
;
2198 maxpri
= BASEPRI_DEFAULT
;
2202 #endif /* !CONFIG_EMBEDDED */
2204 /* TAL apps are cleared with BG handling on first foreground application */
2205 if (task
->ext_appliedstate
.apptype
!= PROC_POLICY_OSX_APPTYPE_NONE
) {
2206 switch (task
->ext_appliedstate
.apptype
) {
2207 #if !CONFIG_EMBEDDED
2208 case PROC_POLICY_OSX_APPTYPE_TAL
:
2209 /* disable foreground/background handling */
2210 task
->ext_appliedstate
.apptype
= PROC_POLICY_OSX_APPTYPE_NONE
;
2211 /* external BG application removal */
2212 proc_restore_bgtaskpolicy_internal(task
, 1, 1, maxpri
);
2213 bsdinfo
= task
->bsd_info
;
2217 case PROC_POLICY_OSX_APPTYPE_DBCLIENT
:
2218 /* disable foreground/background handling */
2219 task
->ext_appliedstate
.apptype
= PROC_POLICY_OSX_APPTYPE_NONE
;
2220 /* internal BG application removal */
2221 proc_restore_bgtaskpolicy_internal(task
, 1, 0, maxpri
);
2222 bsdinfo
= task
->bsd_info
;
2226 #endif /* !CONFIG_EMBEDDED */
2238 /* if backgrounding action ... */
2239 if (bsdinfo
!= NULL
)
2240 proc_set_task_networkbg(bsdinfo
, setbg
);
2246 proc_enable_task_apptype(task_t task
, int policy_subtype
)
2248 void * bsdinfo
= NULL
;
2254 if (task
->ext_policystate
.apptype
!= policy_subtype
) {
2259 if (task
->ext_appliedstate
.apptype
== PROC_POLICY_OSX_APPTYPE_NONE
) {
2260 switch (task
->ext_policystate
.apptype
) {
2261 #if !CONFIG_EMBEDDED
2262 case PROC_POLICY_OSX_APPTYPE_TAL
:
2263 /* TAL policy is activated again */
2264 task
->ext_appliedstate
.apptype
= task
->ext_policystate
.apptype
;
2265 if (task
->role
== TASK_BACKGROUND_APPLICATION
) {
2266 if (task
->role
== TASK_BACKGROUND_APPLICATION
) {
2267 proc_apply_bgtaskpolicy_internal(task
, 1, 1);
2268 bsdinfo
= task
->bsd_info
;
2274 #endif /* !CONFIG_EMBEDDED */
2283 /* if backgrounding action ... */
2284 if (bsdinfo
!= NULL
)
2285 proc_set_task_networkbg(bsdinfo
, setbg
);
2292 proc_setthread_saved_importance(thread_t thread
, int importance
)
2294 if ((thread
->task
->ext_appliedstate
.apptype
== PROC_POLICY_IOS_APPLE_DAEMON
) &&
2295 (thread
->appliedstate
.hw_bg
== TASK_POLICY_BACKGROUND_ATTRIBUTE_ALL
))
2297 /* the thread is still backgrounded , save the importance for restore time */
2298 thread
->saved_importance
= importance
;
2304 #endif /* CONFIG_EMBEDDED */