]>
Commit | Line | Data |
---|---|---|
1c79356b | 1 | /* |
39236c6e | 2 | * Copyright (c) 2000-2012 Apple Inc. All rights reserved. |
1c79356b | 3 | * |
2d21ac55 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
1c79356b | 5 | * |
2d21ac55 A |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
8f6c56a5 | 14 | * |
2d21ac55 A |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
18 | * The Original Code and all software distributed under the License are | |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
8f6c56a5 A |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
2d21ac55 A |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
23 | * Please see the License for the specific language governing rights and | |
24 | * limitations under the License. | |
8f6c56a5 | 25 | * |
2d21ac55 | 26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
1c79356b A |
27 | */ |
28 | /* | |
29 | * @OSF_COPYRIGHT@ | |
30 | */ | |
31 | /* | |
32 | * Mach Operating System | |
33 | * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University | |
34 | * All Rights Reserved. | |
35 | * | |
36 | * Permission to use, copy, modify and distribute this software and its | |
37 | * documentation is hereby granted, provided that both the copyright | |
38 | * notice and this permission notice appear in all copies of the | |
39 | * software, derivative works or modified versions, and any portions | |
40 | * thereof, and that both notices appear in supporting documentation. | |
41 | * | |
42 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" | |
43 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR | |
44 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. | |
45 | * | |
46 | * Carnegie Mellon requests users of this software to return to | |
47 | * | |
48 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU | |
49 | * School of Computer Science | |
50 | * Carnegie Mellon University | |
51 | * Pittsburgh PA 15213-3890 | |
52 | * | |
53 | * any improvements or extensions that they make and grant Carnegie Mellon | |
54 | * the rights to redistribute these changes. | |
55 | */ | |
56 | /* | |
57 | */ | |
58 | /* | |
59 | * File: sched_prim.h | |
60 | * Author: David Golub | |
61 | * | |
62 | * Scheduling primitive definitions file | |
63 | * | |
64 | */ | |
65 | ||
66 | #ifndef _KERN_SCHED_PRIM_H_ | |
67 | #define _KERN_SCHED_PRIM_H_ | |
68 | ||
69 | #include <mach/boolean.h> | |
70 | #include <mach/machine/vm_types.h> | |
71 | #include <mach/kern_return.h> | |
72 | #include <kern/clock.h> | |
73 | #include <kern/kern_types.h> | |
74 | #include <kern/thread.h> | |
91447636 | 75 | #include <sys/cdefs.h> |
813fb2f6 | 76 | #include <kern/block_hint.h> |
9bccf70c A |
77 | |
78 | #ifdef MACH_KERNEL_PRIVATE | |
1c79356b | 79 | |
3e170ce0 A |
80 | #include <mach/branch_predicates.h> |
81 | ||
91447636 | 82 | /* Initialization */ |
39236c6e | 83 | extern void sched_init(void); |
1c79356b | 84 | |
91447636 | 85 | extern void sched_startup(void); |
1c79356b | 86 | |
91447636 | 87 | extern void sched_timebase_init(void); |
1c79356b | 88 | |
91447636 | 89 | /* Force a preemption point for a thread and wait for it to stop running */ |
1c79356b | 90 | extern boolean_t thread_stop( |
39236c6e A |
91 | thread_t thread, |
92 | boolean_t until_not_runnable); | |
1c79356b | 93 | |
91447636 A |
94 | /* Release a previous stop request */ |
95 | extern void thread_unstop( | |
1c79356b A |
96 | thread_t thread); |
97 | ||
91447636 A |
98 | /* Wait for a thread to stop running */ |
99 | extern void thread_wait( | |
316670eb A |
100 | thread_t thread, |
101 | boolean_t until_not_runnable); | |
1c79356b | 102 | |
91447636 A |
103 | /* Unblock thread on wake up */ |
104 | extern boolean_t thread_unblock( | |
105 | thread_t thread, | |
106 | wait_result_t wresult); | |
1c79356b | 107 | |
91447636 A |
108 | /* Unblock and dispatch thread */ |
109 | extern kern_return_t thread_go( | |
110 | thread_t thread, | |
111 | wait_result_t wresult); | |
1c79356b | 112 | |
2d21ac55 | 113 | /* Handle threads at context switch */ |
91447636 | 114 | extern void thread_dispatch( |
2d21ac55 A |
115 | thread_t old_thread, |
116 | thread_t new_thread); | |
1c79356b | 117 | |
91447636 A |
118 | /* Switch directly to a particular thread */ |
119 | extern int thread_run( | |
120 | thread_t self, | |
121 | thread_continue_t continuation, | |
122 | void *parameter, | |
123 | thread_t new_thread); | |
124 | ||
125 | /* Resume thread with new stack */ | |
126 | extern void thread_continue( | |
127 | thread_t old_thread); | |
128 | ||
1c79356b A |
129 | /* Invoke continuation */ |
130 | extern void call_continuation( | |
91447636 A |
131 | thread_continue_t continuation, |
132 | void *parameter, | |
133 | wait_result_t wresult); | |
9bccf70c A |
134 | |
135 | /* Set the current scheduled priority */ | |
136 | extern void set_sched_pri( | |
137 | thread_t thread, | |
138 | int priority); | |
1c79356b | 139 | |
9bccf70c | 140 | /* Set base priority of the specified thread */ |
fe8ab488 | 141 | extern void sched_set_thread_base_priority( |
9bccf70c A |
142 | thread_t thread, |
143 | int priority); | |
144 | ||
fe8ab488 A |
145 | /* Set the thread's true scheduling mode */ |
146 | extern void sched_set_thread_mode(thread_t thread, | |
147 | sched_mode_t mode); | |
148 | /* Demote the true scheduler mode */ | |
149 | extern void sched_thread_mode_demote(thread_t thread, | |
150 | uint32_t reason); | |
151 | /* Un-demote the true scheduler mode */ | |
152 | extern void sched_thread_mode_undemote(thread_t thread, | |
153 | uint32_t reason); | |
154 | ||
3e170ce0 A |
155 | /* Re-evaluate base priority of thread (thread locked) */ |
156 | void thread_recompute_priority(thread_t thread); | |
157 | ||
158 | /* Re-evaluate base priority of thread (thread unlocked) */ | |
159 | void thread_recompute_qos(thread_t thread); | |
160 | ||
9bccf70c | 161 | /* Reset scheduled priority of thread */ |
3e170ce0 | 162 | extern void thread_recompute_sched_pri( |
9bccf70c A |
163 | thread_t thread, |
164 | boolean_t override_depress); | |
1c79356b | 165 | |
1c79356b | 166 | /* Periodic scheduler activity */ |
6d2010ae | 167 | extern void sched_init_thread(void (*)(void)); |
1c79356b | 168 | |
91447636 | 169 | /* Perform sched_tick housekeeping activities */ |
6d2010ae | 170 | extern boolean_t can_update_priority( |
9bccf70c | 171 | thread_t thread); |
1c79356b | 172 | |
6d2010ae A |
173 | extern void update_priority( |
174 | thread_t thread); | |
175 | ||
176 | extern void lightweight_update_priority( | |
177 | thread_t thread); | |
178 | ||
3e170ce0 | 179 | extern void sched_default_quantum_expire(thread_t thread); |
6d2010ae | 180 | |
91447636 | 181 | /* Idle processor thread */ |
1c79356b A |
182 | extern void idle_thread(void); |
183 | ||
91447636 A |
184 | extern kern_return_t idle_thread_create( |
185 | processor_t processor); | |
1c79356b | 186 | |
1c79356b A |
187 | /* Continuation return from syscall */ |
188 | extern void thread_syscall_return( | |
189 | kern_return_t ret); | |
190 | ||
91447636 | 191 | /* Context switch */ |
9bccf70c A |
192 | extern wait_result_t thread_block_reason( |
193 | thread_continue_t continuation, | |
91447636 | 194 | void *parameter, |
9bccf70c | 195 | ast_t reason); |
1c79356b | 196 | |
91447636 | 197 | /* Reschedule thread for execution */ |
1c79356b | 198 | extern void thread_setrun( |
9bccf70c | 199 | thread_t thread, |
55e303ae | 200 | integer_t options); |
1c79356b | 201 | |
2d21ac55 A |
202 | #define SCHED_TAILQ 1 |
203 | #define SCHED_HEADQ 2 | |
204 | #define SCHED_PREEMPT 4 | |
1c79356b | 205 | |
3e170ce0 A |
206 | extern uintptr_t sched_thread_on_rt_queue; |
207 | #define THREAD_ON_RT_RUNQ ((processor_t)(uintptr_t)&sched_thread_on_rt_queue) | |
208 | ||
b0d623f7 A |
209 | extern processor_set_t task_choose_pset( |
210 | task_t task); | |
211 | ||
2d21ac55 | 212 | /* Bind the current thread to a particular processor */ |
55e303ae | 213 | extern processor_t thread_bind( |
55e303ae | 214 | processor_t processor); |
1c79356b | 215 | |
6d2010ae A |
216 | /* Choose the best processor to run a thread */ |
217 | extern processor_t choose_processor( | |
218 | processor_set_t pset, | |
219 | processor_t processor, | |
220 | thread_t thread); | |
221 | ||
6d2010ae A |
222 | |
223 | extern void thread_quantum_init( | |
224 | thread_t thread); | |
225 | ||
2d21ac55 A |
226 | extern void run_queue_init( |
227 | run_queue_t runq); | |
228 | ||
6d2010ae A |
229 | extern thread_t run_queue_dequeue( |
230 | run_queue_t runq, | |
231 | integer_t options); | |
232 | ||
233 | extern boolean_t run_queue_enqueue( | |
234 | run_queue_t runq, | |
235 | thread_t thread, | |
236 | integer_t options); | |
237 | ||
238 | extern void run_queue_remove( | |
239 | run_queue_t runq, | |
240 | thread_t thread); | |
241 | ||
3e170ce0 A |
242 | struct sched_update_scan_context |
243 | { | |
244 | uint64_t earliest_bg_make_runnable_time; | |
245 | uint64_t earliest_normal_make_runnable_time; | |
246 | uint64_t earliest_rt_make_runnable_time; | |
247 | }; | |
248 | typedef struct sched_update_scan_context *sched_update_scan_context_t; | |
fe8ab488 A |
249 | |
250 | #if defined(CONFIG_SCHED_TIMESHARE_CORE) | |
251 | ||
3e170ce0 | 252 | extern boolean_t thread_update_add_thread(thread_t thread); |
fe8ab488 | 253 | extern void thread_update_process_threads(void); |
3e170ce0 A |
254 | extern boolean_t runq_scan(run_queue_t runq, sched_update_scan_context_t scan_context); |
255 | ||
256 | extern void sched_timeshare_init(void); | |
257 | extern void sched_timeshare_timebase_init(void); | |
258 | extern void sched_timeshare_maintenance_continue(void); | |
259 | ||
260 | extern boolean_t priority_is_urgent(int priority); | |
261 | extern uint32_t sched_timeshare_initial_quantum_size(thread_t thread); | |
fe8ab488 | 262 | |
3e170ce0 | 263 | extern int sched_compute_timeshare_priority(thread_t thread); |
fe8ab488 A |
264 | |
265 | #endif /* CONFIG_SCHED_TIMESHARE_CORE */ | |
266 | ||
3e170ce0 A |
267 | extern void rt_runq_scan(sched_update_scan_context_t scan_context); |
268 | ||
6d2010ae | 269 | /* Remove thread from its run queue */ |
3e170ce0 A |
270 | extern boolean_t thread_run_queue_remove(thread_t thread); |
271 | thread_t thread_run_queue_remove_for_handoff(thread_t thread); | |
272 | ||
273 | /* Put a thread back in the run queue after being yanked */ | |
274 | extern void thread_run_queue_reinsert(thread_t thread, integer_t options); | |
6d2010ae | 275 | |
91447636 A |
276 | extern void thread_timer_expire( |
277 | void *thread, | |
278 | void *p1); | |
279 | ||
6d2010ae A |
280 | extern boolean_t thread_eager_preemption( |
281 | thread_t thread); | |
282 | ||
6d2010ae A |
283 | extern boolean_t sched_generic_direct_dispatch_to_idle_processors; |
284 | ||
9bccf70c A |
285 | /* Set the maximum interrupt level for the thread */ |
286 | __private_extern__ wait_interrupt_t thread_interrupt_level( | |
287 | wait_interrupt_t interruptible); | |
288 | ||
289 | __private_extern__ wait_result_t thread_mark_wait_locked( | |
290 | thread_t thread, | |
291 | wait_interrupt_t interruptible); | |
292 | ||
9bccf70c A |
293 | /* Wake up locked thread directly, passing result */ |
294 | __private_extern__ kern_return_t clear_wait_internal( | |
295 | thread_t thread, | |
296 | wait_result_t result); | |
1c79356b | 297 | |
6d2010ae A |
298 | extern void sched_stats_handle_csw( |
299 | processor_t processor, | |
300 | int reasons, | |
301 | int selfpri, | |
302 | int otherpri); | |
303 | ||
304 | extern void sched_stats_handle_runq_change( | |
305 | struct runq_stats *stats, | |
306 | int old_count); | |
307 | ||
308 | ||
309 | ||
310 | #define SCHED_STATS_CSW(processor, reasons, selfpri, otherpri) \ | |
311 | do { \ | |
312 | if (__builtin_expect(sched_stats_active, 0)) { \ | |
313 | sched_stats_handle_csw((processor), \ | |
314 | (reasons), (selfpri), (otherpri)); \ | |
315 | } \ | |
316 | } while (0) | |
317 | ||
318 | ||
319 | #define SCHED_STATS_RUNQ_CHANGE(stats, old_count) \ | |
320 | do { \ | |
321 | if (__builtin_expect(sched_stats_active, 0)) { \ | |
322 | sched_stats_handle_runq_change((stats), \ | |
323 | (old_count)); \ | |
324 | } \ | |
325 | } while (0) | |
326 | ||
3e170ce0 A |
327 | extern uint32_t sched_debug_flags; |
328 | #define SCHED_DEBUG_FLAG_PLATFORM_TRACEPOINTS 0x00000001 | |
329 | #define SCHED_DEBUG_FLAG_CHOOSE_PROCESSOR_TRACEPOINTS 0x00000002 | |
330 | ||
331 | #define SCHED_DEBUG_PLATFORM_KERNEL_DEBUG_CONSTANT(...) do { \ | |
332 | if (__improbable(sched_debug_flags & SCHED_DEBUG_FLAG_PLATFORM_TRACEPOINTS)) { \ | |
333 | KERNEL_DEBUG_CONSTANT(__VA_ARGS__); \ | |
334 | } \ | |
335 | } while(0) | |
336 | ||
337 | #define SCHED_DEBUG_CHOOSE_PROCESSOR_KERNEL_DEBUG_CONSTANT(...) do { \ | |
338 | if (__improbable(sched_debug_flags & SCHED_DEBUG_FLAG_CHOOSE_PROCESSOR_TRACEPOINTS)) { \ | |
339 | KERNEL_DEBUG_CONSTANT(__VA_ARGS__); \ | |
340 | } \ | |
341 | } while(0) | |
342 | ||
6d2010ae A |
343 | #define THREAD_URGENCY_NONE 0 /* indicates that there is no currently runnable */ |
344 | #define THREAD_URGENCY_BACKGROUND 1 /* indicates that the thread is marked as a "background" thread */ | |
345 | #define THREAD_URGENCY_NORMAL 2 /* indicates that the thread is marked as a "normal" thread */ | |
346 | #define THREAD_URGENCY_REAL_TIME 3 /* indicates that the thread is marked as a "real-time" or urgent thread */ | |
347 | #define THREAD_URGENCY_MAX 4 /* Marker */ | |
39236c6e | 348 | /* Returns the "urgency" of a thread (provided by scheduler) */ |
6d2010ae | 349 | extern int thread_get_urgency( |
39236c6e | 350 | thread_t thread, |
6d2010ae A |
351 | uint64_t *rt_period, |
352 | uint64_t *rt_deadline); | |
353 | ||
354 | /* Tells the "urgency" of the just scheduled thread (provided by CPU PM) */ | |
355 | extern void thread_tell_urgency( | |
356 | int urgency, | |
357 | uint64_t rt_period, | |
39236c6e | 358 | uint64_t rt_deadline, |
3e170ce0 | 359 | uint64_t sched_latency, |
39236c6e | 360 | thread_t nthread); |
6d2010ae A |
361 | |
362 | /* Tells if there are "active" RT threads in the system (provided by CPU PM) */ | |
363 | extern void active_rt_threads( | |
364 | boolean_t active); | |
365 | ||
1c79356b A |
366 | #endif /* MACH_KERNEL_PRIVATE */ |
367 | ||
91447636 | 368 | __BEGIN_DECLS |
55e303ae | 369 | |
91447636 A |
370 | #ifdef XNU_KERNEL_PRIVATE |
371 | ||
372 | extern boolean_t assert_wait_possible(void); | |
1c79356b | 373 | |
39236c6e A |
374 | /* Toggles a global override to turn off CPU Throttling */ |
375 | #define CPU_THROTTLE_DISABLE 0 | |
376 | #define CPU_THROTTLE_ENABLE 1 | |
377 | extern void sys_override_cpu_throttle(int flag); | |
378 | ||
1c79356b | 379 | /* |
91447636 | 380 | ****************** Only exported until BSD stops using ******************** |
1c79356b | 381 | */ |
1c79356b | 382 | |
3e170ce0 A |
383 | extern void thread_vm_bind_group_add(void); |
384 | ||
1c79356b | 385 | /* Wake up thread directly, passing result */ |
9bccf70c A |
386 | extern kern_return_t clear_wait( |
387 | thread_t thread, | |
388 | wait_result_t result); | |
1c79356b | 389 | |
b7266188 A |
390 | /* Start thread running */ |
391 | extern void thread_bootstrap_return(void); | |
392 | ||
91447636 | 393 | /* Return from exception (BSD-visible interface) */ |
2d21ac55 | 394 | extern void thread_exception_return(void) __dead2; |
1c79356b | 395 | |
3e170ce0 A |
396 | #define SCHED_STRING_MAX_LENGTH (48) |
397 | /* String declaring the name of the current scheduler */ | |
398 | extern char sched_string[SCHED_STRING_MAX_LENGTH]; | |
399 | ||
400 | extern kern_return_t sched_work_interval_notify(thread_t thread, uint64_t work_interval_id, uint64_t start, uint64_t finish, uint64_t deadline, uint64_t next_start, uint32_t flags); | |
401 | ||
39037602 A |
402 | extern thread_t port_name_to_thread_for_ulock(mach_port_name_t thread_name); |
403 | ||
404 | /* Attempt to context switch to a specific runnable thread */ | |
405 | extern wait_result_t thread_handoff(thread_t thread); | |
406 | ||
407 | extern struct waitq *assert_wait_queue(event_t event); | |
408 | ||
409 | extern kern_return_t thread_wakeup_one_with_pri(event_t event, int priority); | |
410 | ||
411 | extern thread_t thread_wakeup_identify(event_t event, int priority); | |
412 | ||
91447636 | 413 | #endif /* XNU_KERNEL_PRIVATE */ |
1c79356b | 414 | |
813fb2f6 A |
415 | #ifdef KERNEL_PRIVATE |
416 | /* Set pending block hint for a particular object before we go into a wait state */ | |
417 | extern void thread_set_pending_block_hint( | |
418 | thread_t thread, | |
419 | block_hint_t block_hint); | |
420 | #endif /* KERNEL_PRIVATE */ | |
421 | ||
91447636 A |
422 | /* Context switch */ |
423 | extern wait_result_t thread_block( | |
424 | thread_continue_t continuation); | |
1c79356b | 425 | |
91447636 A |
426 | extern wait_result_t thread_block_parameter( |
427 | thread_continue_t continuation, | |
428 | void *parameter); | |
1c79356b | 429 | |
1c79356b | 430 | /* Declare thread will wait on a particular event */ |
91447636 A |
431 | extern wait_result_t assert_wait( |
432 | event_t event, | |
433 | wait_interrupt_t interruptible); | |
1c79356b | 434 | |
91447636 A |
435 | /* Assert that the thread intends to wait with a timeout */ |
436 | extern wait_result_t assert_wait_timeout( | |
437 | event_t event, | |
438 | wait_interrupt_t interruptible, | |
439 | uint32_t interval, | |
440 | uint32_t scale_factor); | |
1c79356b | 441 | |
39236c6e A |
442 | /* Assert that the thread intends to wait with an urgency, timeout and leeway */ |
443 | extern wait_result_t assert_wait_timeout_with_leeway( | |
444 | event_t event, | |
445 | wait_interrupt_t interruptible, | |
446 | wait_timeout_urgency_t urgency, | |
447 | uint32_t interval, | |
448 | uint32_t leeway, | |
449 | uint32_t scale_factor); | |
450 | ||
91447636 A |
451 | extern wait_result_t assert_wait_deadline( |
452 | event_t event, | |
453 | wait_interrupt_t interruptible, | |
454 | uint64_t deadline); | |
1c79356b | 455 | |
39236c6e A |
456 | /* Assert that the thread intends to wait with an urgency, deadline, and leeway */ |
457 | extern wait_result_t assert_wait_deadline_with_leeway( | |
458 | event_t event, | |
459 | wait_interrupt_t interruptible, | |
460 | wait_timeout_urgency_t urgency, | |
461 | uint64_t deadline, | |
462 | uint64_t leeway); | |
463 | ||
91447636 A |
464 | /* Wake up thread (or threads) waiting on a particular event */ |
465 | extern kern_return_t thread_wakeup_prim( | |
466 | event_t event, | |
467 | boolean_t one_thread, | |
6d2010ae A |
468 | wait_result_t result); |
469 | ||
1c79356b | 470 | #define thread_wakeup(x) \ |
316670eb | 471 | thread_wakeup_prim((x), FALSE, THREAD_AWAKENED) |
1c79356b | 472 | #define thread_wakeup_with_result(x, z) \ |
316670eb | 473 | thread_wakeup_prim((x), FALSE, (z)) |
1c79356b | 474 | #define thread_wakeup_one(x) \ |
316670eb | 475 | thread_wakeup_prim((x), TRUE, THREAD_AWAKENED) |
6d2010ae | 476 | |
39037602 A |
477 | /* Wakeup the specified thread if it is waiting on this event */ |
478 | extern kern_return_t thread_wakeup_thread(event_t event, thread_t thread); | |
1c79356b | 479 | |
39037602 | 480 | extern boolean_t preemption_enabled(void); |
91447636 | 481 | |
6d2010ae A |
482 | #ifdef MACH_KERNEL_PRIVATE |
483 | ||
484 | /* | |
485 | * Scheduler algorithm indirection. If only one algorithm is | |
486 | * enabled at compile-time, a direction function call is used. | |
487 | * If more than one is enabled, calls are dispatched through | |
488 | * a function pointer table. | |
489 | */ | |
490 | ||
fe8ab488 | 491 | #if !defined(CONFIG_SCHED_TRADITIONAL) && !defined(CONFIG_SCHED_PROTO) && !defined(CONFIG_SCHED_GRRR) && !defined(CONFIG_SCHED_MULTIQ) |
6d2010ae A |
492 | #error Enable at least one scheduler algorithm in osfmk/conf/MASTER.XXX |
493 | #endif | |
494 | ||
495 | #define SCHED(f) (sched_current_dispatch->f) | |
496 | ||
497 | struct sched_dispatch_table { | |
3e170ce0 | 498 | const char *sched_name; |
6d2010ae A |
499 | void (*init)(void); /* Init global state */ |
500 | void (*timebase_init)(void); /* Timebase-dependent initialization */ | |
501 | void (*processor_init)(processor_t processor); /* Per-processor scheduler init */ | |
502 | void (*pset_init)(processor_set_t pset); /* Per-processor set scheduler init */ | |
3e170ce0 | 503 | |
6d2010ae | 504 | void (*maintenance_continuation)(void); /* Function called regularly */ |
3e170ce0 | 505 | |
6d2010ae A |
506 | /* |
507 | * Choose a thread of greater or equal priority from the per-processor | |
508 | * runqueue for timeshare/fixed threads | |
509 | */ | |
510 | thread_t (*choose_thread)( | |
511 | processor_t processor, | |
fe8ab488 A |
512 | int priority, |
513 | ast_t reason); | |
3e170ce0 A |
514 | |
515 | /* True if scheduler supports stealing threads */ | |
516 | boolean_t steal_thread_enabled; | |
517 | ||
6d2010ae A |
518 | /* |
519 | * Steal a thread from another processor in the pset so that it can run | |
520 | * immediately | |
521 | */ | |
522 | thread_t (*steal_thread)( | |
523 | processor_set_t pset); | |
3e170ce0 | 524 | |
6d2010ae | 525 | /* |
3e170ce0 | 526 | * Compute priority for a timeshare thread based on base priority. |
6d2010ae | 527 | */ |
3e170ce0 A |
528 | int (*compute_timeshare_priority)(thread_t thread); |
529 | ||
6d2010ae A |
530 | /* |
531 | * Pick the best processor for a thread (any kind of thread) to run on. | |
532 | */ | |
533 | processor_t (*choose_processor)( | |
534 | processor_set_t pset, | |
535 | processor_t processor, | |
536 | thread_t thread); | |
537 | /* | |
538 | * Enqueue a timeshare or fixed priority thread onto the per-processor | |
539 | * runqueue | |
540 | */ | |
541 | boolean_t (*processor_enqueue)( | |
542 | processor_t processor, | |
543 | thread_t thread, | |
544 | integer_t options); | |
3e170ce0 | 545 | |
6d2010ae A |
546 | /* Migrate threads away in preparation for processor shutdown */ |
547 | void (*processor_queue_shutdown)( | |
548 | processor_t processor); | |
3e170ce0 | 549 | |
6d2010ae A |
550 | /* Remove the specific thread from the per-processor runqueue */ |
551 | boolean_t (*processor_queue_remove)( | |
fe8ab488 | 552 | processor_t processor, |
6d2010ae | 553 | thread_t thread); |
3e170ce0 | 554 | |
6d2010ae A |
555 | /* |
556 | * Does the per-processor runqueue have any timeshare or fixed priority | |
557 | * threads on it? Called without pset lock held, so should | |
558 | * not assume immutability while executing. | |
559 | */ | |
560 | boolean_t (*processor_queue_empty)(processor_t processor); | |
3e170ce0 | 561 | |
6d2010ae A |
562 | /* |
563 | * Would this priority trigger an urgent preemption if it's sitting | |
564 | * on the per-processor runqueue? | |
565 | */ | |
566 | boolean_t (*priority_is_urgent)(int priority); | |
3e170ce0 | 567 | |
6d2010ae A |
568 | /* |
569 | * Does the per-processor runqueue contain runnable threads that | |
570 | * should cause the currently-running thread to be preempted? | |
571 | */ | |
572 | ast_t (*processor_csw_check)(processor_t processor); | |
3e170ce0 | 573 | |
6d2010ae A |
574 | /* |
575 | * Does the per-processor runqueue contain a runnable thread | |
576 | * of > or >= priority, as a preflight for choose_thread() or other | |
577 | * thread selection | |
578 | */ | |
579 | boolean_t (*processor_queue_has_priority)(processor_t processor, | |
580 | int priority, | |
581 | boolean_t gte); | |
3e170ce0 | 582 | |
6d2010ae A |
583 | /* Quantum size for the specified non-realtime thread. */ |
584 | uint32_t (*initial_quantum_size)(thread_t thread); | |
585 | ||
586 | /* Scheduler mode for a new thread */ | |
587 | sched_mode_t (*initial_thread_sched_mode)(task_t parent_task); | |
3e170ce0 | 588 | |
6d2010ae A |
589 | /* |
590 | * Is it safe to call update_priority, which may change a thread's | |
591 | * runqueue or other state. This can be used to throttle changes | |
592 | * to dynamic priority. | |
593 | */ | |
594 | boolean_t (*can_update_priority)(thread_t thread); | |
595 | ||
596 | /* | |
597 | * Update both scheduled priority and other persistent state. | |
598 | * Side effects may including migration to another processor's runqueue. | |
599 | */ | |
600 | void (*update_priority)(thread_t thread); | |
3e170ce0 | 601 | |
6d2010ae A |
602 | /* Lower overhead update to scheduled priority and state. */ |
603 | void (*lightweight_update_priority)(thread_t thread); | |
3e170ce0 | 604 | |
6d2010ae A |
605 | /* Callback for non-realtime threads when the quantum timer fires */ |
606 | void (*quantum_expire)(thread_t thread); | |
3e170ce0 | 607 | |
6d2010ae A |
608 | /* |
609 | * Runnable threads on per-processor runqueue. Should only | |
610 | * be used for relative comparisons of load between processors. | |
611 | */ | |
612 | int (*processor_runq_count)(processor_t processor); | |
6d2010ae | 613 | |
3e170ce0 A |
614 | /* Aggregate runcount statistics for per-processor runqueue */ |
615 | uint64_t (*processor_runq_stats_count_sum)(processor_t processor); | |
fe8ab488 A |
616 | |
617 | boolean_t (*processor_bound_count)(processor_t processor); | |
618 | ||
3e170ce0 | 619 | void (*thread_update_scan)(sched_update_scan_context_t scan_context); |
fe8ab488 | 620 | |
6d2010ae A |
621 | /* |
622 | * Use processor->next_thread to pin a thread to an idle | |
623 | * processor. If FALSE, threads are enqueued and can | |
624 | * be stolen by other processors. | |
625 | */ | |
626 | boolean_t direct_dispatch_to_idle_processors; | |
3e170ce0 A |
627 | |
628 | /* Supports more than one pset */ | |
629 | boolean_t multiple_psets_enabled; | |
630 | /* Supports scheduler groups */ | |
631 | boolean_t sched_groups_enabled; | |
6d2010ae A |
632 | }; |
633 | ||
634 | #if defined(CONFIG_SCHED_TRADITIONAL) | |
6d2010ae A |
635 | extern const struct sched_dispatch_table sched_traditional_dispatch; |
636 | extern const struct sched_dispatch_table sched_traditional_with_pset_runqueue_dispatch; | |
637 | #endif | |
638 | ||
fe8ab488 A |
639 | #if defined(CONFIG_SCHED_MULTIQ) |
640 | extern const struct sched_dispatch_table sched_multiq_dispatch; | |
fe8ab488 | 641 | extern const struct sched_dispatch_table sched_dualq_dispatch; |
fe8ab488 A |
642 | #endif |
643 | ||
6d2010ae | 644 | #if defined(CONFIG_SCHED_PROTO) |
6d2010ae A |
645 | extern const struct sched_dispatch_table sched_proto_dispatch; |
646 | #endif | |
647 | ||
648 | #if defined(CONFIG_SCHED_GRRR) | |
6d2010ae A |
649 | extern const struct sched_dispatch_table sched_grrr_dispatch; |
650 | #endif | |
651 | ||
6d2010ae A |
652 | /* |
653 | * It is an error to invoke any scheduler-related code | |
654 | * before this is set up | |
655 | */ | |
6d2010ae A |
656 | extern const struct sched_dispatch_table *sched_current_dispatch; |
657 | ||
658 | #endif /* MACH_KERNEL_PRIVATE */ | |
659 | ||
91447636 | 660 | __END_DECLS |
1c79356b A |
661 | |
662 | #endif /* _KERN_SCHED_PRIM_H_ */ |