1/*
2 * Copyright (c) 2013 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29#ifndef _KERN_COALITION_H_
30#define _KERN_COALITION_H_
31
32/* only kernel-private interfaces */
33#ifdef XNU_KERNEL_PRIVATE
34#include <mach/coalition.h>
35#include <kern/thread_group.h>
36
37__BEGIN_DECLS
38
39#if CONFIG_COALITIONS
40
41void coalitions_init(void);
42
43/* These may return:
44 * KERN_ALREADY_IN_SET task is already in a coalition (maybe this one, maybe a different one)
45 * KERN_TERMINATED coalition is already terminated (so it may not adopt any more tasks)
46 */
47kern_return_t coalitions_adopt_task(coalition_t *coaltions, task_t task);
48kern_return_t coalitions_adopt_init_task(task_t task);
49kern_return_t coalitions_adopt_corpse_task(task_t task);
50
51/* Currently, no error conditions. If task is not already in a coalition,
52 * KERN_SUCCESS is returned because removing it did not fail.
53 */
54kern_return_t coalitions_remove_task(task_t task);
55void task_release_coalitions(task_t task);
56
57/*
58 *
59 */
60kern_return_t coalitions_set_roles(coalition_t coalitions[COALITION_NUM_TYPES],
61 task_t task, int roles[COALITION_NUM_TYPES]);
62
63uint64_t coalition_id(coalition_t coal);
64void task_coalition_ids(task_t task, uint64_t ids[COALITION_NUM_TYPES]);
65void task_coalition_roles(task_t task, int roles[COALITION_NUM_TYPES]);
66int task_coalition_role_for_type(task_t task, int coalition_type);
67int coalition_type(coalition_t coal);
68
69void task_coalition_update_gpu_stats(task_t task, uint64_t gpu_ns_delta);
70boolean_t task_coalition_adjust_focal_count(task_t task, int count, uint32_t *new_count);
71uint32_t task_coalition_focal_count(task_t task);
72uint32_t task_coalition_game_mode_count(task_t task);
73bool task_coalition_adjust_game_mode_count(task_t task, int count, uint32_t *new_count);
74boolean_t task_coalition_adjust_nonfocal_count(task_t task, int count, uint32_t *new_count);
75uint32_t task_coalition_nonfocal_count(task_t task);
76
77#if CONFIG_THREAD_GROUPS
78
79/* Thread group lives as long as the task is holding the coalition reference */
80struct thread_group *task_coalition_get_thread_group(task_t task);
81
82/* Donates the thread group reference to the coalition */
83void coalition_set_thread_group(coalition_t coal, struct thread_group *tg);
84struct thread_group *kdp_coalition_get_thread_group(coalition_t coal);
85
86/* Thread group lives as long as the coalition reference is held */
87struct thread_group *coalition_get_thread_group(coalition_t coal);
88
89void task_coalition_thread_group_focal_update(task_t task);
90void task_coalition_thread_group_game_mode_update(task_t task);
91void task_coalition_thread_group_application_set(task_t task);
92#endif /* CONFIG_THREAD_GROUPS */
93
94void coalition_for_each_task(coalition_t coal, void *ctx,
95 void (*callback)(coalition_t, void *, task_t));
96
97/* Coalition ledger */
98struct coalition_ledger_indices {
99 int logical_writes;
100};
101void init_coalition_ledgers(void);
102int coalition_ledger_set_logical_writes_limit(coalition_t coal, int64_t limit);
103void coalition_io_monitor_ctl(struct coalition *coalition, uint32_t flags, int64_t limit);
104ledger_t coalition_ledger_get_from_task(task_t task);
105void coalition_io_rate_exceeded(int warning, const void *param0, __unused const void *param1);
106void coalition_io_ledger_update(task_t task, int32_t flavor, boolean_t is_credit, uint32_t io_size);
107/*
108 * Mark this coalition as eligible for swap.
109 * All tasks currently in this coalition will become swap enabled
110 * and new tasks launched into this coalition will be swap enabled.
111 *
112 * Note:
113 * This function can only be called on jetsam coalitions.
114 */
115void coalition_mark_swappable(coalition_t coal);
116/*
117 * Returns true iff the coalition has been marked as swappable.
118 *
119 * Note:
120 * This function can only be called on jetsam coalitions.
121 */
122bool coalition_is_swappable(coalition_t coal);
123
124/* Max limit for coalition logical_writes ledger in MB. Setting to 16 TB */
125#define COALITION_MAX_LOGICAL_WRITES_LIMIT ((ledger_amount_t)(1ULL << 24))
126/* logical_writes ledger's refill time interval */
127#define COALITION_LEDGER_MONITOR_INTERVAL_SECS (24 * 60 * 60)
128
129
130typedef void (*coalition_iterate_fn_t)(void*, int, coalition_t);
131kern_return_t coalition_iterate_stackshot(coalition_iterate_fn_t callout, void *arg, uint32_t coalition_type);
132
133/* Returns with a reference, or COALITION_NULL.
134 * There is no coalition with id 0.
135 */
136coalition_t coalition_find_by_id(uint64_t coal_id);
137
138/* Returns with a reference and an activation, or COALITION_NULL.
139 * There is no coalition with id 0.
140 */
141coalition_t coalition_find_and_activate_by_id(uint64_t coal_id);
142
143void coalition_remove_active(coalition_t coal);
144
145void coalition_release(coalition_t coal);
146
147/*
148 * The following functions are to be used by the syscall wrapper
149 * in bsd/kern/kern_proc.c, after it has verified the caller's privilege.
150 */
151
152/* This may return:
153 * KERN_DEFAULT_SET The default coalition, which contains the kernel, may
154 * not be terminated.
155 * KERN_TERMINATED The coalition was already reaped.
156 * KERN_FAILURE The coalition was not empty or has never been terminated.
157 */
158kern_return_t coalition_reap_internal(coalition_t coal);
159
160/* This may return:
161 * KERN_DEFAULT_SET The default coalition, which contains the kernel, may
162 * not be terminated.
163 * KERN_TERMINATED The coalition was already terminated (or even reaped)
164 * KERN_INVALID_NAME The coalition was already reaped.
165 */
166kern_return_t coalition_request_terminate_internal(coalition_t coal);
167
168/* This may return:
169 * KERN_RESOURCE_SHORTAGE Unable to allocate kernel resources for a
170 * new coalition.
171 */
172kern_return_t coalition_create_internal(int type, int role, boolean_t privileged, boolean_t efficient, coalition_t *out, uint64_t *cid);
173
174boolean_t coalition_term_requested(coalition_t coal);
175boolean_t coalition_is_terminated(coalition_t coal);
176boolean_t coalition_is_reaped(coalition_t coal);
177boolean_t coalition_is_privileged(coalition_t coal);
178boolean_t task_is_in_privileged_coalition(task_t task, int type);
179
180kern_return_t coalition_resource_usage_internal(coalition_t coal, struct coalition_resource_usage *cru_out);
181
182kern_return_t coalition_debug_info_internal(coalition_t coal,
183 struct coalinfo_debuginfo *c_debuginfo);
184
185task_t kdp_coalition_get_leader(coalition_t coal);
186
187/*
188 * development/debug interfaces
189 */
190#if DEVELOPMENT || DEBUG
191int coalition_should_notify(coalition_t coal);
192void coalition_set_notify(coalition_t coal, int notify);
193#endif
194
195#else /* !CONFIG_COALITIONS */
196
197static inline void
198task_coalition_update_gpu_stats(__unused task_t task,
199 __unused uint64_t gpu_ns_delta)
200{
201 return;
202}
203
204static inline boolean_t
205task_coalition_adjust_focal_count(__unused task_t task,
206 __unused int count,
207 __unused uint32_t *new_count)
208{
209 return FALSE;
210}
211
212static inline boolean_t
213task_coalition_adjust_nonfocal_count(__unused task_t task,
214 __unused int count,
215 __unused uint32_t *new_count)
216{
217 return FALSE;
218}
219
220static inline uint32_t
221task_coalition_focal_count(__unused task_t task)
222{
223 return 0;
224}
225
226static inline void
227coalition_for_each_task(__unused coalition_t coal,
228 __unused void *ctx,
229 __unused void (*callback)(coalition_t, void *, task_t))
230{
231 return;
232}
233
234static inline void
235coalition_mark_swappable(__unused coalition_t coal)
236{
237 return;
238}
239
240static inline bool
241coalition_is_swappable(__unused coalition_t coal)
242{
243 return false;
244}
245
246#endif /* CONFIG_COALITIONS */
247
248__END_DECLS
249
250#endif /* XNU_KERNEL_PRIVATE */
251#endif /* _KERN_COALITION_H */
252