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