]>
Commit | Line | Data |
---|---|---|
3e170ce0 | 1 | /* |
5ba3f43e | 2 | * Copyright (c) 2015-2017 Apple Inc. All rights reserved. |
3e170ce0 A |
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 _SYS_WORK_INTERVAL_H | |
30 | #define _SYS_WORK_INTERVAL_H | |
31 | ||
32 | #include <stdint.h> | |
3e170ce0 | 33 | #include <sys/cdefs.h> |
5ba3f43e A |
34 | #include <sys/_types/_size_t.h> |
35 | ||
36 | #include <mach/port.h> | |
3e170ce0 A |
37 | |
38 | __BEGIN_DECLS | |
39 | ||
40 | /* | |
5ba3f43e A |
41 | * A work interval is a repeatable unit of work characterized by a |
42 | * start, finish, and deadline. | |
43 | * | |
3e170ce0 A |
44 | * Trusted clients with deadline-sensitive work may report information |
45 | * about the execution of their work using the work interval facility. | |
46 | * This is intended to be a higher-level semantic than realtime scheduling, | |
47 | * which operates at the level of thread block/unblock. A high level | |
48 | * operation may have many blocking points, including IPC to other tasks, | |
49 | * and this this metric will capture the overall time to complete a unit of | |
50 | * work. | |
51 | * | |
52 | * A work interval is defined by several timestamps, namely (S)tart, | |
53 | * (F)inish, (D)eadline, and (N)ext start. | |
54 | * | |
55 | * ... ----+==================+--------+--+==== ... | |
56 | * | | | | | |
57 | * S F D N | |
58 | * | |
59 | * \__________________/ | |
60 | * Active | |
61 | * \___________________________/ | |
62 | * Work Interval | |
63 | * | |
64 | * \_________/ | |
65 | * | | |
66 | * report information here ---------+ | |
67 | * | |
68 | * Definitions: | |
69 | * | |
70 | * Start: Absolute time when the current deadline-oriented work began. Due | |
71 | * to scheduling latency, preemption, and blocking points, the | |
72 | * thread controlling the work interval may actually begin | |
73 | * executing after this ideal time (which may be the previous work | |
74 | * interval's "next start") | |
75 | * Finish: Absolute time when the current deadline-oriented work finished. | |
76 | * This will typically be a timestamp taken before reporting using | |
77 | * the work interval interface. | |
78 | * Deadline: Absolute time by which the current work was expected to finish. | |
79 | * In cases where the amount of computation (or preemption, or time | |
80 | * spent blocked) causes the active period to take longer than | |
81 | * expected, F may be greater than D. | |
82 | * Next start: Absolute time when the next deadline-oriented work is | |
83 | * expected to begin. This is typically the same as Deadline. | |
84 | * Active: The fraction of the work interval spent completing the work. In | |
85 | * cases where the Finish time exceeded the Deadline, this fraction | |
86 | * will be >1.0. | |
87 | * | |
88 | * Basic Use: | |
89 | * | |
90 | * Clients should report information for a work interval after finishing | |
91 | * work for the current interval but before the next work interval begins. | |
92 | * | |
93 | * If Finish far exceeds the previously expected Deadline, the | |
94 | * caller may adjust Next Start to align to a multiple of the period | |
95 | * (and skip over several work intervals that could not be | |
96 | * executed). | |
97 | * | |
98 | * Caution (!): | |
99 | * | |
100 | * Because the information supplied via this facility directly influences power | |
101 | * management decisions, clients should strive to be as accurate as possible. | |
102 | * Failure to do so will adversely impact system power and performance. | |
103 | * | |
f427ee49 A |
104 | * Work Interval Auto Join Support: |
105 | * | |
106 | * Work intervals support an optional flag WORK_INTERVAL_FLAG_ENABLE_AUTO_JOIN | |
107 | * which allows RT threads from the same home thread group to join work | |
108 | * intervals via wakeup relationship tracking. Based on the join policy, | |
109 | * RT threads can temporarily join the work interval of other RT threads | |
110 | * which make them runnable. The auto joined thread remains in the work | |
111 | * interval until it blocks or terminates. The mechanism works through | |
112 | * make runnable heuristic and it should be used with extreme caution. | |
113 | * If a client specifies this flag, it gives up explicit control over its | |
114 | * thread group membership and threads unrelated to the work interval | |
115 | * could become part of the thread group. This could lead to serious power | |
116 | * and performance issues. If the make runnable heuristic does not work | |
117 | * for a client use case, it should adopt work_interval_join_port() or | |
118 | * work_interval_join() to explicitly declare its intent. | |
119 | * | |
120 | * Work Interval Deferred Finish Support: | |
121 | * | |
122 | * Another advanced feature for work intervals is the ability to defer the finish | |
123 | * calls for the work interval until all auto-joined threads for the work interval | |
124 | * have blocked or terminated. This feature is enabled via an optional flag | |
125 | * WORK_INTERVAL_FLAG_ENABLE_DEFERRED_FINISH and is valid only if the work interval | |
126 | * is configured with the WORK_INTERVAL_FLAG_ENABLE_AUTO_JOIN flag as well. The | |
127 | * deferred finish mechanism allows the work interval to defer the finish call | |
128 | * for the work interval until all auto-join threads have blocked/terminated | |
129 | * (and have therefore un-joined the work interval) or one of the work interval | |
130 | * threads calls start for the next frame. The deferred finish works only for | |
131 | * workloads that have no temporal overlap across frames i.e. previous frame has to | |
132 | * finish before next frame can start. This feature should be used with caution | |
133 | * since auto-joined threads would delay finish calls to the performance controller | |
134 | * which could lead to poor performance and battery life. | |
3e170ce0 | 135 | */ |
5ba3f43e A |
136 | |
137 | /* Flags to be passed with work_interval_create() */ | |
138 | ||
139 | /* If interval is joinable, create no longer implicitly joins, you must use work_interval_join */ | |
f427ee49 | 140 | #define WORK_INTERVAL_FLAG_JOINABLE (0x1) |
5ba3f43e | 141 | /* Only threads that join the group are measured together, otherwise the group is the creator's home group */ |
f427ee49 A |
142 | #define WORK_INTERVAL_FLAG_GROUP (0x2) |
143 | /* Specifies that the work interval is being created by a client who doesn't | |
144 | * necessarily have the PRIV_WORK_INTERVAL entitlement. Skip privilege checks. | |
145 | * This can only be masked in for work intervals of types COREAUDIO, CA_CLIENT | |
146 | * and DEFAULT */ | |
147 | #define WORK_INTERVAL_FLAG_UNRESTRICTED (0x4) | |
148 | ||
149 | /* [Advanced Flag] Read section on "Work Interval Auto Join Support" above for details */ | |
150 | #define WORK_INTERVAL_FLAG_ENABLE_AUTO_JOIN (0x8) | |
151 | /* [Advanced Flag] Read section on "Work Interval Deferred Finish Support" above for details */ | |
152 | #define WORK_INTERVAL_FLAG_ENABLE_DEFERRED_FINISH (0x10) | |
153 | ||
154 | /* Kernel-supplied flag: Work interval has been ignored by the kernel */ | |
155 | #define WORK_INTERVAL_FLAG_IGNORED (0x20) | |
5ba3f43e | 156 | |
c3c9b80d A |
157 | /* Specifies that the work interval requests the system to provide just enough performance |
158 | * to be able to finish at the provided deadline and no sooner. */ | |
159 | #define WORK_INTERVAL_FLAG_FINISH_AT_DEADLINE (0x40) | |
160 | ||
5ba3f43e A |
161 | /* Flags to describe the interval flavor to the performance controller */ |
162 | #define WORK_INTERVAL_TYPE_MASK (0xF0000000) | |
163 | #define WORK_INTERVAL_TYPE_DEFAULT (0x0 << 28) | |
164 | #define WORK_INTERVAL_TYPE_COREAUDIO (0x1 << 28) | |
165 | #define WORK_INTERVAL_TYPE_COREANIMATION (0x2 << 28) | |
a39ff7e2 A |
166 | #define WORK_INTERVAL_TYPE_CA_RENDER_SERVER (0x2 << 28) |
167 | #define WORK_INTERVAL_TYPE_CA_CLIENT (0x3 << 28) | |
d9a64523 | 168 | #define WORK_INTERVAL_TYPE_HID_DELIVERY (0x4 << 28) |
cb323159 | 169 | #define WORK_INTERVAL_TYPE_COREMEDIA (0x5 << 28) |
c3c9b80d | 170 | #define WORK_INTERVAL_TYPE_ARKIT (0x6 << 28) |
5ba3f43e A |
171 | #define WORK_INTERVAL_TYPE_LAST (0xF << 28) |
172 | ||
3e170ce0 A |
173 | #ifndef KERNEL |
174 | ||
175 | typedef struct work_interval *work_interval_t; | |
a39ff7e2 | 176 | typedef struct work_interval_instance *work_interval_instance_t; |
3e170ce0 | 177 | |
5ba3f43e A |
178 | /* |
179 | * Create a new work interval handle. | |
180 | * | |
181 | * May fail with EALREADY if the current group already has a work interval. | |
182 | * | |
183 | * With no flags: | |
184 | * Auto-joins the work interval to the creating thread | |
185 | * May only use interval_handle from creating thread | |
186 | * Data provided affects native thread group | |
187 | * | |
188 | * With the JOINABLE flag | |
189 | * interval_handle is usable by the process | |
190 | * creating thread does not auto-join | |
191 | * notifying thread must have joined when notifying | |
192 | * | |
193 | * With the GROUP flag | |
194 | * creates a new thread group to isolate the joined threads from | |
195 | * the rest of the process for performance controller analysis | |
196 | * Threads which join the work interval become members of this new group | |
197 | * | |
198 | * TODO: Add a name parameter so that clients can name the work interval | |
199 | * Can also take the thread name from the notifying thread | |
200 | * | |
201 | * Requires the 'com.apple.private.kernel.work-interval' entitlement (PRIV_WORK_INTERVAL) | |
202 | * | |
203 | * Note that joining a work interval supersedes automatic thread group management via vouchers | |
204 | */ | |
205 | int work_interval_create(work_interval_t *interval_handle, uint32_t flags); | |
3e170ce0 | 206 | |
f427ee49 A |
207 | /* Returns the flags used for the work interval when it was created. |
208 | * | |
209 | * May fail with EINVAL if the port isn't from a prior call to | |
210 | * work_interval_copy_port. | |
211 | */ | |
212 | int work_interval_get_flags_from_port(mach_port_t port, uint32_t *flags); | |
213 | ||
a39ff7e2 | 214 | |
5ba3f43e A |
215 | /* |
216 | * Notify the power management subsystem that the work for a current interval has completed | |
217 | * | |
218 | * Only the process which created the work interval may notify | |
219 | */ | |
220 | int work_interval_notify(work_interval_t interval_handle, | |
0a7de745 A |
221 | uint64_t start, uint64_t finish, |
222 | uint64_t deadline, uint64_t next_start, | |
223 | uint32_t flags); | |
3e170ce0 | 224 | |
5ba3f43e A |
225 | /* |
226 | * Notify, with "finish" implicitly set to the current time | |
227 | * | |
228 | * Only the process which created the work interval may notify | |
229 | */ | |
230 | int work_interval_notify_simple(work_interval_t interval_handle, | |
0a7de745 A |
231 | uint64_t start, uint64_t deadline, |
232 | uint64_t next_start); | |
3e170ce0 | 233 | |
5ba3f43e A |
234 | /* |
235 | * Deallocate work interval handle | |
236 | * For non-JOINABLE, also removes thread from work interval | |
237 | * For JOINABLE, does not remove thread (needs a leave as well) | |
238 | */ | |
239 | int work_interval_destroy(work_interval_t interval_handle); | |
3e170ce0 | 240 | |
5ba3f43e A |
241 | /* |
242 | * Join work interval via work interval handle | |
243 | * Only allowed if interval is using the joinable and group flags | |
244 | * | |
245 | * Supersedes automatic thread group management via vouchers | |
246 | */ | |
247 | int work_interval_join(work_interval_t interval_handle); | |
248 | ||
249 | /* | |
250 | * extract Mach send right representing work interval thread group | |
251 | * Returns a +1 send right ref, which must be deallocated via mach_port_deallocate | |
252 | * Only allowed if interval is joinable, otherwise returns ENOTSUP | |
253 | * | |
254 | * Supersedes automatic thread group management via vouchers | |
255 | */ | |
256 | int work_interval_copy_port(work_interval_t interval_handle, mach_port_t *port); | |
257 | ||
258 | /* | |
259 | * Join work interval via Mach send right | |
260 | * | |
261 | * Does NOT consume Mach send right, must deallocate with mach_port_deallocate after using | |
262 | * It's safe to deallocate the right after joining, the thread will stay joined | |
263 | * | |
264 | * Can be sent to clients via xpc_dictionary_copy_mach_send, and similar | |
265 | * | |
266 | * Supersedes automatic thread group management via vouchers | |
267 | * | |
268 | * If the underlying work interval object is terminated then this may return ENOENT | |
269 | * <rdar://problem/31819320> | |
270 | */ | |
271 | int work_interval_join_port(mach_port_t port); | |
272 | ||
273 | /* | |
274 | * Leave the current thread's work interval | |
275 | */ | |
276 | int work_interval_leave(void); | |
277 | ||
5ba3f43e | 278 | #endif /* !KERNEL */ |
3e170ce0 A |
279 | |
280 | #if PRIVATE | |
281 | ||
282 | /* Private interface between Libsyscall and xnu */ | |
5ba3f43e A |
283 | #define WORK_INTERVAL_OPERATION_CREATE 0x00000001 /* deprecated */ |
284 | #define WORK_INTERVAL_OPERATION_DESTROY 0x00000002 /* arg is NULL */ | |
285 | #define WORK_INTERVAL_OPERATION_NOTIFY 0x00000003 /* arg is a work_interval_notification_t */ | |
286 | #define WORK_INTERVAL_OPERATION_CREATE2 0x00000004 /* arg is a work_interval_create_params */ | |
287 | #define WORK_INTERVAL_OPERATION_JOIN 0x00000005 /* arg is a port_name */ | |
f427ee49 | 288 | #define WORK_INTERVAL_OPERATION_GET_FLAGS 0x00000009 /* arg is a port name */ |
3e170ce0 A |
289 | |
290 | struct work_interval_notification { | |
0a7de745 A |
291 | uint64_t start; |
292 | uint64_t finish; | |
293 | uint64_t deadline; | |
294 | uint64_t next_start; | |
295 | uint32_t notify_flags; | |
296 | uint32_t create_flags; | |
3e170ce0 A |
297 | }; |
298 | typedef struct work_interval_notification *work_interval_notification_t; | |
299 | ||
5ba3f43e | 300 | struct work_interval_create_params { |
f427ee49 A |
301 | uint64_t wicp_id; /* in/out param */ |
302 | mach_port_name_t wicp_port; /* in/out param */ | |
5ba3f43e A |
303 | uint32_t wicp_create_flags; |
304 | }; | |
305 | ||
a39ff7e2 | 306 | |
5ba3f43e | 307 | int __work_interval_ctl(uint32_t operation, uint64_t work_interval_id, void *arg, size_t len); |
3e170ce0 A |
308 | |
309 | #endif /* PRIVATE */ | |
310 | ||
311 | __END_DECLS | |
312 | ||
313 | #endif /* _SYS_WORK_INTERVAL_H */ |