]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kern/task_policy.c
xnu-2782.1.97.tar.gz
[apple/xnu.git] / osfmk / kern / task_policy.c
CommitLineData
1c79356b 1/*
91447636 2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
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.
8f6c56a5 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b 27 */
1c79356b 28
91447636
A
29#include <mach/mach_types.h>
30#include <mach/task_server.h>
31
32#include <kern/sched.h>
0b4e3aa0 33#include <kern/task.h>
6d2010ae
A
34#include <mach/thread_policy.h>
35#include <sys/errno.h>
36#include <sys/resource.h>
37#include <machine/limits.h>
316670eb
A
38#include <kern/ledger.h>
39#include <kern/thread_call.h>
fe8ab488 40#include <kern/sfi.h>
39236c6e
A
41#if CONFIG_TELEMETRY
42#include <kern/telemetry.h>
43#endif
44
fe8ab488
A
45#if IMPORTANCE_INHERITANCE
46#include <ipc/ipc_importance.h>
39236c6e
A
47#if IMPORTANCE_DEBUG
48#include <mach/machine/sdt.h>
49#endif /* IMPORTANCE_DEBUG */
fe8ab488 50#endif /* IMPORTANCE_INHERITACE */
39236c6e 51
316670eb
A
52#include <sys/kdebug.h>
53
39236c6e
A
54/*
55 * Task Policy
56 *
57 * This subsystem manages task and thread IO priority and backgrounding,
58 * as well as importance inheritance, process suppression, task QoS, and apptype.
59 * These properties have a suprising number of complex interactions, so they are
60 * centralized here in one state machine to simplify the implementation of those interactions.
61 *
62 * Architecture:
63 * Threads and tasks have three policy fields: requested, effective, and pending.
64 * Requested represents the wishes of each interface that influences task policy.
65 * Effective represents the distillation of that policy into a set of behaviors.
66 * Pending represents updates that haven't been applied yet.
67 *
68 * Each interface that has an input into the task policy state machine controls a field in requested.
69 * If the interface has a getter, it returns what is in the field in requested, but that is
70 * not necessarily what is actually in effect.
71 *
72 * All kernel subsystems that behave differently based on task policy call into
73 * the get_effective_policy function, which returns the decision of the task policy state machine
74 * for that subsystem by querying only the 'effective' field.
75 *
76 * Policy change operations:
77 * Here are the steps to change a policy on a task or thread:
78 * 1) Lock task
79 * 2) Change requested field for the relevant policy
80 * 3) Run a task policy update, which recalculates effective based on requested,
81 * then takes a diff between the old and new versions of requested and calls the relevant
82 * other subsystems to apply these changes, and updates the pending field.
83 * 4) Unlock task
84 * 5) Run task policy update complete, which looks at the pending field to update
85 * subsystems which cannot be touched while holding the task lock.
86 *
87 * To add a new requested policy, add the field in the requested struct, the flavor in task.h,
88 * the setter and getter in proc_(set|get)_task_policy*, and dump the state in task_requested_bitfield,
fe8ab488
A
89 * then set up the effects of that behavior in task_policy_update*. If the policy manifests
90 * itself as a distinct effective policy, add it to the effective struct and add it to the
91 * proc_get_effective_policy accessor.
39236c6e
A
92 *
93 * Most policies are set via proc_set_task_policy, but policies that don't fit that interface
94 * roll their own lock/set/update/unlock/complete code inside this file.
95 *
96 *
97 * Suppression policy
98 *
99 * These are a set of behaviors that can be requested for a task. They currently have specific
100 * implied actions when they're enabled, but they may be made customizable in the future.
101 *
102 * When the affected task is boosted, we temporarily disable the suppression behaviors
103 * so that the affected process has a chance to run so it can call the API to permanently
104 * disable the suppression behaviors.
105 *
106 * Locking
107 *
108 * Changing task policy on a task or thread takes the task lock, and not the thread lock.
109 * TODO: Should changing policy on a thread take the thread lock instead?
110 *
111 * Querying the effective policy does not take the task lock, to prevent deadlocks or slowdown in sensitive code.
112 * This means that any notification of state change needs to be externally synchronized.
113 *
114 */
115
fe8ab488
A
116extern const qos_policy_params_t thread_qos_policy_params;
117
39236c6e
A
118/* for task holds without dropping the lock */
119extern void task_hold_locked(task_t task);
120extern void task_release_locked(task_t task);
121extern void task_wait_locked(task_t task, boolean_t until_not_runnable);
122
fe8ab488
A
123extern void thread_recompute_qos(thread_t thread);
124
39236c6e
A
125/* Task policy related helper functions */
126static void proc_set_task_policy_locked(task_t task, thread_t thread, int category, int flavor, int value);
fe8ab488 127static void proc_set_task_policy2_locked(task_t task, thread_t thread, int category, int flavor, int value1, int value2);
6d2010ae 128
fe8ab488
A
129static void task_policy_update_locked(task_t task, thread_t thread, task_pend_token_t pend_token);
130static void task_policy_update_internal_locked(task_t task, thread_t thread, boolean_t in_create, task_pend_token_t pend_token);
131static void task_policy_update_task_locked(task_t task, boolean_t update_throttle, boolean_t update_bg_throttle, boolean_t update_sfi);
132static void task_policy_update_thread_locked(thread_t thread, int update_cpu, boolean_t update_throttle, boolean_t update_sfi, boolean_t update_qos);
39236c6e
A
133
134static int proc_get_effective_policy(task_t task, thread_t thread, int policy);
135
136static void proc_iopol_to_tier(int iopolicy, int *tier, int *passive);
137static int proc_tier_to_iopol(int tier, int passive);
138
fe8ab488
A
139static uintptr_t trequested_0(task_t task, thread_t thread);
140static uintptr_t trequested_1(task_t task, thread_t thread);
141static uintptr_t teffective_0(task_t task, thread_t thread);
142static uintptr_t teffective_1(task_t task, thread_t thread);
143static uint32_t tpending(task_pend_token_t pend_token);
39236c6e
A
144static uint64_t task_requested_bitfield(task_t task, thread_t thread);
145static uint64_t task_effective_bitfield(task_t task, thread_t thread);
39236c6e
A
146
147void proc_get_thread_policy(thread_t thread, thread_policy_state_t info);
148
149/* CPU Limits related helper functions */
150static int task_get_cpuusage(task_t task, uint8_t *percentagep, uint64_t *intervalp, uint64_t *deadlinep, int *scope);
151int task_set_cpuusage(task_t task, uint8_t percentage, uint64_t interval, uint64_t deadline, int scope, int entitled);
152static int task_clear_cpuusage_locked(task_t task, int cpumon_entitled);
153int task_disable_cpumon(task_t task);
6d2010ae 154static int task_apply_resource_actions(task_t task, int type);
316670eb 155void task_action_cpuusage(thread_call_param_t param0, thread_call_param_t param1);
39236c6e
A
156void proc_init_cpumon_params(void);
157
158#ifdef MACH_BSD
159int proc_pid(void *proc);
160extern int proc_selfpid(void);
161extern char * proc_name_address(void *p);
162extern void rethrottle_thread(void * uthread);
fe8ab488 163extern void proc_apply_task_networkbg(void * bsd_info, thread_t thread);
39236c6e 164#endif /* MACH_BSD */
0b4e3aa0 165
316670eb 166
39236c6e
A
167/* Importance Inheritance related helper functions */
168
39236c6e 169#if IMPORTANCE_INHERITANCE
39236c6e 170
fe8ab488
A
171static void task_add_importance_watchport(task_t task, mach_port_t port, int *boostp);
172static void task_importance_update_live_donor(task_t target_task);
173
39236c6e
A
174#endif /* IMPORTANCE_INHERITANCE */
175
176#if IMPORTANCE_DEBUG
177#define __impdebug_only
178#else
179#define __impdebug_only __unused
180#endif
181
182#if IMPORTANCE_INHERITANCE
183#define __imp_only
184#else
185#define __imp_only __unused
186#endif
187
188#define TASK_LOCKED 1
189#define TASK_UNLOCKED 0
190
191#define DO_LOWPRI_CPU 1
192#define UNDO_LOWPRI_CPU 2
193
194/* Macros for making tracing simpler */
195
196#define tpriority(task, thread) ((uintptr_t)(thread == THREAD_NULL ? (task->priority) : (thread->priority)))
197#define tisthread(thread) (thread == THREAD_NULL ? TASK_POLICY_TASK : TASK_POLICY_THREAD)
198#define targetid(task, thread) ((uintptr_t)(thread == THREAD_NULL ? (audit_token_pid_from_task(task)) : (thread->thread_id)))
199
200/*
201 * Default parameters for certain policies
202 */
203
204int proc_standard_daemon_tier = THROTTLE_LEVEL_TIER1;
205int proc_suppressed_disk_tier = THROTTLE_LEVEL_TIER1;
206int proc_tal_disk_tier = THROTTLE_LEVEL_TIER1;
207
208int proc_graphics_timer_qos = (LATENCY_QOS_TIER_0 & 0xFF);
209
210const int proc_default_bg_iotier = THROTTLE_LEVEL_TIER2;
211
fe8ab488 212/* Latency/throughput QoS fields remain zeroed, i.e. TIER_UNSPECIFIED at creation */
39236c6e
A
213const struct task_requested_policy default_task_requested_policy = {
214 .bg_iotier = proc_default_bg_iotier
215};
216const struct task_effective_policy default_task_effective_policy = {};
217const struct task_pended_policy default_task_pended_policy = {};
218
316670eb 219/*
39236c6e
A
220 * Default parameters for CPU usage monitor.
221 *
222 * Default setting is 50% over 3 minutes.
316670eb 223 */
39236c6e
A
224#define DEFAULT_CPUMON_PERCENTAGE 50
225#define DEFAULT_CPUMON_INTERVAL (3 * 60)
226
227uint8_t proc_max_cpumon_percentage;
228uint64_t proc_max_cpumon_interval;
229
fe8ab488
A
230kern_return_t
231qos_latency_policy_validate(task_latency_qos_t ltier) {
232 if ((ltier != LATENCY_QOS_TIER_UNSPECIFIED) &&
233 ((ltier > LATENCY_QOS_TIER_5) || (ltier < LATENCY_QOS_TIER_0)))
234 return KERN_INVALID_ARGUMENT;
235
236 return KERN_SUCCESS;
237}
238
239kern_return_t
240qos_throughput_policy_validate(task_throughput_qos_t ttier) {
241 if ((ttier != THROUGHPUT_QOS_TIER_UNSPECIFIED) &&
242 ((ttier > THROUGHPUT_QOS_TIER_5) || (ttier < THROUGHPUT_QOS_TIER_0)))
243 return KERN_INVALID_ARGUMENT;
244
245 return KERN_SUCCESS;
246}
247
316670eb 248static kern_return_t
39236c6e
A
249task_qos_policy_validate(task_qos_policy_t qosinfo, mach_msg_type_number_t count) {
250 if (count < TASK_QOS_POLICY_COUNT)
251 return KERN_INVALID_ARGUMENT;
316670eb 252
39236c6e
A
253 task_latency_qos_t ltier = qosinfo->task_latency_qos_tier;
254 task_throughput_qos_t ttier = qosinfo->task_throughput_qos_tier;
316670eb 255
fe8ab488 256 kern_return_t kr = qos_latency_policy_validate(ltier);
39236c6e 257
fe8ab488
A
258 if (kr != KERN_SUCCESS)
259 return kr;
39236c6e 260
fe8ab488
A
261 kr = qos_throughput_policy_validate(ttier);
262
263 return kr;
39236c6e
A
264}
265
fe8ab488
A
266uint32_t
267qos_extract(uint32_t qv) {
39236c6e
A
268 return (qv & 0xFF);
269}
270
fe8ab488
A
271uint32_t
272qos_latency_policy_package(uint32_t qv) {
39236c6e 273 return (qv == LATENCY_QOS_TIER_UNSPECIFIED) ? LATENCY_QOS_TIER_UNSPECIFIED : ((0xFF << 16) | qv);
316670eb
A
274}
275
fe8ab488
A
276uint32_t
277qos_throughput_policy_package(uint32_t qv) {
39236c6e
A
278 return (qv == THROUGHPUT_QOS_TIER_UNSPECIFIED) ? THROUGHPUT_QOS_TIER_UNSPECIFIED : ((0xFE << 16) | qv);
279}
1c79356b 280
fe8ab488
A
281/* TEMPORARY boot-arg controlling task_policy suppression (App Nap) */
282static boolean_t task_policy_suppression_disable = FALSE;
283
1c79356b
A
284kern_return_t
285task_policy_set(
286 task_t task,
287 task_policy_flavor_t flavor,
288 task_policy_t policy_info,
289 mach_msg_type_number_t count)
290{
0b4e3aa0
A
291 kern_return_t result = KERN_SUCCESS;
292
293 if (task == TASK_NULL || task == kernel_task)
1c79356b
A
294 return (KERN_INVALID_ARGUMENT);
295
296 switch (flavor) {
297
39236c6e 298 case TASK_CATEGORY_POLICY: {
6d2010ae 299 task_category_policy_t info = (task_category_policy_t)policy_info;
1c79356b
A
300
301 if (count < TASK_CATEGORY_POLICY_COUNT)
302 return (KERN_INVALID_ARGUMENT);
303
6d2010ae 304
316670eb 305 switch(info->role) {
39236c6e
A
306 case TASK_FOREGROUND_APPLICATION:
307 case TASK_BACKGROUND_APPLICATION:
308 case TASK_DEFAULT_APPLICATION:
309 proc_set_task_policy(task, THREAD_NULL,
310 TASK_POLICY_ATTRIBUTE, TASK_POLICY_ROLE,
311 info->role);
312 break;
316670eb 313
39236c6e
A
314 case TASK_CONTROL_APPLICATION:
315 if (task != current_task() || task->sec_token.val[0] != 0)
316 result = KERN_INVALID_ARGUMENT;
317 else
318 proc_set_task_policy(task, THREAD_NULL,
319 TASK_POLICY_ATTRIBUTE, TASK_POLICY_ROLE,
320 info->role);
321 break;
6d2010ae 322
39236c6e
A
323 case TASK_GRAPHICS_SERVER:
324 /* TODO: Restrict this role to FCFS <rdar://problem/12552788> */
325 if (task != current_task() || task->sec_token.val[0] != 0)
326 result = KERN_INVALID_ARGUMENT;
327 else
328 proc_set_task_policy(task, THREAD_NULL,
329 TASK_POLICY_ATTRIBUTE, TASK_POLICY_ROLE,
330 info->role);
331 break;
332 default:
0b4e3aa0 333 result = KERN_INVALID_ARGUMENT;
39236c6e
A
334 break;
335 } /* switch (info->role) */
316670eb 336
39236c6e
A
337 break;
338 }
316670eb 339
39236c6e
A
340/* Desired energy-efficiency/performance "quality-of-service" */
341 case TASK_BASE_QOS_POLICY:
fe8ab488 342 case TASK_OVERRIDE_QOS_POLICY:
39236c6e
A
343 {
344 task_qos_policy_t qosinfo = (task_qos_policy_t)policy_info;
345 kern_return_t kr = task_qos_policy_validate(qosinfo, count);
346
347 if (kr != KERN_SUCCESS)
348 return kr;
349
1c79356b 350
fe8ab488
A
351 uint32_t lqos = qos_extract(qosinfo->task_latency_qos_tier);
352 uint32_t tqos = qos_extract(qosinfo->task_throughput_qos_tier);
6d2010ae 353
fe8ab488
A
354 proc_set_task_policy2(task, THREAD_NULL, TASK_POLICY_ATTRIBUTE,
355 flavor == TASK_BASE_QOS_POLICY ? TASK_POLICY_BASE_LATENCY_AND_THROUGHPUT_QOS : TASK_POLICY_OVERRIDE_LATENCY_AND_THROUGHPUT_QOS,
356 lqos, tqos);
1c79356b 357 }
fe8ab488 358 break;
39236c6e 359
fe8ab488 360 case TASK_BASE_LATENCY_QOS_POLICY:
39236c6e
A
361 {
362 task_qos_policy_t qosinfo = (task_qos_policy_t)policy_info;
363 kern_return_t kr = task_qos_policy_validate(qosinfo, count);
364
365 if (kr != KERN_SUCCESS)
366 return kr;
367
fe8ab488 368 uint32_t lqos = qos_extract(qosinfo->task_latency_qos_tier);
39236c6e 369
fe8ab488
A
370 proc_set_task_policy(task, NULL, TASK_POLICY_ATTRIBUTE, TASK_BASE_LATENCY_QOS_POLICY, lqos);
371 }
372 break;
39236c6e 373
fe8ab488
A
374 case TASK_BASE_THROUGHPUT_QOS_POLICY:
375 {
376 task_qos_policy_t qosinfo = (task_qos_policy_t)policy_info;
377 kern_return_t kr = task_qos_policy_validate(qosinfo, count);
39236c6e 378
fe8ab488
A
379 if (kr != KERN_SUCCESS)
380 return kr;
39236c6e 381
fe8ab488 382 uint32_t tqos = qos_extract(qosinfo->task_throughput_qos_tier);
39236c6e 383
fe8ab488 384 proc_set_task_policy(task, NULL, TASK_POLICY_ATTRIBUTE, TASK_BASE_THROUGHPUT_QOS_POLICY, tqos);
0b4e3aa0 385 }
fe8ab488 386 break;
0b4e3aa0 387
39236c6e
A
388 case TASK_SUPPRESSION_POLICY:
389 {
0b4e3aa0 390
39236c6e 391 task_suppression_policy_t info = (task_suppression_policy_t)policy_info;
0b4e3aa0 392
39236c6e
A
393 if (count < TASK_SUPPRESSION_POLICY_COUNT)
394 return (KERN_INVALID_ARGUMENT);
0b4e3aa0 395
39236c6e 396 struct task_qos_policy qosinfo;
0b4e3aa0 397
39236c6e
A
398 qosinfo.task_latency_qos_tier = info->timer_throttle;
399 qosinfo.task_throughput_qos_tier = info->throughput_qos;
0b4e3aa0 400
39236c6e
A
401 kern_return_t kr = task_qos_policy_validate(&qosinfo, TASK_QOS_POLICY_COUNT);
402
403 if (kr != KERN_SUCCESS)
404 return kr;
405
fe8ab488
A
406 /* TEMPORARY disablement of task suppression */
407 if (task_policy_suppression_disable && info->active)
408 return KERN_SUCCESS;
409
410 struct task_pend_token pend_token = {};
411
39236c6e
A
412 task_lock(task);
413
414 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
415 (IMPORTANCE_CODE(IMP_TASK_SUPPRESSION, info->active)) | DBG_FUNC_START,
fe8ab488
A
416 proc_selfpid(), audit_token_pid_from_task(task), trequested_0(task, THREAD_NULL),
417 trequested_1(task, THREAD_NULL), 0);
39236c6e
A
418
419 task->requested_policy.t_sup_active = (info->active) ? 1 : 0;
420 task->requested_policy.t_sup_lowpri_cpu = (info->lowpri_cpu) ? 1 : 0;
fe8ab488 421 task->requested_policy.t_sup_timer = qos_extract(info->timer_throttle);
39236c6e
A
422 task->requested_policy.t_sup_disk = (info->disk_throttle) ? 1 : 0;
423 task->requested_policy.t_sup_cpu_limit = (info->cpu_limit) ? 1 : 0;
424 task->requested_policy.t_sup_suspend = (info->suspend) ? 1 : 0;
fe8ab488 425 task->requested_policy.t_sup_throughput = qos_extract(info->throughput_qos);
39236c6e 426 task->requested_policy.t_sup_cpu = (info->suppressed_cpu) ? 1 : 0;
fe8ab488 427 task->requested_policy.t_sup_bg_sockets = (info->background_sockets) ? 1 : 0;
39236c6e 428
fe8ab488 429 task_policy_update_locked(task, THREAD_NULL, &pend_token);
39236c6e
A
430
431 task_unlock(task);
432
fe8ab488 433 task_policy_update_complete_unlocked(task, THREAD_NULL, &pend_token);
39236c6e
A
434
435 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
436 (IMPORTANCE_CODE(IMP_TASK_SUPPRESSION, info->active)) | DBG_FUNC_END,
fe8ab488
A
437 proc_selfpid(), audit_token_pid_from_task(task), trequested_0(task, THREAD_NULL),
438 trequested_1(task, THREAD_NULL), 0);
39236c6e
A
439
440 break;
0b4e3aa0 441
39236c6e 442 }
0b4e3aa0 443
39236c6e
A
444 default:
445 result = KERN_INVALID_ARGUMENT;
446 break;
0b4e3aa0 447 }
39236c6e
A
448
449 return (result);
0b4e3aa0
A
450}
451
39236c6e 452/* Sets BSD 'nice' value on the task */
0b4e3aa0
A
453kern_return_t
454task_importance(
455 task_t task,
456 integer_t importance)
457{
458 if (task == TASK_NULL || task == kernel_task)
459 return (KERN_INVALID_ARGUMENT);
460
461 task_lock(task);
462
463 if (!task->active) {
464 task_unlock(task);
465
466 return (KERN_TERMINATED);
467 }
468
39236c6e 469 if (proc_get_effective_task_policy(task, TASK_POLICY_ROLE) >= TASK_CONTROL_APPLICATION) {
0b4e3aa0
A
470 task_unlock(task);
471
1c79356b
A
472 return (KERN_INVALID_ARGUMENT);
473 }
474
39236c6e
A
475 task->importance = importance;
476
477 /* TODO: tracepoint? */
478
479 /* Redrive only the task priority calculation */
fe8ab488 480 task_policy_update_task_locked(task, FALSE, FALSE, FALSE);
0b4e3aa0
A
481
482 task_unlock(task);
483
1c79356b
A
484 return (KERN_SUCCESS);
485}
39236c6e 486
1c79356b
A
487kern_return_t
488task_policy_get(
489 task_t task,
490 task_policy_flavor_t flavor,
491 task_policy_t policy_info,
492 mach_msg_type_number_t *count,
493 boolean_t *get_default)
494{
0b4e3aa0 495 if (task == TASK_NULL || task == kernel_task)
1c79356b
A
496 return (KERN_INVALID_ARGUMENT);
497
498 switch (flavor) {
499
500 case TASK_CATEGORY_POLICY:
501 {
502 task_category_policy_t info = (task_category_policy_t)policy_info;
503
504 if (*count < TASK_CATEGORY_POLICY_COUNT)
505 return (KERN_INVALID_ARGUMENT);
506
0b4e3aa0
A
507 if (*get_default)
508 info->role = TASK_UNSPECIFIED;
39236c6e
A
509 else
510 info->role = proc_get_task_policy(task, THREAD_NULL, TASK_POLICY_ATTRIBUTE, TASK_POLICY_ROLE);
511 break;
512 }
513
514 case TASK_BASE_QOS_POLICY: /* FALLTHRU */
515 case TASK_OVERRIDE_QOS_POLICY:
516 {
517 task_qos_policy_t info = (task_qos_policy_t)policy_info;
518
519 if (*count < TASK_QOS_POLICY_COUNT)
520 return (KERN_INVALID_ARGUMENT);
521
522 if (*get_default) {
523 info->task_latency_qos_tier = LATENCY_QOS_TIER_UNSPECIFIED;
524 info->task_throughput_qos_tier = THROUGHPUT_QOS_TIER_UNSPECIFIED;
525 } else if (flavor == TASK_BASE_QOS_POLICY) {
fe8ab488 526 int value1, value2;
39236c6e 527
fe8ab488
A
528 proc_get_task_policy2(task, THREAD_NULL, TASK_POLICY_ATTRIBUTE, TASK_POLICY_BASE_LATENCY_AND_THROUGHPUT_QOS, &value1, &value2);
529
530 info->task_latency_qos_tier = qos_latency_policy_package(value1);
531 info->task_throughput_qos_tier = qos_throughput_policy_package(value2);
39236c6e 532
39236c6e 533 } else if (flavor == TASK_OVERRIDE_QOS_POLICY) {
fe8ab488 534 int value1, value2;
39236c6e 535
fe8ab488 536 proc_get_task_policy2(task, THREAD_NULL, TASK_POLICY_ATTRIBUTE, TASK_POLICY_OVERRIDE_LATENCY_AND_THROUGHPUT_QOS, &value1, &value2);
39236c6e 537
fe8ab488
A
538 info->task_latency_qos_tier = qos_latency_policy_package(value1);
539 info->task_throughput_qos_tier = qos_throughput_policy_package(value2);
0b4e3aa0 540 }
39236c6e 541
1c79356b
A
542 break;
543 }
544
39236c6e
A
545 case TASK_POLICY_STATE:
546 {
547 task_policy_state_t info = (task_policy_state_t)policy_info;
1c79356b 548
39236c6e
A
549 if (*count < TASK_POLICY_STATE_COUNT)
550 return (KERN_INVALID_ARGUMENT);
6d2010ae 551
39236c6e
A
552 /* Only root can get this info */
553 if (current_task()->sec_token.val[0] != 0)
554 return KERN_PROTECTION_FAILURE;
6d2010ae 555
39236c6e
A
556 if (*get_default) {
557 info->requested = 0;
558 info->effective = 0;
559 info->pending = 0;
560 info->imp_assertcnt = 0;
561 info->imp_externcnt = 0;
562 info->flags = 0;
fe8ab488 563 info->imp_transitions = 0;
39236c6e 564 } else {
fe8ab488
A
565 task_lock(task);
566
39236c6e
A
567 info->requested = task_requested_bitfield(task, THREAD_NULL);
568 info->effective = task_effective_bitfield(task, THREAD_NULL);
fe8ab488 569 info->pending = 0;
39236c6e
A
570
571 info->flags = 0;
fe8ab488
A
572 if (task->task_imp_base != NULL) {
573 info->imp_assertcnt = task->task_imp_base->iit_assertcnt;
574 info->imp_externcnt = IIT_EXTERN(task->task_imp_base);
575 info->flags |= (task_is_marked_importance_receiver(task) ? TASK_IMP_RECEIVER : 0);
576 info->flags |= (task_is_marked_importance_denap_receiver(task) ? TASK_DENAP_RECEIVER : 0);
577 info->flags |= (task_is_marked_importance_donor(task) ? TASK_IMP_DONOR : 0);
578 info->flags |= (task_is_marked_live_importance_donor(task) ? TASK_IMP_LIVE_DONOR : 0);
579 info->imp_transitions = task->task_imp_base->iit_transitions;
580 } else {
581 info->imp_assertcnt = 0;
582 info->imp_externcnt = 0;
583 info->imp_transitions = 0;
584 }
585 task_unlock(task);
39236c6e 586 }
6d2010ae 587
fe8ab488
A
588 info->reserved[0] = 0;
589 info->reserved[1] = 0;
6d2010ae 590
39236c6e
A
591 break;
592 }
6d2010ae 593
39236c6e
A
594 case TASK_SUPPRESSION_POLICY:
595 {
596 task_suppression_policy_t info = (task_suppression_policy_t)policy_info;
6d2010ae 597
39236c6e
A
598 if (*count < TASK_SUPPRESSION_POLICY_COUNT)
599 return (KERN_INVALID_ARGUMENT);
6d2010ae 600
6d2010ae 601 task_lock(task);
39236c6e
A
602
603 if (*get_default) {
604 info->active = 0;
605 info->lowpri_cpu = 0;
606 info->timer_throttle = LATENCY_QOS_TIER_UNSPECIFIED;
607 info->disk_throttle = 0;
608 info->cpu_limit = 0;
609 info->suspend = 0;
610 info->throughput_qos = 0;
611 info->suppressed_cpu = 0;
612 } else {
613 info->active = task->requested_policy.t_sup_active;
614 info->lowpri_cpu = task->requested_policy.t_sup_lowpri_cpu;
fe8ab488 615 info->timer_throttle = qos_latency_policy_package(task->requested_policy.t_sup_timer);
39236c6e
A
616 info->disk_throttle = task->requested_policy.t_sup_disk;
617 info->cpu_limit = task->requested_policy.t_sup_cpu_limit;
618 info->suspend = task->requested_policy.t_sup_suspend;
fe8ab488 619 info->throughput_qos = qos_throughput_policy_package(task->requested_policy.t_sup_throughput);
39236c6e 620 info->suppressed_cpu = task->requested_policy.t_sup_cpu;
fe8ab488 621 info->background_sockets = task->requested_policy.t_sup_bg_sockets;
39236c6e
A
622 }
623
6d2010ae 624 task_unlock(task);
39236c6e
A
625 break;
626 }
627
628 default:
629 return (KERN_INVALID_ARGUMENT);
6d2010ae
A
630 }
631
39236c6e 632 return (KERN_SUCCESS);
6d2010ae
A
633}
634
39236c6e
A
635/*
636 * Called at task creation
637 * We calculate the correct effective but don't apply it to anything yet.
638 * The threads, etc will inherit from the task as they get created.
639 */
640void
641task_policy_create(task_t task, int parent_boosted)
6d2010ae 642{
39236c6e
A
643 if (task->requested_policy.t_apptype == TASK_APPTYPE_DAEMON_ADAPTIVE) {
644 if (parent_boosted) {
645 task->requested_policy.t_apptype = TASK_APPTYPE_DAEMON_INTERACTIVE;
646 task_importance_mark_donor(task, TRUE);
647 } else {
648 task->requested_policy.t_apptype = TASK_APPTYPE_DAEMON_BACKGROUND;
649 task_importance_mark_receiver(task, FALSE);
650 }
651 }
6d2010ae 652
39236c6e 653 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
fe8ab488
A
654 (IMPORTANCE_CODE(IMP_UPDATE, (IMP_UPDATE_TASK_CREATE | TASK_POLICY_TASK))) | DBG_FUNC_START,
655 audit_token_pid_from_task(task), teffective_0(task, THREAD_NULL),
656 teffective_1(task, THREAD_NULL), tpriority(task, THREAD_NULL), 0);
39236c6e 657
fe8ab488 658 task_policy_update_internal_locked(task, THREAD_NULL, TRUE, NULL);
39236c6e
A
659
660 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
fe8ab488
A
661 (IMPORTANCE_CODE(IMP_UPDATE, (IMP_UPDATE_TASK_CREATE | TASK_POLICY_TASK))) | DBG_FUNC_END,
662 audit_token_pid_from_task(task), teffective_0(task, THREAD_NULL),
663 teffective_1(task, THREAD_NULL), tpriority(task, THREAD_NULL), 0);
664
665 task_importance_update_live_donor(task);
666 task_policy_update_task_locked(task, FALSE, FALSE, FALSE);
667}
668
669void
670thread_policy_create(thread_t thread)
671{
672 task_t task = thread->task;
673
674 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
675 (IMPORTANCE_CODE(IMP_UPDATE, (IMP_UPDATE_TASK_CREATE | TASK_POLICY_THREAD))) | DBG_FUNC_START,
676 targetid(task, thread), teffective_0(task, thread),
677 teffective_1(task, thread), tpriority(task, thread), 0);
678
679 task_policy_update_internal_locked(task, thread, TRUE, NULL);
680
681 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
682 (IMPORTANCE_CODE(IMP_UPDATE, (IMP_UPDATE_TASK_CREATE | TASK_POLICY_THREAD))) | DBG_FUNC_END,
683 targetid(task, thread), teffective_0(task, thread),
684 teffective_1(task, thread), tpriority(task, thread), 0);
6d2010ae
A
685}
686
39236c6e 687static void
fe8ab488 688task_policy_update_locked(task_t task, thread_t thread, task_pend_token_t pend_token)
6d2010ae 689{
39236c6e
A
690 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
691 (IMPORTANCE_CODE(IMP_UPDATE, tisthread(thread)) | DBG_FUNC_START),
fe8ab488
A
692 targetid(task, thread), teffective_0(task, thread),
693 teffective_1(task, thread), tpriority(task, thread), 0);
6d2010ae 694
fe8ab488 695 task_policy_update_internal_locked(task, thread, FALSE, pend_token);
6d2010ae 696
39236c6e 697 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
fe8ab488
A
698 (IMPORTANCE_CODE(IMP_UPDATE, tisthread(thread))) | DBG_FUNC_END,
699 targetid(task, thread), teffective_0(task, thread),
700 teffective_1(task, thread), tpriority(task, thread), 0);
39236c6e 701}
6d2010ae 702
39236c6e
A
703/*
704 * One state update function TO RULE THEM ALL
705 *
706 * This function updates the task or thread effective policy fields
707 * and pushes the results to the relevant subsystems.
708 *
709 * Must call update_complete after unlocking the task,
710 * as some subsystems cannot be updated while holding the task lock.
711 *
712 * Called with task locked, not thread
713 */
fe8ab488 714
39236c6e 715static void
fe8ab488 716task_policy_update_internal_locked(task_t task, thread_t thread, boolean_t in_create, task_pend_token_t pend_token)
6d2010ae 717{
39236c6e
A
718 boolean_t on_task = (thread == THREAD_NULL) ? TRUE : FALSE;
719
720 /*
721 * Step 1:
722 * Gather requested policy
723 */
6d2010ae 724
39236c6e
A
725 struct task_requested_policy requested =
726 (on_task) ? task->requested_policy : thread->requested_policy;
727
fe8ab488 728
39236c6e
A
729 /*
730 * Step 2:
731 * Calculate new effective policies from requested policy and task state
732 * Rules:
733 * If in an 'on_task' block, must only look at and set fields starting with t_
734 * If operating on a task, don't touch anything starting with th_
735 * If operating on a thread, don't touch anything starting with t_
736 * Don't change requested, it won't take effect
737 */
6d2010ae 738
39236c6e 739 struct task_effective_policy next = {};
fe8ab488
A
740 struct task_effective_policy task_effective;
741
742 /* Calculate QoS policies */
743
744 if (on_task) {
745 /* Update task role */
746 next.t_role = requested.t_role;
747
748 /* Set task qos clamp and ceiling */
749 next.t_qos_clamp = requested.t_qos_clamp;
750
751 if (requested.t_apptype == TASK_APPTYPE_APP_DEFAULT ||
752 requested.t_apptype == TASK_APPTYPE_APP_TAL) {
753
754 switch (next.t_role) {
755 case TASK_FOREGROUND_APPLICATION:
756 /* Foreground apps get urgent scheduler priority */
757 next.qos_ui_is_urgent = 1;
758 next.t_qos_ceiling = THREAD_QOS_UNSPECIFIED;
759 break;
760
761 case TASK_BACKGROUND_APPLICATION:
762 /* This is really 'non-focal but on-screen' */
763 next.t_qos_ceiling = THREAD_QOS_UNSPECIFIED;
764 break;
765
766 case TASK_NONUI_APPLICATION:
767 /* i.e. 'off-screen' */
768 next.t_qos_ceiling = THREAD_QOS_LEGACY;
769 break;
770
771 case TASK_CONTROL_APPLICATION:
772 case TASK_GRAPHICS_SERVER:
773 next.qos_ui_is_urgent = 1;
774 next.t_qos_ceiling = THREAD_QOS_UNSPECIFIED;
775 break;
776
777 case TASK_UNSPECIFIED:
778 default:
779 /* Apps that don't have an application role get
780 * USER_INTERACTIVE and USER_INITIATED squashed to LEGACY */
781 next.t_qos_ceiling = THREAD_QOS_LEGACY;
782 break;
783 }
784 } else {
785 /* Daemons get USER_INTERACTIVE squashed to USER_INITIATED */
786 next.t_qos_ceiling = THREAD_QOS_USER_INITIATED;
787 }
788 } else {
789 /*
790 * Set thread qos tier
791 * Note that an override only overrides the QoS field, not other policy settings.
792 * A thread must already be participating in QoS for override to take effect
793 */
794
795 /* Snapshot the task's effective policy */
796 task_effective = task->effective_policy;
797
798 next.qos_ui_is_urgent = task_effective.qos_ui_is_urgent;
799
800 if ((requested.thrp_qos_override != THREAD_QOS_UNSPECIFIED) && (requested.thrp_qos != THREAD_QOS_UNSPECIFIED))
801 next.thep_qos = MAX(requested.thrp_qos_override, requested.thrp_qos);
802 else
803 next.thep_qos = requested.thrp_qos;
804
805 /* A task clamp will result in an effective QoS even when requested is UNSPECIFIED */
806 if (task_effective.t_qos_clamp != THREAD_QOS_UNSPECIFIED) {
807 if (next.thep_qos != THREAD_QOS_UNSPECIFIED)
808 next.thep_qos = MIN(task_effective.t_qos_clamp, next.thep_qos);
809 else
810 next.thep_qos = task_effective.t_qos_clamp;
811 }
812
813 /* The ceiling only applies to threads that are in the QoS world */
814 if (task_effective.t_qos_ceiling != THREAD_QOS_UNSPECIFIED &&
815 next.thep_qos != THREAD_QOS_UNSPECIFIED) {
816 next.thep_qos = MIN(task_effective.t_qos_ceiling, next.thep_qos);
817 }
818
819 /*
820 * The QoS relative priority is only applicable when the original programmer's
821 * intended (requested) QoS is in effect. When the QoS is clamped (e.g.
822 * USER_INITIATED-13REL clamped to UTILITY), the relative priority is not honored,
823 * since otherwise it would be lower than unclamped threads. Similarly, in the
824 * presence of boosting, the programmer doesn't know what other actors
825 * are boosting the thread.
826 */
827 if ((requested.thrp_qos != THREAD_QOS_UNSPECIFIED) &&
828 (requested.thrp_qos == next.thep_qos) &&
829 (requested.thrp_qos_override == THREAD_QOS_UNSPECIFIED)) {
830 next.thep_qos_relprio = requested.thrp_qos_relprio;
831 } else {
832 next.thep_qos_relprio = 0;
833 }
834 }
6d2010ae 835
39236c6e
A
836 /* Calculate DARWIN_BG */
837 boolean_t wants_darwinbg = FALSE;
838 boolean_t wants_all_sockets_bg = FALSE; /* Do I want my existing sockets to be bg */
839 boolean_t wants_watchersbg = FALSE; /* Do I want my pidbound threads to be bg */
840 boolean_t wants_tal = FALSE; /* Do I want the effects of TAL mode */
fe8ab488 841
39236c6e
A
842 /*
843 * If DARWIN_BG has been requested at either level, it's engaged.
844 * Only true DARWIN_BG changes cause watchers to transition.
fe8ab488
A
845 *
846 * Backgrounding due to apptype does.
39236c6e
A
847 */
848 if (requested.int_darwinbg || requested.ext_darwinbg)
849 wants_watchersbg = wants_all_sockets_bg = wants_darwinbg = TRUE;
850
851 if (on_task) {
852 /* Background TAL apps are throttled when TAL is enabled */
853 if (requested.t_apptype == TASK_APPTYPE_APP_TAL &&
854 requested.t_role == TASK_BACKGROUND_APPLICATION &&
855 requested.t_tal_enabled == 1) {
856 wants_tal = TRUE;
857 next.t_tal_engaged = 1;
858 }
6d2010ae 859
39236c6e
A
860 /* Adaptive daemons are DARWIN_BG unless boosted, and don't get network throttled. */
861 if (requested.t_apptype == TASK_APPTYPE_DAEMON_ADAPTIVE &&
862 requested.t_boosted == 0)
863 wants_darwinbg = TRUE;
864
865 /* Background daemons are always DARWIN_BG, no exceptions, and don't get network throttled. */
866 if (requested.t_apptype == TASK_APPTYPE_DAEMON_BACKGROUND)
867 wants_darwinbg = TRUE;
fe8ab488
A
868
869 if (next.t_qos_clamp == THREAD_QOS_BACKGROUND || next.t_qos_clamp == THREAD_QOS_MAINTENANCE)
870 wants_darwinbg = TRUE;
6d2010ae 871 } else {
39236c6e
A
872 if (requested.th_pidbind_bg)
873 wants_all_sockets_bg = wants_darwinbg = TRUE;
6d2010ae 874
39236c6e
A
875 if (requested.th_workq_bg)
876 wants_darwinbg = TRUE;
fe8ab488
A
877
878 if (next.thep_qos == THREAD_QOS_BACKGROUND || next.thep_qos == THREAD_QOS_MAINTENANCE)
879 wants_darwinbg = TRUE;
39236c6e 880 }
6d2010ae 881
39236c6e 882 /* Calculate side effects of DARWIN_BG */
6d2010ae 883
39236c6e
A
884 if (wants_darwinbg) {
885 next.darwinbg = 1;
886 /* darwinbg threads/tasks always create bg sockets, but we don't always loop over all sockets */
887 next.new_sockets_bg = 1;
888 next.lowpri_cpu = 1;
6d2010ae
A
889 }
890
39236c6e
A
891 if (wants_all_sockets_bg)
892 next.all_sockets_bg = 1;
6d2010ae 893
39236c6e
A
894 if (on_task && wants_watchersbg)
895 next.t_watchers_bg = 1;
6d2010ae 896
fe8ab488
A
897 /* darwinbg on either task or thread implies background QOS (or lower) */
898 if (!on_task &&
899 (wants_darwinbg || task_effective.darwinbg) &&
900 (next.thep_qos > THREAD_QOS_BACKGROUND || next.thep_qos == THREAD_QOS_UNSPECIFIED)){
901 next.thep_qos = THREAD_QOS_BACKGROUND;
902 next.thep_qos_relprio = 0;
903 }
904
39236c6e 905 /* Calculate low CPU priority */
6d2010ae 906
39236c6e 907 boolean_t wants_lowpri_cpu = FALSE;
316670eb 908
39236c6e
A
909 if (wants_darwinbg || wants_tal)
910 wants_lowpri_cpu = TRUE;
911
912 if (on_task && requested.t_sup_lowpri_cpu && requested.t_boosted == 0)
913 wants_lowpri_cpu = TRUE;
914
915 if (wants_lowpri_cpu)
916 next.lowpri_cpu = 1;
917
918 /* Calculate IO policy */
919
920 /* Update BG IO policy (so we can see if it has changed) */
921 next.bg_iotier = requested.bg_iotier;
922
923 int iopol = THROTTLE_LEVEL_TIER0;
924
925 if (wants_darwinbg)
926 iopol = MAX(iopol, requested.bg_iotier);
927
928 if (on_task) {
929 if (requested.t_apptype == TASK_APPTYPE_DAEMON_STANDARD)
930 iopol = MAX(iopol, proc_standard_daemon_tier);
931
932 if (requested.t_sup_disk && requested.t_boosted == 0)
933 iopol = MAX(iopol, proc_suppressed_disk_tier);
934
935 if (wants_tal)
936 iopol = MAX(iopol, proc_tal_disk_tier);
fe8ab488
A
937
938 if (next.t_qos_clamp != THREAD_QOS_UNSPECIFIED)
939 iopol = MAX(iopol, thread_qos_policy_params.qos_iotier[next.t_qos_clamp]);
940
941 } else {
942 /* Look up the associated IO tier value for the QoS class */
943 iopol = MAX(iopol, thread_qos_policy_params.qos_iotier[next.thep_qos]);
6d2010ae 944 }
6d2010ae 945
39236c6e
A
946 iopol = MAX(iopol, requested.int_iotier);
947 iopol = MAX(iopol, requested.ext_iotier);
6d2010ae 948
39236c6e 949 next.io_tier = iopol;
6d2010ae 950
39236c6e
A
951 /* Calculate Passive IO policy */
952
953 if (requested.ext_iopassive || requested.int_iopassive)
954 next.io_passive = 1;
955
956 /* Calculate miscellaneous policy */
957
958 if (on_task) {
39236c6e
A
959 /* Calculate suppression-active flag */
960 if (requested.t_sup_active && requested.t_boosted == 0)
961 next.t_sup_active = 1;
962
963 /* Calculate suspend policy */
964 if (requested.t_sup_suspend && requested.t_boosted == 0)
965 next.t_suspended = 1;
966
39236c6e
A
967 /* Calculate timer QOS */
968 int latency_qos = requested.t_base_latency_qos;
969
970 if (requested.t_sup_timer && requested.t_boosted == 0)
971 latency_qos = requested.t_sup_timer;
972
fe8ab488
A
973 if (next.t_qos_clamp != THREAD_QOS_UNSPECIFIED)
974 latency_qos = MAX(latency_qos, (int)thread_qos_policy_params.qos_latency_qos[next.t_qos_clamp]);
975
39236c6e
A
976 if (requested.t_over_latency_qos != 0)
977 latency_qos = requested.t_over_latency_qos;
978
979 /* Treat the windowserver special */
980 if (requested.t_role == TASK_GRAPHICS_SERVER)
981 latency_qos = proc_graphics_timer_qos;
982
983 next.t_latency_qos = latency_qos;
984
985 /* Calculate throughput QOS */
986 int through_qos = requested.t_base_through_qos;
987
988 if (requested.t_sup_throughput && requested.t_boosted == 0)
989 through_qos = requested.t_sup_throughput;
990
fe8ab488
A
991 if (next.t_qos_clamp != THREAD_QOS_UNSPECIFIED)
992 through_qos = MAX(through_qos, (int)thread_qos_policy_params.qos_through_qos[next.t_qos_clamp]);
993
39236c6e
A
994 if (requested.t_over_through_qos != 0)
995 through_qos = requested.t_over_through_qos;
996
997 next.t_through_qos = through_qos;
998
999 /* Calculate suppressed CPU priority */
1000 if (requested.t_sup_cpu && requested.t_boosted == 0)
1001 next.t_suppressed_cpu = 1;
fe8ab488
A
1002
1003 /*
1004 * Calculate background sockets
1005 * Don't take into account boosting to limit transition frequency.
1006 */
1007 if (requested.t_sup_bg_sockets){
1008 next.all_sockets_bg = 1;
1009 next.new_sockets_bg = 1;
1010 }
1011
1012 /* Apply SFI Managed class bit */
1013 next.t_sfi_managed = requested.t_sfi_managed;
1014
1015 /* Calculate 'live donor' status for live importance */
1016 switch (requested.t_apptype) {
1017 case TASK_APPTYPE_APP_TAL:
1018 case TASK_APPTYPE_APP_DEFAULT:
1019 if (requested.ext_darwinbg == 0)
1020 next.t_live_donor = 1;
1021 else
1022 next.t_live_donor = 0;
1023 break;
1024
1025 case TASK_APPTYPE_DAEMON_INTERACTIVE:
1026 case TASK_APPTYPE_DAEMON_STANDARD:
1027 case TASK_APPTYPE_DAEMON_ADAPTIVE:
1028 case TASK_APPTYPE_DAEMON_BACKGROUND:
1029 default:
1030 next.t_live_donor = 0;
1031 break;
1032 }
6d2010ae
A
1033 }
1034
39236c6e
A
1035 if (requested.terminated) {
1036 /*
1037 * Shoot down the throttles that slow down exit or response to SIGTERM
1038 * We don't need to shoot down:
1039 * passive (don't want to cause others to throttle)
1040 * all_sockets_bg (don't need to iterate FDs on every exit)
1041 * new_sockets_bg (doesn't matter for exiting process)
39236c6e
A
1042 * pidsuspend (jetsam-ed BG process shouldn't run again)
1043 * watchers_bg (watcher threads don't need to be unthrottled)
1044 * t_latency_qos (affects userspace timers only)
1045 */
6d2010ae 1046
39236c6e
A
1047 next.terminated = 1;
1048 next.darwinbg = 0;
1049 next.lowpri_cpu = 0;
1050 next.io_tier = THROTTLE_LEVEL_TIER0;
1051 if (on_task) {
1052 next.t_tal_engaged = 0;
1053 next.t_role = TASK_UNSPECIFIED;
1054 next.t_suppressed_cpu = 0;
1055
1056 /* TODO: This should only be shot down on SIGTERM, not exit */
1057 next.t_suspended = 0;
fe8ab488
A
1058 } else {
1059 next.thep_qos = 0;
39236c6e
A
1060 }
1061 }
6d2010ae 1062
39236c6e
A
1063 /*
1064 * Step 3:
1065 * Swap out old policy for new policy
1066 */
6d2010ae 1067
fe8ab488
A
1068 if (!on_task) {
1069 /* Acquire thread mutex to synchronize against
1070 * thread_policy_set(). Consider reworking to separate qos
1071 * fields, or locking the task in thread_policy_set.
1072 * A more efficient model would be to make the thread bits
1073 * authoritative.
1074 */
1075 thread_mtx_lock(thread);
1076 }
1077
39236c6e
A
1078 struct task_effective_policy prev =
1079 (on_task) ? task->effective_policy : thread->effective_policy;
1080
1081 /*
1082 * Check for invalid transitions here for easier debugging
1083 * TODO: dump the structs as hex in the panic string
1084 */
1085 if (task == kernel_task && prev.all_sockets_bg != next.all_sockets_bg)
1086 panic("unexpected network change for kernel task");
1087
1088 /* This is the point where the new values become visible to other threads */
1089 if (on_task)
1090 task->effective_policy = next;
fe8ab488
A
1091 else {
1092 /* Preserve thread specific latency/throughput QoS modified via
1093 * thread_policy_set(). Inelegant in the extreme, to be reworked.
1094 *
1095 * If thread QoS class is set, we don't need to preserve the previously set values.
1096 * We should ensure to not accidentally preserve previous thread QoS values if you set a thread
1097 * back to default QoS.
1098 */
1099 uint32_t lqos = thread->effective_policy.t_latency_qos, tqos = thread->effective_policy.t_through_qos;
1100
1101 if (prev.thep_qos == THREAD_QOS_UNSPECIFIED && next.thep_qos == THREAD_QOS_UNSPECIFIED) {
1102 next.t_latency_qos = lqos;
1103 next.t_through_qos = tqos;
1104 } else if (prev.thep_qos != THREAD_QOS_UNSPECIFIED && next.thep_qos == THREAD_QOS_UNSPECIFIED) {
1105 next.t_latency_qos = 0;
1106 next.t_through_qos = 0;
1107 } else {
1108 next.t_latency_qos = thread_qos_policy_params.qos_latency_qos[next.thep_qos];
1109 next.t_through_qos = thread_qos_policy_params.qos_through_qos[next.thep_qos];
1110 }
1111
1112 thread_update_qos_cpu_time(thread, TRUE);
39236c6e 1113 thread->effective_policy = next;
fe8ab488
A
1114 thread_mtx_unlock(thread);
1115 }
39236c6e
A
1116
1117 /* Don't do anything further to a half-formed task or thread */
1118 if (in_create)
1119 return;
1120
1121 /*
1122 * Step 4:
1123 * Pend updates that can't be done while holding the task lock
39236c6e
A
1124 */
1125
39236c6e 1126 if (prev.all_sockets_bg != next.all_sockets_bg)
fe8ab488 1127 pend_token->tpt_update_sockets = 1;
39236c6e
A
1128
1129 if (on_task) {
1130 /* Only re-scan the timer list if the qos level is getting less strong */
1131 if (prev.t_latency_qos > next.t_latency_qos)
fe8ab488 1132 pend_token->tpt_update_timers = 1;
6d2010ae 1133
6d2010ae 1134
fe8ab488
A
1135 if (prev.t_live_donor != next.t_live_donor)
1136 pend_token->tpt_update_live_donor = 1;
1137 }
39236c6e
A
1138
1139 /*
1140 * Step 5:
1141 * Update other subsystems as necessary if something has changed
1142 */
1143
1144 boolean_t update_throttle = (prev.io_tier != next.io_tier) ? TRUE : FALSE;
1145
1146 if (on_task) {
1147 if (prev.t_suspended == 0 && next.t_suspended == 1 && task->active) {
1148 task_hold_locked(task);
1149 task_wait_locked(task, FALSE);
1150 }
1151 if (prev.t_suspended == 1 && next.t_suspended == 0 && task->active) {
1152 task_release_locked(task);
1153 }
1154
1155 boolean_t update_threads = FALSE;
fe8ab488
A
1156 boolean_t update_sfi = FALSE;
1157
1158 if (prev.bg_iotier != next.bg_iotier ||
1159 prev.terminated != next.terminated ||
1160 prev.t_qos_clamp != next.t_qos_clamp ||
1161 prev.t_qos_ceiling != next.t_qos_ceiling ||
1162 prev.qos_ui_is_urgent != next.qos_ui_is_urgent ||
1163 prev.darwinbg != next.darwinbg)
39236c6e
A
1164 update_threads = TRUE;
1165
fe8ab488
A
1166 /*
1167 * A bit of a layering violation. We know what task policy attributes
1168 * sfi_thread_classify() consults, so if they change, trigger SFI
1169 * re-evaluation.
1170 */
1171 if ((prev.t_latency_qos != next.t_latency_qos) ||
1172 (prev.t_role != next.t_role) ||
1173 (prev.darwinbg != next.darwinbg) ||
1174 (prev.t_sfi_managed != next.t_sfi_managed))
1175 update_sfi = TRUE;
39236c6e 1176
fe8ab488 1177 task_policy_update_task_locked(task, update_throttle, update_threads, update_sfi);
39236c6e
A
1178 } else {
1179 int update_cpu = 0;
fe8ab488
A
1180 boolean_t update_sfi = FALSE;
1181 boolean_t update_qos = FALSE;
39236c6e
A
1182
1183 if (prev.lowpri_cpu != next.lowpri_cpu)
1184 update_cpu = (next.lowpri_cpu ? DO_LOWPRI_CPU : UNDO_LOWPRI_CPU);
1185
fe8ab488
A
1186 if (prev.darwinbg != next.darwinbg ||
1187 prev.thep_qos != next.thep_qos)
1188 update_sfi = TRUE;
1189
1190 if (prev.thep_qos != next.thep_qos ||
1191 prev.thep_qos_relprio != next.thep_qos_relprio ||
1192 prev.qos_ui_is_urgent != next.qos_ui_is_urgent) {
1193 update_qos = TRUE;
1194 }
1195
1196 task_policy_update_thread_locked(thread, update_cpu, update_throttle, update_sfi, update_qos);
39236c6e 1197 }
6d2010ae
A
1198}
1199
39236c6e 1200/* Despite the name, the thread's task is locked, the thread is not */
fe8ab488 1201void
39236c6e
A
1202task_policy_update_thread_locked(thread_t thread,
1203 int update_cpu,
fe8ab488
A
1204 boolean_t update_throttle,
1205 boolean_t update_sfi,
1206 boolean_t update_qos)
6d2010ae 1207{
39236c6e 1208 thread_precedence_policy_data_t policy;
6d2010ae 1209
39236c6e
A
1210 if (update_throttle) {
1211 rethrottle_thread(thread->uthread);
1212 }
316670eb 1213
fe8ab488
A
1214 if (update_sfi) {
1215 sfi_reevaluate(thread);
1216 }
1217
39236c6e
A
1218 /*
1219 * TODO: pidbind needs to stuff remembered importance into saved_importance
1220 * properly deal with bg'ed threads being pidbound and unbging while pidbound
1221 *
1222 * TODO: A BG thread's priority is 0 on desktop and 4 on embedded. Need to reconcile this.
1223 * */
1224 if (update_cpu == DO_LOWPRI_CPU) {
1225 thread->saved_importance = thread->importance;
1226 policy.importance = INT_MIN;
1227 } else if (update_cpu == UNDO_LOWPRI_CPU) {
1228 policy.importance = thread->saved_importance;
1229 thread->saved_importance = 0;
6d2010ae 1230 }
6d2010ae 1231
39236c6e
A
1232 /* Takes thread lock and thread mtx lock */
1233 if (update_cpu)
1234 thread_policy_set_internal(thread, THREAD_PRECEDENCE_POLICY,
1235 (thread_policy_t)&policy,
1236 THREAD_PRECEDENCE_POLICY_COUNT);
fe8ab488
A
1237
1238 if (update_qos)
1239 thread_recompute_qos(thread);
6d2010ae
A
1240}
1241
39236c6e
A
1242/*
1243 * Calculate priority on a task, loop through its threads, and tell them about
1244 * priority changes and throttle changes.
1245 */
fe8ab488 1246void
39236c6e
A
1247task_policy_update_task_locked(task_t task,
1248 boolean_t update_throttle,
fe8ab488
A
1249 boolean_t update_threads,
1250 boolean_t update_sfi)
6d2010ae 1251{
39236c6e 1252 boolean_t update_priority = FALSE;
6d2010ae 1253
39236c6e
A
1254 if (task == kernel_task)
1255 panic("Attempting to set task policy on kernel_task");
6d2010ae 1256
39236c6e
A
1257 int priority = BASEPRI_DEFAULT;
1258 int max_priority = MAXPRI_USER;
6d2010ae 1259
39236c6e
A
1260 if (proc_get_effective_task_policy(task, TASK_POLICY_LOWPRI_CPU)) {
1261 priority = MAXPRI_THROTTLE;
1262 max_priority = MAXPRI_THROTTLE;
1263 } else if (proc_get_effective_task_policy(task, TASK_POLICY_SUPPRESSED_CPU)) {
1264 priority = MAXPRI_SUPPRESSED;
1265 max_priority = MAXPRI_SUPPRESSED;
6d2010ae 1266 } else {
39236c6e 1267 switch (proc_get_effective_task_policy(task, TASK_POLICY_ROLE)) {
39236c6e
A
1268 case TASK_CONTROL_APPLICATION:
1269 priority = BASEPRI_CONTROL;
1270 break;
1271 case TASK_GRAPHICS_SERVER:
1272 priority = BASEPRI_GRAPHICS;
1273 max_priority = MAXPRI_RESERVED;
1274 break;
1275 default:
1276 break;
1277 }
1278
1279 /* factor in 'nice' value */
1280 priority += task->importance;
fe8ab488
A
1281
1282 if (task->effective_policy.t_qos_clamp != THREAD_QOS_UNSPECIFIED) {
1283 int qos_clamp_priority = thread_qos_policy_params.qos_pri[task->effective_policy.t_qos_clamp];
1284
1285 priority = MIN(priority, qos_clamp_priority);
1286 max_priority = MIN(max_priority, qos_clamp_priority);
1287 }
6d2010ae
A
1288 }
1289
39236c6e
A
1290 /* avoid extra work if priority isn't changing */
1291 if (task->priority != priority || task->max_priority != max_priority) {
1292 update_priority = TRUE;
6d2010ae 1293
39236c6e
A
1294 /* update the scheduling priority for the task */
1295 task->max_priority = max_priority;
6d2010ae 1296
39236c6e
A
1297 if (priority > task->max_priority)
1298 priority = task->max_priority;
1299 else if (priority < MINPRI)
1300 priority = MINPRI;
316670eb 1301
39236c6e 1302 task->priority = priority;
6d2010ae 1303 }
6d2010ae 1304
39236c6e 1305 /* Loop over the threads in the task only once, and only if necessary */
fe8ab488 1306 if (update_threads || update_throttle || update_priority || update_sfi ) {
39236c6e 1307 thread_t thread;
6d2010ae 1308
39236c6e
A
1309 queue_iterate(&task->threads, thread, thread_t, task_threads) {
1310 if (update_priority) {
1311 thread_mtx_lock(thread);
6d2010ae 1312
fe8ab488 1313 thread_task_priority(thread, priority, max_priority);
6d2010ae 1314
39236c6e
A
1315 thread_mtx_unlock(thread);
1316 }
6d2010ae 1317
39236c6e
A
1318 if (update_throttle) {
1319 rethrottle_thread(thread->uthread);
1320 }
1321
fe8ab488
A
1322 if (update_sfi) {
1323 sfi_reevaluate(thread);
1324 }
1325
39236c6e
A
1326 if (update_threads) {
1327 thread->requested_policy.bg_iotier = task->effective_policy.bg_iotier;
1328 thread->requested_policy.terminated = task->effective_policy.terminated;
1329
fe8ab488 1330 task_policy_update_internal_locked(task, thread, FALSE, NULL);
39236c6e
A
1331 /* The thread policy must not emit any completion actions due to this change. */
1332 }
1333 }
1334 }
6d2010ae
A
1335}
1336
39236c6e
A
1337/*
1338 * Called with task unlocked to do things that can't be done while holding the task lock
39236c6e 1339 */
fe8ab488
A
1340void
1341task_policy_update_complete_unlocked(task_t task, thread_t thread, task_pend_token_t pend_token)
6d2010ae 1342{
39236c6e
A
1343 boolean_t on_task = (thread == THREAD_NULL) ? TRUE : FALSE;
1344
39236c6e 1345#ifdef MACH_BSD
fe8ab488
A
1346 if (pend_token->tpt_update_sockets)
1347 proc_apply_task_networkbg(task->bsd_info, thread);
39236c6e
A
1348#endif /* MACH_BSD */
1349
1350 if (on_task) {
fe8ab488
A
1351 /* The timer throttle has been removed or reduced, we need to look for expired timers and fire them */
1352 if (pend_token->tpt_update_timers)
39236c6e 1353 ml_timer_evaluate();
316670eb 1354
39236c6e 1355
fe8ab488
A
1356 if (pend_token->tpt_update_live_donor)
1357 task_importance_update_live_donor(task);
1358 }
6d2010ae
A
1359}
1360
39236c6e
A
1361/*
1362 * Initiate a task policy state transition
1363 *
1364 * Everything that modifies requested except functions that need to hold the task lock
1365 * should use this function
1366 *
1367 * Argument validation should be performed before reaching this point.
1368 *
1369 * TODO: Do we need to check task->active or thread->active?
1370 */
1371void
1372proc_set_task_policy(task_t task,
1373 thread_t thread,
1374 int category,
1375 int flavor,
1376 int value)
6d2010ae 1377{
fe8ab488
A
1378 struct task_pend_token pend_token = {};
1379
39236c6e 1380 task_lock(task);
6d2010ae 1381
39236c6e 1382 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
fe8ab488
A
1383 (IMPORTANCE_CODE(flavor, (category | tisthread(thread)))) | DBG_FUNC_START,
1384 targetid(task, thread), trequested_0(task, thread), trequested_1(task, thread), value, 0);
6d2010ae 1385
39236c6e
A
1386 proc_set_task_policy_locked(task, thread, category, flavor, value);
1387
fe8ab488 1388 task_policy_update_locked(task, thread, &pend_token);
39236c6e
A
1389
1390 task_unlock(task);
1391
1392 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
fe8ab488
A
1393 (IMPORTANCE_CODE(flavor, (category | tisthread(thread)))) | DBG_FUNC_END,
1394 targetid(task, thread), trequested_0(task, thread), trequested_1(task, thread), tpending(&pend_token), 0);
39236c6e 1395
fe8ab488 1396 task_policy_update_complete_unlocked(task, thread, &pend_token);
6d2010ae
A
1397}
1398
39236c6e
A
1399/*
1400 * Initiate a task policy state transition on a thread with its TID
1401 * Useful if you cannot guarantee the thread won't get terminated
1402 */
1403void
1404proc_set_task_policy_thread(task_t task,
1405 uint64_t tid,
1406 int category,
1407 int flavor,
1408 int value)
6d2010ae 1409{
39236c6e 1410 thread_t thread;
6d2010ae 1411 thread_t self = current_thread();
fe8ab488 1412 struct task_pend_token pend_token = {};
6d2010ae 1413
39236c6e 1414 task_lock(task);
6d2010ae 1415
39236c6e 1416 if (tid == TID_NULL || tid == self->thread_id)
6d2010ae 1417 thread = self;
39236c6e
A
1418 else
1419 thread = task_findtid(task, tid);
1420
1421 if (thread == THREAD_NULL) {
1422 task_unlock(task);
1423 return;
6d2010ae
A
1424 }
1425
39236c6e 1426 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
fe8ab488
A
1427 (IMPORTANCE_CODE(flavor, (category | TASK_POLICY_THREAD))) | DBG_FUNC_START,
1428 targetid(task, thread), trequested_0(task, thread), trequested_1(task, thread), value, 0);
6d2010ae 1429
39236c6e
A
1430 proc_set_task_policy_locked(task, thread, category, flavor, value);
1431
fe8ab488 1432 task_policy_update_locked(task, thread, &pend_token);
39236c6e
A
1433
1434 task_unlock(task);
1435
1436 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
fe8ab488
A
1437 (IMPORTANCE_CODE(flavor, (category | TASK_POLICY_THREAD))) | DBG_FUNC_END,
1438 targetid(task, thread), trequested_0(task, thread), trequested_1(task, thread), tpending(&pend_token), 0);
39236c6e 1439
fe8ab488 1440 task_policy_update_complete_unlocked(task, thread, &pend_token);
6d2010ae
A
1441}
1442
fe8ab488
A
1443/*
1444 * Variant of proc_set_task_policy() that sets two scalars in the requested policy structure.
1445 * Same locking rules apply.
1446 */
1447void
1448proc_set_task_policy2(task_t task, thread_t thread, int category, int flavor, int value1, int value2)
1449{
1450 struct task_pend_token pend_token = {};
1451
1452 task_lock(task);
1453
1454 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
1455 (IMPORTANCE_CODE(flavor, (category | tisthread(thread)))) | DBG_FUNC_START,
1456 targetid(task, thread), trequested_0(task, thread), trequested_1(task, thread), value1, 0);
1457
1458 proc_set_task_policy2_locked(task, thread, category, flavor, value1, value2);
1459
1460 task_policy_update_locked(task, thread, &pend_token);
1461
1462 task_unlock(task);
1463
1464 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
1465 (IMPORTANCE_CODE(flavor, (category | tisthread(thread)))) | DBG_FUNC_END,
1466 targetid(task, thread), trequested_0(task, thread), trequested_0(task, thread), tpending(&pend_token), 0);
1467
1468 task_policy_update_complete_unlocked(task, thread, &pend_token);
1469}
39236c6e
A
1470
1471/*
1472 * Set the requested state for a specific flavor to a specific value.
1473 *
1474 * TODO:
1475 * Verify that arguments to non iopol things are 1 or 0
1476 */
1477static void
1478proc_set_task_policy_locked(task_t task,
1479 thread_t thread,
1480 int category,
1481 int flavor,
1482 int value)
6d2010ae 1483{
39236c6e
A
1484 boolean_t on_task = (thread == THREAD_NULL) ? TRUE : FALSE;
1485
1486 int tier, passive;
6d2010ae 1487
39236c6e
A
1488 struct task_requested_policy requested =
1489 (on_task) ? task->requested_policy : thread->requested_policy;
316670eb 1490
39236c6e
A
1491 switch (flavor) {
1492
1493 /* Category: EXTERNAL and INTERNAL, thread and task */
1494
1495 case TASK_POLICY_DARWIN_BG:
1496 if (category == TASK_POLICY_EXTERNAL)
1497 requested.ext_darwinbg = value;
1498 else
1499 requested.int_darwinbg = value;
1500 break;
316670eb 1501
39236c6e
A
1502 case TASK_POLICY_IOPOL:
1503 proc_iopol_to_tier(value, &tier, &passive);
1504 if (category == TASK_POLICY_EXTERNAL) {
1505 requested.ext_iotier = tier;
1506 requested.ext_iopassive = passive;
1507 } else {
1508 requested.int_iotier = tier;
1509 requested.int_iopassive = passive;
6d2010ae 1510 }
39236c6e
A
1511 break;
1512
1513 case TASK_POLICY_IO:
1514 if (category == TASK_POLICY_EXTERNAL)
1515 requested.ext_iotier = value;
1516 else
1517 requested.int_iotier = value;
1518 break;
1519
1520 case TASK_POLICY_PASSIVE_IO:
1521 if (category == TASK_POLICY_EXTERNAL)
1522 requested.ext_iopassive = value;
1523 else
1524 requested.int_iopassive = value;
1525 break;
1526
fe8ab488 1527 /* Category: INTERNAL, task only */
316670eb 1528
39236c6e
A
1529 case TASK_POLICY_DARWIN_BG_IOPOL:
1530 assert(on_task && category == TASK_POLICY_INTERNAL);
1531 proc_iopol_to_tier(value, &tier, &passive);
1532 requested.bg_iotier = tier;
1533 break;
1534
1535 /* Category: ATTRIBUTE, task only */
1536
1537 case TASK_POLICY_TAL:
1538 assert(on_task && category == TASK_POLICY_ATTRIBUTE);
1539 requested.t_tal_enabled = value;
1540 break;
1541
1542 case TASK_POLICY_BOOST:
1543 assert(on_task && category == TASK_POLICY_ATTRIBUTE);
1544 requested.t_boosted = value;
1545 break;
1546
1547 case TASK_POLICY_ROLE:
1548 assert(on_task && category == TASK_POLICY_ATTRIBUTE);
1549 requested.t_role = value;
1550 break;
1551
1552 case TASK_POLICY_TERMINATED:
1553 assert(on_task && category == TASK_POLICY_ATTRIBUTE);
1554 requested.terminated = value;
1555 break;
fe8ab488
A
1556 case TASK_BASE_LATENCY_QOS_POLICY:
1557 assert(on_task && category == TASK_POLICY_ATTRIBUTE);
1558 requested.t_base_latency_qos = value;
1559 break;
1560 case TASK_BASE_THROUGHPUT_QOS_POLICY:
1561 assert(on_task && category == TASK_POLICY_ATTRIBUTE);
1562 requested.t_base_through_qos = value;
1563 break;
1564 case TASK_POLICY_SFI_MANAGED:
1565 assert(on_task && category == TASK_POLICY_ATTRIBUTE);
1566 requested.t_sfi_managed = value;
1567 break;
39236c6e
A
1568
1569 /* Category: ATTRIBUTE, thread only */
1570
1571 case TASK_POLICY_PIDBIND_BG:
1572 assert(!on_task && category == TASK_POLICY_ATTRIBUTE);
1573 requested.th_pidbind_bg = value;
1574 break;
1575
1576 case TASK_POLICY_WORKQ_BG:
1577 assert(!on_task && category == TASK_POLICY_ATTRIBUTE);
1578 requested.th_workq_bg = value;
1579 break;
1580
fe8ab488
A
1581 case TASK_POLICY_QOS:
1582 assert(!on_task && category == TASK_POLICY_ATTRIBUTE);
1583 requested.thrp_qos = value;
1584 break;
1585
1586 case TASK_POLICY_QOS_OVERRIDE:
1587 assert(!on_task && category == TASK_POLICY_ATTRIBUTE);
1588 requested.thrp_qos_override = value;
1589 break;
1590
39236c6e
A
1591 default:
1592 panic("unknown task policy: %d %d %d", category, flavor, value);
1593 break;
1594 }
1595
1596 if (on_task)
1597 task->requested_policy = requested;
1598 else
1599 thread->requested_policy = requested;
6d2010ae
A
1600}
1601
39236c6e 1602/*
fe8ab488 1603 * Variant of proc_set_task_policy_locked() that sets two scalars in the requested policy structure.
39236c6e 1604 */
fe8ab488
A
1605static void
1606proc_set_task_policy2_locked(task_t task,
1607 thread_t thread,
1608 int category,
1609 int flavor,
1610 int value1,
1611 int value2)
316670eb 1612{
39236c6e 1613 boolean_t on_task = (thread == THREAD_NULL) ? TRUE : FALSE;
316670eb 1614
fe8ab488
A
1615 struct task_requested_policy requested =
1616 (on_task) ? task->requested_policy : thread->requested_policy;
1617
1618 switch (flavor) {
1619
1620 /* Category: ATTRIBUTE, task only */
1621
1622 case TASK_POLICY_BASE_LATENCY_AND_THROUGHPUT_QOS:
1623 assert(on_task && category == TASK_POLICY_ATTRIBUTE);
1624 requested.t_base_latency_qos = value1;
1625 requested.t_base_through_qos = value2;
1626 break;
1627
1628 case TASK_POLICY_OVERRIDE_LATENCY_AND_THROUGHPUT_QOS:
1629 assert(on_task && category == TASK_POLICY_ATTRIBUTE);
1630 requested.t_over_latency_qos = value1;
1631 requested.t_over_through_qos = value2;
1632 break;
1633
1634 /* Category: ATTRIBUTE, thread only */
1635
1636 case TASK_POLICY_QOS_AND_RELPRIO:
1637
1638 assert(!on_task && category == TASK_POLICY_ATTRIBUTE);
1639 requested.thrp_qos = value1;
1640 requested.thrp_qos_relprio = value2;
1641 DTRACE_BOOST3(qos_set, uint64_t, thread->thread_id, int, requested.thrp_qos, int, requested.thrp_qos_relprio);
1642 break;
1643
1644 default:
1645 panic("unknown task policy: %d %d %d %d", category, flavor, value1, value2);
1646 break;
1647 }
1648
1649 if (on_task)
1650 task->requested_policy = requested;
1651 else
1652 thread->requested_policy = requested;
1653}
1654
1655
1656/*
1657 * Gets what you set. Effective values may be different.
1658 */
1659int
1660proc_get_task_policy(task_t task,
1661 thread_t thread,
1662 int category,
1663 int flavor)
1664{
1665 boolean_t on_task = (thread == THREAD_NULL) ? TRUE : FALSE;
1666
1667 int value = 0;
39236c6e
A
1668
1669 task_lock(task);
316670eb 1670
39236c6e
A
1671 struct task_requested_policy requested =
1672 (on_task) ? task->requested_policy : thread->requested_policy;
316670eb 1673
39236c6e
A
1674 switch (flavor) {
1675 case TASK_POLICY_DARWIN_BG:
1676 if (category == TASK_POLICY_EXTERNAL)
1677 value = requested.ext_darwinbg;
1678 else
1679 value = requested.int_darwinbg;
1680 break;
1681 case TASK_POLICY_IOPOL:
1682 if (category == TASK_POLICY_EXTERNAL)
1683 value = proc_tier_to_iopol(requested.ext_iotier,
1684 requested.ext_iopassive);
1685 else
1686 value = proc_tier_to_iopol(requested.int_iotier,
1687 requested.int_iopassive);
1688 break;
1689 case TASK_POLICY_IO:
1690 if (category == TASK_POLICY_EXTERNAL)
1691 value = requested.ext_iotier;
1692 else
1693 value = requested.int_iotier;
1694 break;
1695 case TASK_POLICY_PASSIVE_IO:
1696 if (category == TASK_POLICY_EXTERNAL)
1697 value = requested.ext_iopassive;
1698 else
1699 value = requested.int_iopassive;
1700 break;
39236c6e
A
1701 case TASK_POLICY_DARWIN_BG_IOPOL:
1702 assert(on_task && category == TASK_POLICY_ATTRIBUTE);
1703 value = proc_tier_to_iopol(requested.bg_iotier, 0);
1704 break;
1705 case TASK_POLICY_ROLE:
1706 assert(on_task && category == TASK_POLICY_ATTRIBUTE);
1707 value = requested.t_role;
1708 break;
fe8ab488
A
1709 case TASK_POLICY_SFI_MANAGED:
1710 assert(on_task && category == TASK_POLICY_ATTRIBUTE);
1711 value = requested.t_sfi_managed;
1712 break;
1713 case TASK_POLICY_QOS:
1714 assert(!on_task && category == TASK_POLICY_ATTRIBUTE);
1715 value = requested.thrp_qos;
1716 break;
1717 case TASK_POLICY_QOS_OVERRIDE:
1718 assert(!on_task && category == TASK_POLICY_ATTRIBUTE);
1719 value = requested.thrp_qos_override;
1720 break;
39236c6e
A
1721 default:
1722 panic("unknown policy_flavor %d", flavor);
1723 break;
316670eb
A
1724 }
1725
39236c6e 1726 task_unlock(task);
316670eb 1727
39236c6e
A
1728 return value;
1729}
1730
fe8ab488
A
1731/*
1732 * Variant of proc_get_task_policy() that returns two scalar outputs.
1733 */
1734void
1735proc_get_task_policy2(task_t task, thread_t thread, int category __unused, int flavor, int *value1, int *value2)
1736{
1737 boolean_t on_task = (thread == THREAD_NULL) ? TRUE : FALSE;
1738
1739 task_lock(task);
1740
1741 struct task_requested_policy requested =
1742 (on_task) ? task->requested_policy : thread->requested_policy;
1743
1744 switch (flavor) {
1745 /* TASK attributes */
1746 case TASK_POLICY_BASE_LATENCY_AND_THROUGHPUT_QOS:
1747 assert(on_task && category == TASK_POLICY_ATTRIBUTE);
1748 *value1 = requested.t_base_latency_qos;
1749 *value2 = requested.t_base_through_qos;
1750 break;
1751
1752 case TASK_POLICY_OVERRIDE_LATENCY_AND_THROUGHPUT_QOS:
1753 assert(on_task && category == TASK_POLICY_ATTRIBUTE);
1754 *value1 = requested.t_over_latency_qos;
1755 *value2 = requested.t_over_through_qos;
1756 break;
1757
1758 /* THREAD attributes */
1759 case TASK_POLICY_QOS_AND_RELPRIO:
1760 assert(!on_task && category == TASK_POLICY_ATTRIBUTE);
1761 *value1 = requested.thrp_qos;
1762 *value2 = requested.thrp_qos_relprio;
1763 break;
1764
1765 default:
1766 panic("unknown policy_flavor %d", flavor);
1767 break;
1768 }
1769
1770 task_unlock(task);
1771}
1772
39236c6e
A
1773
1774/*
1775 * Functions for querying effective state for relevant subsystems
1776 * ONLY the relevant subsystem should query these.
1777 * NEVER take a value from one of the 'effective' functions and stuff it into a setter.
1778 */
1779
1780int
1781proc_get_effective_task_policy(task_t task, int flavor)
1782{
1783 return proc_get_effective_policy(task, THREAD_NULL, flavor);
1784}
1785
1786int
1787proc_get_effective_thread_policy(thread_t thread, int flavor)
1788{
1789 return proc_get_effective_policy(thread->task, thread, flavor);
1790}
1791
1792/*
1793 * Gets what is actually in effect, for subsystems which pull policy instead of receive updates.
1794 *
1795 * NOTE: This accessor does not take the task lock.
1796 * Notifications of state updates need to be externally synchronized with state queries.
1797 * This routine *MUST* remain interrupt safe, as it is potentially invoked
fe8ab488 1798 * within the context of a timer interrupt. It is also called in KDP context for stackshot.
39236c6e
A
1799 */
1800static int
1801proc_get_effective_policy(task_t task,
1802 thread_t thread,
1803 int flavor)
1804{
1805 boolean_t on_task = (thread == THREAD_NULL) ? TRUE : FALSE;
1806 int value = 0;
1807
1808 switch (flavor) {
1809 case TASK_POLICY_DARWIN_BG:
1810 /*
1811 * This backs the KPI call proc_pidbackgrounded to find
1812 * out if a pid is backgrounded,
1813 * as well as proc_get_effective_thread_policy.
1814 * Its main use is within the timer layer, as well as
1815 * prioritizing requests to the graphics system.
1816 * Returns 1 for background mode, 0 for normal mode
1817 */
1818 if (on_task)
1819 value = task->effective_policy.darwinbg;
1820 else
1821 value = (task->effective_policy.darwinbg ||
1822 thread->effective_policy.darwinbg) ? 1 : 0;
1823 break;
1824 case TASK_POLICY_IO:
1825 /*
1826 * The I/O system calls here to find out what throttling tier to apply to an operation.
fe8ab488
A
1827 * Returns THROTTLE_LEVEL_* values. Some userspace spinlock operations can apply
1828 * a temporary iotier override to make the I/O more aggressive to get the lock
1829 * owner to release the spinlock.
39236c6e
A
1830 */
1831 if (on_task)
1832 value = task->effective_policy.io_tier;
1833 else {
1834 value = MAX(task->effective_policy.io_tier,
1835 thread->effective_policy.io_tier);
1836 if (thread->iotier_override != THROTTLE_LEVEL_NONE)
1837 value = MIN(value, thread->iotier_override);
1838 }
1839 break;
1840 case TASK_POLICY_PASSIVE_IO:
1841 /*
1842 * The I/O system calls here to find out whether an operation should be passive.
1843 * (i.e. not cause operations with lower throttle tiers to be throttled)
fe8ab488
A
1844 * Returns 1 for passive mode, 0 for normal mode.
1845 * If a userspace spinlock has applied an override, that I/O should always
1846 * be passive to avoid self-throttling when the override is removed and lower
1847 * iotier I/Os are issued.
39236c6e
A
1848 */
1849 if (on_task)
1850 value = task->effective_policy.io_passive;
fe8ab488
A
1851 else {
1852 int io_tier = MAX(task->effective_policy.io_tier, thread->effective_policy.io_tier);
1853 boolean_t override_in_effect = (thread->iotier_override != THROTTLE_LEVEL_NONE) && (thread->iotier_override < io_tier);
1854
39236c6e 1855 value = (task->effective_policy.io_passive ||
fe8ab488
A
1856 thread->effective_policy.io_passive || override_in_effect) ? 1 : 0;
1857 }
1858 break;
1859 case TASK_POLICY_ALL_SOCKETS_BG:
1860 /*
1861 * do_background_socket() calls this to determine what it should do to the proc's sockets
1862 * Returns 1 for background mode, 0 for normal mode
1863 *
1864 * This consults both thread and task so un-DBGing a thread while the task is BG
1865 * doesn't get you out of the network throttle.
1866 */
1867 if (on_task)
1868 value = task->effective_policy.all_sockets_bg;
1869 else
1870 value = (task->effective_policy.all_sockets_bg ||
1871 thread->effective_policy.all_sockets_bg) ? 1 : 0;
39236c6e
A
1872 break;
1873 case TASK_POLICY_NEW_SOCKETS_BG:
1874 /*
1875 * socreate() calls this to determine if it should mark a new socket as background
1876 * Returns 1 for background mode, 0 for normal mode
1877 */
1878 if (on_task)
1879 value = task->effective_policy.new_sockets_bg;
1880 else
1881 value = (task->effective_policy.new_sockets_bg ||
1882 thread->effective_policy.new_sockets_bg) ? 1 : 0;
1883 break;
1884 case TASK_POLICY_LOWPRI_CPU:
1885 /*
1886 * Returns 1 for low priority cpu mode, 0 for normal mode
1887 */
1888 if (on_task)
1889 value = task->effective_policy.lowpri_cpu;
1890 else
1891 value = (task->effective_policy.lowpri_cpu ||
1892 thread->effective_policy.lowpri_cpu) ? 1 : 0;
1893 break;
1894 case TASK_POLICY_SUPPRESSED_CPU:
1895 /*
1896 * Returns 1 for suppressed cpu mode, 0 for normal mode
1897 */
1898 assert(on_task);
1899 value = task->effective_policy.t_suppressed_cpu;
1900 break;
1901 case TASK_POLICY_LATENCY_QOS:
1902 /*
1903 * timer arming calls into here to find out the timer coalescing level
1904 * Returns a QoS tier (0-6)
1905 */
fe8ab488
A
1906 if (on_task) {
1907 value = task->effective_policy.t_latency_qos;
1908 } else {
1909 value = MAX(task->effective_policy.t_latency_qos, thread->effective_policy.t_latency_qos);
1910 }
39236c6e
A
1911 break;
1912 case TASK_POLICY_THROUGH_QOS:
1913 /*
1914 * Returns a QoS tier (0-6)
1915 */
1916 assert(on_task);
1917 value = task->effective_policy.t_through_qos;
1918 break;
39236c6e
A
1919 case TASK_POLICY_ROLE:
1920 assert(on_task);
1921 value = task->effective_policy.t_role;
1922 break;
1923 case TASK_POLICY_WATCHERS_BG:
1924 assert(on_task);
1925 value = task->effective_policy.t_watchers_bg;
1926 break;
fe8ab488
A
1927 case TASK_POLICY_SFI_MANAGED:
1928 assert(on_task);
1929 value = task->effective_policy.t_sfi_managed;
1930 break;
1931 case TASK_POLICY_QOS:
1932 assert(!on_task);
1933 value = thread->effective_policy.thep_qos;
1934 break;
39236c6e
A
1935 default:
1936 panic("unknown policy_flavor %d", flavor);
1937 break;
316670eb
A
1938 }
1939
39236c6e 1940 return value;
6d2010ae
A
1941}
1942
39236c6e
A
1943/*
1944 * Convert from IOPOL_* values to throttle tiers.
1945 *
1946 * TODO: Can this be made more compact, like an array lookup
1947 * Note that it is possible to support e.g. IOPOL_PASSIVE_STANDARD in the future
1948 */
6d2010ae 1949
39236c6e
A
1950static void
1951proc_iopol_to_tier(int iopolicy, int *tier, int *passive)
6d2010ae 1952{
39236c6e
A
1953 *passive = 0;
1954 *tier = 0;
1955 switch (iopolicy) {
1956 case IOPOL_IMPORTANT:
1957 *tier = THROTTLE_LEVEL_TIER0;
1958 break;
1959 case IOPOL_PASSIVE:
1960 *tier = THROTTLE_LEVEL_TIER0;
1961 *passive = 1;
1962 break;
1963 case IOPOL_STANDARD:
1964 *tier = THROTTLE_LEVEL_TIER1;
1965 break;
1966 case IOPOL_UTILITY:
1967 *tier = THROTTLE_LEVEL_TIER2;
1968 break;
1969 case IOPOL_THROTTLE:
1970 *tier = THROTTLE_LEVEL_TIER3;
1971 break;
1972 default:
1973 panic("unknown I/O policy %d", iopolicy);
1974 break;
1975 }
6d2010ae
A
1976}
1977
1978static int
39236c6e 1979proc_tier_to_iopol(int tier, int passive)
6d2010ae 1980{
39236c6e
A
1981 if (passive == 1) {
1982 switch (tier) {
1983 case THROTTLE_LEVEL_TIER0:
1984 return IOPOL_PASSIVE;
1985 break;
1986 default:
1987 panic("unknown passive tier %d", tier);
1988 return IOPOL_DEFAULT;
1989 break;
6d2010ae 1990 }
39236c6e
A
1991 } else {
1992 switch (tier) {
1993 case THROTTLE_LEVEL_NONE:
39236c6e 1994 case THROTTLE_LEVEL_TIER0:
fe8ab488 1995 return IOPOL_DEFAULT;
39236c6e
A
1996 break;
1997 case THROTTLE_LEVEL_TIER1:
1998 return IOPOL_STANDARD;
1999 break;
2000 case THROTTLE_LEVEL_TIER2:
2001 return IOPOL_UTILITY;
2002 break;
2003 case THROTTLE_LEVEL_TIER3:
2004 return IOPOL_THROTTLE;
2005 break;
2006 default:
2007 panic("unknown tier %d", tier);
2008 return IOPOL_DEFAULT;
2009 break;
6d2010ae
A
2010 }
2011 }
39236c6e
A
2012}
2013
2014/* apply internal backgrounding for workqueue threads */
2015int
2016proc_apply_workq_bgthreadpolicy(thread_t thread)
2017{
2018 if (thread == THREAD_NULL)
2019 return ESRCH;
2020
2021 proc_set_task_policy(thread->task, thread, TASK_POLICY_ATTRIBUTE,
2022 TASK_POLICY_WORKQ_BG, TASK_POLICY_ENABLE);
6d2010ae
A
2023
2024 return(0);
2025}
2026
39236c6e
A
2027/*
2028 * remove internal backgrounding for workqueue threads
2029 * does NOT go find sockets created while BG and unbackground them
2030 */
2031int
6d2010ae
A
2032proc_restore_workq_bgthreadpolicy(thread_t thread)
2033{
39236c6e
A
2034 if (thread == THREAD_NULL)
2035 return ESRCH;
6d2010ae 2036
39236c6e
A
2037 proc_set_task_policy(thread->task, thread, TASK_POLICY_ATTRIBUTE,
2038 TASK_POLICY_WORKQ_BG, TASK_POLICY_DISABLE);
2039
2040 return(0);
6d2010ae
A
2041}
2042
39236c6e
A
2043/* here for temporary compatibility */
2044int
2045proc_setthread_saved_importance(__unused thread_t thread, __unused int importance)
6d2010ae 2046{
39236c6e 2047 return(0);
6d2010ae
A
2048}
2049
39236c6e
A
2050/*
2051 * Set an override on the thread which is consulted with a
2052 * higher priority than the task/thread policy. This should
2053 * only be set for temporary grants until the thread
2054 * returns to the userspace boundary
2055 *
2056 * We use atomic operations to swap in the override, with
2057 * the assumption that the thread itself can
2058 * read the override and clear it on return to userspace.
2059 *
2060 * No locking is performed, since it is acceptable to see
2061 * a stale override for one loop through throttle_lowpri_io().
2062 * However a thread reference must be held on the thread.
2063 */
316670eb 2064
39236c6e
A
2065void set_thread_iotier_override(thread_t thread, int policy)
2066{
2067 int current_override;
6d2010ae 2068
39236c6e
A
2069 /* Let most aggressive I/O policy win until user boundary */
2070 do {
2071 current_override = thread->iotier_override;
316670eb 2072
39236c6e
A
2073 if (current_override != THROTTLE_LEVEL_NONE)
2074 policy = MIN(current_override, policy);
6d2010ae 2075
39236c6e
A
2076 if (current_override == policy) {
2077 /* no effective change */
2078 return;
316670eb 2079 }
39236c6e 2080 } while (!OSCompareAndSwap(current_override, policy, &thread->iotier_override));
6d2010ae 2081
39236c6e
A
2082 /*
2083 * Since the thread may be currently throttled,
2084 * re-evaluate tiers and potentially break out
2085 * of an msleep
2086 */
2087 rethrottle_thread(thread->uthread);
6d2010ae
A
2088}
2089
39236c6e 2090/*
fe8ab488
A
2091 * Userspace synchronization routines (like pthread mutexes, pthread reader-writer locks,
2092 * semaphores, dispatch_sync) may result in priority inversions where a higher priority
2093 * (i.e. scheduler priority, I/O tier, QoS tier) is waiting on a resource owned by a lower
2094 * priority thread. In these cases, we attempt to propagate the priority token, as long
2095 * as the subsystem informs us of the relationships between the threads. The userspace
2096 * synchronization subsystem should maintain the information of owner->resource and
2097 * resource->waiters itself.
2098 *
2099 * The add/remove routines can return failure if the target of the override cannot be
2100 * found, perhaps because the resource subsystem doesn't have an accurate view of the
2101 * resource owner in the face of race conditions.
39236c6e 2102 */
fe8ab488
A
2103
2104boolean_t proc_thread_qos_add_override(task_t task, thread_t thread, uint64_t tid, int override_qos, boolean_t first_override_for_resource)
2105{
2106 thread_t self = current_thread();
2107 int resource_count;
2108 struct task_pend_token pend_token = {};
2109
2110 /* XXX move to thread mutex when thread policy does */
2111 task_lock(task);
2112
2113 /*
2114 * If thread is passed, it is assumed to be most accurate, since the caller must have an explicit (or implicit) reference
2115 * to the thread
2116 */
2117
2118 if (thread != THREAD_NULL) {
2119 assert(task == thread->task);
2120 } else {
2121 if (tid == self->thread_id) {
2122 thread = self;
2123 } else {
2124 thread = task_findtid(task, tid);
2125
2126 if (thread == THREAD_NULL) {
2127 KERNEL_DEBUG_CONSTANT((IMPORTANCE_CODE(IMP_USYNCH_QOS_OVERRIDE, IMP_USYNCH_ADD_OVERRIDE)) | DBG_FUNC_NONE,
2128 tid, 0, 0xdead, 0, 0);
2129 task_unlock(task);
2130 return FALSE;
2131 }
2132 }
2133 }
2134
2135 KERNEL_DEBUG_CONSTANT((IMPORTANCE_CODE(IMP_USYNCH_QOS_OVERRIDE, IMP_USYNCH_ADD_OVERRIDE)) | DBG_FUNC_START,
2136 thread_tid(thread), override_qos, first_override_for_resource ? 1 : 0, 0, 0);
2137
2138 DTRACE_BOOST5(qos_add_override_pre, uint64_t, tid, uint64_t, thread->requested_policy.thrp_qos,
2139 uint64_t, thread->effective_policy.thep_qos, int, override_qos, boolean_t, first_override_for_resource);
2140
2141 if (first_override_for_resource) {
2142 resource_count = ++thread->usynch_override_contended_resource_count;
2143 } else {
2144 resource_count = thread->usynch_override_contended_resource_count;
2145 }
2146
2147 struct task_requested_policy requested = thread->requested_policy;
2148
2149 if (requested.thrp_qos_override == THREAD_QOS_UNSPECIFIED)
2150 requested.thrp_qos_override = override_qos;
2151 else
2152 requested.thrp_qos_override = MAX(requested.thrp_qos_override, override_qos);
2153
2154 thread->requested_policy = requested;
2155
2156 task_policy_update_locked(task, thread, &pend_token);
2157
2158 thread_reference(thread);
2159
2160 task_unlock(task);
2161
2162 task_policy_update_complete_unlocked(task, thread, &pend_token);
2163
2164 DTRACE_BOOST3(qos_add_override_post, uint64_t, requested.thrp_qos_override,
2165 uint64_t, thread->effective_policy.thep_qos, int, resource_count);
2166
2167 thread_deallocate(thread);
2168
2169 KERNEL_DEBUG_CONSTANT((IMPORTANCE_CODE(IMP_USYNCH_QOS_OVERRIDE, IMP_USYNCH_ADD_OVERRIDE)) | DBG_FUNC_END,
2170 requested.thrp_qos_override, resource_count, 0, 0, 0);
2171
2172 return TRUE;
2173}
2174
2175boolean_t proc_thread_qos_remove_override(task_t task, thread_t thread, uint64_t tid)
6d2010ae 2176{
fe8ab488
A
2177 thread_t self = current_thread();
2178 int resource_count;
2179 struct task_pend_token pend_token = {};
2180
2181 /* XXX move to thread mutex when thread policy does */
39236c6e 2182 task_lock(task);
6d2010ae 2183
fe8ab488
A
2184 /*
2185 * If thread is passed, it is assumed to be most accurate, since the caller must have an explicit (or implicit) reference
2186 * to the thread
2187 */
2188 if (thread != THREAD_NULL) {
2189 assert(task == thread->task);
2190 } else {
2191 if (tid == self->thread_id) {
2192 thread = self;
2193 } else {
2194 thread = task_findtid(task, tid);
2195
2196 if (thread == THREAD_NULL) {
2197 KERNEL_DEBUG_CONSTANT((IMPORTANCE_CODE(IMP_USYNCH_QOS_OVERRIDE, IMP_USYNCH_REMOVE_OVERRIDE)) | DBG_FUNC_NONE,
2198 tid, 0, 0xdead, 0, 0);
2199 task_unlock(task);
2200 return FALSE;
2201 }
2202 }
2203 }
2204
2205 resource_count = --thread->usynch_override_contended_resource_count;
2206
2207 KERNEL_DEBUG_CONSTANT((IMPORTANCE_CODE(IMP_USYNCH_QOS_OVERRIDE, IMP_USYNCH_REMOVE_OVERRIDE)) | DBG_FUNC_START,
2208 thread_tid(thread), resource_count, 0, 0, 0);
2209
2210 if (0 == resource_count) {
2211 thread->requested_policy.thrp_qos_override = THREAD_QOS_UNSPECIFIED;
2212
2213 task_policy_update_locked(task, thread, &pend_token);
2214
2215 thread_reference(thread);
2216
2217 task_unlock(task);
2218
2219 task_policy_update_complete_unlocked(task, thread, &pend_token);
2220
2221 thread_deallocate(thread);
2222 } else if (0 > resource_count) {
2223 // panic("usynch_override_contended_resource_count underflow for thread %p", thread);
2224 task_unlock(task);
2225 } else {
2226 task_unlock(task);
2227 }
2228
2229 KERNEL_DEBUG_CONSTANT((IMPORTANCE_CODE(IMP_USYNCH_QOS_OVERRIDE, IMP_USYNCH_REMOVE_OVERRIDE)) | DBG_FUNC_END,
2230 0, 0, 0, 0, 0);
2231
2232 return TRUE;
2233}
2234
2235/* TODO: remove this variable when interactive daemon audit period is over */
2236extern boolean_t ipc_importance_interactive_receiver;
2237
2238/*
2239 * Called at process exec to initialize the apptype, qos clamp, and qos seed of a process
2240 *
2241 * TODO: Make this function more table-driven instead of ad-hoc
2242 */
2243void
2244proc_set_task_spawnpolicy(task_t task, int apptype, int qos_clamp,
2245 ipc_port_t * portwatch_ports, int portwatch_count)
2246{
2247 struct task_pend_token pend_token = {};
2248
39236c6e 2249 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
fe8ab488
A
2250 (IMPORTANCE_CODE(IMP_TASK_APPTYPE, apptype)) | DBG_FUNC_START,
2251 audit_token_pid_from_task(task), trequested_0(task, THREAD_NULL), trequested_1(task, THREAD_NULL),
2252 apptype, 0);
316670eb 2253
39236c6e
A
2254 switch (apptype) {
2255 case TASK_APPTYPE_APP_TAL:
39236c6e 2256 case TASK_APPTYPE_APP_DEFAULT:
fe8ab488
A
2257 /* Apps become donors via the 'live-donor' flag instead of the static donor flag */
2258 task_importance_mark_donor(task, FALSE);
2259 task_importance_mark_live_donor(task, TRUE);
2260 task_importance_mark_receiver(task, FALSE);
2261 /* Apps are de-nap recievers on desktop for suppression behaviors */
2262 task_importance_mark_denap_receiver(task, TRUE);
2263 break;
316670eb 2264
fe8ab488 2265 case TASK_APPTYPE_DAEMON_INTERACTIVE:
39236c6e 2266 task_importance_mark_donor(task, TRUE);
fe8ab488
A
2267 task_importance_mark_live_donor(task, FALSE);
2268
2269 /*
2270 * A boot arg controls whether interactive daemons are importance receivers.
2271 * Normally, they are not. But for testing their behavior as an adaptive
2272 * daemon, the boot-arg can be set.
2273 *
2274 * TODO: remove this when the interactive daemon audit period is over.
2275 */
2276 task_importance_mark_receiver(task, /* FALSE */ ipc_importance_interactive_receiver);
2277 task_importance_mark_denap_receiver(task, FALSE);
6d2010ae
A
2278 break;
2279
39236c6e 2280 case TASK_APPTYPE_DAEMON_STANDARD:
39236c6e 2281 task_importance_mark_donor(task, TRUE);
fe8ab488 2282 task_importance_mark_live_donor(task, FALSE);
39236c6e 2283 task_importance_mark_receiver(task, FALSE);
fe8ab488 2284 task_importance_mark_denap_receiver(task, FALSE);
6d2010ae 2285 break;
39236c6e
A
2286
2287 case TASK_APPTYPE_DAEMON_ADAPTIVE:
39236c6e 2288 task_importance_mark_donor(task, FALSE);
fe8ab488 2289 task_importance_mark_live_donor(task, FALSE);
39236c6e 2290 task_importance_mark_receiver(task, TRUE);
fe8ab488 2291 task_importance_mark_denap_receiver(task, FALSE);
316670eb
A
2292 break;
2293
39236c6e 2294 case TASK_APPTYPE_DAEMON_BACKGROUND:
39236c6e 2295 task_importance_mark_donor(task, FALSE);
fe8ab488 2296 task_importance_mark_live_donor(task, FALSE);
39236c6e 2297 task_importance_mark_receiver(task, FALSE);
fe8ab488 2298 task_importance_mark_denap_receiver(task, FALSE);
316670eb 2299 break;
6d2010ae 2300
fe8ab488
A
2301 case TASK_APPTYPE_NONE:
2302 break;
2303 }
2304
2305 if (portwatch_ports != NULL && apptype == TASK_APPTYPE_DAEMON_ADAPTIVE) {
2306 int portwatch_boosts = 0;
2307
2308 for (int i = 0; i < portwatch_count; i++) {
2309 ipc_port_t port = NULL;
2310
2311 if ((port = portwatch_ports[i]) != NULL) {
2312 int boost = 0;
2313 task_add_importance_watchport(task, port, &boost);
2314 portwatch_boosts += boost;
2315 }
2316 }
2317
2318 if (portwatch_boosts > 0) {
2319 task_importance_hold_internal_assertion(task, portwatch_boosts);
2320 }
2321 }
2322
2323 task_lock(task);
2324
2325 if (apptype == TASK_APPTYPE_APP_TAL) {
2326 /* TAL starts off enabled by default */
2327 task->requested_policy.t_tal_enabled = 1;
2328 }
2329
2330 if (apptype != TASK_APPTYPE_NONE) {
2331 task->requested_policy.t_apptype = apptype;
2332
2333 }
2334
2335 if (qos_clamp != THREAD_QOS_UNSPECIFIED) {
2336 task->requested_policy.t_qos_clamp = qos_clamp;
2337 }
2338
2339 task_policy_update_locked(task, THREAD_NULL, &pend_token);
2340
2341 task_unlock(task);
2342
2343 /* Ensure the donor bit is updated to be in sync with the new live donor status */
2344 pend_token.tpt_update_live_donor = 1;
2345
2346 task_policy_update_complete_unlocked(task, THREAD_NULL, &pend_token);
2347
2348 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
2349 (IMPORTANCE_CODE(IMP_TASK_APPTYPE, apptype)) | DBG_FUNC_END,
2350 audit_token_pid_from_task(task), trequested_0(task, THREAD_NULL), trequested_1(task, THREAD_NULL),
2351 task_is_importance_receiver(task), 0);
2352}
2353
2354/* Set up the primordial thread's QoS */
2355void
2356task_set_main_thread_qos(task_t task, thread_t main_thread) {
2357 struct task_pend_token pend_token = {};
2358
2359 assert(main_thread->task == task);
2360
2361 task_lock(task);
2362
2363 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
2364 (IMPORTANCE_CODE(IMP_MAIN_THREAD_QOS, 0)) | DBG_FUNC_START,
2365 audit_token_pid_from_task(task), trequested_0(task, THREAD_NULL), trequested_1(task, THREAD_NULL),
2366 main_thread->requested_policy.thrp_qos, 0);
2367
2368 int primordial_qos = THREAD_QOS_UNSPECIFIED;
2369
2370 int qos_clamp = task->requested_policy.t_qos_clamp;
2371
2372 switch (task->requested_policy.t_apptype) {
2373 case TASK_APPTYPE_APP_TAL:
2374 case TASK_APPTYPE_APP_DEFAULT:
2375 primordial_qos = THREAD_QOS_USER_INTERACTIVE;
2376 break;
2377
2378 case TASK_APPTYPE_DAEMON_INTERACTIVE:
2379 case TASK_APPTYPE_DAEMON_STANDARD:
2380 case TASK_APPTYPE_DAEMON_ADAPTIVE:
2381 primordial_qos = THREAD_QOS_LEGACY;
2382 break;
2383
2384 case TASK_APPTYPE_DAEMON_BACKGROUND:
2385 primordial_qos = THREAD_QOS_BACKGROUND;
6d2010ae
A
2386 break;
2387 }
39236c6e 2388
fe8ab488
A
2389 if (qos_clamp != THREAD_QOS_UNSPECIFIED) {
2390 if (primordial_qos != THREAD_QOS_UNSPECIFIED) {
2391 primordial_qos = MIN(qos_clamp, primordial_qos);
2392 } else {
2393 primordial_qos = qos_clamp;
2394 }
2395 }
2396
2397 main_thread->requested_policy.thrp_qos = primordial_qos;
2398
2399 task_policy_update_locked(task, main_thread, &pend_token);
39236c6e
A
2400
2401 task_unlock(task);
2402
fe8ab488 2403 task_policy_update_complete_unlocked(task, main_thread, &pend_token);
39236c6e
A
2404
2405 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
fe8ab488
A
2406 (IMPORTANCE_CODE(IMP_MAIN_THREAD_QOS, 0)) | DBG_FUNC_END,
2407 audit_token_pid_from_task(task), trequested_0(task, THREAD_NULL), trequested_1(task, THREAD_NULL),
2408 primordial_qos, 0);
39236c6e
A
2409}
2410
2411/* for process_policy to check before attempting to set */
2412boolean_t
2413proc_task_is_tal(task_t task)
2414{
2415 return (task->requested_policy.t_apptype == TASK_APPTYPE_APP_TAL) ? TRUE : FALSE;
6d2010ae
A
2416}
2417
39236c6e
A
2418/* for telemetry */
2419integer_t
2420task_grab_latency_qos(task_t task)
2421{
fe8ab488 2422 return qos_latency_policy_package(proc_get_effective_task_policy(task, TASK_POLICY_LATENCY_QOS));
39236c6e 2423}
6d2010ae 2424
39236c6e 2425/* update the darwin background action state in the flags field for libproc */
6d2010ae
A
2426int
2427proc_get_darwinbgstate(task_t task, uint32_t * flagsp)
2428{
39236c6e 2429 if (task->requested_policy.ext_darwinbg)
6d2010ae 2430 *flagsp |= PROC_FLAG_EXT_DARWINBG;
39236c6e
A
2431
2432 if (task->requested_policy.int_darwinbg)
6d2010ae 2433 *flagsp |= PROC_FLAG_DARWINBG;
6d2010ae 2434
6d2010ae 2435
fe8ab488
A
2436 if (task->requested_policy.t_apptype == TASK_APPTYPE_APP_DEFAULT ||
2437 task->requested_policy.t_apptype == TASK_APPTYPE_APP_TAL)
2438 *flagsp |= PROC_FLAG_APPLICATION;
2439
39236c6e
A
2440 if (task->requested_policy.t_apptype == TASK_APPTYPE_DAEMON_ADAPTIVE)
2441 *flagsp |= PROC_FLAG_ADAPTIVE;
6d2010ae 2442
39236c6e
A
2443 if (task->requested_policy.t_apptype == TASK_APPTYPE_DAEMON_ADAPTIVE && task->requested_policy.t_boosted == 1)
2444 *flagsp |= PROC_FLAG_ADAPTIVE_IMPORTANT;
316670eb 2445
fe8ab488 2446 if (task_is_importance_donor(task))
39236c6e 2447 *flagsp |= PROC_FLAG_IMPORTANCE_DONOR;
316670eb 2448
39236c6e
A
2449 if (task->effective_policy.t_sup_active)
2450 *flagsp |= PROC_FLAG_SUPPRESSED;
316670eb 2451
39236c6e
A
2452 return(0);
2453}
316670eb 2454
39236c6e
A
2455/* All per-thread state is in the first 32-bits of the bitfield */
2456void
2457proc_get_thread_policy(thread_t thread, thread_policy_state_t info)
316670eb 2458{
39236c6e
A
2459 task_t task = thread->task;
2460 task_lock(task);
2461 info->requested = (integer_t)task_requested_bitfield(task, thread);
2462 info->effective = (integer_t)task_effective_bitfield(task, thread);
fe8ab488 2463 info->pending = 0;
39236c6e 2464 task_unlock(task);
6d2010ae
A
2465}
2466
fe8ab488
A
2467/*
2468 * Tracepoint data... Reading the tracepoint data can be somewhat complicated.
2469 * The current scheme packs as much data into a single tracepoint as it can.
2470 *
2471 * Each task/thread requested/effective structure is 64 bits in size. Any
2472 * given tracepoint will emit either requested or effective data, but not both.
2473 *
2474 * A tracepoint may emit any of task, thread, or task & thread data.
2475 *
2476 * The type of data emitted varies with pointer size. Where possible, both
2477 * task and thread data are emitted. In LP32 systems, the first and second
2478 * halves of either the task or thread data is emitted.
2479 *
2480 * The code uses uintptr_t array indexes instead of high/low to avoid
2481 * confusion WRT big vs little endian.
2482 *
2483 * The truth table for the tracepoint data functions is below, and has the
2484 * following invariants:
2485 *
2486 * 1) task and thread are uintptr_t*
2487 * 2) task may never be NULL
2488 *
2489 *
2490 * LP32 LP64
2491 * trequested_0(task, NULL) task[0] task[0]
2492 * trequested_1(task, NULL) task[1] NULL
2493 * trequested_0(task, thread) thread[0] task[0]
2494 * trequested_1(task, thread) thread[1] thread[0]
2495 *
2496 * Basically, you get a full task or thread on LP32, and both on LP64.
2497 *
2498 * The uintptr_t munging here is squicky enough to deserve a comment.
2499 *
2500 * The variables we are accessing are laid out in memory like this:
2501 *
2502 * [ LP64 uintptr_t 0 ]
2503 * [ LP32 uintptr_t 0 ] [ LP32 uintptr_t 1 ]
2504 *
2505 * 1 2 3 4 5 6 7 8
2506 *
2507 */
316670eb 2508
39236c6e 2509static uintptr_t
fe8ab488 2510trequested_0(task_t task, thread_t thread)
6d2010ae 2511{
fe8ab488
A
2512 assert(task);
2513 _Static_assert(sizeof(struct task_requested_policy) == sizeof(uint64_t), "size invariant violated");
2514 _Static_assert(sizeof(task->requested_policy) == sizeof(thread->requested_policy), "size invariant violated");
2515
2516 uintptr_t* raw = (uintptr_t*)((thread == THREAD_NULL) ? &task->requested_policy : &thread->requested_policy);
2517 return raw[0];
6d2010ae
A
2518}
2519
39236c6e 2520static uintptr_t
fe8ab488 2521trequested_1(task_t task, thread_t thread)
6d2010ae 2522{
fe8ab488
A
2523 assert(task);
2524 _Static_assert(sizeof(struct task_requested_policy) == sizeof(uint64_t), "size invariant violated");
2525 _Static_assert(sizeof(task->requested_policy) == sizeof(thread->requested_policy), "size invariant violated");
2526
2527#if defined __LP64__
2528 return (thread == NULL) ? 0 : *(uintptr_t*)&thread->requested_policy;
2529#else
2530 uintptr_t* raw = (uintptr_t*)((thread == THREAD_NULL) ? &task->requested_policy : &thread->requested_policy);
2531 return raw[1];
2532#endif
6d2010ae
A
2533}
2534
39236c6e 2535static uintptr_t
fe8ab488 2536teffective_0(task_t task, thread_t thread)
6d2010ae 2537{
fe8ab488
A
2538 assert(task);
2539 _Static_assert(sizeof(struct task_effective_policy) == sizeof(uint64_t), "size invariant violated");
2540 _Static_assert(sizeof(task->effective_policy) == sizeof(thread->effective_policy), "size invariant violated");
2541
2542 uintptr_t* raw = (uintptr_t*)((thread == THREAD_NULL) ? &task->effective_policy : &thread->effective_policy);
2543 return raw[0];
2544}
2545
2546static uintptr_t
2547teffective_1(task_t task, thread_t thread)
2548{
2549 assert(task);
2550 _Static_assert(sizeof(struct task_effective_policy) == sizeof(uint64_t), "size invariant violated");
2551 _Static_assert(sizeof(task->effective_policy) == sizeof(thread->effective_policy), "size invariant violated");
2552
2553#if defined __LP64__
2554 return (thread == NULL) ? 0 : *(uintptr_t*)&thread->effective_policy;
2555#else
2556 uintptr_t* raw = (uintptr_t*)((thread == THREAD_NULL) ? &task->effective_policy : &thread->effective_policy);
2557 return raw[1];
2558#endif
6d2010ae
A
2559}
2560
fe8ab488
A
2561/* dump pending for tracepoint */
2562static uint32_t tpending(task_pend_token_t pend_token) { return *(uint32_t*)(void*)(pend_token); }
2563
39236c6e
A
2564uint64_t
2565task_requested_bitfield(task_t task, thread_t thread)
6d2010ae 2566{
39236c6e
A
2567 uint64_t bits = 0;
2568 struct task_requested_policy requested =
2569 (thread == THREAD_NULL) ? task->requested_policy : thread->requested_policy;
6d2010ae 2570
39236c6e
A
2571 bits |= (requested.int_darwinbg ? POLICY_REQ_INT_DARWIN_BG : 0);
2572 bits |= (requested.ext_darwinbg ? POLICY_REQ_EXT_DARWIN_BG : 0);
2573 bits |= (requested.int_iotier ? (((uint64_t)requested.int_iotier) << POLICY_REQ_INT_IO_TIER_SHIFT) : 0);
2574 bits |= (requested.ext_iotier ? (((uint64_t)requested.ext_iotier) << POLICY_REQ_EXT_IO_TIER_SHIFT) : 0);
2575 bits |= (requested.int_iopassive ? POLICY_REQ_INT_PASSIVE_IO : 0);
2576 bits |= (requested.ext_iopassive ? POLICY_REQ_EXT_PASSIVE_IO : 0);
2577 bits |= (requested.bg_iotier ? (((uint64_t)requested.bg_iotier) << POLICY_REQ_BG_IOTIER_SHIFT) : 0);
2578 bits |= (requested.terminated ? POLICY_REQ_TERMINATED : 0);
6d2010ae 2579
39236c6e
A
2580 bits |= (requested.th_pidbind_bg ? POLICY_REQ_PIDBIND_BG : 0);
2581 bits |= (requested.th_workq_bg ? POLICY_REQ_WORKQ_BG : 0);
316670eb 2582
fe8ab488
A
2583 if (thread != THREAD_NULL) {
2584 bits |= (requested.thrp_qos ? (((uint64_t)requested.thrp_qos) << POLICY_REQ_TH_QOS_SHIFT) : 0);
2585 bits |= (requested.thrp_qos_override ? (((uint64_t)requested.thrp_qos_override) << POLICY_REQ_TH_QOS_OVER_SHIFT) : 0);
2586 }
2587
39236c6e
A
2588 bits |= (requested.t_boosted ? POLICY_REQ_BOOSTED : 0);
2589 bits |= (requested.t_tal_enabled ? POLICY_REQ_TAL_ENABLED : 0);
39236c6e
A
2590 bits |= (requested.t_apptype ? (((uint64_t)requested.t_apptype) << POLICY_REQ_APPTYPE_SHIFT) : 0);
2591 bits |= (requested.t_role ? (((uint64_t)requested.t_role) << POLICY_REQ_ROLE_SHIFT) : 0);
316670eb 2592
39236c6e
A
2593 bits |= (requested.t_sup_active ? POLICY_REQ_SUP_ACTIVE : 0);
2594 bits |= (requested.t_sup_lowpri_cpu ? POLICY_REQ_SUP_LOWPRI_CPU : 0);
2595 bits |= (requested.t_sup_cpu ? POLICY_REQ_SUP_CPU : 0);
2596 bits |= (requested.t_sup_timer ? (((uint64_t)requested.t_sup_timer) << POLICY_REQ_SUP_TIMER_THROTTLE_SHIFT) : 0);
2597 bits |= (requested.t_sup_throughput ? (((uint64_t)requested.t_sup_throughput) << POLICY_REQ_SUP_THROUGHPUT_SHIFT) : 0);
2598 bits |= (requested.t_sup_disk ? POLICY_REQ_SUP_DISK_THROTTLE : 0);
2599 bits |= (requested.t_sup_cpu_limit ? POLICY_REQ_SUP_CPU_LIMIT : 0);
2600 bits |= (requested.t_sup_suspend ? POLICY_REQ_SUP_SUSPEND : 0);
fe8ab488 2601 bits |= (requested.t_sup_bg_sockets ? POLICY_REQ_SUP_BG_SOCKETS : 0);
39236c6e
A
2602 bits |= (requested.t_base_latency_qos ? (((uint64_t)requested.t_base_latency_qos) << POLICY_REQ_BASE_LATENCY_QOS_SHIFT) : 0);
2603 bits |= (requested.t_over_latency_qos ? (((uint64_t)requested.t_over_latency_qos) << POLICY_REQ_OVER_LATENCY_QOS_SHIFT) : 0);
2604 bits |= (requested.t_base_through_qos ? (((uint64_t)requested.t_base_through_qos) << POLICY_REQ_BASE_THROUGH_QOS_SHIFT) : 0);
2605 bits |= (requested.t_over_through_qos ? (((uint64_t)requested.t_over_through_qos) << POLICY_REQ_OVER_THROUGH_QOS_SHIFT) : 0);
fe8ab488
A
2606 bits |= (requested.t_sfi_managed ? POLICY_REQ_SFI_MANAGED : 0);
2607 bits |= (requested.t_qos_clamp ? (((uint64_t)requested.t_qos_clamp) << POLICY_REQ_QOS_CLAMP_SHIFT) : 0);
316670eb 2608
39236c6e 2609 return bits;
316670eb
A
2610}
2611
39236c6e
A
2612uint64_t
2613task_effective_bitfield(task_t task, thread_t thread)
2614{
2615 uint64_t bits = 0;
2616 struct task_effective_policy effective =
2617 (thread == THREAD_NULL) ? task->effective_policy : thread->effective_policy;
316670eb 2618
39236c6e
A
2619 bits |= (effective.io_tier ? (((uint64_t)effective.io_tier) << POLICY_EFF_IO_TIER_SHIFT) : 0);
2620 bits |= (effective.io_passive ? POLICY_EFF_IO_PASSIVE : 0);
2621 bits |= (effective.darwinbg ? POLICY_EFF_DARWIN_BG : 0);
2622 bits |= (effective.lowpri_cpu ? POLICY_EFF_LOWPRI_CPU : 0);
2623 bits |= (effective.terminated ? POLICY_EFF_TERMINATED : 0);
2624 bits |= (effective.all_sockets_bg ? POLICY_EFF_ALL_SOCKETS_BG : 0);
2625 bits |= (effective.new_sockets_bg ? POLICY_EFF_NEW_SOCKETS_BG : 0);
2626 bits |= (effective.bg_iotier ? (((uint64_t)effective.bg_iotier) << POLICY_EFF_BG_IOTIER_SHIFT) : 0);
fe8ab488
A
2627 bits |= (effective.qos_ui_is_urgent ? POLICY_EFF_QOS_UI_IS_URGENT : 0);
2628
2629 if (thread != THREAD_NULL)
2630 bits |= (effective.thep_qos ? (((uint64_t)effective.thep_qos) << POLICY_EFF_TH_QOS_SHIFT) : 0);
316670eb 2631
39236c6e
A
2632 bits |= (effective.t_tal_engaged ? POLICY_EFF_TAL_ENGAGED : 0);
2633 bits |= (effective.t_suspended ? POLICY_EFF_SUSPENDED : 0);
2634 bits |= (effective.t_watchers_bg ? POLICY_EFF_WATCHERS_BG : 0);
2635 bits |= (effective.t_sup_active ? POLICY_EFF_SUP_ACTIVE : 0);
2636 bits |= (effective.t_suppressed_cpu ? POLICY_EFF_SUP_CPU : 0);
2637 bits |= (effective.t_role ? (((uint64_t)effective.t_role) << POLICY_EFF_ROLE_SHIFT) : 0);
2638 bits |= (effective.t_latency_qos ? (((uint64_t)effective.t_latency_qos) << POLICY_EFF_LATENCY_QOS_SHIFT) : 0);
2639 bits |= (effective.t_through_qos ? (((uint64_t)effective.t_through_qos) << POLICY_EFF_THROUGH_QOS_SHIFT) : 0);
fe8ab488
A
2640 bits |= (effective.t_sfi_managed ? POLICY_EFF_SFI_MANAGED : 0);
2641 bits |= (effective.t_qos_ceiling ? (((uint64_t)effective.t_qos_ceiling) << POLICY_EFF_QOS_CEILING_SHIFT) : 0);
6d2010ae 2642
39236c6e 2643 return bits;
6d2010ae
A
2644}
2645
6d2010ae 2646
39236c6e
A
2647/*
2648 * Resource usage and CPU related routines
2649 */
6d2010ae 2650
6d2010ae 2651int
39236c6e 2652proc_get_task_ruse_cpu(task_t task, uint32_t *policyp, uint8_t *percentagep, uint64_t *intervalp, uint64_t *deadlinep)
6d2010ae
A
2653{
2654
2655 int error = 0;
39236c6e 2656 int scope;
6d2010ae
A
2657
2658 task_lock(task);
39236c6e 2659
6d2010ae 2660
39236c6e
A
2661 error = task_get_cpuusage(task, percentagep, intervalp, deadlinep, &scope);
2662 task_unlock(task);
2663
2664 /*
2665 * Reverse-map from CPU resource limit scopes back to policies (see comment below).
2666 */
2667 if (scope == TASK_RUSECPU_FLAGS_PERTHR_LIMIT) {
2668 *policyp = TASK_POLICY_RESOURCE_ATTRIBUTE_NOTIFY_EXC;
2669 } else if (scope == TASK_RUSECPU_FLAGS_PROC_LIMIT) {
2670 *policyp = TASK_POLICY_RESOURCE_ATTRIBUTE_THROTTLE;
2671 } else if (scope == TASK_RUSECPU_FLAGS_DEADLINE) {
2672 *policyp = TASK_POLICY_RESOURCE_ATTRIBUTE_NONE;
2673 }
6d2010ae
A
2674
2675 return(error);
2676}
2677
39236c6e
A
2678/*
2679 * Configure the default CPU usage monitor parameters.
2680 *
2681 * For tasks which have this mechanism activated: if any thread in the
2682 * process consumes more CPU than this, an EXC_RESOURCE exception will be generated.
2683 */
2684void
2685proc_init_cpumon_params(void)
2686{
2687 if (!PE_parse_boot_argn("max_cpumon_percentage", &proc_max_cpumon_percentage,
2688 sizeof (proc_max_cpumon_percentage))) {
2689 proc_max_cpumon_percentage = DEFAULT_CPUMON_PERCENTAGE;
2690 }
2691
2692 if (proc_max_cpumon_percentage > 100) {
2693 proc_max_cpumon_percentage = 100;
2694 }
2695
2696 /* The interval should be specified in seconds. */
2697 if (!PE_parse_boot_argn("max_cpumon_interval", &proc_max_cpumon_interval,
2698 sizeof (proc_max_cpumon_interval))) {
2699 proc_max_cpumon_interval = DEFAULT_CPUMON_INTERVAL;
2700 }
2701
2702 proc_max_cpumon_interval *= NSEC_PER_SEC;
fe8ab488
A
2703
2704 /* TEMPORARY boot arg to control App suppression */
2705 PE_parse_boot_argn("task_policy_suppression_disable",
2706 &task_policy_suppression_disable,
2707 sizeof(task_policy_suppression_disable));
39236c6e
A
2708}
2709
316670eb
A
2710/*
2711 * Currently supported configurations for CPU limits.
2712 *
39236c6e
A
2713 * Policy | Deadline-based CPU limit | Percentage-based CPU limit
2714 * -------------------------------------+--------------------------+------------------------------
2715 * PROC_POLICY_RSRCACT_THROTTLE | ENOTSUP | Task-wide scope only
2716 * PROC_POLICY_RSRCACT_SUSPEND | Task-wide scope only | ENOTSUP
2717 * PROC_POLICY_RSRCACT_TERMINATE | Task-wide scope only | ENOTSUP
2718 * PROC_POLICY_RSRCACT_NOTIFY_KQ | Task-wide scope only | ENOTSUP
2719 * PROC_POLICY_RSRCACT_NOTIFY_EXC | ENOTSUP | Per-thread scope only
316670eb
A
2720 *
2721 * A deadline-based CPU limit is actually a simple wallclock timer - the requested action is performed
2722 * after the specified amount of wallclock time has elapsed.
2723 *
2724 * A percentage-based CPU limit performs the requested action after the specified amount of actual CPU time
2725 * has been consumed -- regardless of how much wallclock time has elapsed -- by either the task as an
2726 * aggregate entity (so-called "Task-wide" or "Proc-wide" scope, whereby the CPU time consumed by all threads
2727 * in the task are added together), or by any one thread in the task (so-called "per-thread" scope).
2728 *
2729 * We support either deadline != 0 OR percentage != 0, but not both. The original intention in having them
2730 * share an API was to use actual CPU time as the basis of the deadline-based limit (as in: perform an action
2731 * after I have used some amount of CPU time; this is different than the recurring percentage/interval model)
2732 * but the potential consumer of the API at the time was insisting on wallclock time instead.
2733 *
2734 * Currently, requesting notification via an exception is the only way to get per-thread scope for a
2735 * CPU limit. All other types of notifications force task-wide scope for the limit.
2736 */
6d2010ae 2737int
39236c6e
A
2738proc_set_task_ruse_cpu(task_t task, uint32_t policy, uint8_t percentage, uint64_t interval, uint64_t deadline,
2739 int cpumon_entitled)
6d2010ae
A
2740{
2741 int error = 0;
316670eb
A
2742 int scope;
2743
2744 /*
2745 * Enforce the matrix of supported configurations for policy, percentage, and deadline.
2746 */
2747 switch (policy) {
2748 // If no policy is explicitly given, the default is to throttle.
2749 case TASK_POLICY_RESOURCE_ATTRIBUTE_NONE:
2750 case TASK_POLICY_RESOURCE_ATTRIBUTE_THROTTLE:
2751 if (deadline != 0)
2752 return (ENOTSUP);
2753 scope = TASK_RUSECPU_FLAGS_PROC_LIMIT;
2754 break;
2755 case TASK_POLICY_RESOURCE_ATTRIBUTE_SUSPEND:
2756 case TASK_POLICY_RESOURCE_ATTRIBUTE_TERMINATE:
2757 case TASK_POLICY_RESOURCE_ATTRIBUTE_NOTIFY_KQ:
2758 if (percentage != 0)
2759 return (ENOTSUP);
2760 scope = TASK_RUSECPU_FLAGS_DEADLINE;
2761 break;
2762 case TASK_POLICY_RESOURCE_ATTRIBUTE_NOTIFY_EXC:
2763 if (deadline != 0)
2764 return (ENOTSUP);
2765 scope = TASK_RUSECPU_FLAGS_PERTHR_LIMIT;
39236c6e
A
2766#ifdef CONFIG_NOMONITORS
2767 return (error);
2768#endif /* CONFIG_NOMONITORS */
316670eb
A
2769 break;
2770 default:
2771 return (EINVAL);
2772 }
6d2010ae
A
2773
2774 task_lock(task);
2775 if (task != current_task()) {
39236c6e 2776 task->policy_ru_cpu_ext = policy;
6d2010ae 2777 } else {
39236c6e 2778 task->policy_ru_cpu = policy;
6d2010ae 2779 }
39236c6e 2780 error = task_set_cpuusage(task, percentage, interval, deadline, scope, cpumon_entitled);
6d2010ae
A
2781 task_unlock(task);
2782 return(error);
2783}
2784
316670eb 2785int
39236c6e 2786proc_clear_task_ruse_cpu(task_t task, int cpumon_entitled)
316670eb
A
2787{
2788 int error = 0;
2789 int action;
2790 void * bsdinfo = NULL;
2791
2792 task_lock(task);
2793 if (task != current_task()) {
39236c6e 2794 task->policy_ru_cpu_ext = TASK_POLICY_RESOURCE_ATTRIBUTE_DEFAULT;
316670eb 2795 } else {
39236c6e 2796 task->policy_ru_cpu = TASK_POLICY_RESOURCE_ATTRIBUTE_DEFAULT;
316670eb
A
2797 }
2798
39236c6e 2799 error = task_clear_cpuusage_locked(task, cpumon_entitled);
316670eb
A
2800 if (error != 0)
2801 goto out;
2802
39236c6e
A
2803 action = task->applied_ru_cpu;
2804 if (task->applied_ru_cpu_ext != TASK_POLICY_RESOURCE_ATTRIBUTE_NONE) {
316670eb 2805 /* reset action */
39236c6e 2806 task->applied_ru_cpu_ext = TASK_POLICY_RESOURCE_ATTRIBUTE_NONE;
316670eb
A
2807 }
2808 if (action != TASK_POLICY_RESOURCE_ATTRIBUTE_NONE) {
2809 bsdinfo = task->bsd_info;
2810 task_unlock(task);
2811 proc_restore_resource_actions(bsdinfo, TASK_POLICY_CPU_RESOURCE_USAGE, action);
2812 goto out1;
2813 }
2814
2815out:
2816 task_unlock(task);
2817out1:
2818 return(error);
2819
2820}
6d2010ae
A
2821
2822/* used to apply resource limit related actions */
2823static int
2824task_apply_resource_actions(task_t task, int type)
2825{
2826 int action = TASK_POLICY_RESOURCE_ATTRIBUTE_NONE;
2827 void * bsdinfo = NULL;
2828
2829 switch (type) {
2830 case TASK_POLICY_CPU_RESOURCE_USAGE:
2831 break;
2832 case TASK_POLICY_WIREDMEM_RESOURCE_USAGE:
2833 case TASK_POLICY_VIRTUALMEM_RESOURCE_USAGE:
2834 case TASK_POLICY_DISK_RESOURCE_USAGE:
2835 case TASK_POLICY_NETWORK_RESOURCE_USAGE:
2836 case TASK_POLICY_POWER_RESOURCE_USAGE:
2837 return(0);
2838
2839 default:
2840 return(1);
2841 };
2842
2843 /* only cpu actions for now */
2844 task_lock(task);
2845
39236c6e 2846 if (task->applied_ru_cpu_ext == TASK_POLICY_RESOURCE_ATTRIBUTE_NONE) {
6d2010ae 2847 /* apply action */
39236c6e
A
2848 task->applied_ru_cpu_ext = task->policy_ru_cpu_ext;
2849 action = task->applied_ru_cpu_ext;
316670eb 2850 } else {
39236c6e 2851 action = task->applied_ru_cpu_ext;
6d2010ae 2852 }
316670eb 2853
6d2010ae
A
2854 if (action != TASK_POLICY_RESOURCE_ATTRIBUTE_NONE) {
2855 bsdinfo = task->bsd_info;
2856 task_unlock(task);
2857 proc_apply_resource_actions(bsdinfo, TASK_POLICY_CPU_RESOURCE_USAGE, action);
2858 } else
2859 task_unlock(task);
2860
2861 return(0);
2862}
2863
39236c6e
A
2864/*
2865 * XXX This API is somewhat broken; we support multiple simultaneous CPU limits, but the get/set API
2866 * only allows for one at a time. This means that if there is a per-thread limit active, the other
2867 * "scopes" will not be accessible via this API. We could change it to pass in the scope of interest
2868 * to the caller, and prefer that, but there's no need for that at the moment.
2869 */
2870int
2871task_get_cpuusage(task_t task, uint8_t *percentagep, uint64_t *intervalp, uint64_t *deadlinep, int *scope)
2872{
2873 *percentagep = 0;
2874 *intervalp = 0;
2875 *deadlinep = 0;
2876
2877 if ((task->rusage_cpu_flags & TASK_RUSECPU_FLAGS_PERTHR_LIMIT) != 0) {
2878 *scope = TASK_RUSECPU_FLAGS_PERTHR_LIMIT;
2879 *percentagep = task->rusage_cpu_perthr_percentage;
2880 *intervalp = task->rusage_cpu_perthr_interval;
2881 } else if ((task->rusage_cpu_flags & TASK_RUSECPU_FLAGS_PROC_LIMIT) != 0) {
2882 *scope = TASK_RUSECPU_FLAGS_PROC_LIMIT;
2883 *percentagep = task->rusage_cpu_percentage;
2884 *intervalp = task->rusage_cpu_interval;
2885 } else if ((task->rusage_cpu_flags & TASK_RUSECPU_FLAGS_DEADLINE) != 0) {
2886 *scope = TASK_RUSECPU_FLAGS_DEADLINE;
2887 *deadlinep = task->rusage_cpu_deadline;
2888 } else {
2889 *scope = 0;
2890 }
316670eb
A
2891
2892 return(0);
2893}
2894
39236c6e
A
2895/*
2896 * Disable the CPU usage monitor for the task. Return value indicates
2897 * if the mechanism was actually enabled.
2898 */
2899int
2900task_disable_cpumon(task_t task) {
2901 thread_t thread;
2902
2903 task_lock_assert_owned(task);
2904
2905 if ((task->rusage_cpu_flags & TASK_RUSECPU_FLAGS_PERTHR_LIMIT) == 0) {
2906 return (KERN_INVALID_ARGUMENT);
2907 }
2908
2909#if CONFIG_TELEMETRY
2910 /*
2911 * Disable task-wide telemetry if it was ever enabled by the CPU usage
2912 * monitor's warning zone.
2913 */
fe8ab488 2914 telemetry_task_ctl_locked(task, TF_CPUMON_WARNING, 0);
39236c6e
A
2915#endif
2916
2917 /*
2918 * Disable the monitor for the task, and propagate that change to each thread.
2919 */
2920 task->rusage_cpu_flags &= ~(TASK_RUSECPU_FLAGS_PERTHR_LIMIT | TASK_RUSECPU_FLAGS_FATAL_CPUMON);
2921 queue_iterate(&task->threads, thread, thread_t, task_threads) {
2922 set_astledger(thread);
2923 }
2924 task->rusage_cpu_perthr_percentage = 0;
2925 task->rusage_cpu_perthr_interval = 0;
2926
2927 return (KERN_SUCCESS);
2928}
2929
6d2010ae 2930int
39236c6e 2931task_set_cpuusage(task_t task, uint8_t percentage, uint64_t interval, uint64_t deadline, int scope, int cpumon_entitled)
6d2010ae 2932{
39236c6e 2933 thread_t thread;
316670eb 2934 uint64_t abstime = 0;
316670eb 2935 uint64_t limittime = 0;
6d2010ae 2936
316670eb
A
2937 lck_mtx_assert(&task->lock, LCK_MTX_ASSERT_OWNED);
2938
2939 /* By default, refill once per second */
2940 if (interval == 0)
2941 interval = NSEC_PER_SEC;
2942
39236c6e
A
2943 if (percentage != 0) {
2944 if (scope == TASK_RUSECPU_FLAGS_PERTHR_LIMIT) {
2945 boolean_t warn = FALSE;
2946
2947 /*
2948 * A per-thread CPU limit on a task generates an exception
2949 * (LEDGER_ACTION_EXCEPTION) if any one thread in the task
2950 * exceeds the limit.
2951 */
2952
2953 if (percentage == TASK_POLICY_CPUMON_DISABLE) {
2954 if (cpumon_entitled) {
2955 task_disable_cpumon(task);
2956 return (0);
2957 }
2958
2959 /*
2960 * This task wishes to disable the CPU usage monitor, but it's
2961 * missing the required entitlement:
2962 * com.apple.private.kernel.override-cpumon
2963 *
2964 * Instead, treat this as a request to reset its params
2965 * back to the defaults.
2966 */
2967 warn = TRUE;
2968 percentage = TASK_POLICY_CPUMON_DEFAULTS;
2969 }
2970
2971 if (percentage == TASK_POLICY_CPUMON_DEFAULTS) {
2972 percentage = proc_max_cpumon_percentage;
2973 interval = proc_max_cpumon_interval;
2974 }
2975
2976 if (percentage > 100) {
2977 percentage = 100;
2978 }
2979
2980 /*
2981 * Passing in an interval of -1 means either:
2982 * - Leave the interval as-is, if there's already a per-thread
2983 * limit configured
2984 * - Use the system default.
2985 */
2986 if (interval == -1ULL) {
2987 if (task->rusage_cpu_flags & TASK_RUSECPU_FLAGS_PERTHR_LIMIT) {
2988 interval = task->rusage_cpu_perthr_interval;
2989 } else {
2990 interval = proc_max_cpumon_interval;
2991 }
2992 }
2993
316670eb 2994 /*
39236c6e
A
2995 * Enforce global caps on CPU usage monitor here if the process is not
2996 * entitled to escape the global caps.
316670eb 2997 */
39236c6e
A
2998 if ((percentage > proc_max_cpumon_percentage) && (cpumon_entitled == 0)) {
2999 warn = TRUE;
3000 percentage = proc_max_cpumon_percentage;
3001 }
3002
3003 if ((interval > proc_max_cpumon_interval) && (cpumon_entitled == 0)) {
3004 warn = TRUE;
3005 interval = proc_max_cpumon_interval;
3006 }
3007
3008 if (warn) {
3009 int pid = 0;
3010 char *procname = (char *)"unknown";
3011
3012#ifdef MACH_BSD
3013 pid = proc_selfpid();
3014 if (current_task()->bsd_info != NULL) {
3015 procname = proc_name_address(current_task()->bsd_info);
3016 }
3017#endif
3018
3019 printf("process %s[%d] denied attempt to escape CPU monitor"
3020 " (missing required entitlement).\n", procname, pid);
3021 }
3022
316670eb
A
3023 task->rusage_cpu_flags |= TASK_RUSECPU_FLAGS_PERTHR_LIMIT;
3024 task->rusage_cpu_perthr_percentage = percentage;
3025 task->rusage_cpu_perthr_interval = interval;
3026 queue_iterate(&task->threads, thread, thread_t, task_threads) {
3027 set_astledger(thread);
3028 }
3029 } else if (scope == TASK_RUSECPU_FLAGS_PROC_LIMIT) {
3030 /*
3031 * Currently, a proc-wide CPU limit always blocks if the limit is
3032 * exceeded (LEDGER_ACTION_BLOCK).
3033 */
3034 task->rusage_cpu_flags |= TASK_RUSECPU_FLAGS_PROC_LIMIT;
3035 task->rusage_cpu_percentage = percentage;
3036 task->rusage_cpu_interval = interval;
3037
39236c6e
A
3038 limittime = (interval * percentage) / 100;
3039 nanoseconds_to_absolutetime(limittime, &abstime);
3040
3041 ledger_set_limit(task->ledger, task_ledgers.cpu_time, abstime, 0);
316670eb
A
3042 ledger_set_period(task->ledger, task_ledgers.cpu_time, interval);
3043 ledger_set_action(task->ledger, task_ledgers.cpu_time, LEDGER_ACTION_BLOCK);
3044 }
3045 }
6d2010ae 3046
316670eb
A
3047 if (deadline != 0) {
3048 assert(scope == TASK_RUSECPU_FLAGS_DEADLINE);
3049
3050 /* if already in use, cancel and wait for it to cleanout */
3051 if (task->rusage_cpu_callt != NULL) {
3052 task_unlock(task);
3053 thread_call_cancel_wait(task->rusage_cpu_callt);
3054 task_lock(task);
3055 }
3056 if (task->rusage_cpu_callt == NULL) {
3057 task->rusage_cpu_callt = thread_call_allocate_with_priority(task_action_cpuusage, (thread_call_param_t)task, THREAD_CALL_PRIORITY_KERNEL);
3058 }
3059 /* setup callout */
3060 if (task->rusage_cpu_callt != 0) {
39236c6e
A
3061 uint64_t save_abstime = 0;
3062
316670eb
A
3063 task->rusage_cpu_flags |= TASK_RUSECPU_FLAGS_DEADLINE;
3064 task->rusage_cpu_deadline = deadline;
3065
3066 nanoseconds_to_absolutetime(deadline, &abstime);
3067 save_abstime = abstime;
3068 clock_absolutetime_interval_to_deadline(save_abstime, &abstime);
3069 thread_call_enter_delayed(task->rusage_cpu_callt, abstime);
3070 }
6d2010ae 3071 }
6d2010ae
A
3072
3073 return(0);
6d2010ae
A
3074}
3075
316670eb 3076int
39236c6e 3077task_clear_cpuusage(task_t task, int cpumon_entitled)
6d2010ae 3078{
316670eb 3079 int retval = 0;
6d2010ae 3080
316670eb 3081 task_lock(task);
39236c6e 3082 retval = task_clear_cpuusage_locked(task, cpumon_entitled);
316670eb
A
3083 task_unlock(task);
3084
3085 return(retval);
6d2010ae
A
3086}
3087
316670eb 3088int
39236c6e 3089task_clear_cpuusage_locked(task_t task, int cpumon_entitled)
6d2010ae 3090{
316670eb 3091 thread_call_t savecallt;
316670eb
A
3092
3093 /* cancel percentage handling if set */
3094 if (task->rusage_cpu_flags & TASK_RUSECPU_FLAGS_PROC_LIMIT) {
3095 task->rusage_cpu_flags &= ~TASK_RUSECPU_FLAGS_PROC_LIMIT;
39236c6e 3096 ledger_set_limit(task->ledger, task_ledgers.cpu_time, LEDGER_LIMIT_INFINITY, 0);
316670eb
A
3097 task->rusage_cpu_percentage = 0;
3098 task->rusage_cpu_interval = 0;
3099 }
3100
39236c6e
A
3101 /*
3102 * Disable the CPU usage monitor.
3103 */
3104 if (cpumon_entitled) {
3105 task_disable_cpumon(task);
316670eb
A
3106 }
3107
3108 /* cancel deadline handling if set */
3109 if (task->rusage_cpu_flags & TASK_RUSECPU_FLAGS_DEADLINE) {
3110 task->rusage_cpu_flags &= ~TASK_RUSECPU_FLAGS_DEADLINE;
3111 if (task->rusage_cpu_callt != 0) {
3112 savecallt = task->rusage_cpu_callt;
3113 task->rusage_cpu_callt = NULL;
3114 task->rusage_cpu_deadline = 0;
3115 task_unlock(task);
3116 thread_call_cancel_wait(savecallt);
3117 thread_call_free(savecallt);
3118 task_lock(task);
3119 }
3120 }
6d2010ae
A
3121 return(0);
3122}
3123
3124/* called by ledger unit to enforce action due to resource usage criteria being met */
316670eb
A
3125void
3126task_action_cpuusage(thread_call_param_t param0, __unused thread_call_param_t param1)
3127{
3128 task_t task = (task_t)param0;
3129 (void)task_apply_resource_actions(task, TASK_POLICY_CPU_RESOURCE_USAGE);
3130 return;
3131}
3132
316670eb 3133
39236c6e
A
3134/*
3135 * Routines for taskwatch and pidbind
3136 */
6d2010ae 3137
316670eb 3138
39236c6e
A
3139/*
3140 * Routines for importance donation/inheritance/boosting
3141 */
316670eb 3142
fe8ab488
A
3143static void
3144task_importance_update_live_donor(task_t target_task)
3145{
3146#if IMPORTANCE_INHERITANCE
3147
3148 ipc_importance_task_t task_imp;
3149
3150 task_imp = ipc_importance_for_task(target_task, FALSE);
3151 if (IIT_NULL != task_imp) {
3152 ipc_importance_task_update_live_donor(task_imp);
3153 ipc_importance_task_release(task_imp);
3154 }
3155#endif /* IMPORTANCE_INHERITANCE */
3156}
3157
39236c6e
A
3158void
3159task_importance_mark_donor(task_t task, boolean_t donating)
3160{
3161#if IMPORTANCE_INHERITANCE
fe8ab488
A
3162 ipc_importance_task_t task_imp;
3163
3164 task_imp = ipc_importance_for_task(task, FALSE);
3165 if (IIT_NULL != task_imp) {
3166 ipc_importance_task_mark_donor(task_imp, donating);
3167 ipc_importance_task_release(task_imp);
3168 }
3169#endif /* IMPORTANCE_INHERITANCE */
3170}
3171
3172void
3173task_importance_mark_live_donor(task_t task, boolean_t live_donating)
3174{
3175#if IMPORTANCE_INHERITANCE
3176 ipc_importance_task_t task_imp;
3177
3178 task_imp = ipc_importance_for_task(task, FALSE);
3179 if (IIT_NULL != task_imp) {
3180 ipc_importance_task_mark_live_donor(task_imp, live_donating);
3181 ipc_importance_task_release(task_imp);
3182 }
39236c6e
A
3183#endif /* IMPORTANCE_INHERITANCE */
3184}
316670eb 3185
39236c6e
A
3186void
3187task_importance_mark_receiver(task_t task, boolean_t receiving)
3188{
3189#if IMPORTANCE_INHERITANCE
fe8ab488 3190 ipc_importance_task_t task_imp;
39236c6e 3191
fe8ab488
A
3192 task_imp = ipc_importance_for_task(task, FALSE);
3193 if (IIT_NULL != task_imp) {
3194 ipc_importance_task_mark_receiver(task_imp, receiving);
3195 ipc_importance_task_release(task_imp);
316670eb 3196 }
39236c6e
A
3197#endif /* IMPORTANCE_INHERITANCE */
3198}
316670eb 3199
fe8ab488
A
3200void
3201task_importance_mark_denap_receiver(task_t task, boolean_t denap)
3202{
3203#if IMPORTANCE_INHERITANCE
3204 ipc_importance_task_t task_imp;
3205
3206 task_imp = ipc_importance_for_task(task, FALSE);
3207 if (IIT_NULL != task_imp) {
3208 ipc_importance_task_mark_denap_receiver(task_imp, denap);
3209 ipc_importance_task_release(task_imp);
3210 }
3211#endif /* IMPORTANCE_INHERITANCE */
3212}
316670eb 3213
fe8ab488
A
3214void
3215task_importance_reset(__imp_only task_t task)
3216{
39236c6e 3217#if IMPORTANCE_INHERITANCE
fe8ab488 3218 ipc_importance_task_t task_imp;
316670eb 3219
fe8ab488
A
3220 /* TODO: Lower importance downstream before disconnect */
3221 task_imp = task->task_imp_base;
3222 ipc_importance_reset(task_imp, FALSE);
3223 task_importance_update_live_donor(task);
3224#endif /* IMPORTANCE_INHERITANCE */
3225}
3226
3227#if IMPORTANCE_INHERITANCE
3228
3229/*
3230 * Sets the task boost bit to the provided value. Does NOT run the update function.
3231 *
3232 * Task lock must be held.
3233 */
3234void
3235task_set_boost_locked(task_t task, boolean_t boost_active)
39236c6e
A
3236{
3237#if IMPORTANCE_DEBUG
3238 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, (IMPORTANCE_CODE(IMP_BOOST, (boost_active ? IMP_BOOSTED : IMP_UNBOOSTED)) | DBG_FUNC_START),
fe8ab488 3239 proc_selfpid(), audit_token_pid_from_task(task), trequested_0(task, THREAD_NULL), trequested_1(task, THREAD_NULL), 0);
39236c6e 3240#endif
316670eb 3241
fe8ab488 3242 task->requested_policy.t_boosted = boost_active;
39236c6e
A
3243
3244#if IMPORTANCE_DEBUG
3245 if (boost_active == TRUE){
3246 DTRACE_BOOST2(boost, task_t, task, int, audit_token_pid_from_task(task));
3247 } else {
3248 DTRACE_BOOST2(unboost, task_t, task, int, audit_token_pid_from_task(task));
3249 }
3250 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, (IMPORTANCE_CODE(IMP_BOOST, (boost_active ? IMP_BOOSTED : IMP_UNBOOSTED)) | DBG_FUNC_END),
3251 proc_selfpid(), audit_token_pid_from_task(task),
fe8ab488 3252 trequested_0(task, THREAD_NULL), trequested_1(task, THREAD_NULL), 0);
39236c6e 3253#endif
316670eb
A
3254}
3255
fe8ab488
A
3256/*
3257 * Sets the task boost bit to the provided value and applies the update.
3258 *
3259 * Task lock must be held. Must call update complete after unlocking the task.
3260 */
3261void
3262task_update_boost_locked(task_t task, boolean_t boost_active, task_pend_token_t pend_token)
3263{
3264 task_set_boost_locked(task, boost_active);
3265
3266 task_policy_update_locked(task, THREAD_NULL, pend_token);
3267}
3268
39236c6e
A
3269/*
3270 * Check if this task should donate importance.
3271 *
3272 * May be called without taking the task lock. In that case, donor status can change
3273 * so you must check only once for each donation event.
3274 */
3275boolean_t
3276task_is_importance_donor(task_t task)
316670eb 3277{
fe8ab488
A
3278 if (task->task_imp_base == IIT_NULL)
3279 return FALSE;
3280 return ipc_importance_task_is_donor(task->task_imp_base);
316670eb
A
3281}
3282
39236c6e 3283/*
fe8ab488 3284 * Query the status of the task's donor mark.
39236c6e
A
3285 */
3286boolean_t
fe8ab488 3287task_is_marked_importance_donor(task_t task)
316670eb 3288{
fe8ab488
A
3289 if (task->task_imp_base == IIT_NULL)
3290 return FALSE;
3291 return ipc_importance_task_is_marked_donor(task->task_imp_base);
316670eb
A
3292}
3293
39236c6e 3294/*
fe8ab488 3295 * Query the status of the task's live donor and donor mark.
39236c6e 3296 */
fe8ab488
A
3297boolean_t
3298task_is_marked_live_importance_donor(task_t task)
316670eb 3299{
fe8ab488
A
3300 if (task->task_imp_base == IIT_NULL)
3301 return FALSE;
3302 return ipc_importance_task_is_marked_live_donor(task->task_imp_base);
3303}
316670eb 3304
39236c6e 3305
fe8ab488
A
3306/*
3307 * This routine may be called without holding task lock
3308 * since the value of imp_receiver can never be unset.
3309 */
3310boolean_t
3311task_is_importance_receiver(task_t task)
3312{
3313 if (task->task_imp_base == IIT_NULL)
3314 return FALSE;
3315 return ipc_importance_task_is_marked_receiver(task->task_imp_base);
316670eb
A
3316}
3317
fe8ab488
A
3318/*
3319 * Query the task's receiver mark.
3320 */
3321boolean_t
3322task_is_marked_importance_receiver(task_t task)
316670eb 3323{
fe8ab488
A
3324 if (task->task_imp_base == IIT_NULL)
3325 return FALSE;
3326 return ipc_importance_task_is_marked_receiver(task->task_imp_base);
316670eb
A
3327}
3328
fe8ab488
A
3329/*
3330 * This routine may be called without holding task lock
3331 * since the value of de-nap receiver can never be unset.
3332 */
3333boolean_t
3334task_is_importance_denap_receiver(task_t task)
39236c6e 3335{
fe8ab488
A
3336 if (task->task_imp_base == IIT_NULL)
3337 return FALSE;
3338 return ipc_importance_task_is_denap_receiver(task->task_imp_base);
39236c6e
A
3339}
3340
fe8ab488
A
3341/*
3342 * Query the task's de-nap receiver mark.
3343 */
3344boolean_t
3345task_is_marked_importance_denap_receiver(task_t task)
316670eb 3346{
fe8ab488
A
3347 if (task->task_imp_base == IIT_NULL)
3348 return FALSE;
3349 return ipc_importance_task_is_marked_denap_receiver(task->task_imp_base);
39236c6e 3350}
316670eb 3351
39236c6e 3352/*
fe8ab488
A
3353 * This routine may be called without holding task lock
3354 * since the value of imp_receiver can never be unset.
39236c6e 3355 */
fe8ab488
A
3356boolean_t
3357task_is_importance_receiver_type(task_t task)
39236c6e 3358{
fe8ab488
A
3359 if (task->task_imp_base == IIT_NULL)
3360 return FALSE;
3361 return (task_is_importance_receiver(task) ||
3362 task_is_importance_denap_receiver(task));
39236c6e 3363}
316670eb 3364
39236c6e 3365/*
fe8ab488
A
3366 * External importance assertions are managed by the process in userspace
3367 * Internal importance assertions are the responsibility of the kernel
3368 * Assertions are changed from internal to external via task_importance_externalize_assertion
39236c6e 3369 */
fe8ab488
A
3370
3371int
3372task_importance_hold_watchport_assertion(task_t target_task, uint32_t count)
39236c6e 3373{
fe8ab488
A
3374 ipc_importance_task_t task_imp;
3375 kern_return_t ret;
316670eb 3376
fe8ab488
A
3377 /* must already have set up an importance */
3378 task_imp = target_task->task_imp_base;
3379 assert(IIT_NULL != task_imp);
316670eb 3380
fe8ab488
A
3381 ret = ipc_importance_task_hold_internal_assertion(task_imp, count);
3382 return (KERN_SUCCESS != ret) ? ENOTSUP : 0;
3383}
316670eb 3384
fe8ab488
A
3385int
3386task_importance_hold_internal_assertion(task_t target_task, uint32_t count)
3387{
3388 ipc_importance_task_t task_imp;
3389 kern_return_t ret;
39236c6e 3390
fe8ab488
A
3391 /* may be first time, so allow for possible importance setup */
3392 task_imp = ipc_importance_for_task(target_task, FALSE);
3393 if (IIT_NULL == task_imp) {
3394 return EOVERFLOW;
316670eb 3395 }
fe8ab488
A
3396 ret = ipc_importance_task_hold_internal_assertion(task_imp, count);
3397 ipc_importance_task_release(task_imp);
316670eb 3398
fe8ab488
A
3399 return (KERN_SUCCESS != ret) ? ENOTSUP : 0;
3400}
39236c6e 3401
fe8ab488
A
3402int
3403task_importance_hold_file_lock_assertion(task_t target_task, uint32_t count)
3404{
3405 ipc_importance_task_t task_imp;
3406 kern_return_t ret;
39236c6e 3407
fe8ab488
A
3408 /* may be first time, so allow for possible importance setup */
3409 task_imp = ipc_importance_for_task(target_task, FALSE);
3410 if (IIT_NULL == task_imp) {
3411 return EOVERFLOW;
316670eb 3412 }
fe8ab488
A
3413 ret = ipc_importance_task_hold_file_lock_assertion(task_imp, count);
3414 ipc_importance_task_release(task_imp);
39236c6e 3415
fe8ab488 3416 return (KERN_SUCCESS != ret) ? ENOTSUP : 0;
316670eb
A
3417}
3418
39236c6e 3419int
fe8ab488 3420task_importance_hold_legacy_external_assertion(task_t target_task, uint32_t count)
316670eb 3421{
fe8ab488
A
3422 ipc_importance_task_t task_imp;
3423 kern_return_t ret;
3424
3425 /* must already have set up an importance */
3426 task_imp = target_task->task_imp_base;
3427 if (IIT_NULL == task_imp) {
3428 return EOVERFLOW;
3429 }
3430 ret = ipc_importance_task_hold_legacy_external_assertion(task_imp, count);
3431 return (KERN_SUCCESS != ret) ? ENOTSUP : 0;
316670eb
A
3432}
3433
fe8ab488
A
3434int
3435task_importance_drop_internal_assertion(task_t target_task, uint32_t count)
3436{
3437 ipc_importance_task_t task_imp;
3438 kern_return_t ret;
3439
3440 /* must already have set up an importance */
3441 task_imp = target_task->task_imp_base;
3442 if (IIT_NULL == task_imp) {
3443 return EOVERFLOW;
3444 }
3445 ret = ipc_importance_task_drop_internal_assertion(target_task->task_imp_base, count);
3446 return (KERN_SUCCESS != ret) ? ENOTSUP : 0;
3447}
39236c6e 3448
fe8ab488
A
3449int
3450task_importance_drop_file_lock_assertion(task_t target_task, uint32_t count)
316670eb 3451{
fe8ab488
A
3452 ipc_importance_task_t task_imp;
3453 kern_return_t ret;
3454
3455 /* must already have set up an importance */
3456 task_imp = target_task->task_imp_base;
3457 if (IIT_NULL == task_imp) {
3458 return EOVERFLOW;
3459 }
3460 ret = ipc_importance_task_drop_file_lock_assertion(target_task->task_imp_base, count);
3461 return (KERN_SUCCESS != ret) ? EOVERFLOW : 0;
3462}
316670eb 3463
fe8ab488
A
3464int
3465task_importance_drop_legacy_external_assertion(task_t target_task, uint32_t count)
3466{
3467 ipc_importance_task_t task_imp;
3468 kern_return_t ret;
3469
3470 /* must already have set up an importance */
3471 task_imp = target_task->task_imp_base;
3472 if (IIT_NULL == task_imp) {
3473 return EOVERFLOW;
3474 }
3475 ret = ipc_importance_task_drop_legacy_external_assertion(task_imp, count);
3476 return (KERN_SUCCESS != ret) ? EOVERFLOW : 0;
316670eb
A
3477}
3478
fe8ab488
A
3479static void
3480task_add_importance_watchport(task_t task, mach_port_t port, int *boostp)
316670eb 3481{
39236c6e 3482 int boost = 0;
316670eb 3483
39236c6e 3484 __impdebug_only int released_pid = 0;
fe8ab488 3485 __impdebug_only int pid = audit_token_pid_from_task(task);
316670eb 3486
fe8ab488 3487 ipc_importance_task_t release_imp_task = IIT_NULL;
316670eb 3488
39236c6e 3489 if (IP_VALID(port) != 0) {
fe8ab488
A
3490 ipc_importance_task_t new_imp_task = ipc_importance_for_task(task, FALSE);
3491
39236c6e 3492 ip_lock(port);
316670eb 3493
39236c6e
A
3494 /*
3495 * The port must have been marked tempowner already.
3496 * This also filters out ports whose receive rights
3497 * are already enqueued in a message, as you can't
3498 * change the right's destination once it's already
3499 * on its way.
316670eb 3500 */
39236c6e
A
3501 if (port->ip_tempowner != 0) {
3502 assert(port->ip_impdonation != 0);
3503
3504 boost = port->ip_impcount;
fe8ab488 3505 if (IIT_NULL != port->ip_imp_task) {
39236c6e
A
3506 /*
3507 * if this port is already bound to a task,
3508 * release the task reference and drop any
3509 * watchport-forwarded boosts
3510 */
3511 release_imp_task = port->ip_imp_task;
fe8ab488 3512 port->ip_imp_task = IIT_NULL;
39236c6e 3513 }
316670eb 3514
fe8ab488
A
3515 /* mark the port is watching another task (reference held in port->ip_imp_task) */
3516 if (ipc_importance_task_is_marked_receiver(new_imp_task)) {
3517 port->ip_imp_task = new_imp_task;
3518 new_imp_task = IIT_NULL;
3519 }
39236c6e
A
3520 }
3521 ip_unlock(port);
316670eb 3522
fe8ab488
A
3523 if (IIT_NULL != new_imp_task) {
3524 ipc_importance_task_release(new_imp_task);
3525 }
3526
3527 if (IIT_NULL != release_imp_task) {
39236c6e 3528 if (boost > 0)
fe8ab488
A
3529 ipc_importance_task_drop_internal_assertion(release_imp_task, boost);
3530
3531 // released_pid = audit_token_pid_from_task(release_imp_task); /* TODO: Need ref-safe way to get pid */
3532 ipc_importance_task_release(release_imp_task);
39236c6e
A
3533 }
3534#if IMPORTANCE_DEBUG
3535 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, (IMPORTANCE_CODE(IMP_WATCHPORT, 0)) | DBG_FUNC_NONE,
3536 proc_selfpid(), pid, boost, released_pid, 0);
3537#endif /* IMPORTANCE_DEBUG */
316670eb
A
3538 }
3539
39236c6e
A
3540 *boostp = boost;
3541 return;
316670eb 3542}
316670eb 3543
fe8ab488 3544#endif /* IMPORTANCE_INHERITANCE */
316670eb 3545
39236c6e
A
3546/*
3547 * Routines for VM to query task importance
3548 */
6d2010ae 3549
6d2010ae 3550
39236c6e
A
3551/*
3552 * Order to be considered while estimating importance
3553 * for low memory notification and purging purgeable memory.
3554 */
3555#define TASK_IMPORTANCE_FOREGROUND 4
3556#define TASK_IMPORTANCE_NOTDARWINBG 1
3557
3558
3559/*
3560 * Checks if the task is already notified.
3561 *
3562 * Condition: task lock should be held while calling this function.
3563 */
3564boolean_t
3565task_has_been_notified(task_t task, int pressurelevel)
3566{
3567 if (task == NULL) {
3568 return FALSE;
6d2010ae 3569 }
39236c6e
A
3570
3571 if (pressurelevel == kVMPressureWarning)
3572 return (task->low_mem_notified_warn ? TRUE : FALSE);
3573 else if (pressurelevel == kVMPressureCritical)
3574 return (task->low_mem_notified_critical ? TRUE : FALSE);
3575 else
3576 return TRUE;
3577}
6d2010ae 3578
316670eb 3579
39236c6e
A
3580/*
3581 * Checks if the task is used for purging.
3582 *
3583 * Condition: task lock should be held while calling this function.
3584 */
3585boolean_t
3586task_used_for_purging(task_t task, int pressurelevel)
3587{
3588 if (task == NULL) {
3589 return FALSE;
316670eb 3590 }
39236c6e
A
3591
3592 if (pressurelevel == kVMPressureWarning)
3593 return (task->purged_memory_warn ? TRUE : FALSE);
3594 else if (pressurelevel == kVMPressureCritical)
3595 return (task->purged_memory_critical ? TRUE : FALSE);
3596 else
3597 return TRUE;
3598}
6d2010ae 3599
6d2010ae 3600
39236c6e
A
3601/*
3602 * Mark the task as notified with memory notification.
3603 *
3604 * Condition: task lock should be held while calling this function.
3605 */
3606void
3607task_mark_has_been_notified(task_t task, int pressurelevel)
3608{
3609 if (task == NULL) {
3610 return;
3611 }
3612
3613 if (pressurelevel == kVMPressureWarning)
3614 task->low_mem_notified_warn = 1;
3615 else if (pressurelevel == kVMPressureCritical)
3616 task->low_mem_notified_critical = 1;
6d2010ae
A
3617}
3618
39236c6e
A
3619
3620/*
3621 * Mark the task as purged.
3622 *
3623 * Condition: task lock should be held while calling this function.
3624 */
3625void
3626task_mark_used_for_purging(task_t task, int pressurelevel)
6d2010ae 3627{
39236c6e
A
3628 if (task == NULL) {
3629 return;
3630 }
3631
3632 if (pressurelevel == kVMPressureWarning)
3633 task->purged_memory_warn = 1;
3634 else if (pressurelevel == kVMPressureCritical)
3635 task->purged_memory_critical = 1;
3636}
6d2010ae 3637
6d2010ae 3638
39236c6e
A
3639/*
3640 * Mark the task eligible for low memory notification.
3641 *
3642 * Condition: task lock should be held while calling this function.
3643 */
3644void
3645task_clear_has_been_notified(task_t task, int pressurelevel)
3646{
3647 if (task == NULL) {
3648 return;
3649 }
3650
3651 if (pressurelevel == kVMPressureWarning)
3652 task->low_mem_notified_warn = 0;
3653 else if (pressurelevel == kVMPressureCritical)
3654 task->low_mem_notified_critical = 0;
3655}
6d2010ae 3656
6d2010ae 3657
39236c6e
A
3658/*
3659 * Mark the task eligible for purging its purgeable memory.
3660 *
3661 * Condition: task lock should be held while calling this function.
3662 */
3663void
3664task_clear_used_for_purging(task_t task)
3665{
3666 if (task == NULL) {
3667 return;
3668 }
3669
3670 task->purged_memory_warn = 0;
3671 task->purged_memory_critical = 0;
6d2010ae
A
3672}
3673
39236c6e
A
3674
3675/*
3676 * Estimate task importance for purging its purgeable memory
3677 * and low memory notification.
3678 *
3679 * Importance is calculated in the following order of criteria:
3680 * -Task role : Background vs Foreground
3681 * -Boost status: Not boosted vs Boosted
3682 * -Darwin BG status.
3683 *
3684 * Returns: Estimated task importance. Less important task will have lower
3685 * estimated importance.
3686 */
316670eb 3687int
39236c6e 3688task_importance_estimate(task_t task)
316670eb 3689{
39236c6e 3690 int task_importance = 0;
316670eb 3691
39236c6e
A
3692 if (task == NULL) {
3693 return 0;
3694 }
3695
3696 if (proc_get_effective_task_policy(task, TASK_POLICY_ROLE) == TASK_FOREGROUND_APPLICATION)
3697 task_importance += TASK_IMPORTANCE_FOREGROUND;
3698
3699 if (proc_get_effective_task_policy(task, TASK_POLICY_DARWIN_BG) == 0)
3700 task_importance += TASK_IMPORTANCE_NOTDARWINBG;
3701
3702 return task_importance;
316670eb 3703}
39236c6e 3704