]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kern/sched_prim.c
xnu-2050.24.15.tar.gz
[apple/xnu.git] / osfmk / kern / sched_prim.c
CommitLineData
1c79356b 1/*
316670eb 2 * Copyright (c) 2000-2010 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_FREE_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.c
60 * Author: Avadis Tevanian, Jr.
61 * Date: 1986
62 *
63 * Scheduling primitives
64 *
65 */
66
67#include <debug.h>
91447636
A
68
69#include <mach/mach_types.h>
1c79356b 70#include <mach/machine.h>
91447636
A
71#include <mach/policy.h>
72#include <mach/sync_policy.h>
6d2010ae 73#include <mach/thread_act.h>
91447636 74
1c79356b
A
75#include <machine/machine_routines.h>
76#include <machine/sched_param.h>
0c530ab8 77#include <machine/machine_cpu.h>
6d2010ae 78#include <machine/machlimits.h>
91447636
A
79
80#include <kern/kern_types.h>
1c79356b
A
81#include <kern/clock.h>
82#include <kern/counters.h>
83#include <kern/cpu_number.h>
84#include <kern/cpu_data.h>
91447636 85#include <kern/debug.h>
1c79356b
A
86#include <kern/lock.h>
87#include <kern/macro_help.h>
88#include <kern/machine.h>
89#include <kern/misc_protos.h>
90#include <kern/processor.h>
91#include <kern/queue.h>
92#include <kern/sched.h>
93#include <kern/sched_prim.h>
94#include <kern/syscall_subr.h>
95#include <kern/task.h>
96#include <kern/thread.h>
91447636 97#include <kern/wait_queue.h>
316670eb 98#include <kern/ledger.h>
91447636 99
1c79356b
A
100#include <vm/pmap.h>
101#include <vm/vm_kern.h>
102#include <vm/vm_map.h>
91447636 103
b0d623f7
A
104#include <mach/sdt.h>
105
1c79356b
A
106#include <sys/kdebug.h>
107
0c530ab8 108#include <kern/pms.h>
3a60a9f5 109
6d2010ae 110struct rt_queue rt_runq;
2d21ac55
A
111#define RT_RUNQ ((processor_t)-1)
112decl_simple_lock_data(static,rt_lock);
113
6d2010ae
A
114#if defined(CONFIG_SCHED_TRADITIONAL) || defined(CONFIG_SCHED_PROTO) || defined(CONFIG_SCHED_GRRR) || defined(CONFIG_SCHED_FIXEDPRIORITY)
115static struct fairshare_queue fs_runq;
116#define FS_RUNQ ((processor_t)-2)
117decl_simple_lock_data(static,fs_lock);
118#endif
119
0b4e3aa0 120#define DEFAULT_PREEMPTION_RATE 100 /* (1/s) */
1c79356b
A
121int default_preemption_rate = DEFAULT_PREEMPTION_RATE;
122
316670eb
A
123#define DEFAULT_BG_PREEMPTION_RATE 400 /* (1/s) */
124int default_bg_preemption_rate = DEFAULT_BG_PREEMPTION_RATE;
125
0b4e3aa0
A
126#define MAX_UNSAFE_QUANTA 800
127int max_unsafe_quanta = MAX_UNSAFE_QUANTA;
128
129#define MAX_POLL_QUANTA 2
130int max_poll_quanta = MAX_POLL_QUANTA;
131
132#define SCHED_POLL_YIELD_SHIFT 4 /* 1/16 */
133int sched_poll_yield_shift = SCHED_POLL_YIELD_SHIFT;
134
55e303ae
A
135uint64_t max_poll_computation;
136
6d2010ae
A
137uint64_t max_unsafe_computation;
138uint64_t sched_safe_duration;
139
140#if defined(CONFIG_SCHED_TRADITIONAL)
141
55e303ae
A
142uint32_t std_quantum;
143uint32_t min_std_quantum;
316670eb 144uint32_t bg_quantum;
55e303ae 145
91447636 146uint32_t std_quantum_us;
316670eb 147uint32_t bg_quantum_us;
91447636 148
6d2010ae
A
149#endif /* CONFIG_SCHED_TRADITIONAL */
150
151uint32_t thread_depress_time;
152uint32_t default_timeshare_computation;
153uint32_t default_timeshare_constraint;
154
55e303ae
A
155uint32_t max_rt_quantum;
156uint32_t min_rt_quantum;
157
6d2010ae
A
158#if defined(CONFIG_SCHED_TRADITIONAL)
159
1c79356b 160unsigned sched_tick;
91447636 161uint32_t sched_tick_interval;
1c79356b 162
2d21ac55
A
163uint32_t sched_pri_shift = INT8_MAX;
164uint32_t sched_fixed_shift;
165
6d2010ae
A
166static boolean_t sched_traditional_use_pset_runqueue = FALSE;
167
4b17d6b6
A
168/* Defaults for timer deadline profiling */
169#define TIMER_DEADLINE_TRACKING_BIN_1_DEFAULT 2000000 /* Timers with deadlines <=
170 * 2ms */
171#define TIMER_DEADLINE_TRACKING_BIN_2_DEFAULT 5000000 /* Timers with deadlines
172 <= 5ms */
173uint64_t timer_deadline_tracking_bin_1;
174uint64_t timer_deadline_tracking_bin_2;
175
6d2010ae
A
176__attribute__((always_inline))
177static inline run_queue_t runq_for_processor(processor_t processor)
178{
179 if (sched_traditional_use_pset_runqueue)
180 return &processor->processor_set->pset_runq;
181 else
182 return &processor->runq;
183}
184
185__attribute__((always_inline))
186static inline void runq_consider_incr_bound_count(processor_t processor, thread_t thread)
187{
188 if (thread->bound_processor == PROCESSOR_NULL)
189 return;
190
191 assert(thread->bound_processor == processor);
192
193 if (sched_traditional_use_pset_runqueue)
194 processor->processor_set->pset_runq_bound_count++;
195
196 processor->runq_bound_count++;
197}
198
199__attribute__((always_inline))
200static inline void runq_consider_decr_bound_count(processor_t processor, thread_t thread)
201{
202 if (thread->bound_processor == PROCESSOR_NULL)
203 return;
204
205 assert(thread->bound_processor == processor);
206
207 if (sched_traditional_use_pset_runqueue)
208 processor->processor_set->pset_runq_bound_count--;
209
210 processor->runq_bound_count--;
211}
212
213#endif /* CONFIG_SCHED_TRADITIONAL */
214
215uint64_t sched_one_second_interval;
216
2d21ac55
A
217uint32_t sched_run_count, sched_share_count;
218uint32_t sched_load_average, sched_mach_factor;
219
1c79356b 220/* Forwards */
6d2010ae
A
221
222#if defined(CONFIG_SCHED_TRADITIONAL)
223
2d21ac55 224static void load_shift_init(void) __attribute__((section("__TEXT, initcode")));
4a3eedf9 225static void preempt_pri_init(void) __attribute__((section("__TEXT, initcode")));
2d21ac55 226
6d2010ae 227#endif /* CONFIG_SCHED_TRADITIONAL */
c910b4d9 228
6d2010ae
A
229static thread_t thread_select(
230 thread_t thread,
231 processor_t processor);
b0d623f7 232
6d2010ae 233#if CONFIG_SCHED_IDLE_IN_PLACE
2d21ac55
A
234static thread_t thread_select_idle(
235 thread_t thread,
236 processor_t processor);
6d2010ae 237#endif
1c79356b 238
6d2010ae 239thread_t processor_idle(
2d21ac55
A
240 thread_t thread,
241 processor_t processor);
91447636 242
6d2010ae
A
243#if defined(CONFIG_SCHED_TRADITIONAL)
244
2d21ac55 245static thread_t steal_thread(
cf7d32b8
A
246 processor_set_t pset);
247
6d2010ae
A
248static thread_t steal_thread_disabled(
249 processor_set_t pset) __attribute__((unused));
250
251
cf7d32b8 252static thread_t steal_processor_thread(
55e303ae 253 processor_t processor);
1c79356b 254
91447636 255static void thread_update_scan(void);
1c79356b 256
6d2010ae
A
257static void processor_setrun(
258 processor_t processor,
259 thread_t thread,
260 integer_t options);
261
262static boolean_t
263processor_enqueue(
264 processor_t processor,
265 thread_t thread,
266 integer_t options);
267
268static boolean_t
269processor_queue_remove(
270 processor_t processor,
271 thread_t thread);
272
273static boolean_t processor_queue_empty(processor_t processor);
274
275static boolean_t priority_is_urgent(int priority);
276
277static ast_t processor_csw_check(processor_t processor);
278
279static boolean_t processor_queue_has_priority(processor_t processor,
280 int priority,
281 boolean_t gte);
282
283static boolean_t should_current_thread_rechoose_processor(processor_t processor);
284
285static int sched_traditional_processor_runq_count(processor_t processor);
286
287static boolean_t sched_traditional_with_pset_runqueue_processor_queue_empty(processor_t processor);
288
289static uint64_t sched_traditional_processor_runq_stats_count_sum(processor_t processor);
290
291static uint64_t sched_traditional_with_pset_runqueue_processor_runq_stats_count_sum(processor_t processor);
292#endif
293
294
295#if defined(CONFIG_SCHED_TRADITIONAL)
296
297static void
298sched_traditional_init(void);
299
300static void
301sched_traditional_timebase_init(void);
302
303static void
304sched_traditional_processor_init(processor_t processor);
305
306static void
307sched_traditional_pset_init(processor_set_t pset);
308
309static void
310sched_traditional_with_pset_runqueue_init(void);
311
312#endif
313
314static void
315sched_realtime_init(void) __attribute__((section("__TEXT, initcode")));
316
317static void
318sched_realtime_timebase_init(void);
319
4b17d6b6
A
320static void
321sched_timer_deadline_tracking_init(void);
322
6d2010ae
A
323#if defined(CONFIG_SCHED_TRADITIONAL)
324static void
325sched_traditional_tick_continue(void);
326
327static uint32_t
328sched_traditional_initial_quantum_size(thread_t thread);
329
330static sched_mode_t
331sched_traditional_initial_thread_sched_mode(task_t parent_task);
332
333static boolean_t
334sched_traditional_supports_timeshare_mode(void);
335
336static thread_t
337sched_traditional_choose_thread(
338 processor_t processor,
339 int priority);
340
341#endif
342
2d21ac55
A
343#if DEBUG
344extern int debug_task;
345#define TLOG(a, fmt, args...) if(debug_task & a) kprintf(fmt, ## args)
346#else
347#define TLOG(a, fmt, args...) do {} while (0)
348#endif
349
1c79356b 350#if DEBUG
0b4e3aa0 351static
1c79356b
A
352boolean_t thread_runnable(
353 thread_t thread);
354
0b4e3aa0
A
355#endif /*DEBUG*/
356
1c79356b
A
357/*
358 * State machine
359 *
360 * states are combinations of:
361 * R running
362 * W waiting (or on wait queue)
363 * N non-interruptible
364 * O swapped out
365 * I being swapped in
366 *
367 * init action
368 * assert_wait thread_block clear_wait swapout swapin
369 *
370 * R RW, RWN R; setrun - -
371 * RN RWN RN; setrun - -
372 *
373 * RW W R -
374 * RWN WN RN -
375 *
376 * W R; setrun WO
377 * WN RN; setrun -
378 *
379 * RO - - R
380 *
381 */
382
6d2010ae 383#if defined(CONFIG_SCHED_TRADITIONAL)
91447636 384int8_t sched_load_shifts[NRQS];
b0d623f7 385int sched_preempt_pri[NRQBM];
6d2010ae
A
386#endif
387
388
389#if defined(CONFIG_SCHED_TRADITIONAL)
390
391const struct sched_dispatch_table sched_traditional_dispatch = {
392 sched_traditional_init,
393 sched_traditional_timebase_init,
394 sched_traditional_processor_init,
395 sched_traditional_pset_init,
396 sched_traditional_tick_continue,
397 sched_traditional_choose_thread,
398 steal_thread,
399 compute_priority,
400 choose_processor,
401 processor_enqueue,
402 processor_queue_shutdown,
403 processor_queue_remove,
404 processor_queue_empty,
405 priority_is_urgent,
406 processor_csw_check,
407 processor_queue_has_priority,
408 sched_traditional_initial_quantum_size,
409 sched_traditional_initial_thread_sched_mode,
410 sched_traditional_supports_timeshare_mode,
411 can_update_priority,
412 update_priority,
413 lightweight_update_priority,
414 sched_traditional_quantum_expire,
415 should_current_thread_rechoose_processor,
416 sched_traditional_processor_runq_count,
417 sched_traditional_processor_runq_stats_count_sum,
418 sched_traditional_fairshare_init,
419 sched_traditional_fairshare_runq_count,
420 sched_traditional_fairshare_runq_stats_count_sum,
421 sched_traditional_fairshare_enqueue,
422 sched_traditional_fairshare_dequeue,
423 sched_traditional_fairshare_queue_remove,
424 TRUE /* direct_dispatch_to_idle_processors */
425};
426
427const struct sched_dispatch_table sched_traditional_with_pset_runqueue_dispatch = {
428 sched_traditional_with_pset_runqueue_init,
429 sched_traditional_timebase_init,
430 sched_traditional_processor_init,
431 sched_traditional_pset_init,
432 sched_traditional_tick_continue,
433 sched_traditional_choose_thread,
434 steal_thread,
435 compute_priority,
436 choose_processor,
437 processor_enqueue,
438 processor_queue_shutdown,
439 processor_queue_remove,
440 sched_traditional_with_pset_runqueue_processor_queue_empty,
441 priority_is_urgent,
442 processor_csw_check,
443 processor_queue_has_priority,
444 sched_traditional_initial_quantum_size,
445 sched_traditional_initial_thread_sched_mode,
446 sched_traditional_supports_timeshare_mode,
447 can_update_priority,
448 update_priority,
449 lightweight_update_priority,
450 sched_traditional_quantum_expire,
451 should_current_thread_rechoose_processor,
452 sched_traditional_processor_runq_count,
453 sched_traditional_with_pset_runqueue_processor_runq_stats_count_sum,
454 sched_traditional_fairshare_init,
455 sched_traditional_fairshare_runq_count,
456 sched_traditional_fairshare_runq_stats_count_sum,
457 sched_traditional_fairshare_enqueue,
458 sched_traditional_fairshare_dequeue,
459 sched_traditional_fairshare_queue_remove,
460 FALSE /* direct_dispatch_to_idle_processors */
461};
462
463#endif
464
465const struct sched_dispatch_table *sched_current_dispatch = NULL;
466
467/*
468 * Statically allocate a buffer to hold the longest possible
469 * scheduler description string, as currently implemented.
470 * bsd/kern/kern_sysctl.c has a corresponding definition in bsd/
471 * to export to userspace via sysctl(3). If either version
472 * changes, update the other.
473 *
474 * Note that in addition to being an upper bound on the strings
475 * in the kernel, it's also an exact parameter to PE_get_default(),
476 * which interrogates the device tree on some platforms. That
477 * API requires the caller know the exact size of the device tree
478 * property, so we need both a legacy size (32) and the current size
479 * (48) to deal with old and new device trees. The device tree property
480 * is similarly padded to a fixed size so that the same kernel image
481 * can run on multiple devices with different schedulers configured
482 * in the device tree.
483 */
484#define SCHED_STRING_MAX_LENGTH (48)
485
486char sched_string[SCHED_STRING_MAX_LENGTH];
487static enum sched_enum _sched_enum = sched_enum_unknown;
91447636 488
1c79356b
A
489void
490sched_init(void)
6d2010ae
A
491{
492 char sched_arg[SCHED_STRING_MAX_LENGTH] = { '\0' };
493
494 /* Check for runtime selection of the scheduler algorithm */
495 if (!PE_parse_boot_argn("sched", sched_arg, sizeof (sched_arg))) {
496 /* If no boot-args override, look in device tree */
497 if (!PE_get_default("kern.sched", sched_arg,
498 SCHED_STRING_MAX_LENGTH)) {
499 sched_arg[0] = '\0';
500 }
501 }
502
503 if (strlen(sched_arg) > 0) {
504 if (0) {
505 /* Allow pattern below */
506#if defined(CONFIG_SCHED_TRADITIONAL)
507 } else if (0 == strcmp(sched_arg, kSchedTraditionalString)) {
508 sched_current_dispatch = &sched_traditional_dispatch;
509 _sched_enum = sched_enum_traditional;
510 strlcpy(sched_string, kSchedTraditionalString, sizeof(sched_string));
511 kprintf("Scheduler: Runtime selection of %s\n", kSchedTraditionalString);
512 } else if (0 == strcmp(sched_arg, kSchedTraditionalWithPsetRunqueueString)) {
513 sched_current_dispatch = &sched_traditional_with_pset_runqueue_dispatch;
514 _sched_enum = sched_enum_traditional_with_pset_runqueue;
515 strlcpy(sched_string, kSchedTraditionalWithPsetRunqueueString, sizeof(sched_string));
516 kprintf("Scheduler: Runtime selection of %s\n", kSchedTraditionalWithPsetRunqueueString);
517#endif
518#if defined(CONFIG_SCHED_PROTO)
519 } else if (0 == strcmp(sched_arg, kSchedProtoString)) {
520 sched_current_dispatch = &sched_proto_dispatch;
521 _sched_enum = sched_enum_proto;
522 strlcpy(sched_string, kSchedProtoString, sizeof(sched_string));
523 kprintf("Scheduler: Runtime selection of %s\n", kSchedProtoString);
524#endif
525#if defined(CONFIG_SCHED_GRRR)
526 } else if (0 == strcmp(sched_arg, kSchedGRRRString)) {
527 sched_current_dispatch = &sched_grrr_dispatch;
528 _sched_enum = sched_enum_grrr;
529 strlcpy(sched_string, kSchedGRRRString, sizeof(sched_string));
530 kprintf("Scheduler: Runtime selection of %s\n", kSchedGRRRString);
531#endif
532#if defined(CONFIG_SCHED_FIXEDPRIORITY)
533 } else if (0 == strcmp(sched_arg, kSchedFixedPriorityString)) {
534 sched_current_dispatch = &sched_fixedpriority_dispatch;
535 _sched_enum = sched_enum_fixedpriority;
536 strlcpy(sched_string, kSchedFixedPriorityString, sizeof(sched_string));
537 kprintf("Scheduler: Runtime selection of %s\n", kSchedFixedPriorityString);
538 } else if (0 == strcmp(sched_arg, kSchedFixedPriorityWithPsetRunqueueString)) {
539 sched_current_dispatch = &sched_fixedpriority_with_pset_runqueue_dispatch;
540 _sched_enum = sched_enum_fixedpriority_with_pset_runqueue;
541 strlcpy(sched_string, kSchedFixedPriorityWithPsetRunqueueString, sizeof(sched_string));
542 kprintf("Scheduler: Runtime selection of %s\n", kSchedFixedPriorityWithPsetRunqueueString);
543#endif
544 } else {
545 panic("Unrecognized scheduler algorithm: %s", sched_arg);
546 }
547 } else {
548#if defined(CONFIG_SCHED_TRADITIONAL)
549 sched_current_dispatch = &sched_traditional_dispatch;
550 _sched_enum = sched_enum_traditional;
551 strlcpy(sched_string, kSchedTraditionalString, sizeof(sched_string));
552 kprintf("Scheduler: Default of %s\n", kSchedTraditionalString);
553#elif defined(CONFIG_SCHED_PROTO)
554 sched_current_dispatch = &sched_proto_dispatch;
555 _sched_enum = sched_enum_proto;
556 strlcpy(sched_string, kSchedProtoString, sizeof(sched_string));
557 kprintf("Scheduler: Default of %s\n", kSchedProtoString);
558#elif defined(CONFIG_SCHED_GRRR)
559 sched_current_dispatch = &sched_grrr_dispatch;
560 _sched_enum = sched_enum_grrr;
561 strlcpy(sched_string, kSchedGRRRString, sizeof(sched_string));
562 kprintf("Scheduler: Default of %s\n", kSchedGRRRString);
563#elif defined(CONFIG_SCHED_FIXEDPRIORITY)
564 sched_current_dispatch = &sched_fixedpriority_dispatch;
565 _sched_enum = sched_enum_fixedpriority;
566 strlcpy(sched_string, kSchedFixedPriorityString, sizeof(sched_string));
567 kprintf("Scheduler: Default of %s\n", kSchedFixedPriorityString);
568#else
569#error No default scheduler implementation
570#endif
571 }
572
573 SCHED(init)();
574 SCHED(fairshare_init)();
575 sched_realtime_init();
576 ast_init();
4b17d6b6 577 sched_timer_deadline_tracking_init();
6d2010ae
A
578
579 SCHED(pset_init)(&pset0);
580 SCHED(processor_init)(master_processor);
581}
582
583void
584sched_timebase_init(void)
585{
586 uint64_t abstime;
587
588 clock_interval_to_absolutetime_interval(1, NSEC_PER_SEC, &abstime);
589 sched_one_second_interval = abstime;
590
591 SCHED(timebase_init)();
592 sched_realtime_timebase_init();
593}
594
595#if defined(CONFIG_SCHED_TRADITIONAL)
596
597static void
598sched_traditional_init(void)
1c79356b
A
599{
600 /*
0b4e3aa0
A
601 * Calculate the timeslicing quantum
602 * in us.
1c79356b
A
603 */
604 if (default_preemption_rate < 1)
605 default_preemption_rate = DEFAULT_PREEMPTION_RATE;
0b4e3aa0 606 std_quantum_us = (1000 * 1000) / default_preemption_rate;
1c79356b 607
0b4e3aa0 608 printf("standard timeslicing quantum is %d us\n", std_quantum_us);
1c79356b 609
316670eb
A
610 if (default_bg_preemption_rate < 1)
611 default_bg_preemption_rate = DEFAULT_BG_PREEMPTION_RATE;
612 bg_quantum_us = (1000 * 1000) / default_bg_preemption_rate;
613
614 printf("standard background quantum is %d us\n", bg_quantum_us);
615
91447636 616 load_shift_init();
4a3eedf9 617 preempt_pri_init();
1c79356b 618 sched_tick = 0;
1c79356b
A
619}
620
6d2010ae
A
621static void
622sched_traditional_timebase_init(void)
55e303ae 623{
91447636
A
624 uint64_t abstime;
625 uint32_t shift;
55e303ae 626
91447636 627 /* standard timeslicing quantum */
55e303ae
A
628 clock_interval_to_absolutetime_interval(
629 std_quantum_us, NSEC_PER_USEC, &abstime);
630 assert((abstime >> 32) == 0 && (uint32_t)abstime != 0);
b0d623f7 631 std_quantum = (uint32_t)abstime;
55e303ae 632
91447636 633 /* smallest remaining quantum (250 us) */
55e303ae
A
634 clock_interval_to_absolutetime_interval(250, NSEC_PER_USEC, &abstime);
635 assert((abstime >> 32) == 0 && (uint32_t)abstime != 0);
b0d623f7 636 min_std_quantum = (uint32_t)abstime;
55e303ae 637
316670eb
A
638 /* quantum for background tasks */
639 clock_interval_to_absolutetime_interval(
640 bg_quantum_us, NSEC_PER_USEC, &abstime);
641 assert((abstime >> 32) == 0 && (uint32_t)abstime != 0);
642 bg_quantum = (uint32_t)abstime;
643
91447636
A
644 /* scheduler tick interval */
645 clock_interval_to_absolutetime_interval(USEC_PER_SEC >> SCHED_TICK_SHIFT,
646 NSEC_PER_USEC, &abstime);
cf7d32b8 647 assert((abstime >> 32) == 0 && (uint32_t)abstime != 0);
b0d623f7 648 sched_tick_interval = (uint32_t)abstime;
55e303ae 649
91447636
A
650 /*
651 * Compute conversion factor from usage to
652 * timesharing priorities with 5/8 ** n aging.
653 */
654 abstime = (abstime * 5) / 3;
655 for (shift = 0; abstime > BASEPRI_DEFAULT; ++shift)
656 abstime >>= 1;
2d21ac55 657 sched_fixed_shift = shift;
91447636 658
55e303ae 659 max_unsafe_computation = max_unsafe_quanta * std_quantum;
6d2010ae
A
660 sched_safe_duration = 2 * max_unsafe_quanta * std_quantum;
661
55e303ae 662 max_poll_computation = max_poll_quanta * std_quantum;
6d2010ae
A
663 thread_depress_time = 1 * std_quantum;
664 default_timeshare_computation = std_quantum / 2;
665 default_timeshare_constraint = std_quantum;
666
667}
668
669static void
670sched_traditional_processor_init(processor_t processor)
671{
672 if (!sched_traditional_use_pset_runqueue) {
673 run_queue_init(&processor->runq);
674 }
675 processor->runq_bound_count = 0;
676}
677
678static void
679sched_traditional_pset_init(processor_set_t pset)
680{
681 if (sched_traditional_use_pset_runqueue) {
682 run_queue_init(&pset->pset_runq);
683 }
684 pset->pset_runq_bound_count = 0;
685}
686
687static void
688sched_traditional_with_pset_runqueue_init(void)
689{
690 sched_traditional_init();
691 sched_traditional_use_pset_runqueue = TRUE;
692}
693
694#endif /* CONFIG_SCHED_TRADITIONAL */
695
696#if defined(CONFIG_SCHED_TRADITIONAL) || defined(CONFIG_SCHED_PROTO) || defined(CONFIG_SCHED_GRRR) || defined(CONFIG_SCHED_FIXEDPRIORITY)
697void
698sched_traditional_fairshare_init(void)
699{
700 simple_lock_init(&fs_lock, 0);
701
702 fs_runq.count = 0;
703 queue_init(&fs_runq.queue);
704}
705#endif
706
707static void
708sched_realtime_init(void)
709{
710 simple_lock_init(&rt_lock, 0);
711
712 rt_runq.count = 0;
713 queue_init(&rt_runq.queue);
55e303ae
A
714}
715
6d2010ae
A
716static void
717sched_realtime_timebase_init(void)
718{
719 uint64_t abstime;
720
721 /* smallest rt computaton (50 us) */
722 clock_interval_to_absolutetime_interval(50, NSEC_PER_USEC, &abstime);
723 assert((abstime >> 32) == 0 && (uint32_t)abstime != 0);
724 min_rt_quantum = (uint32_t)abstime;
725
726 /* maximum rt computation (50 ms) */
727 clock_interval_to_absolutetime_interval(
728 50, 1000*NSEC_PER_USEC, &abstime);
729 assert((abstime >> 32) == 0 && (uint32_t)abstime != 0);
730 max_rt_quantum = (uint32_t)abstime;
731
732}
733
734#if defined(CONFIG_SCHED_TRADITIONAL)
735
91447636
A
736/*
737 * Set up values for timeshare
738 * loading factors.
739 */
740static void
741load_shift_init(void)
742{
743 int8_t k, *p = sched_load_shifts;
744 uint32_t i, j;
745
746 *p++ = INT8_MIN; *p++ = 0;
747
748 for (i = j = 2, k = 1; i < NRQS; ++k) {
749 for (j <<= 1; i < j; ++i)
750 *p++ = k;
751 }
752}
753
4a3eedf9
A
754static void
755preempt_pri_init(void)
756{
757 int i, *p = sched_preempt_pri;
758
759 for (i = BASEPRI_FOREGROUND + 1; i < MINPRI_KERNEL; ++i)
760 setbit(i, p);
761
762 for (i = BASEPRI_PREEMPT; i <= MAXPRI; ++i)
763 setbit(i, p);
764}
765
6d2010ae
A
766#endif /* CONFIG_SCHED_TRADITIONAL */
767
1c79356b 768/*
0b4e3aa0 769 * Thread wait timer expiration.
1c79356b
A
770 */
771void
772thread_timer_expire(
91447636
A
773 void *p0,
774 __unused void *p1)
1c79356b
A
775{
776 thread_t thread = p0;
777 spl_t s;
778
779 s = splsched();
55e303ae 780 thread_lock(thread);
91447636 781 if (--thread->wait_timer_active == 0) {
0b4e3aa0
A
782 if (thread->wait_timer_is_set) {
783 thread->wait_timer_is_set = FALSE;
55e303ae 784 clear_wait_internal(thread, THREAD_TIMED_OUT);
0b4e3aa0 785 }
1c79356b 786 }
55e303ae 787 thread_unlock(thread);
1c79356b
A
788 splx(s);
789}
790
b0d623f7
A
791#ifndef __LP64__
792
1c79356b
A
793/*
794 * thread_set_timer:
795 *
796 * Set a timer for the current thread, if the thread
797 * is ready to wait. Must be called between assert_wait()
798 * and thread_block().
799 */
800void
801thread_set_timer(
0b4e3aa0
A
802 uint32_t interval,
803 uint32_t scale_factor)
1c79356b
A
804{
805 thread_t thread = current_thread();
0b4e3aa0 806 uint64_t deadline;
1c79356b
A
807 spl_t s;
808
809 s = splsched();
1c79356b
A
810 thread_lock(thread);
811 if ((thread->state & TH_WAIT) != 0) {
812 clock_interval_to_deadline(interval, scale_factor, &deadline);
6d2010ae 813 if (!timer_call_enter(&thread->wait_timer, deadline, thread->sched_pri >= BASEPRI_RTQUEUES ? TIMER_CALL_CRITICAL : 0))
91447636 814 thread->wait_timer_active++;
1c79356b
A
815 thread->wait_timer_is_set = TRUE;
816 }
817 thread_unlock(thread);
1c79356b
A
818 splx(s);
819}
820
821void
822thread_set_timer_deadline(
0b4e3aa0 823 uint64_t deadline)
1c79356b
A
824{
825 thread_t thread = current_thread();
826 spl_t s;
827
828 s = splsched();
1c79356b
A
829 thread_lock(thread);
830 if ((thread->state & TH_WAIT) != 0) {
6d2010ae 831 if (!timer_call_enter(&thread->wait_timer, deadline, thread->sched_pri >= BASEPRI_RTQUEUES ? TIMER_CALL_CRITICAL : 0))
91447636 832 thread->wait_timer_active++;
1c79356b
A
833 thread->wait_timer_is_set = TRUE;
834 }
835 thread_unlock(thread);
1c79356b
A
836 splx(s);
837}
838
839void
840thread_cancel_timer(void)
841{
842 thread_t thread = current_thread();
843 spl_t s;
844
845 s = splsched();
55e303ae 846 thread_lock(thread);
1c79356b
A
847 if (thread->wait_timer_is_set) {
848 if (timer_call_cancel(&thread->wait_timer))
849 thread->wait_timer_active--;
850 thread->wait_timer_is_set = FALSE;
851 }
55e303ae 852 thread_unlock(thread);
1c79356b
A
853 splx(s);
854}
855
b0d623f7
A
856#endif /* __LP64__ */
857
1c79356b 858/*
91447636
A
859 * thread_unblock:
860 *
861 * Unblock thread on wake up.
862 *
863 * Returns TRUE if the thread is still running.
864 *
865 * Thread must be locked.
1c79356b 866 */
91447636
A
867boolean_t
868thread_unblock(
869 thread_t thread,
870 wait_result_t wresult)
1c79356b 871{
91447636 872 boolean_t result = FALSE;
4b17d6b6 873 thread_t cthread = current_thread();
0b4e3aa0 874
91447636 875 /*
2d21ac55 876 * Set wait_result.
91447636
A
877 */
878 thread->wait_result = wresult;
1c79356b 879
91447636 880 /*
2d21ac55 881 * Cancel pending wait timer.
91447636 882 */
1c79356b
A
883 if (thread->wait_timer_is_set) {
884 if (timer_call_cancel(&thread->wait_timer))
885 thread->wait_timer_active--;
886 thread->wait_timer_is_set = FALSE;
887 }
888
91447636 889 /*
2d21ac55
A
890 * Update scheduling state: not waiting,
891 * set running.
91447636
A
892 */
893 thread->state &= ~(TH_WAIT|TH_UNINT);
1c79356b 894
91447636
A
895 if (!(thread->state & TH_RUN)) {
896 thread->state |= TH_RUN;
1c79356b 897
2d21ac55 898 (*thread->sched_call)(SCHED_CALL_UNBLOCK, thread);
1c79356b 899
91447636 900 /*
2d21ac55 901 * Update run counts.
91447636 902 */
2d21ac55 903 sched_run_incr();
6d2010ae 904 if (thread->sched_mode == TH_MODE_TIMESHARE)
2d21ac55 905 sched_share_incr();
1c79356b 906 }
2d21ac55
A
907 else {
908 /*
909 * Signal if idling on another processor.
910 */
6d2010ae 911#if CONFIG_SCHED_IDLE_IN_PLACE
2d21ac55
A
912 if (thread->state & TH_IDLE) {
913 processor_t processor = thread->last_processor;
914
915 if (processor != current_processor())
916 machine_signal_idle(processor);
917 }
6d2010ae
A
918#else
919 assert((thread->state & TH_IDLE) == 0);
920#endif
921
91447636 922 result = TRUE;
2d21ac55 923 }
1c79356b 924
91447636
A
925 /*
926 * Calculate deadline for real-time threads.
927 */
6d2010ae 928 if (thread->sched_mode == TH_MODE_REALTIME) {
91447636
A
929 thread->realtime.deadline = mach_absolute_time();
930 thread->realtime.deadline += thread->realtime.constraint;
0b4e3aa0
A
931 }
932
91447636
A
933 /*
934 * Clear old quantum, fail-safe computation, etc.
935 */
936 thread->current_quantum = 0;
937 thread->computation_metered = 0;
938 thread->reason = AST_NONE;
1c79356b 939
4b17d6b6
A
940 /* Obtain power-relevant interrupt and "platform-idle exit" statistics.
941 * We also account for "double hop" thread signaling via
942 * the thread callout infrastructure.
943 * DRK: consider removing the callout wakeup counters in the future
944 * they're present for verification at the moment.
945 */
946 boolean_t aticontext, pidle;
947 ml_get_power_state(&aticontext, &pidle);
948 if (__improbable(aticontext)) {
949 ledger_credit(thread->t_ledger, task_ledgers.interrupt_wakeups, 1);
950 uint64_t ttd = PROCESSOR_DATA(current_processor(), timer_call_ttd);
951 if (ttd) {
952 if (ttd <= timer_deadline_tracking_bin_1)
953 thread->thread_timer_wakeups_bin_1++;
954 else
955 if (ttd <= timer_deadline_tracking_bin_2)
956 thread->thread_timer_wakeups_bin_2++;
957 }
958 if (pidle) {
959 ledger_credit(thread->t_ledger, task_ledgers.platform_idle_wakeups, 1);
960 }
961 } else if (thread_get_tag_internal(cthread) & THREAD_TAG_CALLOUT) {
962 if (cthread->callout_woken_from_icontext) {
963 ledger_credit(thread->t_ledger, task_ledgers.interrupt_wakeups, 1);
964 thread->thread_callout_interrupt_wakeups++;
965 if (cthread->callout_woken_from_platform_idle) {
966 ledger_credit(thread->t_ledger, task_ledgers.platform_idle_wakeups, 1);
967 thread->thread_callout_platform_idle_wakeups++;
968 }
969 }
970 }
971
972 if (thread_get_tag_internal(thread) & THREAD_TAG_CALLOUT) {
973 thread->callout_woken_from_icontext = aticontext;
974 thread->callout_woken_from_platform_idle = pidle;
975 }
976
316670eb
A
977 /* Event should only be triggered if thread is not already running */
978 if (result == FALSE) {
979 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
980 MACHDBG_CODE(DBG_MACH_SCHED,MACH_MAKE_RUNNABLE) | DBG_FUNC_NONE,
981 (uintptr_t)thread_tid(thread), thread->sched_pri, thread->wait_result, 0, 0);
982 }
b0d623f7
A
983
984 DTRACE_SCHED2(wakeup, struct thread *, thread, struct proc *, thread->task->bsd_info);
91447636
A
985
986 return (result);
1c79356b
A
987}
988
989/*
91447636 990 * Routine: thread_go
1c79356b 991 * Purpose:
91447636 992 * Unblock and dispatch thread.
1c79356b
A
993 * Conditions:
994 * thread lock held, IPC locks may be held.
995 * thread must have been pulled from wait queue under same lock hold.
9bccf70c
A
996 * Returns:
997 * KERN_SUCCESS - Thread was set running
998 * KERN_NOT_WAITING - Thread was not waiting
1c79356b 999 */
9bccf70c 1000kern_return_t
91447636 1001thread_go(
1c79356b 1002 thread_t thread,
55e303ae 1003 wait_result_t wresult)
1c79356b 1004{
1c79356b 1005 assert(thread->at_safe_point == FALSE);
9bccf70c 1006 assert(thread->wait_event == NO_EVENT64);
1c79356b
A
1007 assert(thread->wait_queue == WAIT_QUEUE_NULL);
1008
9bccf70c 1009 if ((thread->state & (TH_WAIT|TH_TERMINATE)) == TH_WAIT) {
91447636 1010 if (!thread_unblock(thread, wresult))
55e303ae 1011 thread_setrun(thread, SCHED_PREEMPT | SCHED_TAILQ);
55e303ae
A
1012
1013 return (KERN_SUCCESS);
1c79356b 1014 }
55e303ae
A
1015
1016 return (KERN_NOT_WAITING);
1c79356b
A
1017}
1018
9bccf70c
A
1019/*
1020 * Routine: thread_mark_wait_locked
1021 * Purpose:
1022 * Mark a thread as waiting. If, given the circumstances,
1023 * it doesn't want to wait (i.e. already aborted), then
1024 * indicate that in the return value.
1025 * Conditions:
1026 * at splsched() and thread is locked.
1027 */
1028__private_extern__
1029wait_result_t
1c79356b 1030thread_mark_wait_locked(
9bccf70c
A
1031 thread_t thread,
1032 wait_interrupt_t interruptible)
1c79356b 1033{
55e303ae 1034 boolean_t at_safe_point;
1c79356b 1035
b0d623f7
A
1036 assert(thread == current_thread());
1037
9bccf70c
A
1038 /*
1039 * The thread may have certain types of interrupts/aborts masked
1040 * off. Even if the wait location says these types of interrupts
1041 * are OK, we have to honor mask settings (outer-scoped code may
1042 * not be able to handle aborts at the moment).
1043 */
91447636
A
1044 if (interruptible > (thread->options & TH_OPT_INTMASK))
1045 interruptible = thread->options & TH_OPT_INTMASK;
9bccf70c
A
1046
1047 at_safe_point = (interruptible == THREAD_ABORTSAFE);
1048
55e303ae 1049 if ( interruptible == THREAD_UNINT ||
6d2010ae 1050 !(thread->sched_flags & TH_SFLAG_ABORT) ||
55e303ae 1051 (!at_safe_point &&
6d2010ae 1052 (thread->sched_flags & TH_SFLAG_ABORTSAFELY))) {
b0d623f7 1053
316670eb
A
1054 if ( !(thread->state & TH_TERMINATE))
1055 DTRACE_SCHED(sleep);
b0d623f7 1056
9bccf70c
A
1057 thread->state |= (interruptible) ? TH_WAIT : (TH_WAIT | TH_UNINT);
1058 thread->at_safe_point = at_safe_point;
9bccf70c 1059 return (thread->wait_result = THREAD_WAITING);
9bccf70c 1060 }
55e303ae 1061 else
6d2010ae
A
1062 if (thread->sched_flags & TH_SFLAG_ABORTSAFELY)
1063 thread->sched_flags &= ~TH_SFLAG_ABORTED_MASK;
55e303ae 1064
9bccf70c 1065 return (thread->wait_result = THREAD_INTERRUPTED);
1c79356b
A
1066}
1067
9bccf70c
A
1068/*
1069 * Routine: thread_interrupt_level
1070 * Purpose:
1071 * Set the maximum interruptible state for the
1072 * current thread. The effective value of any
1073 * interruptible flag passed into assert_wait
1074 * will never exceed this.
1075 *
1076 * Useful for code that must not be interrupted,
1077 * but which calls code that doesn't know that.
1078 * Returns:
1079 * The old interrupt level for the thread.
1080 */
1081__private_extern__
1082wait_interrupt_t
1083thread_interrupt_level(
1084 wait_interrupt_t new_level)
1085{
1086 thread_t thread = current_thread();
91447636 1087 wait_interrupt_t result = thread->options & TH_OPT_INTMASK;
1c79356b 1088
91447636 1089 thread->options = (thread->options & ~TH_OPT_INTMASK) | (new_level & TH_OPT_INTMASK);
1c79356b 1090
91447636 1091 return result;
1c79356b
A
1092}
1093
1094/*
1095 * Check to see if an assert wait is possible, without actually doing one.
1096 * This is used by debug code in locks and elsewhere to verify that it is
1097 * always OK to block when trying to take a blocking lock (since waiting
1098 * for the actual assert_wait to catch the case may make it hard to detect
1099 * this case.
1100 */
1101boolean_t
1102assert_wait_possible(void)
1103{
1104
1105 thread_t thread;
1c79356b
A
1106
1107#if DEBUG
1108 if(debug_mode) return TRUE; /* Always succeed in debug mode */
1109#endif
1110
1111 thread = current_thread();
1112
1113 return (thread == NULL || wait_queue_assert_possible(thread));
1114}
1115
1116/*
1117 * assert_wait:
1118 *
1119 * Assert that the current thread is about to go to
1120 * sleep until the specified event occurs.
1121 */
9bccf70c 1122wait_result_t
1c79356b
A
1123assert_wait(
1124 event_t event,
9bccf70c 1125 wait_interrupt_t interruptible)
1c79356b
A
1126{
1127 register wait_queue_t wq;
1128 register int index;
1129
1130 assert(event != NO_EVENT);
1c79356b 1131
316670eb
A
1132 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
1133 MACHDBG_CODE(DBG_MACH_SCHED, MACH_WAIT)|DBG_FUNC_NONE,
1134 VM_KERNEL_UNSLIDE(event), 0, 0, 0, 0);
1135
1c79356b
A
1136 index = wait_hash(event);
1137 wq = &wait_queues[index];
91447636 1138 return wait_queue_assert_wait(wq, event, interruptible, 0);
9bccf70c
A
1139}
1140
91447636
A
1141wait_result_t
1142assert_wait_timeout(
1143 event_t event,
1144 wait_interrupt_t interruptible,
1145 uint32_t interval,
1146 uint32_t scale_factor)
55e303ae 1147{
91447636
A
1148 thread_t thread = current_thread();
1149 wait_result_t wresult;
1150 wait_queue_t wqueue;
1151 uint64_t deadline;
1152 spl_t s;
1153
55e303ae 1154 assert(event != NO_EVENT);
91447636
A
1155 wqueue = &wait_queues[wait_hash(event)];
1156
1157 s = splsched();
1158 wait_queue_lock(wqueue);
1159 thread_lock(thread);
1160
1161 clock_interval_to_deadline(interval, scale_factor, &deadline);
316670eb
A
1162
1163 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
1164 MACHDBG_CODE(DBG_MACH_SCHED, MACH_WAIT)|DBG_FUNC_NONE,
1165 VM_KERNEL_UNSLIDE(event), interruptible, deadline, 0, 0);
1166
b0d623f7 1167 wresult = wait_queue_assert_wait64_locked(wqueue, CAST_DOWN(event64_t, event),
91447636
A
1168 interruptible, deadline, thread);
1169
1170 thread_unlock(thread);
1171 wait_queue_unlock(wqueue);
1172 splx(s);
55e303ae 1173
91447636 1174 return (wresult);
55e303ae
A
1175}
1176
1177wait_result_t
91447636 1178assert_wait_deadline(
55e303ae 1179 event_t event,
91447636
A
1180 wait_interrupt_t interruptible,
1181 uint64_t deadline)
55e303ae
A
1182{
1183 thread_t thread = current_thread();
91447636
A
1184 wait_result_t wresult;
1185 wait_queue_t wqueue;
55e303ae
A
1186 spl_t s;
1187
1188 assert(event != NO_EVENT);
91447636 1189 wqueue = &wait_queues[wait_hash(event)];
55e303ae
A
1190
1191 s = splsched();
91447636 1192 wait_queue_lock(wqueue);
55e303ae
A
1193 thread_lock(thread);
1194
316670eb
A
1195 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
1196 MACHDBG_CODE(DBG_MACH_SCHED, MACH_WAIT)|DBG_FUNC_NONE,
1197 VM_KERNEL_UNSLIDE(event), interruptible, deadline, 0, 0);
1198
b0d623f7 1199 wresult = wait_queue_assert_wait64_locked(wqueue, CAST_DOWN(event64_t,event),
91447636 1200 interruptible, deadline, thread);
55e303ae
A
1201
1202 thread_unlock(thread);
91447636 1203 wait_queue_unlock(wqueue);
55e303ae
A
1204 splx(s);
1205
1206 return (wresult);
1207}
9bccf70c
A
1208
1209/*
1210 * thread_sleep_fast_usimple_lock:
1211 *
1212 * Cause the current thread to wait until the specified event
1213 * occurs. The specified simple_lock is unlocked before releasing
1214 * the cpu and re-acquired as part of waking up.
1215 *
1216 * This is the simple lock sleep interface for components that use a
1217 * faster version of simple_lock() than is provided by usimple_lock().
1218 */
1219__private_extern__ wait_result_t
1220thread_sleep_fast_usimple_lock(
1221 event_t event,
1222 simple_lock_t lock,
1223 wait_interrupt_t interruptible)
1224{
1225 wait_result_t res;
1226
1227 res = assert_wait(event, interruptible);
1228 if (res == THREAD_WAITING) {
1229 simple_unlock(lock);
1230 res = thread_block(THREAD_CONTINUE_NULL);
1231 simple_lock(lock);
1232 }
1233 return res;
1c79356b
A
1234}
1235
9bccf70c
A
1236
1237/*
1238 * thread_sleep_usimple_lock:
1239 *
1240 * Cause the current thread to wait until the specified event
1241 * occurs. The specified usimple_lock is unlocked before releasing
1242 * the cpu and re-acquired as part of waking up.
1243 *
1244 * This is the simple lock sleep interface for components where
1245 * simple_lock() is defined in terms of usimple_lock().
1246 */
1247wait_result_t
1248thread_sleep_usimple_lock(
1249 event_t event,
1250 usimple_lock_t lock,
1251 wait_interrupt_t interruptible)
1252{
1253 wait_result_t res;
1254
1255 res = assert_wait(event, interruptible);
1256 if (res == THREAD_WAITING) {
1257 usimple_unlock(lock);
1258 res = thread_block(THREAD_CONTINUE_NULL);
1259 usimple_lock(lock);
1260 }
1261 return res;
1262}
1263
9bccf70c
A
1264/*
1265 * thread_sleep_lock_write:
1266 *
1267 * Cause the current thread to wait until the specified event
1268 * occurs. The specified (write) lock is unlocked before releasing
1269 * the cpu. The (write) lock will be re-acquired before returning.
9bccf70c
A
1270 */
1271wait_result_t
1272thread_sleep_lock_write(
1273 event_t event,
1274 lock_t *lock,
1275 wait_interrupt_t interruptible)
1276{
1277 wait_result_t res;
1278
1279 res = assert_wait(event, interruptible);
1280 if (res == THREAD_WAITING) {
1281 lock_write_done(lock);
1282 res = thread_block(THREAD_CONTINUE_NULL);
1283 lock_write(lock);
1284 }
1285 return res;
1286}
1287
1c79356b 1288/*
91447636 1289 * thread_stop:
1c79356b 1290 *
91447636
A
1291 * Force a preemption point for a thread and wait
1292 * for it to stop running. Arbitrates access among
1293 * multiple stop requests. (released by unstop)
1c79356b 1294 *
91447636
A
1295 * The thread must enter a wait state and stop via a
1296 * separate means.
1c79356b 1297 *
91447636 1298 * Returns FALSE if interrupted.
1c79356b
A
1299 */
1300boolean_t
1301thread_stop(
91447636 1302 thread_t thread)
1c79356b 1303{
91447636 1304 wait_result_t wresult;
2d21ac55 1305 spl_t s = splsched();
1c79356b 1306
1c79356b 1307 wake_lock(thread);
2d21ac55 1308 thread_lock(thread);
1c79356b
A
1309
1310 while (thread->state & TH_SUSP) {
1311 thread->wake_active = TRUE;
2d21ac55
A
1312 thread_unlock(thread);
1313
91447636 1314 wresult = assert_wait(&thread->wake_active, THREAD_ABORTSAFE);
1c79356b
A
1315 wake_unlock(thread);
1316 splx(s);
1317
91447636
A
1318 if (wresult == THREAD_WAITING)
1319 wresult = thread_block(THREAD_CONTINUE_NULL);
9bccf70c 1320
91447636 1321 if (wresult != THREAD_AWAKENED)
1c79356b
A
1322 return (FALSE);
1323
1324 s = splsched();
1325 wake_lock(thread);
2d21ac55 1326 thread_lock(thread);
1c79356b 1327 }
9bccf70c 1328
1c79356b 1329 thread->state |= TH_SUSP;
1c79356b 1330
9bccf70c 1331 while (thread->state & TH_RUN) {
9bccf70c
A
1332 processor_t processor = thread->last_processor;
1333
2d21ac55 1334 if (processor != PROCESSOR_NULL && processor->active_thread == thread)
9bccf70c 1335 cause_ast_check(processor);
9bccf70c
A
1336
1337 thread->wake_active = TRUE;
2d21ac55
A
1338 thread_unlock(thread);
1339
91447636 1340 wresult = assert_wait(&thread->wake_active, THREAD_ABORTSAFE);
9bccf70c
A
1341 wake_unlock(thread);
1342 splx(s);
1343
91447636
A
1344 if (wresult == THREAD_WAITING)
1345 wresult = thread_block(THREAD_CONTINUE_NULL);
9bccf70c 1346
91447636 1347 if (wresult != THREAD_AWAKENED) {
9bccf70c
A
1348 thread_unstop(thread);
1349 return (FALSE);
1350 }
1351
1352 s = splsched();
1353 wake_lock(thread);
1354 thread_lock(thread);
1355 }
1356
1357 thread_unlock(thread);
1c79356b
A
1358 wake_unlock(thread);
1359 splx(s);
1360
1361 return (TRUE);
1362}
1363
1364/*
91447636
A
1365 * thread_unstop:
1366 *
1367 * Release a previous stop request and set
1368 * the thread running if appropriate.
1369 *
1370 * Use only after a successful stop operation.
1c79356b
A
1371 */
1372void
1373thread_unstop(
9bccf70c 1374 thread_t thread)
1c79356b 1375{
9bccf70c 1376 spl_t s = splsched();
1c79356b 1377
1c79356b
A
1378 wake_lock(thread);
1379 thread_lock(thread);
1380
9bccf70c 1381 if ((thread->state & (TH_RUN|TH_WAIT|TH_SUSP)) == TH_SUSP) {
0b4e3aa0 1382 thread->state &= ~TH_SUSP;
91447636 1383 thread_unblock(thread, THREAD_AWAKENED);
55e303ae
A
1384
1385 thread_setrun(thread, SCHED_PREEMPT | SCHED_TAILQ);
1c79356b
A
1386 }
1387 else
1388 if (thread->state & TH_SUSP) {
1389 thread->state &= ~TH_SUSP;
1390
1391 if (thread->wake_active) {
1392 thread->wake_active = FALSE;
1393 thread_unlock(thread);
2d21ac55
A
1394
1395 thread_wakeup(&thread->wake_active);
1c79356b
A
1396 wake_unlock(thread);
1397 splx(s);
1c79356b
A
1398
1399 return;
1400 }
1401 }
1402
1403 thread_unlock(thread);
1404 wake_unlock(thread);
1405 splx(s);
1406}
1407
316670eb
A
1408/*
1409 * Thread locked, returns the same way
1410 */
1411static inline boolean_t
1412thread_isoncpu(thread_t thread)
1413{
1414 processor_t processor = thread->last_processor;
1415
1416 return ((processor != PROCESSOR_NULL) && (processor->active_thread == thread));
1417}
1c79356b 1418/*
91447636
A
1419 * thread_wait:
1420 *
1421 * Wait for a thread to stop running. (non-interruptible)
1422 *
1c79356b 1423 */
91447636 1424void
1c79356b 1425thread_wait(
316670eb
A
1426 thread_t thread,
1427 boolean_t until_not_runnable)
1c79356b 1428{
91447636 1429 wait_result_t wresult;
316670eb
A
1430 boolean_t oncpu;
1431 processor_t processor;
1432 spl_t s = splsched();
1c79356b 1433
1c79356b 1434 wake_lock(thread);
9bccf70c 1435 thread_lock(thread);
1c79356b 1436
316670eb
A
1437 /*
1438 * Wait until not running on a CPU. If stronger requirement
1439 * desired, wait until not runnable. Assumption: if thread is
1440 * on CPU, then TH_RUN is set, so we're not waiting in any case
1441 * where the original, pure "TH_RUN" check would have let us
1442 * finish.
1443 */
1444 while ((oncpu = thread_isoncpu(thread)) ||
1445 (until_not_runnable && (thread->state & TH_RUN))) {
e7c99d92 1446
316670eb
A
1447 if (oncpu) {
1448 assert(thread->state & TH_RUN);
1449 processor = thread->last_processor;
9bccf70c 1450 cause_ast_check(processor);
316670eb 1451 }
1c79356b
A
1452
1453 thread->wake_active = TRUE;
2d21ac55
A
1454 thread_unlock(thread);
1455
91447636 1456 wresult = assert_wait(&thread->wake_active, THREAD_UNINT);
1c79356b
A
1457 wake_unlock(thread);
1458 splx(s);
1459
91447636
A
1460 if (wresult == THREAD_WAITING)
1461 thread_block(THREAD_CONTINUE_NULL);
1c79356b
A
1462
1463 s = splsched();
1464 wake_lock(thread);
9bccf70c 1465 thread_lock(thread);
1c79356b 1466 }
0b4e3aa0 1467
9bccf70c 1468 thread_unlock(thread);
1c79356b
A
1469 wake_unlock(thread);
1470 splx(s);
1c79356b
A
1471}
1472
1c79356b
A
1473/*
1474 * Routine: clear_wait_internal
1475 *
1476 * Clear the wait condition for the specified thread.
1477 * Start the thread executing if that is appropriate.
1478 * Arguments:
1479 * thread thread to awaken
1480 * result Wakeup result the thread should see
1481 * Conditions:
1482 * At splsched
1483 * the thread is locked.
9bccf70c
A
1484 * Returns:
1485 * KERN_SUCCESS thread was rousted out a wait
1486 * KERN_FAILURE thread was waiting but could not be rousted
1487 * KERN_NOT_WAITING thread was not waiting
1c79356b 1488 */
9bccf70c 1489__private_extern__ kern_return_t
1c79356b 1490clear_wait_internal(
9bccf70c 1491 thread_t thread,
55e303ae 1492 wait_result_t wresult)
1c79356b 1493{
9bccf70c 1494 wait_queue_t wq = thread->wait_queue;
060df5ea 1495 uint32_t i = LockTimeOut;
9bccf70c 1496
9bccf70c 1497 do {
55e303ae
A
1498 if (wresult == THREAD_INTERRUPTED && (thread->state & TH_UNINT))
1499 return (KERN_FAILURE);
9bccf70c
A
1500
1501 if (wq != WAIT_QUEUE_NULL) {
1502 if (wait_queue_lock_try(wq)) {
1503 wait_queue_pull_thread_locked(wq, thread, TRUE);
1504 /* wait queue unlocked, thread still locked */
55e303ae
A
1505 }
1506 else {
9bccf70c
A
1507 thread_unlock(thread);
1508 delay(1);
55e303ae 1509
9bccf70c 1510 thread_lock(thread);
55e303ae
A
1511 if (wq != thread->wait_queue)
1512 return (KERN_NOT_WAITING);
9bccf70c 1513
9bccf70c
A
1514 continue;
1515 }
1c79356b 1516 }
55e303ae 1517
91447636 1518 return (thread_go(thread, wresult));
060df5ea 1519 } while ((--i > 0) || machine_timeout_suspended());
55e303ae 1520
2d21ac55 1521 panic("clear_wait_internal: deadlock: thread=%p, wq=%p, cpu=%d\n",
9bccf70c 1522 thread, wq, cpu_number());
55e303ae
A
1523
1524 return (KERN_FAILURE);
1c79356b
A
1525}
1526
1527
1528/*
1529 * clear_wait:
1530 *
1531 * Clear the wait condition for the specified thread. Start the thread
1532 * executing if that is appropriate.
1533 *
1534 * parameters:
1535 * thread thread to awaken
1536 * result Wakeup result the thread should see
1537 */
9bccf70c 1538kern_return_t
1c79356b 1539clear_wait(
9bccf70c
A
1540 thread_t thread,
1541 wait_result_t result)
1c79356b 1542{
9bccf70c 1543 kern_return_t ret;
1c79356b
A
1544 spl_t s;
1545
1546 s = splsched();
1547 thread_lock(thread);
9bccf70c 1548 ret = clear_wait_internal(thread, result);
1c79356b
A
1549 thread_unlock(thread);
1550 splx(s);
9bccf70c 1551 return ret;
1c79356b
A
1552}
1553
1554
1555/*
1556 * thread_wakeup_prim:
1557 *
1558 * Common routine for thread_wakeup, thread_wakeup_with_result,
1559 * and thread_wakeup_one.
1560 *
1561 */
9bccf70c 1562kern_return_t
1c79356b
A
1563thread_wakeup_prim(
1564 event_t event,
1565 boolean_t one_thread,
6d2010ae
A
1566 wait_result_t result)
1567{
1568 return (thread_wakeup_prim_internal(event, one_thread, result, -1));
1569}
1570
1571
1572kern_return_t
1573thread_wakeup_prim_internal(
1574 event_t event,
1575 boolean_t one_thread,
1576 wait_result_t result,
1577 int priority)
1c79356b
A
1578{
1579 register wait_queue_t wq;
1580 register int index;
1581
1582 index = wait_hash(event);
1583 wq = &wait_queues[index];
1584 if (one_thread)
6d2010ae 1585 return (wait_queue_wakeup_one(wq, event, result, priority));
1c79356b 1586 else
316670eb 1587 return (wait_queue_wakeup_all(wq, event, result));
1c79356b
A
1588}
1589
1590/*
1591 * thread_bind:
1592 *
2d21ac55 1593 * Force the current thread to execute on the specified processor.
1c79356b 1594 *
55e303ae
A
1595 * Returns the previous binding. PROCESSOR_NULL means
1596 * not bound.
1597 *
1598 * XXX - DO NOT export this to users - XXX
1c79356b 1599 */
55e303ae 1600processor_t
1c79356b 1601thread_bind(
2d21ac55 1602 processor_t processor)
1c79356b 1603{
2d21ac55 1604 thread_t self = current_thread();
55e303ae 1605 processor_t prev;
55e303ae 1606 spl_t s;
1c79356b
A
1607
1608 s = splsched();
2d21ac55 1609 thread_lock(self);
55e303ae 1610
2d21ac55
A
1611 prev = self->bound_processor;
1612 self->bound_processor = processor;
55e303ae 1613
2d21ac55 1614 thread_unlock(self);
1c79356b 1615 splx(s);
55e303ae
A
1616
1617 return (prev);
1c79356b
A
1618}
1619
1620/*
2d21ac55
A
1621 * thread_select:
1622 *
1623 * Select a new thread for the current processor to execute.
55e303ae
A
1624 *
1625 * May select the current thread, which must be locked.
1c79356b 1626 */
2d21ac55 1627static thread_t
1c79356b 1628thread_select(
2d21ac55
A
1629 thread_t thread,
1630 processor_t processor)
1c79356b 1631{
2d21ac55 1632 processor_set_t pset = processor->processor_set;
cf7d32b8 1633 thread_t new_thread = THREAD_NULL;
b0d623f7 1634 boolean_t inactive_state;
1c79356b 1635
6d2010ae
A
1636 assert(processor == current_processor());
1637
2d21ac55
A
1638 do {
1639 /*
1640 * Update the priority.
1641 */
6d2010ae
A
1642 if (SCHED(can_update_priority)(thread))
1643 SCHED(update_priority)(thread);
1644
2d21ac55 1645 processor->current_pri = thread->sched_pri;
6d2010ae 1646 processor->current_thmode = thread->sched_mode;
1c79356b 1647
2d21ac55
A
1648 pset_lock(pset);
1649
6d2010ae
A
1650 assert(pset->low_count);
1651 assert(pset->low_pri);
1652
b7266188 1653 inactive_state = processor->state != PROCESSOR_SHUTDOWN && machine_processor_is_inactive(processor);
c910b4d9 1654
2d21ac55
A
1655 simple_lock(&rt_lock);
1656
2d21ac55
A
1657 /*
1658 * Test to see if the current thread should continue
1659 * to run on this processor. Must be runnable, and not
1660 * bound to a different processor, nor be in the wrong
1661 * processor set.
1662 */
6d2010ae 1663 if ( ((thread->state & ~TH_SUSP) == TH_RUN) &&
b0d623f7
A
1664 (thread->sched_pri >= BASEPRI_RTQUEUES ||
1665 processor->processor_meta == PROCESSOR_META_NULL ||
1666 processor->processor_meta->primary == processor) &&
2d21ac55
A
1667 (thread->bound_processor == PROCESSOR_NULL ||
1668 thread->bound_processor == processor) &&
1669 (thread->affinity_set == AFFINITY_SET_NULL ||
1670 thread->affinity_set->aset_pset == pset) ) {
1671 if ( thread->sched_pri >= BASEPRI_RTQUEUES &&
1672 first_timeslice(processor) ) {
6d2010ae 1673 if (rt_runq.count > 0) {
2d21ac55
A
1674 register queue_t q;
1675
6d2010ae 1676 q = &rt_runq.queue;
2d21ac55
A
1677 if (((thread_t)q->next)->realtime.deadline <
1678 processor->deadline) {
6d2010ae 1679 thread = (thread_t)dequeue_head(q);
2d21ac55 1680 thread->runq = PROCESSOR_NULL;
6d2010ae
A
1681 SCHED_STATS_RUNQ_CHANGE(&rt_runq.runq_stats, rt_runq.count);
1682 rt_runq.count--;
55e303ae
A
1683 }
1684 }
2d21ac55
A
1685
1686 simple_unlock(&rt_lock);
1687
1688 processor->deadline = thread->realtime.deadline;
1689
1690 pset_unlock(pset);
1691
1692 return (thread);
55e303ae
A
1693 }
1694
6d2010ae
A
1695 if (!inactive_state && (thread->sched_mode != TH_MODE_FAIRSHARE || SCHED(fairshare_runq_count)() == 0) && (rt_runq.count == 0 || BASEPRI_RTQUEUES < thread->sched_pri) &&
1696 (new_thread = SCHED(choose_thread)(processor, thread->sched_mode == TH_MODE_FAIRSHARE ? MINPRI : thread->sched_pri)) == THREAD_NULL) {
55e303ae 1697
2d21ac55 1698 simple_unlock(&rt_lock);
55e303ae 1699
2d21ac55 1700 /* I am the highest priority runnable (non-idle) thread */
1c79356b 1701
cf7d32b8 1702 pset_pri_hint(pset, processor, processor->current_pri);
1c79356b 1703
6d2010ae 1704 pset_count_hint(pset, processor, SCHED(processor_runq_count)(processor));
c910b4d9 1705
2d21ac55 1706 processor->deadline = UINT64_MAX;
55e303ae 1707
2d21ac55 1708 pset_unlock(pset);
55e303ae 1709
2d21ac55
A
1710 return (thread);
1711 }
1712 }
1713
b0d623f7 1714 if (new_thread != THREAD_NULL ||
6d2010ae
A
1715 (SCHED(processor_queue_has_priority)(processor, rt_runq.count == 0 ? IDLEPRI : BASEPRI_RTQUEUES, TRUE) &&
1716 (new_thread = SCHED(choose_thread)(processor, MINPRI)) != THREAD_NULL)) {
c910b4d9
A
1717 simple_unlock(&rt_lock);
1718
c910b4d9 1719 if (!inactive_state) {
b0d623f7 1720 pset_pri_hint(pset, processor, new_thread->sched_pri);
c910b4d9 1721
6d2010ae 1722 pset_count_hint(pset, processor, SCHED(processor_runq_count)(processor));
c910b4d9
A
1723 }
1724
1725 processor->deadline = UINT64_MAX;
1726 pset_unlock(pset);
1727
b0d623f7
A
1728 return (new_thread);
1729 }
c910b4d9 1730
b0d623f7 1731 if (rt_runq.count > 0) {
6d2010ae
A
1732 thread = (thread_t)dequeue_head(&rt_runq.queue);
1733
1734 thread->runq = PROCESSOR_NULL;
1735 SCHED_STATS_RUNQ_CHANGE(&rt_runq.runq_stats, rt_runq.count);
1736 rt_runq.count--;
1737
c910b4d9
A
1738 simple_unlock(&rt_lock);
1739
1740 processor->deadline = thread->realtime.deadline;
1741 pset_unlock(pset);
1742
1743 return (thread);
1744 }
2d21ac55
A
1745
1746 simple_unlock(&rt_lock);
55e303ae 1747
6d2010ae
A
1748 /* No realtime threads and no normal threads on the per-processor
1749 * runqueue. Finally check for global fairshare threads.
1750 */
1751 if ((new_thread = SCHED(fairshare_dequeue)()) != THREAD_NULL) {
1752
1753 processor->deadline = UINT64_MAX;
1754 pset_unlock(pset);
1755
1756 return (new_thread);
1757 }
1758
c910b4d9
A
1759 processor->deadline = UINT64_MAX;
1760
b0d623f7
A
1761 /*
1762 * Set processor inactive based on
1763 * indication from the platform code.
1764 */
c910b4d9
A
1765 if (inactive_state) {
1766 if (processor->state == PROCESSOR_RUNNING)
6d2010ae 1767 remqueue((queue_entry_t)processor);
c910b4d9
A
1768 else
1769 if (processor->state == PROCESSOR_IDLE)
6d2010ae 1770 remqueue((queue_entry_t)processor);
c910b4d9
A
1771
1772 processor->state = PROCESSOR_INACTIVE;
1773
1774 pset_unlock(pset);
1775
1776 return (processor->idle_thread);
1777 }
1778
2d21ac55
A
1779 /*
1780 * No runnable threads, attempt to steal
1781 * from other processors.
1782 */
6d2010ae
A
1783 new_thread = SCHED(steal_thread)(pset);
1784 if (new_thread != THREAD_NULL) {
cf7d32b8 1785 return (new_thread);
6d2010ae 1786 }
2d21ac55 1787
cf7d32b8
A
1788 /*
1789 * If other threads have appeared, shortcut
1790 * around again.
1791 */
6d2010ae 1792 if (!SCHED(processor_queue_empty)(processor) || rt_runq.count > 0 || SCHED(fairshare_runq_count)() > 0)
cf7d32b8
A
1793 continue;
1794
1795 pset_lock(pset);
55e303ae 1796
1c79356b
A
1797 /*
1798 * Nothing is runnable, so set this processor idle if it
2d21ac55 1799 * was running.
1c79356b 1800 */
55e303ae 1801 if (processor->state == PROCESSOR_RUNNING) {
6d2010ae 1802 remqueue((queue_entry_t)processor);
55e303ae 1803 processor->state = PROCESSOR_IDLE;
1c79356b 1804
b0d623f7
A
1805 if (processor->processor_meta == PROCESSOR_META_NULL || processor->processor_meta->primary == processor) {
1806 enqueue_head(&pset->idle_queue, (queue_entry_t)processor);
6d2010ae
A
1807 pset_pri_init_hint(pset, processor);
1808 pset_count_init_hint(pset, processor);
b0d623f7
A
1809 }
1810 else {
1811 enqueue_head(&processor->processor_meta->idle_queue, (queue_entry_t)processor);
6d2010ae
A
1812 pset_unlock(pset);
1813 return (processor->idle_thread);
b0d623f7 1814 }
1c79356b 1815 }
1c79356b 1816
2d21ac55
A
1817 pset_unlock(pset);
1818
6d2010ae 1819#if CONFIG_SCHED_IDLE_IN_PLACE
2d21ac55
A
1820 /*
1821 * Choose idle thread if fast idle is not possible.
1822 */
6d2010ae 1823 if ((thread->state & (TH_IDLE|TH_TERMINATE|TH_SUSP)) || !(thread->state & TH_WAIT) || thread->wake_active || thread->sched_pri >= BASEPRI_RTQUEUES)
2d21ac55
A
1824 return (processor->idle_thread);
1825
1826 /*
1827 * Perform idling activities directly without a
1828 * context switch. Return dispatched thread,
1829 * else check again for a runnable thread.
1830 */
1831 new_thread = thread_select_idle(thread, processor);
1832
6d2010ae
A
1833#else /* !CONFIG_SCHED_IDLE_IN_PLACE */
1834
1835 /*
1836 * Do a full context switch to idle so that the current
1837 * thread can start running on another processor without
1838 * waiting for the fast-idled processor to wake up.
1839 */
1840 return (processor->idle_thread);
1841
1842#endif /* !CONFIG_SCHED_IDLE_IN_PLACE */
1843
2d21ac55
A
1844 } while (new_thread == THREAD_NULL);
1845
1846 return (new_thread);
1847}
1848
6d2010ae 1849#if CONFIG_SCHED_IDLE_IN_PLACE
2d21ac55
A
1850/*
1851 * thread_select_idle:
1852 *
1853 * Idle the processor using the current thread context.
1854 *
1855 * Called with thread locked, then dropped and relocked.
1856 */
1857static thread_t
1858thread_select_idle(
1859 thread_t thread,
1860 processor_t processor)
1861{
1862 thread_t new_thread;
1863
6d2010ae 1864 if (thread->sched_mode == TH_MODE_TIMESHARE)
2d21ac55
A
1865 sched_share_decr();
1866 sched_run_decr();
1867
1868 thread->state |= TH_IDLE;
1869 processor->current_pri = IDLEPRI;
6d2010ae 1870 processor->current_thmode = TH_MODE_NONE;
2d21ac55 1871
316670eb
A
1872 /* Reload precise timing global policy to thread-local policy */
1873 thread->precise_user_kernel_time = use_precise_user_kernel_time(thread);
1874
2d21ac55
A
1875 thread_unlock(thread);
1876
1877 /*
1878 * Switch execution timing to processor idle thread.
1879 */
1880 processor->last_dispatch = mach_absolute_time();
6d2010ae 1881 thread->last_run_time = processor->last_dispatch;
2d21ac55
A
1882 thread_timer_event(processor->last_dispatch, &processor->idle_thread->system_timer);
1883 PROCESSOR_DATA(processor, kernel_timer) = &processor->idle_thread->system_timer;
1884
1885 /*
1886 * Cancel the quantum timer while idling.
1887 */
1888 timer_call_cancel(&processor->quantum_timer);
1889 processor->timeslice = 0;
1890
1891 (*thread->sched_call)(SCHED_CALL_BLOCK, thread);
1892
6d2010ae
A
1893 thread_tell_urgency(THREAD_URGENCY_NONE, 0, 0);
1894
2d21ac55
A
1895 /*
1896 * Enable interrupts and perform idling activities. No
1897 * preemption due to TH_IDLE being set.
1898 */
1899 spllo(); new_thread = processor_idle(thread, processor);
1900
cf7d32b8
A
1901 /*
1902 * Return at splsched.
1903 */
2d21ac55
A
1904 (*thread->sched_call)(SCHED_CALL_UNBLOCK, thread);
1905
1906 thread_lock(thread);
1907
6d2010ae
A
1908 /*
1909 * If we idled in place, simulate a context switch back
1910 * to the original priority of the thread so that the
1911 * platform layer cannot distinguish this from a true
1912 * switch to the idle thread.
1913 */
1914 if (thread->sched_mode == TH_MODE_REALTIME)
1915 thread_tell_urgency(THREAD_URGENCY_REAL_TIME, thread->realtime.period, thread->realtime.deadline);
1916 /* Identify non-promoted threads which have requested a
1917 * "background" priority.
1918 */
1919 else if ((thread->sched_pri <= MAXPRI_THROTTLE) &&
1920 (thread->priority <= MAXPRI_THROTTLE))
1921 thread_tell_urgency(THREAD_URGENCY_BACKGROUND, thread->sched_pri, thread->priority);
1922 else
1923 thread_tell_urgency(THREAD_URGENCY_NORMAL, thread->sched_pri, thread->priority);
1924
2d21ac55
A
1925 /*
1926 * If awakened, switch to thread timer and start a new quantum.
1927 * Otherwise skip; we will context switch to another thread or return here.
1928 */
1929 if (!(thread->state & TH_WAIT)) {
1930 processor->last_dispatch = mach_absolute_time();
1931 thread_timer_event(processor->last_dispatch, &thread->system_timer);
1932 PROCESSOR_DATA(processor, kernel_timer) = &thread->system_timer;
1933
1934 thread_quantum_init(thread);
6d2010ae 1935 thread->last_quantum_refill_time = processor->last_dispatch;
2d21ac55
A
1936
1937 processor->quantum_end = processor->last_dispatch + thread->current_quantum;
ebb1b9f4 1938 timer_call_enter1(&processor->quantum_timer, thread, processor->quantum_end, TIMER_CALL_CRITICAL);
2d21ac55
A
1939 processor->timeslice = 1;
1940
1941 thread->computation_epoch = processor->last_dispatch;
1c79356b
A
1942 }
1943
2d21ac55 1944 thread->state &= ~TH_IDLE;
55e303ae 1945
2d21ac55 1946 sched_run_incr();
6d2010ae 1947 if (thread->sched_mode == TH_MODE_TIMESHARE)
2d21ac55
A
1948 sched_share_incr();
1949
1950 return (new_thread);
1c79356b 1951}
6d2010ae
A
1952#endif /* CONFIG_SCHED_IDLE_IN_PLACE */
1953
1954#if defined(CONFIG_SCHED_TRADITIONAL)
1955static thread_t
1956sched_traditional_choose_thread(
1957 processor_t processor,
1958 int priority)
1959{
1960 thread_t thread;
1961
1962 thread = choose_thread(processor, runq_for_processor(processor), priority);
1963 if (thread != THREAD_NULL) {
1964 runq_consider_decr_bound_count(processor, thread);
1965 }
1966
1967 return thread;
1968}
1969
1970#endif /* defined(CONFIG_SCHED_TRADITIONAL) */
1971
1972#if defined(CONFIG_SCHED_TRADITIONAL) || defined(CONFIG_SCHED_FIXEDPRIORITY)
1c79356b 1973
b0d623f7
A
1974/*
1975 * choose_thread:
1976 *
1977 * Locate a thread to execute from the processor run queue
1978 * and return it. Only choose a thread with greater or equal
1979 * priority.
1980 *
1981 * Associated pset must be locked. Returns THREAD_NULL
1982 * on failure.
1983 */
6d2010ae 1984thread_t
b0d623f7
A
1985choose_thread(
1986 processor_t processor,
6d2010ae 1987 run_queue_t rq,
b0d623f7
A
1988 int priority)
1989{
b0d623f7
A
1990 queue_t queue = rq->queues + rq->highq;
1991 int pri = rq->highq, count = rq->count;
1992 thread_t thread;
1993
1994 while (count > 0 && pri >= priority) {
1995 thread = (thread_t)queue_first(queue);
1996 while (!queue_end(queue, (queue_entry_t)thread)) {
1997 if (thread->bound_processor == PROCESSOR_NULL ||
1998 thread->bound_processor == processor) {
6d2010ae 1999 remqueue((queue_entry_t)thread);
b0d623f7
A
2000
2001 thread->runq = PROCESSOR_NULL;
6d2010ae 2002 SCHED_STATS_RUNQ_CHANGE(&rq->runq_stats, rq->count);
b0d623f7 2003 rq->count--;
6d2010ae 2004 if (SCHED(priority_is_urgent)(pri)) {
b0d623f7
A
2005 rq->urgency--; assert(rq->urgency >= 0);
2006 }
2007 if (queue_empty(queue)) {
2008 if (pri != IDLEPRI)
2009 clrbit(MAXPRI - pri, rq->bitmap);
2010 rq->highq = MAXPRI - ffsbit(rq->bitmap);
2011 }
2012
2013 return (thread);
2014 }
2015 count--;
2016
2017 thread = (thread_t)queue_next((queue_entry_t)thread);
2018 }
2019
2020 queue--; pri--;
2021 }
2022
2023 return (THREAD_NULL);
2024}
2025
6d2010ae
A
2026#endif /* defined(CONFIG_SCHED_TRADITIONAL) || defined(CONFIG_SCHED_FIXEDPRIORITY) */
2027
1c79356b 2028/*
55e303ae
A
2029 * Perform a context switch and start executing the new thread.
2030 *
91447636 2031 * Returns FALSE on failure, and the thread is re-dispatched.
9bccf70c 2032 *
55e303ae 2033 * Called at splsched.
1c79356b
A
2034 */
2035
55e303ae
A
2036#define funnel_release_check(thread, debug) \
2037MACRO_BEGIN \
2038 if ((thread)->funnel_state & TH_FN_OWNED) { \
2039 (thread)->funnel_state = TH_FN_REFUNNEL; \
2040 KERNEL_DEBUG(0x603242c | DBG_FUNC_NONE, \
2041 (thread)->funnel_lock, (debug), 0, 0, 0); \
2042 funnel_unlock((thread)->funnel_lock); \
2043 } \
2044MACRO_END
2045
2046#define funnel_refunnel_check(thread, debug) \
2047MACRO_BEGIN \
2048 if ((thread)->funnel_state & TH_FN_REFUNNEL) { \
2049 kern_return_t result = (thread)->wait_result; \
2050 \
2051 (thread)->funnel_state = 0; \
2052 KERNEL_DEBUG(0x6032428 | DBG_FUNC_NONE, \
2053 (thread)->funnel_lock, (debug), 0, 0, 0); \
2054 funnel_lock((thread)->funnel_lock); \
2055 KERNEL_DEBUG(0x6032430 | DBG_FUNC_NONE, \
2056 (thread)->funnel_lock, (debug), 0, 0, 0); \
2057 (thread)->funnel_state = TH_FN_OWNED; \
2058 (thread)->wait_result = result; \
2059 } \
2060MACRO_END
2061
2d21ac55 2062static boolean_t
1c79356b 2063thread_invoke(
2d21ac55
A
2064 register thread_t self,
2065 register thread_t thread,
91447636 2066 ast_t reason)
1c79356b 2067{
2d21ac55
A
2068 thread_continue_t continuation = self->continuation;
2069 void *parameter = self->parameter;
9bccf70c 2070 processor_t processor;
1c79356b 2071
b0d623f7
A
2072 if (get_preemption_level() != 0) {
2073 int pl = get_preemption_level();
2074 panic("thread_invoke: preemption_level %d, possible cause: %s",
2075 pl, (pl < 0 ? "unlocking an unlocked mutex or spinlock" :
2076 "blocking while holding a spinlock, or within interrupt context"));
2077 }
0b4e3aa0 2078
2d21ac55 2079 assert(self == current_thread());
91447636 2080
1c79356b 2081 /*
9bccf70c 2082 * Mark thread interruptible.
1c79356b 2083 */
2d21ac55
A
2084 thread_lock(thread);
2085 thread->state &= ~TH_UNINT;
1c79356b 2086
2d21ac55
A
2087#if DEBUG
2088 assert(thread_runnable(thread));
2089#endif
1c79356b 2090
316670eb
A
2091 /* Reload precise timing global policy to thread-local policy */
2092 thread->precise_user_kernel_time = use_precise_user_kernel_time(thread);
2093
9bccf70c
A
2094 /*
2095 * Allow time constraint threads to hang onto
2096 * a stack.
2097 */
6d2010ae 2098 if ((self->sched_mode == TH_MODE_REALTIME) && !self->reserved_stack)
2d21ac55 2099 self->reserved_stack = self->kernel_stack;
1c79356b 2100
91447636 2101 if (continuation != NULL) {
2d21ac55 2102 if (!thread->kernel_stack) {
9bccf70c 2103 /*
2d21ac55 2104 * If we are using a privileged stack,
9bccf70c 2105 * check to see whether we can exchange it with
2d21ac55 2106 * that of the other thread.
9bccf70c 2107 */
2d21ac55 2108 if (self->kernel_stack == self->reserved_stack && !thread->reserved_stack)
9bccf70c 2109 goto need_stack;
1c79356b 2110
91447636
A
2111 /*
2112 * Context switch by performing a stack handoff.
2113 */
2d21ac55
A
2114 continuation = thread->continuation;
2115 parameter = thread->parameter;
1c79356b 2116
9bccf70c 2117 processor = current_processor();
2d21ac55
A
2118 processor->active_thread = thread;
2119 processor->current_pri = thread->sched_pri;
6d2010ae 2120 processor->current_thmode = thread->sched_mode;
2d21ac55
A
2121 if (thread->last_processor != processor && thread->last_processor != NULL) {
2122 if (thread->last_processor->processor_set != processor->processor_set)
2123 thread->ps_switch++;
2124 thread->p_switch++;
2125 }
2126 thread->last_processor = processor;
2127 thread->c_switch++;
2128 ast_context(thread);
2129 thread_unlock(thread);
1c79356b 2130
2d21ac55 2131 self->reason = reason;
91447636
A
2132
2133 processor->last_dispatch = mach_absolute_time();
6d2010ae 2134 self->last_run_time = processor->last_dispatch;
2d21ac55
A
2135 thread_timer_event(processor->last_dispatch, &thread->system_timer);
2136 PROCESSOR_DATA(processor, kernel_timer) = &thread->system_timer;
316670eb
A
2137
2138 /*
2139 * Since non-precise user/kernel time doesn't update the state timer
2140 * during privilege transitions, synthesize an event now.
2141 */
2142 if (!thread->precise_user_kernel_time) {
2143 timer_switch(PROCESSOR_DATA(processor, current_state),
2144 processor->last_dispatch,
2145 PROCESSOR_DATA(processor, current_state));
2146 }
2d21ac55 2147
316670eb
A
2148 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
2149 MACHDBG_CODE(DBG_MACH_SCHED, MACH_STACK_HANDOFF)|DBG_FUNC_NONE,
2150 self->reason, (uintptr_t)thread_tid(thread), self->sched_pri, thread->sched_pri, 0);
1c79356b 2151
6d2010ae
A
2152 if ((thread->chosen_processor != processor) && (thread->chosen_processor != NULL)) {
2153 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED, MACH_MOVED)|DBG_FUNC_NONE,
2154 (uintptr_t)thread_tid(thread), (uintptr_t)thread->chosen_processor->cpu_id, 0, 0, 0);
2155 }
2156
b0d623f7
A
2157 DTRACE_SCHED2(off__cpu, struct thread *, thread, struct proc *, thread->task->bsd_info);
2158
6d2010ae
A
2159 SCHED_STATS_CSW(processor, self->reason, self->sched_pri, thread->sched_pri);
2160
2161 TLOG(1, "thread_invoke: calling stack_handoff\n");
2162 stack_handoff(self, thread);
9bccf70c 2163
b0d623f7
A
2164 DTRACE_SCHED(on__cpu);
2165
2d21ac55 2166 thread_dispatch(self, thread);
1c79356b 2167
2d21ac55 2168 thread->continuation = thread->parameter = NULL;
1c79356b 2169
2d21ac55 2170 counter(c_thread_invoke_hits++);
1c79356b 2171
2d21ac55 2172 funnel_refunnel_check(thread, 2);
9bccf70c 2173 (void) spllo();
1c79356b 2174
2d21ac55
A
2175 assert(continuation);
2176 call_continuation(continuation, parameter, thread->wait_result);
9bccf70c 2177 /*NOTREACHED*/
9bccf70c 2178 }
2d21ac55 2179 else if (thread == self) {
9bccf70c 2180 /* same thread but with continuation */
2d21ac55 2181 ast_context(self);
9bccf70c 2182 counter(++c_thread_invoke_same);
2d21ac55 2183 thread_unlock(self);
9bccf70c 2184
316670eb
A
2185 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
2186 MACHDBG_CODE(DBG_MACH_SCHED,MACH_SCHED) | DBG_FUNC_NONE,
2187 self->reason, (uintptr_t)thread_tid(thread), self->sched_pri, thread->sched_pri, 0);
6d2010ae 2188
2d21ac55
A
2189 self->continuation = self->parameter = NULL;
2190
2191 funnel_refunnel_check(self, 3);
9bccf70c 2192 (void) spllo();
55e303ae 2193
2d21ac55 2194 call_continuation(continuation, parameter, self->wait_result);
9bccf70c
A
2195 /*NOTREACHED*/
2196 }
1c79356b 2197 }
9bccf70c
A
2198 else {
2199 /*
2d21ac55 2200 * Check that the other thread has a stack
9bccf70c 2201 */
2d21ac55 2202 if (!thread->kernel_stack) {
9bccf70c 2203need_stack:
2d21ac55
A
2204 if (!stack_alloc_try(thread)) {
2205 counter(c_thread_invoke_misses++);
2206 thread_unlock(thread);
2207 thread_stack_enqueue(thread);
9bccf70c
A
2208 return (FALSE);
2209 }
9bccf70c 2210 }
2d21ac55
A
2211 else if (thread == self) {
2212 ast_context(self);
9bccf70c 2213 counter(++c_thread_invoke_same);
2d21ac55 2214 thread_unlock(self);
6d2010ae 2215
316670eb
A
2216 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
2217 MACHDBG_CODE(DBG_MACH_SCHED,MACH_SCHED) | DBG_FUNC_NONE,
2218 self->reason, (uintptr_t)thread_tid(thread), self->sched_pri, thread->sched_pri, 0);
6d2010ae 2219
9bccf70c
A
2220 return (TRUE);
2221 }
2222 }
1c79356b
A
2223
2224 /*
91447636 2225 * Context switch by full context save.
1c79356b 2226 */
9bccf70c 2227 processor = current_processor();
2d21ac55
A
2228 processor->active_thread = thread;
2229 processor->current_pri = thread->sched_pri;
6d2010ae 2230 processor->current_thmode = thread->sched_mode;
2d21ac55
A
2231 if (thread->last_processor != processor && thread->last_processor != NULL) {
2232 if (thread->last_processor->processor_set != processor->processor_set)
2233 thread->ps_switch++;
2234 thread->p_switch++;
2235 }
2236 thread->last_processor = processor;
2237 thread->c_switch++;
2238 ast_context(thread);
2239 thread_unlock(thread);
1c79356b 2240
2d21ac55 2241 counter(c_thread_invoke_csw++);
1c79356b 2242
2d21ac55
A
2243 assert(self->runq == PROCESSOR_NULL);
2244 self->reason = reason;
1c79356b 2245
91447636 2246 processor->last_dispatch = mach_absolute_time();
6d2010ae 2247 self->last_run_time = processor->last_dispatch;
2d21ac55
A
2248 thread_timer_event(processor->last_dispatch, &thread->system_timer);
2249 PROCESSOR_DATA(processor, kernel_timer) = &thread->system_timer;
91447636 2250
316670eb
A
2251 /*
2252 * Since non-precise user/kernel time doesn't update the state timer
2253 * during privilege transitions, synthesize an event now.
2254 */
2255 if (!thread->precise_user_kernel_time) {
2256 timer_switch(PROCESSOR_DATA(processor, current_state),
2257 processor->last_dispatch,
2258 PROCESSOR_DATA(processor, current_state));
2259 }
2260
2261
2262 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
2263 MACHDBG_CODE(DBG_MACH_SCHED,MACH_SCHED) | DBG_FUNC_NONE,
2264 self->reason, (uintptr_t)thread_tid(thread), self->sched_pri, thread->sched_pri, 0);
b0d623f7 2265
6d2010ae
A
2266 if ((thread->chosen_processor != processor) && (thread->chosen_processor != NULL)) {
2267 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED, MACH_MOVED)|DBG_FUNC_NONE,
2268 (uintptr_t)thread_tid(thread), (uintptr_t)thread->chosen_processor->cpu_id, 0, 0, 0);
2269 }
2270
b0d623f7 2271 DTRACE_SCHED2(off__cpu, struct thread *, thread, struct proc *, thread->task->bsd_info);
1c79356b 2272
6d2010ae
A
2273 SCHED_STATS_CSW(processor, self->reason, self->sched_pri, thread->sched_pri);
2274
1c79356b 2275 /*
91447636 2276 * This is where we actually switch register context,
2d21ac55
A
2277 * and address space if required. We will next run
2278 * as a result of a subsequent context switch.
91447636 2279 */
316670eb 2280 assert(continuation == self->continuation);
2d21ac55 2281 thread = machine_switch_context(self, continuation, thread);
316670eb 2282 assert(self == current_thread());
b0d623f7
A
2283 TLOG(1,"thread_invoke: returning machine_switch_context: self %p continuation %p thread %p\n", self, continuation, thread);
2284
2285 DTRACE_SCHED(on__cpu);
1c79356b
A
2286
2287 /*
2d21ac55 2288 * We have been resumed and are set to run.
1c79356b 2289 */
2d21ac55 2290 thread_dispatch(thread, self);
9bccf70c 2291
91447636 2292 if (continuation) {
2d21ac55
A
2293 self->continuation = self->parameter = NULL;
2294
2295 funnel_refunnel_check(self, 3);
9bccf70c 2296 (void) spllo();
55e303ae 2297
2d21ac55 2298 call_continuation(continuation, parameter, self->wait_result);
9bccf70c 2299 /*NOTREACHED*/
1c79356b
A
2300 }
2301
9bccf70c 2302 return (TRUE);
1c79356b
A
2303}
2304
2305/*
2d21ac55 2306 * thread_dispatch:
1c79356b 2307 *
2d21ac55
A
2308 * Handle threads at context switch. Re-dispatch other thread
2309 * if still running, otherwise update run state and perform
2310 * special actions. Update quantum for other thread and begin
2311 * the quantum for ourselves.
91447636
A
2312 *
2313 * Called at splsched.
1c79356b
A
2314 */
2315void
2d21ac55
A
2316thread_dispatch(
2317 thread_t thread,
2318 thread_t self)
1c79356b 2319{
2d21ac55
A
2320 processor_t processor = self->last_processor;
2321
2322 if (thread != THREAD_NULL) {
91447636 2323 /*
2d21ac55
A
2324 * If blocked at a continuation, discard
2325 * the stack.
91447636 2326 */
2d21ac55
A
2327 if (thread->continuation != NULL && thread->kernel_stack != 0)
2328 stack_free(thread);
2329
2330 if (!(thread->state & TH_IDLE)) {
316670eb
A
2331 int64_t consumed;
2332 int64_t remainder = 0;
2333
2334 if (processor->quantum_end > processor->last_dispatch)
2335 remainder = processor->quantum_end -
2336 processor->last_dispatch;
2337
2338 consumed = thread->current_quantum - remainder;
2339
2340 if ((thread->reason & AST_LEDGER) == 0)
2341 /*
2342 * Bill CPU time to both the individual thread
2343 * and the task.
2344 */
2345 ledger_credit(thread->t_ledger,
2346 task_ledgers.cpu_time, consumed);
2347 ledger_credit(thread->t_threadledger,
2348 thread_ledgers.cpu_time, consumed);
2349
2d21ac55
A
2350 wake_lock(thread);
2351 thread_lock(thread);
9bccf70c 2352
91447636 2353 /*
2d21ac55 2354 * Compute remainder of current quantum.
91447636 2355 */
316670eb
A
2356 if (first_timeslice(processor) &&
2357 processor->quantum_end > processor->last_dispatch)
2358 thread->current_quantum = (uint32_t)remainder;
2d21ac55
A
2359 else
2360 thread->current_quantum = 0;
2361
6d2010ae 2362 if (thread->sched_mode == TH_MODE_REALTIME) {
2d21ac55
A
2363 /*
2364 * Cancel the deadline if the thread has
2365 * consumed the entire quantum.
2366 */
2367 if (thread->current_quantum == 0) {
2368 thread->realtime.deadline = UINT64_MAX;
2369 thread->reason |= AST_QUANTUM;
2370 }
b7266188 2371 } else {
6d2010ae 2372#if defined(CONFIG_SCHED_TRADITIONAL)
2d21ac55
A
2373 /*
2374 * For non-realtime threads treat a tiny
2375 * remaining quantum as an expired quantum
2376 * but include what's left next time.
2377 */
2378 if (thread->current_quantum < min_std_quantum) {
2379 thread->reason |= AST_QUANTUM;
316670eb 2380 thread->current_quantum += SCHED(initial_quantum_size)(thread);
2d21ac55 2381 }
6d2010ae 2382#endif
2d21ac55
A
2383 }
2384
91447636 2385 /*
2d21ac55
A
2386 * If we are doing a direct handoff then
2387 * take the remainder of the quantum.
91447636 2388 */
2d21ac55
A
2389 if ((thread->reason & (AST_HANDOFF|AST_QUANTUM)) == AST_HANDOFF) {
2390 self->current_quantum = thread->current_quantum;
2391 thread->reason |= AST_QUANTUM;
2392 thread->current_quantum = 0;
91447636 2393 }
91447636 2394
b0d623f7 2395 thread->computation_metered += (processor->last_dispatch - thread->computation_epoch);
2d21ac55
A
2396
2397 if (!(thread->state & TH_WAIT)) {
2398 /*
2399 * Still running.
2400 */
2401 if (thread->reason & AST_QUANTUM)
2402 thread_setrun(thread, SCHED_TAILQ);
2403 else
2404 if (thread->reason & AST_PREEMPT)
2405 thread_setrun(thread, SCHED_HEADQ);
2406 else
2407 thread_setrun(thread, SCHED_PREEMPT | SCHED_TAILQ);
2408
2409 thread->reason = AST_NONE;
2410
316670eb
A
2411 if (thread->wake_active) {
2412 thread->wake_active = FALSE;
2413 thread_unlock(thread);
2414
2415 thread_wakeup(&thread->wake_active);
2416 }
2417 else
2418 thread_unlock(thread);
2419
2d21ac55
A
2420 wake_unlock(thread);
2421 }
2422 else {
2423 /*
2424 * Waiting.
2425 */
b7266188
A
2426 boolean_t should_terminate = FALSE;
2427
2428 /* Only the first call to thread_dispatch
2429 * after explicit termination should add
2430 * the thread to the termination queue
2431 */
2432 if ((thread->state & (TH_TERMINATE|TH_TERMINATE2)) == TH_TERMINATE) {
2433 should_terminate = TRUE;
2434 thread->state |= TH_TERMINATE2;
2435 }
2436
2d21ac55
A
2437 thread->state &= ~TH_RUN;
2438
6d2010ae 2439 if (thread->sched_mode == TH_MODE_TIMESHARE)
2d21ac55
A
2440 sched_share_decr();
2441 sched_run_decr();
2442
b7266188
A
2443 (*thread->sched_call)(SCHED_CALL_BLOCK, thread);
2444
2d21ac55
A
2445 if (thread->wake_active) {
2446 thread->wake_active = FALSE;
2447 thread_unlock(thread);
2448
2449 thread_wakeup(&thread->wake_active);
2450 }
2451 else
2452 thread_unlock(thread);
91447636 2453
2d21ac55 2454 wake_unlock(thread);
91447636 2455
b7266188 2456 if (should_terminate)
2d21ac55
A
2457 thread_terminate_enqueue(thread);
2458 }
2459 }
91447636 2460 }
91447636 2461
2d21ac55 2462 if (!(self->state & TH_IDLE)) {
6d2010ae
A
2463
2464 if (self->sched_mode == TH_MODE_REALTIME)
2465 thread_tell_urgency(THREAD_URGENCY_REAL_TIME, self->realtime.period, self->realtime.deadline);
2466 /* Identify non-promoted threads which have requested a
2467 * "background" priority.
2468 */
2469 else if ((self->sched_pri <= MAXPRI_THROTTLE) &&
2470 (self->priority <= MAXPRI_THROTTLE))
2471 thread_tell_urgency(THREAD_URGENCY_BACKGROUND, self->sched_pri, self->priority);
2472 else
2473 thread_tell_urgency(THREAD_URGENCY_NORMAL, self->sched_pri, self->priority);
91447636 2474 /*
2d21ac55 2475 * Get a new quantum if none remaining.
91447636 2476 */
6d2010ae 2477 if (self->current_quantum == 0) {
2d21ac55 2478 thread_quantum_init(self);
6d2010ae
A
2479 self->last_quantum_refill_time = processor->last_dispatch;
2480 }
91447636
A
2481
2482 /*
2d21ac55 2483 * Set up quantum timer and timeslice.
91447636 2484 */
2d21ac55 2485 processor->quantum_end = (processor->last_dispatch + self->current_quantum);
ebb1b9f4 2486 timer_call_enter1(&processor->quantum_timer, self, processor->quantum_end, TIMER_CALL_CRITICAL);
91447636 2487
2d21ac55 2488 processor->timeslice = 1;
91447636 2489
b0d623f7 2490 self->computation_epoch = processor->last_dispatch;
91447636
A
2491 }
2492 else {
2493 timer_call_cancel(&processor->quantum_timer);
2d21ac55 2494 processor->timeslice = 0;
6d2010ae
A
2495
2496 thread_tell_urgency(THREAD_URGENCY_NONE, 0, 0);
91447636
A
2497 }
2498}
2499
b0d623f7
A
2500#include <libkern/OSDebug.h>
2501
2502uint32_t kdebug_thread_block = 0;
2503
2504
91447636 2505/*
2d21ac55 2506 * thread_block_reason:
91447636 2507 *
2d21ac55
A
2508 * Forces a reschedule, blocking the caller if a wait
2509 * has been asserted.
91447636 2510 *
2d21ac55
A
2511 * If a continuation is specified, then thread_invoke will
2512 * attempt to discard the thread's kernel stack. When the
2513 * thread resumes, it will execute the continuation function
2514 * on a new kernel stack.
91447636 2515 */
2d21ac55
A
2516counter(mach_counter_t c_thread_block_calls = 0;)
2517
2518wait_result_t
2519thread_block_reason(
2520 thread_continue_t continuation,
2521 void *parameter,
2522 ast_t reason)
91447636 2523{
2d21ac55
A
2524 register thread_t self = current_thread();
2525 register processor_t processor;
2526 register thread_t new_thread;
2527 spl_t s;
1c79356b
A
2528
2529 counter(++c_thread_block_calls);
2530
1c79356b
A
2531 s = splsched();
2532
55e303ae 2533 if (!(reason & AST_PREEMPT))
91447636 2534 funnel_release_check(self, 2);
1c79356b 2535
55e303ae 2536 processor = current_processor();
1c79356b 2537
9bccf70c
A
2538 /* If we're explicitly yielding, force a subsequent quantum */
2539 if (reason & AST_YIELD)
55e303ae 2540 processor->timeslice = 0;
0b4e3aa0 2541
9bccf70c
A
2542 /* We're handling all scheduling AST's */
2543 ast_off(AST_SCHEDULING);
1c79356b 2544
91447636
A
2545 self->continuation = continuation;
2546 self->parameter = parameter;
2547
316670eb
A
2548 if (__improbable(kdebug_thread_block && kdebug_enable && self->state != TH_RUN)) {
2549 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
2550 MACHDBG_CODE(DBG_MACH_SCHED,MACH_BLOCK),
2551 reason, VM_KERNEL_UNSLIDE(continuation), 0, 0, 0);
b0d623f7
A
2552 }
2553
2d21ac55 2554 do {
91447636 2555 thread_lock(self);
2d21ac55 2556 new_thread = thread_select(self, processor);
91447636 2557 thread_unlock(self);
2d21ac55 2558 } while (!thread_invoke(self, new_thread, reason));
1c79356b 2559
91447636 2560 funnel_refunnel_check(self, 5);
1c79356b
A
2561 splx(s);
2562
91447636 2563 return (self->wait_result);
1c79356b
A
2564}
2565
2566/*
2567 * thread_block:
2568 *
9bccf70c 2569 * Block the current thread if a wait has been asserted.
1c79356b 2570 */
91447636 2571wait_result_t
1c79356b 2572thread_block(
9bccf70c 2573 thread_continue_t continuation)
1c79356b 2574{
91447636
A
2575 return thread_block_reason(continuation, NULL, AST_NONE);
2576}
2577
2578wait_result_t
2579thread_block_parameter(
2580 thread_continue_t continuation,
2581 void *parameter)
2582{
2583 return thread_block_reason(continuation, parameter, AST_NONE);
1c79356b
A
2584}
2585
2586/*
2587 * thread_run:
2588 *
91447636 2589 * Switch directly from the current thread to the
55e303ae 2590 * new thread, handing off our quantum if appropriate.
9bccf70c
A
2591 *
2592 * New thread must be runnable, and not on a run queue.
1c79356b 2593 *
55e303ae 2594 * Called at splsched.
1c79356b
A
2595 */
2596int
2597thread_run(
91447636 2598 thread_t self,
9bccf70c 2599 thread_continue_t continuation,
91447636 2600 void *parameter,
9bccf70c 2601 thread_t new_thread)
1c79356b 2602{
9bccf70c
A
2603 ast_t handoff = AST_HANDOFF;
2604
91447636 2605 funnel_release_check(self, 3);
9bccf70c 2606
91447636
A
2607 self->continuation = continuation;
2608 self->parameter = parameter;
9bccf70c 2609
91447636 2610 while (!thread_invoke(self, new_thread, handoff)) {
2d21ac55 2611 processor_t processor = current_processor();
9bccf70c 2612
91447636 2613 thread_lock(self);
2d21ac55 2614 new_thread = thread_select(self, processor);
91447636 2615 thread_unlock(self);
9bccf70c
A
2616 handoff = AST_NONE;
2617 }
2618
91447636 2619 funnel_refunnel_check(self, 6);
9bccf70c 2620
91447636 2621 return (self->wait_result);
1c79356b
A
2622}
2623
2624/*
91447636 2625 * thread_continue:
55e303ae 2626 *
91447636
A
2627 * Called at splsched when a thread first receives
2628 * a new stack after a continuation.
1c79356b
A
2629 */
2630void
91447636 2631thread_continue(
2d21ac55 2632 register thread_t thread)
1c79356b 2633{
316670eb 2634 register thread_t self = current_thread();
91447636 2635 register thread_continue_t continuation;
316670eb 2636 register void *parameter;
b0d623f7
A
2637
2638 DTRACE_SCHED(on__cpu);
2639
91447636 2640 continuation = self->continuation;
91447636 2641 parameter = self->parameter;
9bccf70c 2642
2d21ac55 2643 thread_dispatch(thread, self);
9bccf70c 2644
2d21ac55 2645 self->continuation = self->parameter = NULL;
1c79356b 2646
91447636 2647 funnel_refunnel_check(self, 4);
1c79356b 2648
2d21ac55 2649 if (thread != THREAD_NULL)
91447636 2650 (void)spllo();
9bccf70c 2651
2d21ac55 2652 TLOG(1, "thread_continue: calling call_continuation \n");
91447636
A
2653 call_continuation(continuation, parameter, self->wait_result);
2654 /*NOTREACHED*/
1c79356b
A
2655}
2656
2d21ac55 2657void
6d2010ae 2658thread_quantum_init(thread_t thread)
2d21ac55 2659{
6d2010ae
A
2660 if (thread->sched_mode == TH_MODE_REALTIME) {
2661 thread->current_quantum = thread->realtime.computation;
2662 } else {
2663 thread->current_quantum = SCHED(initial_quantum_size)(thread);
2664 }
2665}
2d21ac55 2666
6d2010ae
A
2667#if defined(CONFIG_SCHED_TRADITIONAL)
2668static uint32_t
316670eb 2669sched_traditional_initial_quantum_size(thread_t thread)
6d2010ae 2670{
316670eb
A
2671 if ((thread == THREAD_NULL) || thread->priority > MAXPRI_THROTTLE)
2672 return std_quantum;
2673 else
2674 return bg_quantum;
6d2010ae
A
2675}
2676
2677static sched_mode_t
2678sched_traditional_initial_thread_sched_mode(task_t parent_task)
2679{
2680 if (parent_task == kernel_task)
2681 return TH_MODE_FIXED;
2682 else
2683 return TH_MODE_TIMESHARE;
2684}
2685
2686static boolean_t
2687sched_traditional_supports_timeshare_mode(void)
2688{
2689 return TRUE;
2690}
2691
2692#endif /* CONFIG_SCHED_TRADITIONAL */
2693
2694/*
2695 * run_queue_init:
2696 *
2697 * Initialize a run queue before first use.
2698 */
2699void
2700run_queue_init(
2701 run_queue_t rq)
2702{
2703 int i;
2704
2705 rq->highq = IDLEPRI;
2d21ac55
A
2706 for (i = 0; i < NRQBM; i++)
2707 rq->bitmap[i] = 0;
2708 setbit(MAXPRI - IDLEPRI, rq->bitmap);
2709 rq->urgency = rq->count = 0;
2710 for (i = 0; i < NRQS; i++)
2711 queue_init(&rq->queues[i]);
2712}
1c79356b 2713
6d2010ae
A
2714#if defined(CONFIG_SCHED_TRADITIONAL) || defined(CONFIG_SCHED_PROTO) || defined(CONFIG_SCHED_GRRR) || defined(CONFIG_SCHED_FIXEDPRIORITY)
2715int
2716sched_traditional_fairshare_runq_count(void)
2717{
2718 return fs_runq.count;
2719}
2720
2721uint64_t
2722sched_traditional_fairshare_runq_stats_count_sum(void)
2723{
2724 return fs_runq.runq_stats.count_sum;
2725}
2726
2727void
2728sched_traditional_fairshare_enqueue(thread_t thread)
2729{
2730 queue_t queue = &fs_runq.queue;
2731
2732 simple_lock(&fs_lock);
2733
2734 enqueue_tail(queue, (queue_entry_t)thread);
2735
2736 thread->runq = FS_RUNQ;
2737 SCHED_STATS_RUNQ_CHANGE(&fs_runq.runq_stats, fs_runq.count);
2738 fs_runq.count++;
2739
2740 simple_unlock(&fs_lock);
2741}
2742
2743thread_t
2744sched_traditional_fairshare_dequeue(void)
2745{
2746 thread_t thread;
2747
2748 simple_lock(&fs_lock);
2749 if (fs_runq.count > 0) {
2750 thread = (thread_t)dequeue_head(&fs_runq.queue);
2751
2752 thread->runq = PROCESSOR_NULL;
2753 SCHED_STATS_RUNQ_CHANGE(&fs_runq.runq_stats, fs_runq.count);
2754 fs_runq.count--;
2755
2756 simple_unlock(&fs_lock);
2757
2758 return (thread);
2759 }
2760 simple_unlock(&fs_lock);
2761
2762 return THREAD_NULL;
2763}
2764
2765boolean_t
2766sched_traditional_fairshare_queue_remove(thread_t thread)
2767{
2768 queue_t q;
2769
2770 simple_lock(&fs_lock);
2771 q = &fs_runq.queue;
2772
2773 if (FS_RUNQ == thread->runq) {
2774 remqueue((queue_entry_t)thread);
2775 SCHED_STATS_RUNQ_CHANGE(&fs_runq.runq_stats, fs_runq.count);
2776 fs_runq.count--;
2777
2778 thread->runq = PROCESSOR_NULL;
2779 simple_unlock(&fs_lock);
2780 return (TRUE);
2781 }
2782 else {
2783 /*
2784 * The thread left the run queue before we could
2785 * lock the run queue.
2786 */
2787 assert(thread->runq == PROCESSOR_NULL);
2788 simple_unlock(&fs_lock);
2789 return (FALSE);
2790 }
2791}
2792
2793#endif /* defined(CONFIG_SCHED_TRADITIONAL) || defined(CONFIG_SCHED_PROTO) || defined(CONFIG_SCHED_GRRR) || defined(CONFIG_SCHED_FIXEDPRIORITY) */
2794
2d21ac55
A
2795/*
2796 * run_queue_dequeue:
2797 *
2798 * Perform a dequeue operation on a run queue,
2799 * and return the resulting thread.
2800 *
6d2010ae 2801 * The run queue must be locked (see thread_run_queue_remove()
2d21ac55
A
2802 * for more info), and not empty.
2803 */
6d2010ae 2804thread_t
2d21ac55
A
2805run_queue_dequeue(
2806 run_queue_t rq,
2807 integer_t options)
2808{
2809 thread_t thread;
2810 queue_t queue = rq->queues + rq->highq;
9bccf70c 2811
2d21ac55 2812 if (options & SCHED_HEADQ) {
6d2010ae 2813 thread = (thread_t)dequeue_head(queue);
2d21ac55
A
2814 }
2815 else {
6d2010ae 2816 thread = (thread_t)dequeue_tail(queue);
9bccf70c 2817 }
1c79356b 2818
2d21ac55 2819 thread->runq = PROCESSOR_NULL;
6d2010ae 2820 SCHED_STATS_RUNQ_CHANGE(&rq->runq_stats, rq->count);
2d21ac55 2821 rq->count--;
6d2010ae 2822 if (SCHED(priority_is_urgent)(rq->highq)) {
4a3eedf9
A
2823 rq->urgency--; assert(rq->urgency >= 0);
2824 }
2d21ac55
A
2825 if (queue_empty(queue)) {
2826 if (rq->highq != IDLEPRI)
2827 clrbit(MAXPRI - rq->highq, rq->bitmap);
2828 rq->highq = MAXPRI - ffsbit(rq->bitmap);
2829 }
1c79356b 2830
2d21ac55 2831 return (thread);
1c79356b
A
2832}
2833
6d2010ae
A
2834/*
2835 * run_queue_enqueue:
2836 *
2837 * Perform a enqueue operation on a run queue.
2838 *
2839 * The run queue must be locked (see thread_run_queue_remove()
2840 * for more info).
2841 */
2842boolean_t
2843run_queue_enqueue(
2844 run_queue_t rq,
2845 thread_t thread,
2846 integer_t options)
2847{
2848 queue_t queue = rq->queues + thread->sched_pri;
2849 boolean_t result = FALSE;
2850
2851 if (queue_empty(queue)) {
2852 enqueue_tail(queue, (queue_entry_t)thread);
2853
2854 setbit(MAXPRI - thread->sched_pri, rq->bitmap);
2855 if (thread->sched_pri > rq->highq) {
2856 rq->highq = thread->sched_pri;
2857 result = TRUE;
2858 }
2859 }
2860 else
2861 if (options & SCHED_TAILQ)
2862 enqueue_tail(queue, (queue_entry_t)thread);
2863 else
2864 enqueue_head(queue, (queue_entry_t)thread);
2865
2866 if (SCHED(priority_is_urgent)(thread->sched_pri))
2867 rq->urgency++;
2868 SCHED_STATS_RUNQ_CHANGE(&rq->runq_stats, rq->count);
2869 rq->count++;
2870
2871 return (result);
2872
2873}
2874
2875/*
2876 * run_queue_remove:
2877 *
2878 * Remove a specific thread from a runqueue.
2879 *
2880 * The run queue must be locked.
2881 */
2882void
2883run_queue_remove(
2884 run_queue_t rq,
2885 thread_t thread)
2886{
2887
2888 remqueue((queue_entry_t)thread);
2889 SCHED_STATS_RUNQ_CHANGE(&rq->runq_stats, rq->count);
2890 rq->count--;
2891 if (SCHED(priority_is_urgent)(thread->sched_pri)) {
2892 rq->urgency--; assert(rq->urgency >= 0);
2893 }
2894
2895 if (queue_empty(rq->queues + thread->sched_pri)) {
2896 /* update run queue status */
2897 if (thread->sched_pri != IDLEPRI)
2898 clrbit(MAXPRI - thread->sched_pri, rq->bitmap);
2899 rq->highq = MAXPRI - ffsbit(rq->bitmap);
2900 }
2901
2902 thread->runq = PROCESSOR_NULL;
2903}
2904
2905/*
2906 * fairshare_setrun:
2907 *
2908 * Dispatch a thread for round-robin execution.
2909 *
2910 * Thread must be locked. Associated pset must
2911 * be locked, and is returned unlocked.
2912 */
2913static void
2914fairshare_setrun(
2915 processor_t processor,
2916 thread_t thread)
2917{
2918 processor_set_t pset = processor->processor_set;
2919
2920 thread->chosen_processor = processor;
2921
2922 SCHED(fairshare_enqueue)(thread);
2923
2924 if (processor != current_processor())
2925 machine_signal_idle(processor);
2926
2927 pset_unlock(pset);
2928
2929}
2930
1c79356b 2931/*
2d21ac55
A
2932 * realtime_queue_insert:
2933 *
2934 * Enqueue a thread for realtime execution.
1c79356b 2935 */
2d21ac55
A
2936static boolean_t
2937realtime_queue_insert(
2938 thread_t thread)
1c79356b 2939{
6d2010ae 2940 queue_t queue = &rt_runq.queue;
2d21ac55
A
2941 uint64_t deadline = thread->realtime.deadline;
2942 boolean_t preempt = FALSE;
1c79356b 2943
2d21ac55 2944 simple_lock(&rt_lock);
1c79356b 2945
55e303ae
A
2946 if (queue_empty(queue)) {
2947 enqueue_tail(queue, (queue_entry_t)thread);
2d21ac55 2948 preempt = TRUE;
55e303ae
A
2949 }
2950 else {
2951 register thread_t entry = (thread_t)queue_first(queue);
2952
2953 while (TRUE) {
2954 if ( queue_end(queue, (queue_entry_t)entry) ||
2955 deadline < entry->realtime.deadline ) {
2956 entry = (thread_t)queue_prev((queue_entry_t)entry);
2957 break;
2958 }
2959
2960 entry = (thread_t)queue_next((queue_entry_t)entry);
2961 }
2962
2963 if ((queue_entry_t)entry == queue)
2d21ac55 2964 preempt = TRUE;
55e303ae
A
2965
2966 insque((queue_entry_t)thread, (queue_entry_t)entry);
2967 }
2968
2d21ac55 2969 thread->runq = RT_RUNQ;
6d2010ae
A
2970 SCHED_STATS_RUNQ_CHANGE(&rt_runq.runq_stats, rt_runq.count);
2971 rt_runq.count++;
55e303ae 2972
2d21ac55 2973 simple_unlock(&rt_lock);
55e303ae 2974
2d21ac55
A
2975 return (preempt);
2976}
55e303ae 2977
2d21ac55
A
2978/*
2979 * realtime_setrun:
2980 *
2981 * Dispatch a thread for realtime execution.
2982 *
2983 * Thread must be locked. Associated pset must
2984 * be locked, and is returned unlocked.
2985 */
2986static void
2987realtime_setrun(
2988 processor_t processor,
2989 thread_t thread)
2990{
2991 processor_set_t pset = processor->processor_set;
55e303ae 2992
6d2010ae
A
2993 thread->chosen_processor = processor;
2994
2d21ac55
A
2995 /*
2996 * Dispatch directly onto idle processor.
2997 */
6d2010ae
A
2998 if ( (thread->bound_processor == processor)
2999 && processor->state == PROCESSOR_IDLE) {
3000 remqueue((queue_entry_t)processor);
cf7d32b8 3001 enqueue_tail(&pset->active_queue, (queue_entry_t)processor);
55e303ae 3002
2d21ac55
A
3003 processor->next_thread = thread;
3004 processor->deadline = thread->realtime.deadline;
3005 processor->state = PROCESSOR_DISPATCHING;
3006 pset_unlock(pset);
55e303ae 3007
2d21ac55
A
3008 if (processor != current_processor())
3009 machine_signal_idle(processor);
3010 return;
3011 }
55e303ae 3012
2d21ac55 3013 if (realtime_queue_insert(thread)) {
6d2010ae 3014 int prstate = processor->state;
2d21ac55
A
3015 if (processor == current_processor())
3016 ast_on(AST_PREEMPT | AST_URGENT);
316670eb 3017 else if ((prstate == PROCESSOR_IDLE) || (prstate == PROCESSOR_DISPATCHING))
6d2010ae 3018 machine_signal_idle(processor);
2d21ac55
A
3019 else
3020 cause_ast_check(processor);
3021 }
3022
3023 pset_unlock(pset);
3024}
3025
6d2010ae
A
3026#if defined(CONFIG_SCHED_TRADITIONAL)
3027
3028static boolean_t
3029priority_is_urgent(int priority)
3030{
3031 return testbit(priority, sched_preempt_pri) ? TRUE : FALSE;
3032}
3033
2d21ac55
A
3034/*
3035 * processor_enqueue:
3036 *
3037 * Enqueue thread on a processor run queue. Thread must be locked,
3038 * and not already be on a run queue.
3039 *
3040 * Returns TRUE if a preemption is indicated based on the state
3041 * of the run queue.
3042 *
6d2010ae 3043 * The run queue must be locked (see thread_run_queue_remove()
2d21ac55
A
3044 * for more info).
3045 */
3046static boolean_t
3047processor_enqueue(
3048 processor_t processor,
3049 thread_t thread,
3050 integer_t options)
3051{
6d2010ae
A
3052 run_queue_t rq = runq_for_processor(processor);
3053 boolean_t result;
2d21ac55 3054
6d2010ae 3055 result = run_queue_enqueue(rq, thread, options);
2d21ac55 3056 thread->runq = processor;
6d2010ae 3057 runq_consider_incr_bound_count(processor, thread);
2d21ac55
A
3058
3059 return (result);
55e303ae
A
3060}
3061
6d2010ae
A
3062#endif /* CONFIG_SCHED_TRADITIONAL */
3063
55e303ae 3064/*
2d21ac55 3065 * processor_setrun:
55e303ae 3066 *
2d21ac55
A
3067 * Dispatch a thread for execution on a
3068 * processor.
55e303ae 3069 *
2d21ac55
A
3070 * Thread must be locked. Associated pset must
3071 * be locked, and is returned unlocked.
55e303ae 3072 */
2d21ac55
A
3073static void
3074processor_setrun(
3075 processor_t processor,
3076 thread_t thread,
3077 integer_t options)
55e303ae 3078{
2d21ac55
A
3079 processor_set_t pset = processor->processor_set;
3080 ast_t preempt;
55e303ae 3081
6d2010ae
A
3082 thread->chosen_processor = processor;
3083
55e303ae 3084 /*
2d21ac55 3085 * Dispatch directly onto idle processor.
55e303ae 3086 */
6d2010ae
A
3087 if ( (SCHED(direct_dispatch_to_idle_processors) ||
3088 thread->bound_processor == processor)
3089 && processor->state == PROCESSOR_IDLE) {
3090 remqueue((queue_entry_t)processor);
cf7d32b8 3091 enqueue_tail(&pset->active_queue, (queue_entry_t)processor);
2d21ac55
A
3092
3093 processor->next_thread = thread;
3094 processor->deadline = UINT64_MAX;
3095 processor->state = PROCESSOR_DISPATCHING;
3096 pset_unlock(pset);
3097
3098 if (processor != current_processor())
3099 machine_signal_idle(processor);
3100 return;
3101 }
55e303ae
A
3102
3103 /*
2d21ac55 3104 * Set preemption mode.
1c79356b 3105 */
6d2010ae
A
3106 if (SCHED(priority_is_urgent)(thread->sched_pri) && thread->sched_pri > processor->current_pri)
3107 preempt = (AST_PREEMPT | AST_URGENT);
3108 else if(processor->active_thread && thread_eager_preemption(processor->active_thread))
55e303ae 3109 preempt = (AST_PREEMPT | AST_URGENT);
2d21ac55 3110 else
6d2010ae 3111 if ((thread->sched_mode == TH_MODE_TIMESHARE) && thread->sched_pri < thread->priority)
2d21ac55
A
3112 preempt = AST_NONE;
3113 else
3114 preempt = (options & SCHED_PREEMPT)? AST_PREEMPT: AST_NONE;
9bccf70c 3115
6d2010ae 3116 if (!SCHED(processor_enqueue)(processor, thread, options))
2d21ac55 3117 preempt = AST_NONE;
9bccf70c 3118
2d21ac55
A
3119 if (preempt != AST_NONE) {
3120 if (processor == current_processor()) {
c910b4d9 3121 if (csw_check(processor) != AST_NONE)
2d21ac55 3122 ast_on(preempt);
9bccf70c
A
3123 }
3124 else
6d2010ae
A
3125 if ( processor->state == PROCESSOR_IDLE || processor->state == PROCESSOR_DISPATCHING) {
3126 machine_signal_idle(processor);
3127 }
3128 else
2d21ac55
A
3129 if ( (processor->state == PROCESSOR_RUNNING ||
3130 processor->state == PROCESSOR_SHUTDOWN) &&
6d2010ae
A
3131 (thread->sched_pri >= processor->current_pri ||
3132 processor->current_thmode == TH_MODE_FAIRSHARE)) {
2d21ac55
A
3133 cause_ast_check(processor);
3134 }
3135 }
3136 else
3137 if ( processor->state == PROCESSOR_SHUTDOWN &&
3138 thread->sched_pri >= processor->current_pri ) {
3139 cause_ast_check(processor);
3140 }
6d2010ae
A
3141 else
3142 if ( processor->state == PROCESSOR_IDLE &&
3143 processor != current_processor() ) {
3144 machine_signal_idle(processor);
3145 }
2d21ac55
A
3146
3147 pset_unlock(pset);
3148}
9bccf70c 3149
6d2010ae
A
3150#if defined(CONFIG_SCHED_TRADITIONAL)
3151
3152static boolean_t
3153processor_queue_empty(processor_t processor)
3154{
3155 return runq_for_processor(processor)->count == 0;
3156
3157}
3158
3159static boolean_t
3160sched_traditional_with_pset_runqueue_processor_queue_empty(processor_t processor)
3161{
3162 processor_set_t pset = processor->processor_set;
3163 int count = runq_for_processor(processor)->count;
3164
3165 /*
3166 * The pset runq contains the count of all runnable threads
3167 * for all processors in the pset. However, for threads that
3168 * are bound to another processor, the current "processor"
3169 * is not eligible to execute the thread. So we only
3170 * include bound threads that our bound to the current
3171 * "processor". This allows the processor to idle when the
3172 * count of eligible threads drops to 0, even if there's
3173 * a runnable thread bound to a different processor in the
3174 * shared runq.
3175 */
3176
3177 count -= pset->pset_runq_bound_count;
3178 count += processor->runq_bound_count;
3179
3180 return count == 0;
3181}
3182
3183static ast_t
3184processor_csw_check(processor_t processor)
3185{
3186 run_queue_t runq;
316670eb 3187 boolean_t has_higher;
6d2010ae
A
3188
3189 assert(processor->active_thread != NULL);
3190
3191 runq = runq_for_processor(processor);
316670eb
A
3192 if (first_timeslice(processor)) {
3193 has_higher = (runq->highq > processor->current_pri);
3194 } else {
3195 has_higher = (runq->highq >= processor->current_pri);
3196 }
3197 if (has_higher) {
6d2010ae
A
3198 if (runq->urgency > 0)
3199 return (AST_PREEMPT | AST_URGENT);
3200
3201 if (processor->active_thread && thread_eager_preemption(processor->active_thread))
3202 return (AST_PREEMPT | AST_URGENT);
3203
3204 return AST_PREEMPT;
3205 }
3206
3207 return AST_NONE;
3208}
3209
3210static boolean_t
3211processor_queue_has_priority(processor_t processor,
3212 int priority,
3213 boolean_t gte)
3214{
3215 if (gte)
3216 return runq_for_processor(processor)->highq >= priority;
3217 else
3218 return runq_for_processor(processor)->highq > priority;
3219}
3220
3221static boolean_t
3222should_current_thread_rechoose_processor(processor_t processor)
3223{
3224 return (processor->current_pri < BASEPRI_RTQUEUES
3225 && processor->processor_meta != PROCESSOR_META_NULL
3226 && processor->processor_meta->primary != processor);
3227}
3228
3229static int
3230sched_traditional_processor_runq_count(processor_t processor)
3231{
3232 return runq_for_processor(processor)->count;
3233}
3234
3235
3236static uint64_t
3237sched_traditional_processor_runq_stats_count_sum(processor_t processor)
3238{
3239 return runq_for_processor(processor)->runq_stats.count_sum;
3240}
3241
3242static uint64_t
3243sched_traditional_with_pset_runqueue_processor_runq_stats_count_sum(processor_t processor)
3244{
3245 if (processor->cpu_id == processor->processor_set->cpu_set_low)
3246 return runq_for_processor(processor)->runq_stats.count_sum;
3247 else
3248 return 0ULL;
3249}
3250
3251#endif /* CONFIG_SCHED_TRADITIONAL */
3252
2d21ac55
A
3253#define next_pset(p) (((p)->pset_list != PROCESSOR_SET_NULL)? (p)->pset_list: (p)->node->psets)
3254
3255/*
3256 * choose_next_pset:
3257 *
3258 * Return the next sibling pset containing
3259 * available processors.
3260 *
3261 * Returns the original pset if none other is
3262 * suitable.
3263 */
3264static processor_set_t
3265choose_next_pset(
3266 processor_set_t pset)
3267{
3268 processor_set_t nset = pset;
3269
3270 do {
3271 nset = next_pset(nset);
6d2010ae 3272 } while (nset->online_processor_count < 1 && nset != pset);
2d21ac55 3273
cf7d32b8 3274 return (nset);
2d21ac55
A
3275}
3276
3277/*
3278 * choose_processor:
3279 *
3280 * Choose a processor for the thread, beginning at
b7266188 3281 * the pset. Accepts an optional processor hint in
2d21ac55
A
3282 * the pset.
3283 *
3284 * Returns a processor, possibly from a different pset.
3285 *
3286 * The thread must be locked. The pset must be locked,
3287 * and the resulting pset is locked on return.
3288 */
6d2010ae 3289processor_t
2d21ac55
A
3290choose_processor(
3291 processor_set_t pset,
b7266188 3292 processor_t processor,
2d21ac55
A
3293 thread_t thread)
3294{
3295 processor_set_t nset, cset = pset;
b0d623f7 3296 processor_meta_t pmeta = PROCESSOR_META_NULL;
6d2010ae 3297 processor_t mprocessor;
0b4c1975 3298
cf7d32b8 3299 /*
b7266188 3300 * Prefer the hinted processor, when appropriate.
cf7d32b8 3301 */
b7266188 3302
0b4c1975 3303 if (processor != PROCESSOR_NULL) {
7e4a7d39 3304 if (processor->processor_meta != PROCESSOR_META_NULL)
b0d623f7 3305 processor = processor->processor_meta->primary;
0b4c1975 3306 }
b0d623f7 3307
0b4c1975
A
3308 mprocessor = machine_choose_processor(pset, processor);
3309 if (mprocessor != PROCESSOR_NULL)
3310 processor = mprocessor;
b7266188 3311
0b4c1975
A
3312 if (processor != PROCESSOR_NULL) {
3313 if (processor->processor_set != pset ||
3314 processor->state == PROCESSOR_INACTIVE ||
3315 processor->state == PROCESSOR_SHUTDOWN ||
3316 processor->state == PROCESSOR_OFF_LINE)
cf7d32b8
A
3317 processor = PROCESSOR_NULL;
3318 else
0b4c1975
A
3319 if (processor->state == PROCESSOR_IDLE ||
3320 ((thread->sched_pri >= BASEPRI_RTQUEUES) &&
3321 (processor->current_pri < BASEPRI_RTQUEUES)))
3322 return (processor);
b7266188 3323 }
2d21ac55
A
3324
3325 /*
3326 * Iterate through the processor sets to locate
3327 * an appropriate processor.
3328 */
3329 do {
9bccf70c 3330 /*
2d21ac55 3331 * Choose an idle processor.
9bccf70c 3332 */
2d21ac55
A
3333 if (!queue_empty(&cset->idle_queue))
3334 return ((processor_t)queue_first(&cset->idle_queue));
1c79356b 3335
2d21ac55 3336 if (thread->sched_pri >= BASEPRI_RTQUEUES) {
0b4c1975
A
3337 integer_t lowest_priority = MAXPRI + 1;
3338 integer_t lowest_unpaired = MAXPRI + 1;
3339 uint64_t furthest_deadline = 1;
3340 processor_t lp_processor = PROCESSOR_NULL;
3341 processor_t lp_unpaired = PROCESSOR_NULL;
3342 processor_t fd_processor = PROCESSOR_NULL;
3343
3344 lp_processor = cset->low_pri;
3345 /* Consider hinted processor */
3346 if (lp_processor != PROCESSOR_NULL &&
6d2010ae
A
3347 ((lp_processor->processor_meta == PROCESSOR_META_NULL) ||
3348 ((lp_processor == lp_processor->processor_meta->primary) &&
0b4c1975
A
3349 !queue_empty(&lp_processor->processor_meta->idle_queue))) &&
3350 lp_processor->state != PROCESSOR_INACTIVE &&
3351 lp_processor->state != PROCESSOR_SHUTDOWN &&
3352 lp_processor->state != PROCESSOR_OFF_LINE &&
3353 (lp_processor->current_pri < thread->sched_pri))
3354 return lp_processor;
3355
2d21ac55
A
3356 processor = (processor_t)queue_first(&cset->active_queue);
3357 while (!queue_end(&cset->active_queue, (queue_entry_t)processor)) {
0b4c1975
A
3358 /* Discover the processor executing the
3359 * thread with the lowest priority within
3360 * this pset, or the one with the furthest
3361 * deadline
3362 */
3363 integer_t cpri = processor->current_pri;
3364 if (cpri < lowest_priority) {
3365 lowest_priority = cpri;
3366 lp_processor = processor;
3367 }
2d21ac55 3368
0b4c1975
A
3369 if ((cpri >= BASEPRI_RTQUEUES) && (processor->deadline > furthest_deadline)) {
3370 furthest_deadline = processor->deadline;
3371 fd_processor = processor;
b0d623f7
A
3372 }
3373
0b4c1975
A
3374
3375 if (processor->processor_meta != PROCESSOR_META_NULL &&
3376 !queue_empty(&processor->processor_meta->idle_queue)) {
3377 if (cpri < lowest_unpaired) {
3378 lowest_unpaired = cpri;
3379 lp_unpaired = processor;
3380 pmeta = processor->processor_meta;
3381 }
3382 else
3383 if (pmeta == PROCESSOR_META_NULL)
3384 pmeta = processor->processor_meta;
3385 }
2d21ac55
A
3386 processor = (processor_t)queue_next((queue_entry_t)processor);
3387 }
cf7d32b8 3388
0b4c1975
A
3389 if (thread->sched_pri > lowest_unpaired)
3390 return lp_unpaired;
3391
b0d623f7
A
3392 if (pmeta != PROCESSOR_META_NULL)
3393 return ((processor_t)queue_first(&pmeta->idle_queue));
0b4c1975
A
3394 if (thread->sched_pri > lowest_priority)
3395 return lp_processor;
3396 if (thread->realtime.deadline < furthest_deadline)
3397 return fd_processor;
6d2010ae 3398
cf7d32b8 3399 processor = PROCESSOR_NULL;
2d21ac55 3400 }
55e303ae 3401 else {
2d21ac55 3402 /*
c910b4d9 3403 * Check any hinted processors in the processor set if available.
2d21ac55 3404 */
c910b4d9
A
3405 if (cset->low_pri != PROCESSOR_NULL && cset->low_pri->state != PROCESSOR_INACTIVE &&
3406 cset->low_pri->state != PROCESSOR_SHUTDOWN && cset->low_pri->state != PROCESSOR_OFF_LINE &&
3407 (processor == PROCESSOR_NULL ||
3408 (thread->sched_pri > BASEPRI_DEFAULT && cset->low_pri->current_pri < thread->sched_pri))) {
3409 processor = cset->low_pri;
3410 }
3411 else
3412 if (cset->low_count != PROCESSOR_NULL && cset->low_count->state != PROCESSOR_INACTIVE &&
3413 cset->low_count->state != PROCESSOR_SHUTDOWN && cset->low_count->state != PROCESSOR_OFF_LINE &&
b0d623f7 3414 (processor == PROCESSOR_NULL || (thread->sched_pri <= BASEPRI_DEFAULT &&
6d2010ae 3415 SCHED(processor_runq_count)(cset->low_count) < SCHED(processor_runq_count)(processor)))) {
c910b4d9 3416 processor = cset->low_count;
cf7d32b8 3417 }
9bccf70c 3418
9bccf70c 3419 /*
cf7d32b8 3420 * Otherwise, choose an available processor in the set.
1c79356b 3421 */
cf7d32b8
A
3422 if (processor == PROCESSOR_NULL) {
3423 processor = (processor_t)dequeue_head(&cset->active_queue);
3424 if (processor != PROCESSOR_NULL)
3425 enqueue_tail(&cset->active_queue, (queue_entry_t)processor);
2d21ac55 3426 }
6d2010ae 3427
b0d623f7
A
3428 if (processor != PROCESSOR_NULL && pmeta == PROCESSOR_META_NULL) {
3429 if (processor->processor_meta != PROCESSOR_META_NULL &&
6d2010ae 3430 !queue_empty(&processor->processor_meta->idle_queue))
b0d623f7
A
3431 pmeta = processor->processor_meta;
3432 }
2d21ac55
A
3433 }
3434
3435 /*
3436 * Move onto the next processor set.
3437 */
3438 nset = next_pset(cset);
3439
3440 if (nset != pset) {
3441 pset_unlock(cset);
3442
3443 cset = nset;
3444 pset_lock(cset);
3445 }
3446 } while (nset != pset);
3447
3448 /*
cf7d32b8
A
3449 * Make sure that we pick a running processor,
3450 * and that the correct processor set is locked.
2d21ac55 3451 */
cf7d32b8 3452 do {
b0d623f7
A
3453 if (pmeta != PROCESSOR_META_NULL) {
3454 if (cset != pmeta->primary->processor_set) {
3455 pset_unlock(cset);
3456
3457 cset = pmeta->primary->processor_set;
3458 pset_lock(cset);
3459 }
3460
3461 if (!queue_empty(&pmeta->idle_queue))
3462 return ((processor_t)queue_first(&pmeta->idle_queue));
3463
3464 pmeta = PROCESSOR_META_NULL;
3465 }
3466
cf7d32b8
A
3467 /*
3468 * If we haven't been able to choose a processor,
c910b4d9 3469 * pick the boot processor and return it.
cf7d32b8
A
3470 */
3471 if (processor == PROCESSOR_NULL) {
c910b4d9 3472 processor = master_processor;
2d21ac55 3473
cf7d32b8
A
3474 /*
3475 * Check that the correct processor set is
3476 * returned locked.
3477 */
3478 if (cset != processor->processor_set) {
3479 pset_unlock(cset);
3480
3481 cset = processor->processor_set;
3482 pset_lock(cset);
3483 }
3484
3485 return (processor);
3486 }
3487
3488 /*
3489 * Check that the processor set for the chosen
3490 * processor is locked.
3491 */
3492 if (cset != processor->processor_set) {
3493 pset_unlock(cset);
3494
3495 cset = processor->processor_set;
3496 pset_lock(cset);
3497 }
3498
3499 /*
3500 * We must verify that the chosen processor is still available.
3501 */
c910b4d9
A
3502 if (processor->state == PROCESSOR_INACTIVE ||
3503 processor->state == PROCESSOR_SHUTDOWN || processor->state == PROCESSOR_OFF_LINE)
cf7d32b8
A
3504 processor = PROCESSOR_NULL;
3505 } while (processor == PROCESSOR_NULL);
2d21ac55
A
3506
3507 return (processor);
3508}
3509
3510/*
3511 * thread_setrun:
3512 *
3513 * Dispatch thread for execution, onto an idle
3514 * processor or run queue, and signal a preemption
3515 * as appropriate.
3516 *
3517 * Thread must be locked.
3518 */
3519void
3520thread_setrun(
3521 thread_t thread,
3522 integer_t options)
3523{
3524 processor_t processor;
3525 processor_set_t pset;
3526
3527#if DEBUG
3528 assert(thread_runnable(thread));
3529#endif
55e303ae 3530
2d21ac55
A
3531 /*
3532 * Update priority if needed.
3533 */
6d2010ae
A
3534 if (SCHED(can_update_priority)(thread))
3535 SCHED(update_priority)(thread);
2d21ac55
A
3536
3537 assert(thread->runq == PROCESSOR_NULL);
3538
3539 if (thread->bound_processor == PROCESSOR_NULL) {
3540 /*
3541 * Unbound case.
3542 */
3543 if (thread->affinity_set != AFFINITY_SET_NULL) {
3544 /*
3545 * Use affinity set policy hint.
3546 */
3547 pset = thread->affinity_set->aset_pset;
3548 pset_lock(pset);
3549
6d2010ae 3550 processor = SCHED(choose_processor)(pset, PROCESSOR_NULL, thread);
2d21ac55
A
3551 }
3552 else
3553 if (thread->last_processor != PROCESSOR_NULL) {
3554 /*
3555 * Simple (last processor) affinity case.
3556 */
3557 processor = thread->last_processor;
3558 pset = processor->processor_set;
3559 pset_lock(pset);
6d2010ae
A
3560 processor = SCHED(choose_processor)(pset, processor, thread);
3561
3562 if ((thread->last_processor != processor) && (thread->last_processor != PROCESSOR_NULL)) {
3563 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED, MACH_SCHED_LPA_BROKEN)|DBG_FUNC_NONE,
3564 (uintptr_t)thread_tid(thread), (uintptr_t)thread->last_processor->cpu_id, (uintptr_t)processor->cpu_id, thread->last_processor->state, 0);
3565 }
3566
2d21ac55
A
3567 }
3568 else {
3569 /*
3570 * No Affinity case:
3571 *
cf7d32b8
A
3572 * Utilitize a per task hint to spread threads
3573 * among the available processor sets.
2d21ac55 3574 */
cf7d32b8
A
3575 task_t task = thread->task;
3576
3577 pset = task->pset_hint;
3578 if (pset == PROCESSOR_SET_NULL)
3579 pset = current_processor()->processor_set;
3580
3581 pset = choose_next_pset(pset);
2d21ac55 3582 pset_lock(pset);
9bccf70c 3583
6d2010ae 3584 processor = SCHED(choose_processor)(pset, PROCESSOR_NULL, thread);
cf7d32b8 3585 task->pset_hint = processor->processor_set;
55e303ae 3586 }
1c79356b
A
3587 }
3588 else {
2d21ac55
A
3589 /*
3590 * Bound case:
3591 *
3592 * Unconditionally dispatch on the processor.
3593 */
3594 processor = thread->bound_processor;
55e303ae 3595 pset = processor->processor_set;
2d21ac55
A
3596 pset_lock(pset);
3597 }
3598
3599 /*
3600 * Dispatch the thread on the choosen processor.
3601 */
3602 if (thread->sched_pri >= BASEPRI_RTQUEUES)
3603 realtime_setrun(processor, thread);
6d2010ae
A
3604 else if (thread->sched_mode == TH_MODE_FAIRSHARE)
3605 fairshare_setrun(processor, thread);
2d21ac55
A
3606 else
3607 processor_setrun(processor, thread, options);
3608}
3609
b0d623f7
A
3610processor_set_t
3611task_choose_pset(
3612 task_t task)
3613{
3614 processor_set_t pset = task->pset_hint;
3615
3616 if (pset != PROCESSOR_SET_NULL)
3617 pset = choose_next_pset(pset);
3618
3619 return (pset);
3620}
3621
6d2010ae
A
3622#if defined(CONFIG_SCHED_TRADITIONAL)
3623
2d21ac55
A
3624/*
3625 * processor_queue_shutdown:
3626 *
c910b4d9
A
3627 * Shutdown a processor run queue by
3628 * re-dispatching non-bound threads.
2d21ac55
A
3629 *
3630 * Associated pset must be locked, and is
3631 * returned unlocked.
3632 */
3633void
3634processor_queue_shutdown(
3635 processor_t processor)
3636{
3637 processor_set_t pset = processor->processor_set;
6d2010ae 3638 run_queue_t rq = runq_for_processor(processor);
2d21ac55
A
3639 queue_t queue = rq->queues + rq->highq;
3640 int pri = rq->highq, count = rq->count;
3641 thread_t next, thread;
3642 queue_head_t tqueue;
3643
3644 queue_init(&tqueue);
3645
3646 while (count > 0) {
3647 thread = (thread_t)queue_first(queue);
3648 while (!queue_end(queue, (queue_entry_t)thread)) {
3649 next = (thread_t)queue_next((queue_entry_t)thread);
3650
b0d623f7 3651 if (thread->bound_processor == PROCESSOR_NULL) {
6d2010ae 3652 remqueue((queue_entry_t)thread);
2d21ac55
A
3653
3654 thread->runq = PROCESSOR_NULL;
6d2010ae
A
3655 SCHED_STATS_RUNQ_CHANGE(&rq->runq_stats, rq->count);
3656 runq_consider_decr_bound_count(processor, thread);
2d21ac55 3657 rq->count--;
6d2010ae 3658 if (SCHED(priority_is_urgent)(pri)) {
4a3eedf9
A
3659 rq->urgency--; assert(rq->urgency >= 0);
3660 }
2d21ac55
A
3661 if (queue_empty(queue)) {
3662 if (pri != IDLEPRI)
3663 clrbit(MAXPRI - pri, rq->bitmap);
3664 rq->highq = MAXPRI - ffsbit(rq->bitmap);
9bccf70c 3665 }
2d21ac55
A
3666
3667 enqueue_tail(&tqueue, (queue_entry_t)thread);
9bccf70c 3668 }
2d21ac55
A
3669 count--;
3670
3671 thread = next;
9bccf70c 3672 }
55e303ae 3673
2d21ac55
A
3674 queue--; pri--;
3675 }
3676
3677 pset_unlock(pset);
3678
2d21ac55
A
3679 while ((thread = (thread_t)dequeue_head(&tqueue)) != THREAD_NULL) {
3680 thread_lock(thread);
55e303ae 3681
c910b4d9 3682 thread_setrun(thread, SCHED_TAILQ);
2d21ac55
A
3683
3684 thread_unlock(thread);
9bccf70c
A
3685 }
3686}
3687
6d2010ae
A
3688#endif /* CONFIG_SCHED_TRADITIONAL */
3689
9bccf70c 3690/*
c910b4d9
A
3691 * Check for a preemption point in
3692 * the current context.
55e303ae
A
3693 *
3694 * Called at splsched.
9bccf70c
A
3695 */
3696ast_t
3697csw_check(
9bccf70c
A
3698 processor_t processor)
3699{
9bccf70c 3700 ast_t result = AST_NONE;
316670eb 3701 thread_t thread = processor->active_thread;
9bccf70c 3702
55e303ae 3703 if (first_timeslice(processor)) {
6d2010ae 3704 if (rt_runq.count > 0)
55e303ae 3705 return (AST_PREEMPT | AST_URGENT);
9bccf70c
A
3706 }
3707 else {
6d2010ae
A
3708 if (rt_runq.count > 0 && BASEPRI_RTQUEUES >= processor->current_pri)
3709 return (AST_PREEMPT | AST_URGENT);
1c79356b 3710 }
9bccf70c 3711
316670eb 3712 result = SCHED(processor_csw_check)(processor);
9bccf70c
A
3713 if (result != AST_NONE)
3714 return (result);
3715
6d2010ae 3716 if (SCHED(should_current_thread_rechoose_processor)(processor))
b0d623f7 3717 return (AST_PREEMPT);
6d2010ae 3718
b7266188 3719 if (machine_processor_is_inactive(processor))
c910b4d9 3720 return (AST_PREEMPT);
9bccf70c 3721
316670eb 3722 if (thread->state & TH_SUSP)
c910b4d9
A
3723 return (AST_PREEMPT);
3724
3725 return (AST_NONE);
1c79356b
A
3726}
3727
3728/*
9bccf70c 3729 * set_sched_pri:
1c79356b 3730 *
55e303ae
A
3731 * Set the scheduled priority of the specified thread.
3732 *
9bccf70c 3733 * This may cause the thread to change queues.
1c79356b 3734 *
55e303ae 3735 * Thread must be locked.
1c79356b
A
3736 */
3737void
9bccf70c 3738set_sched_pri(
2d21ac55
A
3739 thread_t thread,
3740 int priority)
1c79356b 3741{
6d2010ae 3742 boolean_t removed = thread_run_queue_remove(thread);
9bccf70c 3743
9bccf70c 3744 thread->sched_pri = priority;
2d21ac55 3745 if (removed)
55e303ae 3746 thread_setrun(thread, SCHED_PREEMPT | SCHED_TAILQ);
9bccf70c 3747 else
55e303ae 3748 if (thread->state & TH_RUN) {
9bccf70c
A
3749 processor_t processor = thread->last_processor;
3750
3751 if (thread == current_thread()) {
c910b4d9 3752 ast_t preempt;
9bccf70c 3753
9bccf70c 3754 processor->current_pri = priority;
6d2010ae 3755 processor->current_thmode = thread->sched_mode;
c910b4d9
A
3756 if ((preempt = csw_check(processor)) != AST_NONE)
3757 ast_on(preempt);
9bccf70c
A
3758 }
3759 else
3760 if ( processor != PROCESSOR_NULL &&
55e303ae 3761 processor->active_thread == thread )
9bccf70c 3762 cause_ast_check(processor);
1c79356b
A
3763 }
3764}
3765
91447636
A
3766#if 0
3767
3768static void
3769run_queue_check(
3770 run_queue_t rq,
3771 thread_t thread)
3772{
3773 queue_t q;
3774 queue_entry_t qe;
3775
3776 if (rq != thread->runq)
3777 panic("run_queue_check: thread runq");
3778
3779 if (thread->sched_pri > MAXPRI || thread->sched_pri < MINPRI)
3780 panic("run_queue_check: thread sched_pri");
3781
3782 q = &rq->queues[thread->sched_pri];
3783 qe = queue_first(q);
3784 while (!queue_end(q, qe)) {
3785 if (qe == (queue_entry_t)thread)
3786 return;
3787
3788 qe = queue_next(qe);
3789 }
3790
3791 panic("run_queue_check: end");
3792}
3793
3794#endif /* DEBUG */
3795
6d2010ae
A
3796#if defined(CONFIG_SCHED_TRADITIONAL)
3797
3798/* locks the runqueue itself */
3799
3800static boolean_t
3801processor_queue_remove(
3802 processor_t processor,
3803 thread_t thread)
3804{
3805 void * rqlock;
3806 run_queue_t rq;
3807
3808 rqlock = &processor->processor_set->sched_lock;
3809 rq = runq_for_processor(processor);
3810
3811 simple_lock(rqlock);
3812 if (processor == thread->runq) {
3813 /*
3814 * Thread is on a run queue and we have a lock on
3815 * that run queue.
3816 */
3817 runq_consider_decr_bound_count(processor, thread);
3818 run_queue_remove(rq, thread);
3819 }
3820 else {
3821 /*
3822 * The thread left the run queue before we could
3823 * lock the run queue.
3824 */
3825 assert(thread->runq == PROCESSOR_NULL);
3826 processor = PROCESSOR_NULL;
3827 }
3828
3829 simple_unlock(rqlock);
3830
3831 return (processor != PROCESSOR_NULL);
3832}
3833
3834#endif /* CONFIG_SCHED_TRADITIONAL */
3835
1c79356b 3836/*
6d2010ae 3837 * thread_run_queue_remove:
1c79356b 3838 *
2d21ac55
A
3839 * Remove a thread from a current run queue and
3840 * return TRUE if successful.
55e303ae
A
3841 *
3842 * Thread must be locked.
1c79356b 3843 */
2d21ac55 3844boolean_t
6d2010ae 3845thread_run_queue_remove(
2d21ac55 3846 thread_t thread)
1c79356b 3847{
2d21ac55 3848 processor_t processor = thread->runq;
1c79356b 3849
1c79356b 3850 /*
2d21ac55 3851 * If processor is PROCESSOR_NULL, the thread will stay out of the
55e303ae
A
3852 * run queues because the caller locked the thread. Otherwise
3853 * the thread is on a run queue, but could be chosen for dispatch
3854 * and removed.
1c79356b 3855 */
2d21ac55 3856 if (processor != PROCESSOR_NULL) {
6d2010ae 3857 queue_t q;
55e303ae
A
3858
3859 /*
2d21ac55
A
3860 * The processor run queues are locked by the
3861 * processor set. Real-time priorities use a
3862 * global queue with a dedicated lock.
55e303ae 3863 */
6d2010ae
A
3864 if (thread->sched_mode == TH_MODE_FAIRSHARE) {
3865 return SCHED(fairshare_queue_remove)(thread);
2d21ac55 3866 }
6d2010ae
A
3867
3868 if (thread->sched_pri < BASEPRI_RTQUEUES) {
3869 return SCHED(processor_queue_remove)(processor, thread);
55e303ae
A
3870 }
3871
6d2010ae
A
3872 simple_lock(&rt_lock);
3873 q = &rt_runq.queue;
55e303ae 3874
2d21ac55 3875 if (processor == thread->runq) {
1c79356b 3876 /*
55e303ae
A
3877 * Thread is on a run queue and we have a lock on
3878 * that run queue.
1c79356b 3879 */
6d2010ae
A
3880 remqueue((queue_entry_t)thread);
3881 SCHED_STATS_RUNQ_CHANGE(&rt_runq.runq_stats, rt_runq.count);
3882 rt_runq.count--;
55e303ae 3883
2d21ac55 3884 thread->runq = PROCESSOR_NULL;
1c79356b
A
3885 }
3886 else {
3887 /*
55e303ae
A
3888 * The thread left the run queue before we could
3889 * lock the run queue.
1c79356b 3890 */
2d21ac55
A
3891 assert(thread->runq == PROCESSOR_NULL);
3892 processor = PROCESSOR_NULL;
1c79356b 3893 }
55e303ae 3894
6d2010ae 3895 simple_unlock(&rt_lock);
1c79356b
A
3896 }
3897
2d21ac55 3898 return (processor != PROCESSOR_NULL);
1c79356b
A
3899}
3900
6d2010ae
A
3901#if defined(CONFIG_SCHED_TRADITIONAL)
3902
2d21ac55 3903/*
cf7d32b8 3904 * steal_processor_thread:
2d21ac55 3905 *
cf7d32b8
A
3906 * Locate a thread to steal from the processor and
3907 * return it.
2d21ac55
A
3908 *
3909 * Associated pset must be locked. Returns THREAD_NULL
3910 * on failure.
3911 */
3912static thread_t
cf7d32b8 3913steal_processor_thread(
2d21ac55 3914 processor_t processor)
91447636 3915{
6d2010ae 3916 run_queue_t rq = runq_for_processor(processor);
2d21ac55
A
3917 queue_t queue = rq->queues + rq->highq;
3918 int pri = rq->highq, count = rq->count;
cf7d32b8 3919 thread_t thread;
2d21ac55
A
3920
3921 while (count > 0) {
3922 thread = (thread_t)queue_first(queue);
3923 while (!queue_end(queue, (queue_entry_t)thread)) {
b0d623f7 3924 if (thread->bound_processor == PROCESSOR_NULL) {
6d2010ae 3925 remqueue((queue_entry_t)thread);
2d21ac55
A
3926
3927 thread->runq = PROCESSOR_NULL;
6d2010ae
A
3928 SCHED_STATS_RUNQ_CHANGE(&rq->runq_stats, rq->count);
3929 runq_consider_decr_bound_count(processor, thread);
2d21ac55 3930 rq->count--;
6d2010ae 3931 if (SCHED(priority_is_urgent)(pri)) {
4a3eedf9
A
3932 rq->urgency--; assert(rq->urgency >= 0);
3933 }
2d21ac55
A
3934 if (queue_empty(queue)) {
3935 if (pri != IDLEPRI)
3936 clrbit(MAXPRI - pri, rq->bitmap);
3937 rq->highq = MAXPRI - ffsbit(rq->bitmap);
3938 }
91447636 3939
2d21ac55
A
3940 return (thread);
3941 }
3942 count--;
91447636 3943
2d21ac55 3944 thread = (thread_t)queue_next((queue_entry_t)thread);
91447636 3945 }
91447636 3946
2d21ac55
A
3947 queue--; pri--;
3948 }
91447636 3949
2d21ac55 3950 return (THREAD_NULL);
91447636
A
3951}
3952
cf7d32b8
A
3953/*
3954 * Locate and steal a thread, beginning
3955 * at the pset.
3956 *
3957 * The pset must be locked, and is returned
3958 * unlocked.
3959 *
3960 * Returns the stolen thread, or THREAD_NULL on
3961 * failure.
3962 */
3963static thread_t
3964steal_thread(
3965 processor_set_t pset)
3966{
3967 processor_set_t nset, cset = pset;
3968 processor_t processor;
3969 thread_t thread;
3970
3971 do {
3972 processor = (processor_t)queue_first(&cset->active_queue);
3973 while (!queue_end(&cset->active_queue, (queue_entry_t)processor)) {
6d2010ae 3974 if (runq_for_processor(processor)->count > 0) {
cf7d32b8
A
3975 thread = steal_processor_thread(processor);
3976 if (thread != THREAD_NULL) {
6d2010ae 3977 remqueue((queue_entry_t)processor);
cf7d32b8
A
3978 enqueue_tail(&cset->active_queue, (queue_entry_t)processor);
3979
cf7d32b8
A
3980 pset_unlock(cset);
3981
3982 return (thread);
3983 }
3984 }
3985
3986 processor = (processor_t)queue_next((queue_entry_t)processor);
3987 }
3988
3989 nset = next_pset(cset);
3990
3991 if (nset != pset) {
3992 pset_unlock(cset);
3993
3994 cset = nset;
3995 pset_lock(cset);
3996 }
3997 } while (nset != pset);
3998
3999 pset_unlock(cset);
4000
4001 return (THREAD_NULL);
4002}
4003
6d2010ae
A
4004static thread_t steal_thread_disabled(
4005 processor_set_t pset)
4006{
4007 pset_unlock(pset);
4008
4009 return (THREAD_NULL);
4010}
4011
4012#endif /* CONFIG_SCHED_TRADITIONAL */
4013
4014
4015int
4016thread_get_urgency(uint64_t *rt_period, uint64_t *rt_deadline)
4017{
4018 processor_t processor;
4019 thread_t thread;
4020
4021 processor = current_processor();
4022
4023 thread = processor->next_thread;
4024
4025 if (thread != NULL) {
4026 if (thread->sched_mode == TH_MODE_REALTIME) {
4027
4028 if (rt_period != NULL)
4029 *rt_period = thread->realtime.period;
4030 if (rt_deadline != NULL)
4031 *rt_deadline = thread->realtime.deadline;
4032
4033 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED, MACH_SCHED_GET_URGENCY), THREAD_URGENCY_REAL_TIME, thread->realtime.period,
4034 (thread->realtime.deadline >> 32), thread->realtime.deadline, 0);
4035
4036 return (THREAD_URGENCY_REAL_TIME);
4037 } else if ((thread->sched_pri <= MAXPRI_THROTTLE) &&
4038 (thread->priority <= MAXPRI_THROTTLE)) {
4039 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED, MACH_SCHED_GET_URGENCY), THREAD_URGENCY_BACKGROUND, thread->sched_pri, thread->priority, 0, 0);
4040 return (THREAD_URGENCY_BACKGROUND);
4041 }
4042 else
4043 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED, MACH_SCHED_GET_URGENCY), THREAD_URGENCY_NORMAL, 0, 0, 0, 0);
4044
4045 return (THREAD_URGENCY_NORMAL);
4046 }
4047 else
4048 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED, MACH_SCHED_GET_URGENCY), THREAD_URGENCY_NONE, 0, 0, 0, 0);
4049 return (THREAD_URGENCY_NONE);
4050}
4051
4052
1c79356b 4053/*
2d21ac55
A
4054 * This is the processor idle loop, which just looks for other threads
4055 * to execute. Processor idle threads invoke this without supplying a
4056 * current thread to idle without an asserted wait state.
4057 *
4058 * Returns a the next thread to execute if dispatched directly.
1c79356b 4059 */
6d2010ae
A
4060
4061#if 0
4062#define IDLE_KERNEL_DEBUG_CONSTANT(...) KERNEL_DEBUG_CONSTANT(__VA_ARGS__)
4063#else
4064#define IDLE_KERNEL_DEBUG_CONSTANT(...) do { } while(0)
4065#endif
4066
4067thread_t
2d21ac55
A
4068processor_idle(
4069 thread_t thread,
4070 processor_t processor)
1c79356b 4071{
2d21ac55
A
4072 processor_set_t pset = processor->processor_set;
4073 thread_t new_thread;
4074 int state;
2d21ac55 4075 (void)splsched();
1c79356b 4076
316670eb
A
4077 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
4078 MACHDBG_CODE(DBG_MACH_SCHED,MACH_IDLE) | DBG_FUNC_START,
4079 (uintptr_t)thread_tid(thread), 0, 0, 0, 0);
3a60a9f5 4080
6d2010ae
A
4081 SCHED_STATS_CPU_IDLE_START(processor);
4082
2d21ac55
A
4083 timer_switch(&PROCESSOR_DATA(processor, system_state),
4084 mach_absolute_time(), &PROCESSOR_DATA(processor, idle_state));
4085 PROCESSOR_DATA(processor, current_state) = &PROCESSOR_DATA(processor, idle_state);
3a60a9f5 4086
6d2010ae 4087 while (processor->next_thread == THREAD_NULL && SCHED(processor_queue_empty)(processor) && rt_runq.count == 0 && SCHED(fairshare_runq_count)() == 0 &&
2d21ac55 4088 (thread == THREAD_NULL || ((thread->state & (TH_WAIT|TH_SUSP)) == TH_WAIT && !thread->wake_active))) {
6d2010ae
A
4089 IDLE_KERNEL_DEBUG_CONSTANT(
4090 MACHDBG_CODE(DBG_MACH_SCHED,MACH_IDLE) | DBG_FUNC_NONE, (uintptr_t)thread_tid(thread), rt_runq.count, SCHED(processor_runq_count)(processor), -1, 0);
4091
4b17d6b6
A
4092 machine_track_platform_idle(TRUE);
4093
2d21ac55 4094 machine_idle();
55e303ae 4095
4b17d6b6
A
4096 machine_track_platform_idle(FALSE);
4097
55e303ae 4098 (void)splsched();
c910b4d9 4099
6d2010ae
A
4100 IDLE_KERNEL_DEBUG_CONSTANT(
4101 MACHDBG_CODE(DBG_MACH_SCHED,MACH_IDLE) | DBG_FUNC_NONE, (uintptr_t)thread_tid(thread), rt_runq.count, SCHED(processor_runq_count)(processor), -2, 0);
4102
b7266188 4103 if (processor->state == PROCESSOR_INACTIVE && !machine_processor_is_inactive(processor))
c910b4d9 4104 break;
55e303ae
A
4105 }
4106
2d21ac55
A
4107 timer_switch(&PROCESSOR_DATA(processor, idle_state),
4108 mach_absolute_time(), &PROCESSOR_DATA(processor, system_state));
4109 PROCESSOR_DATA(processor, current_state) = &PROCESSOR_DATA(processor, system_state);
1c79356b 4110
2d21ac55
A
4111 pset_lock(pset);
4112
55e303ae
A
4113 state = processor->state;
4114 if (state == PROCESSOR_DISPATCHING) {
1c79356b 4115 /*
55e303ae 4116 * Commmon case -- cpu dispatched.
1c79356b 4117 */
2d21ac55
A
4118 new_thread = processor->next_thread;
4119 processor->next_thread = THREAD_NULL;
55e303ae 4120 processor->state = PROCESSOR_RUNNING;
1c79356b 4121
6d2010ae
A
4122 if (SCHED(processor_queue_has_priority)(processor, new_thread->sched_pri, FALSE) ||
4123 (rt_runq.count > 0 && BASEPRI_RTQUEUES >= new_thread->sched_pri) ) {
2d21ac55 4124 processor->deadline = UINT64_MAX;
55e303ae 4125
2d21ac55 4126 pset_unlock(pset);
1c79356b 4127
2d21ac55 4128 thread_lock(new_thread);
6d2010ae 4129 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED, MACH_REDISPATCH), (uintptr_t)thread_tid(new_thread), new_thread->sched_pri, rt_runq.count, 0, 0);
2d21ac55
A
4130 thread_setrun(new_thread, SCHED_HEADQ);
4131 thread_unlock(new_thread);
55e303ae 4132
316670eb
A
4133 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
4134 MACHDBG_CODE(DBG_MACH_SCHED,MACH_IDLE) | DBG_FUNC_END,
4135 (uintptr_t)thread_tid(thread), state, 0, 0, 0);
6d2010ae 4136
2d21ac55 4137 return (THREAD_NULL);
1c79356b 4138 }
1c79356b 4139
2d21ac55
A
4140 pset_unlock(pset);
4141
316670eb
A
4142 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
4143 MACHDBG_CODE(DBG_MACH_SCHED,MACH_IDLE) | DBG_FUNC_END,
4144 (uintptr_t)thread_tid(thread), state, (uintptr_t)thread_tid(new_thread), 0, 0);
6d2010ae 4145
2d21ac55 4146 return (new_thread);
55e303ae
A
4147 }
4148 else
4149 if (state == PROCESSOR_IDLE) {
6d2010ae 4150 remqueue((queue_entry_t)processor);
1c79356b 4151
2d21ac55 4152 processor->state = PROCESSOR_RUNNING;
cf7d32b8 4153 enqueue_tail(&pset->active_queue, (queue_entry_t)processor);
1c79356b 4154 }
55e303ae 4155 else
c910b4d9
A
4156 if (state == PROCESSOR_INACTIVE) {
4157 processor->state = PROCESSOR_RUNNING;
4158 enqueue_tail(&pset->active_queue, (queue_entry_t)processor);
4159 }
4160 else
55e303ae
A
4161 if (state == PROCESSOR_SHUTDOWN) {
4162 /*
4163 * Going off-line. Force a
4164 * reschedule.
4165 */
2d21ac55
A
4166 if ((new_thread = processor->next_thread) != THREAD_NULL) {
4167 processor->next_thread = THREAD_NULL;
55e303ae 4168 processor->deadline = UINT64_MAX;
2d21ac55
A
4169
4170 pset_unlock(pset);
55e303ae
A
4171
4172 thread_lock(new_thread);
4173 thread_setrun(new_thread, SCHED_HEADQ);
4174 thread_unlock(new_thread);
55e303ae 4175
316670eb
A
4176 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
4177 MACHDBG_CODE(DBG_MACH_SCHED,MACH_IDLE) | DBG_FUNC_END,
4178 (uintptr_t)thread_tid(thread), state, 0, 0, 0);
6d2010ae 4179
2d21ac55
A
4180 return (THREAD_NULL);
4181 }
55e303ae
A
4182 }
4183
2d21ac55
A
4184 pset_unlock(pset);
4185
316670eb
A
4186 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
4187 MACHDBG_CODE(DBG_MACH_SCHED,MACH_IDLE) | DBG_FUNC_END,
4188 (uintptr_t)thread_tid(thread), state, 0, 0, 0);
6d2010ae 4189
2d21ac55
A
4190 return (THREAD_NULL);
4191}
4192
cf7d32b8
A
4193/*
4194 * Each processor has a dedicated thread which
4195 * executes the idle loop when there is no suitable
4196 * previous context.
4197 */
2d21ac55
A
4198void
4199idle_thread(void)
4200{
4201 processor_t processor = current_processor();
4202 thread_t new_thread;
4203
4204 new_thread = processor_idle(THREAD_NULL, processor);
4205 if (new_thread != THREAD_NULL) {
4206 thread_run(processor->idle_thread, (thread_continue_t)idle_thread, NULL, new_thread);
4207 /*NOTREACHED*/
4208 }
55e303ae 4209
2d21ac55 4210 thread_block((thread_continue_t)idle_thread);
55e303ae 4211 /*NOTREACHED*/
1c79356b
A
4212}
4213
91447636
A
4214kern_return_t
4215idle_thread_create(
4216 processor_t processor)
1c79356b 4217{
91447636
A
4218 kern_return_t result;
4219 thread_t thread;
4220 spl_t s;
4221
4222 result = kernel_thread_create((thread_continue_t)idle_thread, NULL, MAXPRI_KERNEL, &thread);
4223 if (result != KERN_SUCCESS)
4224 return (result);
4225
4226 s = splsched();
4227 thread_lock(thread);
4228 thread->bound_processor = processor;
4229 processor->idle_thread = thread;
4230 thread->sched_pri = thread->priority = IDLEPRI;
4231 thread->state = (TH_RUN | TH_IDLE);
4232 thread_unlock(thread);
4233 splx(s);
4234
4235 thread_deallocate(thread);
4236
4237 return (KERN_SUCCESS);
1c79356b
A
4238}
4239
91447636
A
4240/*
4241 * sched_startup:
4242 *
4243 * Kicks off scheduler services.
4244 *
4245 * Called at splsched.
4246 */
0b4e3aa0 4247void
91447636 4248sched_startup(void)
0b4e3aa0 4249{
91447636
A
4250 kern_return_t result;
4251 thread_t thread;
4252
6d2010ae
A
4253 result = kernel_thread_start_priority((thread_continue_t)sched_init_thread,
4254 (void *)SCHED(maintenance_continuation),
4255 MAXPRI_KERNEL, &thread);
91447636
A
4256 if (result != KERN_SUCCESS)
4257 panic("sched_startup");
4258
4259 thread_deallocate(thread);
4260
4261 /*
316670eb
A
4262 * Yield to the sched_init_thread once, to
4263 * initialize our own thread after being switched
4264 * back to.
91447636
A
4265 *
4266 * The current thread is the only other thread
4267 * active at this point.
4268 */
316670eb 4269 thread_block(THREAD_CONTINUE_NULL);
6d2010ae 4270}
91447636 4271
6d2010ae 4272#if defined(CONFIG_SCHED_TRADITIONAL)
91447636 4273
6d2010ae 4274static uint64_t sched_tick_deadline = 0;
1c79356b
A
4275
4276/*
6d2010ae 4277 * sched_init_thread:
1c79356b 4278 *
55e303ae
A
4279 * Perform periodic bookkeeping functions about ten
4280 * times per second.
1c79356b 4281 */
91447636 4282static void
6d2010ae 4283sched_traditional_tick_continue(void)
1c79356b 4284{
91447636 4285 uint64_t abstime = mach_absolute_time();
1c79356b 4286
91447636 4287 sched_tick++;
1c79356b
A
4288
4289 /*
91447636 4290 * Compute various averages.
1c79356b 4291 */
91447636 4292 compute_averages();
1c79356b
A
4293
4294 /*
91447636
A
4295 * Scan the run queues for threads which
4296 * may need to be updated.
1c79356b 4297 */
91447636 4298 thread_update_scan();
1c79356b 4299
6d2010ae
A
4300 if (sched_tick_deadline == 0)
4301 sched_tick_deadline = abstime;
4302
1c79356b
A
4303 clock_deadline_for_periodic_event(sched_tick_interval, abstime,
4304 &sched_tick_deadline);
4305
6d2010ae
A
4306 assert_wait_deadline((event_t)sched_traditional_tick_continue, THREAD_UNINT, sched_tick_deadline);
4307 thread_block((thread_continue_t)sched_traditional_tick_continue);
1c79356b
A
4308 /*NOTREACHED*/
4309}
4310
6d2010ae
A
4311#endif /* CONFIG_SCHED_TRADITIONAL */
4312
1c79356b 4313void
6d2010ae 4314sched_init_thread(void (*continuation)(void))
1c79356b 4315{
316670eb 4316 thread_block(THREAD_CONTINUE_NULL);
91447636 4317
6d2010ae 4318 continuation();
1c79356b 4319
1c79356b
A
4320 /*NOTREACHED*/
4321}
4322
6d2010ae
A
4323#if defined(CONFIG_SCHED_TRADITIONAL)
4324
1c79356b 4325/*
91447636 4326 * thread_update_scan / runq_scan:
55e303ae 4327 *
91447636
A
4328 * Scan the run queues to account for timesharing threads
4329 * which need to be updated.
1c79356b
A
4330 *
4331 * Scanner runs in two passes. Pass one squirrels likely
91447636 4332 * threads away in an array, pass two does the update.
1c79356b 4333 *
91447636
A
4334 * This is necessary because the run queue is locked for
4335 * the candidate scan, but the thread is locked for the update.
1c79356b 4336 *
91447636
A
4337 * Array should be sized to make forward progress, without
4338 * disabling preemption for long periods.
1c79356b 4339 */
55e303ae 4340
91447636 4341#define THREAD_UPDATE_SIZE 128
55e303ae 4342
91447636
A
4343static thread_t thread_update_array[THREAD_UPDATE_SIZE];
4344static int thread_update_count = 0;
1c79356b
A
4345
4346/*
91447636
A
4347 * Scan a runq for candidate threads.
4348 *
4349 * Returns TRUE if retry is needed.
1c79356b 4350 */
55e303ae 4351static boolean_t
91447636 4352runq_scan(
1c79356b
A
4353 run_queue_t runq)
4354{
91447636 4355 register int count;
1c79356b
A
4356 register queue_t q;
4357 register thread_t thread;
1c79356b 4358
1c79356b
A
4359 if ((count = runq->count) > 0) {
4360 q = runq->queues + runq->highq;
4361 while (count > 0) {
4362 queue_iterate(q, thread, thread_t, links) {
55e303ae 4363 if ( thread->sched_stamp != sched_tick &&
6d2010ae 4364 (thread->sched_mode == TH_MODE_TIMESHARE) ) {
91447636 4365 if (thread_update_count == THREAD_UPDATE_SIZE)
55e303ae 4366 return (TRUE);
1c79356b 4367
91447636
A
4368 thread_update_array[thread_update_count++] = thread;
4369 thread_reference_internal(thread);
1c79356b
A
4370 }
4371
4372 count--;
4373 }
4374
4375 q--;
4376 }
4377 }
1c79356b 4378
91447636 4379 return (FALSE);
1c79356b
A
4380}
4381
55e303ae 4382static void
91447636 4383thread_update_scan(void)
1c79356b 4384{
2d21ac55
A
4385 boolean_t restart_needed = FALSE;
4386 processor_t processor = processor_list;
4387 processor_set_t pset;
4388 thread_t thread;
4389 spl_t s;
1c79356b 4390
1c79356b 4391 do {
2d21ac55
A
4392 do {
4393 pset = processor->processor_set;
1c79356b 4394
2d21ac55
A
4395 s = splsched();
4396 pset_lock(pset);
0b4e3aa0 4397
6d2010ae 4398 restart_needed = runq_scan(runq_for_processor(processor));
2d21ac55
A
4399
4400 pset_unlock(pset);
4401 splx(s);
4402
4403 if (restart_needed)
4404 break;
4405
4406 thread = processor->idle_thread;
4407 if (thread != THREAD_NULL && thread->sched_stamp != sched_tick) {
4408 if (thread_update_count == THREAD_UPDATE_SIZE) {
4409 restart_needed = TRUE;
4410 break;
0b4e3aa0
A
4411 }
4412
2d21ac55
A
4413 thread_update_array[thread_update_count++] = thread;
4414 thread_reference_internal(thread);
1c79356b 4415 }
2d21ac55 4416 } while ((processor = processor->processor_list) != NULL);
1c79356b
A
4417
4418 /*
4419 * Ok, we now have a collection of candidates -- fix them.
4420 */
91447636
A
4421 while (thread_update_count > 0) {
4422 thread = thread_update_array[--thread_update_count];
4423 thread_update_array[thread_update_count] = THREAD_NULL;
55e303ae 4424
1c79356b
A
4425 s = splsched();
4426 thread_lock(thread);
6d2010ae
A
4427 if ( !(thread->state & (TH_WAIT)) ) {
4428 if (SCHED(can_update_priority)(thread))
4429 SCHED(update_priority)(thread);
4430 }
1c79356b
A
4431 thread_unlock(thread);
4432 splx(s);
55e303ae 4433
91447636 4434 thread_deallocate(thread);
1c79356b 4435 }
1c79356b
A
4436 } while (restart_needed);
4437}
6d2010ae
A
4438
4439#endif /* CONFIG_SCHED_TRADITIONAL */
4440
4441boolean_t
4442thread_eager_preemption(thread_t thread)
4443{
4444 return ((thread->sched_flags & TH_SFLAG_EAGERPREEMPT) != 0);
4445}
4446
4447void
4448thread_set_eager_preempt(thread_t thread)
4449{
4450 spl_t x;
4451 processor_t p;
4452 ast_t ast = AST_NONE;
4453
4454 x = splsched();
4455 p = current_processor();
4456
4457 thread_lock(thread);
4458 thread->sched_flags |= TH_SFLAG_EAGERPREEMPT;
4459
4460 if (thread == current_thread()) {
4461 thread_unlock(thread);
4462
4463 ast = csw_check(p);
4464 if (ast != AST_NONE) {
4465 (void) thread_block_reason(THREAD_CONTINUE_NULL, NULL, ast);
4466 }
4467 } else {
4468 p = thread->last_processor;
4469
4470 if (p != PROCESSOR_NULL && p->state == PROCESSOR_RUNNING &&
4471 p->active_thread == thread) {
4472 cause_ast_check(p);
4473 }
1c79356b 4474
6d2010ae
A
4475 thread_unlock(thread);
4476 }
4477
4478 splx(x);
4479}
4480
4481void
4482thread_clear_eager_preempt(thread_t thread)
4483{
4484 spl_t x;
4485
4486 x = splsched();
4487 thread_lock(thread);
4488
4489 thread->sched_flags &= ~TH_SFLAG_EAGERPREEMPT;
4490
4491 thread_unlock(thread);
4492 splx(x);
4493}
4494/*
4495 * Scheduling statistics
4496 */
4497void
4498sched_stats_handle_csw(processor_t processor, int reasons, int selfpri, int otherpri)
4499{
4500 struct processor_sched_statistics *stats;
4501 boolean_t to_realtime = FALSE;
4502
4503 stats = &processor->processor_data.sched_stats;
4504 stats->csw_count++;
4505
4506 if (otherpri >= BASEPRI_REALTIME) {
4507 stats->rt_sched_count++;
4508 to_realtime = TRUE;
4509 }
4510
4511 if ((reasons & AST_PREEMPT) != 0) {
4512 stats->preempt_count++;
4513
4514 if (selfpri >= BASEPRI_REALTIME) {
4515 stats->preempted_rt_count++;
4516 }
4517
4518 if (to_realtime) {
4519 stats->preempted_by_rt_count++;
4520 }
4521
4522 }
4523}
4524
4525void
4526sched_stats_handle_runq_change(struct runq_stats *stats, int old_count)
4527{
4528 uint64_t timestamp = mach_absolute_time();
4529
4530 stats->count_sum += (timestamp - stats->last_change_timestamp) * old_count;
4531 stats->last_change_timestamp = timestamp;
4532}
4533
1c79356b 4534/*
6d2010ae 4535 * For calls from assembly code
1c79356b 4536 */
6d2010ae 4537#undef thread_wakeup
1c79356b
A
4538void
4539thread_wakeup(
6d2010ae 4540 event_t x);
1c79356b
A
4541
4542void
4543thread_wakeup(
6d2010ae 4544 event_t x)
1c79356b 4545{
6d2010ae 4546 thread_wakeup_with_result(x, THREAD_AWAKENED);
1c79356b
A
4547}
4548
91447636
A
4549boolean_t
4550preemption_enabled(void)
4551{
4552 return (get_preemption_level() == 0 && ml_get_interrupts_enabled());
4553}
9bccf70c 4554
0b4e3aa0 4555#if DEBUG
0b4e3aa0 4556static boolean_t
1c79356b 4557thread_runnable(
0b4e3aa0 4558 thread_t thread)
1c79356b 4559{
0b4e3aa0 4560 return ((thread->state & (TH_RUN|TH_WAIT)) == TH_RUN);
1c79356b 4561}
1c79356b 4562#endif /* DEBUG */
4b17d6b6
A
4563
4564static void
4565sched_timer_deadline_tracking_init(void) {
4566 nanoseconds_to_absolutetime(TIMER_DEADLINE_TRACKING_BIN_1_DEFAULT, &timer_deadline_tracking_bin_1);
4567 nanoseconds_to_absolutetime(TIMER_DEADLINE_TRACKING_BIN_2_DEFAULT, &timer_deadline_tracking_bin_2);
4568}