]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kern/sched_prim.c
xnu-1504.7.4.tar.gz
[apple/xnu.git] / osfmk / kern / sched_prim.c
CommitLineData
1c79356b 1/*
c910b4d9 2 * Copyright (c) 2000-2009 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>
1c79356b 68#include <mach_kdb.h>
1c79356b
A
69
70#include <ddb/db_output.h>
91447636
A
71
72#include <mach/mach_types.h>
1c79356b 73#include <mach/machine.h>
91447636
A
74#include <mach/policy.h>
75#include <mach/sync_policy.h>
76
1c79356b
A
77#include <machine/machine_routines.h>
78#include <machine/sched_param.h>
0c530ab8 79#include <machine/machine_cpu.h>
91447636
A
80
81#include <kern/kern_types.h>
1c79356b
A
82#include <kern/clock.h>
83#include <kern/counters.h>
84#include <kern/cpu_number.h>
85#include <kern/cpu_data.h>
91447636 86#include <kern/debug.h>
1c79356b
A
87#include <kern/lock.h>
88#include <kern/macro_help.h>
89#include <kern/machine.h>
90#include <kern/misc_protos.h>
91#include <kern/processor.h>
92#include <kern/queue.h>
93#include <kern/sched.h>
94#include <kern/sched_prim.h>
95#include <kern/syscall_subr.h>
96#include <kern/task.h>
97#include <kern/thread.h>
91447636
A
98#include <kern/wait_queue.h>
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
2d21ac55
A
110struct run_queue rt_runq;
111#define RT_RUNQ ((processor_t)-1)
112decl_simple_lock_data(static,rt_lock);
113
0b4e3aa0 114#define DEFAULT_PREEMPTION_RATE 100 /* (1/s) */
1c79356b
A
115int default_preemption_rate = DEFAULT_PREEMPTION_RATE;
116
0b4e3aa0
A
117#define MAX_UNSAFE_QUANTA 800
118int max_unsafe_quanta = MAX_UNSAFE_QUANTA;
119
120#define MAX_POLL_QUANTA 2
121int max_poll_quanta = MAX_POLL_QUANTA;
122
123#define SCHED_POLL_YIELD_SHIFT 4 /* 1/16 */
124int sched_poll_yield_shift = SCHED_POLL_YIELD_SHIFT;
125
55e303ae
A
126uint64_t max_unsafe_computation;
127uint32_t sched_safe_duration;
128uint64_t max_poll_computation;
129
130uint32_t std_quantum;
131uint32_t min_std_quantum;
132
91447636
A
133uint32_t std_quantum_us;
134
55e303ae
A
135uint32_t max_rt_quantum;
136uint32_t min_rt_quantum;
137
91447636
A
138uint32_t sched_cswtime;
139
1c79356b 140unsigned sched_tick;
91447636 141uint32_t sched_tick_interval;
1c79356b 142
2d21ac55
A
143uint32_t sched_pri_shift = INT8_MAX;
144uint32_t sched_fixed_shift;
145
146uint32_t sched_run_count, sched_share_count;
147uint32_t sched_load_average, sched_mach_factor;
148
1c79356b 149/* Forwards */
2d21ac55 150static void load_shift_init(void) __attribute__((section("__TEXT, initcode")));
4a3eedf9 151static void preempt_pri_init(void) __attribute__((section("__TEXT, initcode")));
2d21ac55 152
c910b4d9
A
153static thread_t run_queue_dequeue(
154 run_queue_t runq,
155 integer_t options);
156
b0d623f7
A
157static thread_t choose_thread(
158 processor_t processor,
159 int priority);
160
2d21ac55
A
161static thread_t thread_select_idle(
162 thread_t thread,
163 processor_t processor);
1c79356b 164
2d21ac55
A
165static thread_t processor_idle(
166 thread_t thread,
167 processor_t processor);
91447636 168
2d21ac55 169static thread_t steal_thread(
cf7d32b8
A
170 processor_set_t pset);
171
172static thread_t steal_processor_thread(
55e303ae 173 processor_t processor);
1c79356b 174
91447636 175static void thread_update_scan(void);
1c79356b 176
2d21ac55
A
177#if DEBUG
178extern int debug_task;
179#define TLOG(a, fmt, args...) if(debug_task & a) kprintf(fmt, ## args)
180#else
181#define TLOG(a, fmt, args...) do {} while (0)
182#endif
183
1c79356b 184#if DEBUG
0b4e3aa0 185static
1c79356b
A
186boolean_t thread_runnable(
187 thread_t thread);
188
0b4e3aa0
A
189#endif /*DEBUG*/
190
1c79356b
A
191/*
192 * State machine
193 *
194 * states are combinations of:
195 * R running
196 * W waiting (or on wait queue)
197 * N non-interruptible
198 * O swapped out
199 * I being swapped in
200 *
201 * init action
202 * assert_wait thread_block clear_wait swapout swapin
203 *
204 * R RW, RWN R; setrun - -
205 * RN RWN RN; setrun - -
206 *
207 * RW W R -
208 * RWN WN RN -
209 *
210 * W R; setrun WO
211 * WN RN; setrun -
212 *
213 * RO - - R
214 *
215 */
216
91447636 217int8_t sched_load_shifts[NRQS];
b0d623f7 218int sched_preempt_pri[NRQBM];
91447636 219
1c79356b
A
220void
221sched_init(void)
222{
223 /*
0b4e3aa0
A
224 * Calculate the timeslicing quantum
225 * in us.
1c79356b
A
226 */
227 if (default_preemption_rate < 1)
228 default_preemption_rate = DEFAULT_PREEMPTION_RATE;
0b4e3aa0 229 std_quantum_us = (1000 * 1000) / default_preemption_rate;
1c79356b 230
0b4e3aa0 231 printf("standard timeslicing quantum is %d us\n", std_quantum_us);
1c79356b 232
55e303ae
A
233 sched_safe_duration = (2 * max_unsafe_quanta / default_preemption_rate) *
234 (1 << SCHED_TICK_SHIFT);
235
91447636 236 load_shift_init();
4a3eedf9 237 preempt_pri_init();
2d21ac55
A
238 simple_lock_init(&rt_lock, 0);
239 run_queue_init(&rt_runq);
1c79356b 240 sched_tick = 0;
1c79356b 241 ast_init();
1c79356b
A
242}
243
55e303ae
A
244void
245sched_timebase_init(void)
246{
91447636
A
247 uint64_t abstime;
248 uint32_t shift;
55e303ae 249
91447636 250 /* standard timeslicing quantum */
55e303ae
A
251 clock_interval_to_absolutetime_interval(
252 std_quantum_us, NSEC_PER_USEC, &abstime);
253 assert((abstime >> 32) == 0 && (uint32_t)abstime != 0);
b0d623f7 254 std_quantum = (uint32_t)abstime;
55e303ae 255
91447636 256 /* smallest remaining quantum (250 us) */
55e303ae
A
257 clock_interval_to_absolutetime_interval(250, NSEC_PER_USEC, &abstime);
258 assert((abstime >> 32) == 0 && (uint32_t)abstime != 0);
b0d623f7 259 min_std_quantum = (uint32_t)abstime;
55e303ae 260
91447636 261 /* smallest rt computaton (50 us) */
55e303ae
A
262 clock_interval_to_absolutetime_interval(50, NSEC_PER_USEC, &abstime);
263 assert((abstime >> 32) == 0 && (uint32_t)abstime != 0);
b0d623f7 264 min_rt_quantum = (uint32_t)abstime;
55e303ae 265
91447636 266 /* maximum rt computation (50 ms) */
55e303ae
A
267 clock_interval_to_absolutetime_interval(
268 50, 1000*NSEC_PER_USEC, &abstime);
269 assert((abstime >> 32) == 0 && (uint32_t)abstime != 0);
b0d623f7 270 max_rt_quantum = (uint32_t)abstime;
55e303ae 271
91447636
A
272 /* scheduler tick interval */
273 clock_interval_to_absolutetime_interval(USEC_PER_SEC >> SCHED_TICK_SHIFT,
274 NSEC_PER_USEC, &abstime);
cf7d32b8 275 assert((abstime >> 32) == 0 && (uint32_t)abstime != 0);
b0d623f7 276 sched_tick_interval = (uint32_t)abstime;
55e303ae 277
91447636
A
278 /*
279 * Compute conversion factor from usage to
280 * timesharing priorities with 5/8 ** n aging.
281 */
282 abstime = (abstime * 5) / 3;
283 for (shift = 0; abstime > BASEPRI_DEFAULT; ++shift)
284 abstime >>= 1;
2d21ac55 285 sched_fixed_shift = shift;
91447636 286
55e303ae
A
287 max_unsafe_computation = max_unsafe_quanta * std_quantum;
288 max_poll_computation = max_poll_quanta * std_quantum;
289}
290
91447636
A
291/*
292 * Set up values for timeshare
293 * loading factors.
294 */
295static void
296load_shift_init(void)
297{
298 int8_t k, *p = sched_load_shifts;
299 uint32_t i, j;
300
301 *p++ = INT8_MIN; *p++ = 0;
302
303 for (i = j = 2, k = 1; i < NRQS; ++k) {
304 for (j <<= 1; i < j; ++i)
305 *p++ = k;
306 }
307}
308
4a3eedf9
A
309static void
310preempt_pri_init(void)
311{
312 int i, *p = sched_preempt_pri;
313
314 for (i = BASEPRI_FOREGROUND + 1; i < MINPRI_KERNEL; ++i)
315 setbit(i, p);
316
317 for (i = BASEPRI_PREEMPT; i <= MAXPRI; ++i)
318 setbit(i, p);
319}
320
1c79356b 321/*
0b4e3aa0 322 * Thread wait timer expiration.
1c79356b
A
323 */
324void
325thread_timer_expire(
91447636
A
326 void *p0,
327 __unused void *p1)
1c79356b
A
328{
329 thread_t thread = p0;
330 spl_t s;
331
332 s = splsched();
55e303ae 333 thread_lock(thread);
91447636 334 if (--thread->wait_timer_active == 0) {
0b4e3aa0
A
335 if (thread->wait_timer_is_set) {
336 thread->wait_timer_is_set = FALSE;
55e303ae 337 clear_wait_internal(thread, THREAD_TIMED_OUT);
0b4e3aa0 338 }
1c79356b 339 }
55e303ae 340 thread_unlock(thread);
1c79356b
A
341 splx(s);
342}
343
b0d623f7
A
344#ifndef __LP64__
345
1c79356b
A
346/*
347 * thread_set_timer:
348 *
349 * Set a timer for the current thread, if the thread
350 * is ready to wait. Must be called between assert_wait()
351 * and thread_block().
352 */
353void
354thread_set_timer(
0b4e3aa0
A
355 uint32_t interval,
356 uint32_t scale_factor)
1c79356b
A
357{
358 thread_t thread = current_thread();
0b4e3aa0 359 uint64_t deadline;
1c79356b
A
360 spl_t s;
361
362 s = splsched();
1c79356b
A
363 thread_lock(thread);
364 if ((thread->state & TH_WAIT) != 0) {
365 clock_interval_to_deadline(interval, scale_factor, &deadline);
91447636
A
366 if (!timer_call_enter(&thread->wait_timer, deadline))
367 thread->wait_timer_active++;
1c79356b
A
368 thread->wait_timer_is_set = TRUE;
369 }
370 thread_unlock(thread);
1c79356b
A
371 splx(s);
372}
373
374void
375thread_set_timer_deadline(
0b4e3aa0 376 uint64_t deadline)
1c79356b
A
377{
378 thread_t thread = current_thread();
379 spl_t s;
380
381 s = splsched();
1c79356b
A
382 thread_lock(thread);
383 if ((thread->state & TH_WAIT) != 0) {
91447636
A
384 if (!timer_call_enter(&thread->wait_timer, deadline))
385 thread->wait_timer_active++;
1c79356b
A
386 thread->wait_timer_is_set = TRUE;
387 }
388 thread_unlock(thread);
1c79356b
A
389 splx(s);
390}
391
392void
393thread_cancel_timer(void)
394{
395 thread_t thread = current_thread();
396 spl_t s;
397
398 s = splsched();
55e303ae 399 thread_lock(thread);
1c79356b
A
400 if (thread->wait_timer_is_set) {
401 if (timer_call_cancel(&thread->wait_timer))
402 thread->wait_timer_active--;
403 thread->wait_timer_is_set = FALSE;
404 }
55e303ae 405 thread_unlock(thread);
1c79356b
A
406 splx(s);
407}
408
b0d623f7
A
409#endif /* __LP64__ */
410
1c79356b 411/*
91447636
A
412 * thread_unblock:
413 *
414 * Unblock thread on wake up.
415 *
416 * Returns TRUE if the thread is still running.
417 *
418 * Thread must be locked.
1c79356b 419 */
91447636
A
420boolean_t
421thread_unblock(
422 thread_t thread,
423 wait_result_t wresult)
1c79356b 424{
91447636 425 boolean_t result = FALSE;
0b4e3aa0 426
91447636 427 /*
2d21ac55 428 * Set wait_result.
91447636
A
429 */
430 thread->wait_result = wresult;
1c79356b 431
91447636 432 /*
2d21ac55 433 * Cancel pending wait timer.
91447636 434 */
1c79356b
A
435 if (thread->wait_timer_is_set) {
436 if (timer_call_cancel(&thread->wait_timer))
437 thread->wait_timer_active--;
438 thread->wait_timer_is_set = FALSE;
439 }
440
91447636 441 /*
2d21ac55
A
442 * Update scheduling state: not waiting,
443 * set running.
91447636
A
444 */
445 thread->state &= ~(TH_WAIT|TH_UNINT);
1c79356b 446
91447636
A
447 if (!(thread->state & TH_RUN)) {
448 thread->state |= TH_RUN;
1c79356b 449
2d21ac55 450 (*thread->sched_call)(SCHED_CALL_UNBLOCK, thread);
1c79356b 451
91447636 452 /*
2d21ac55 453 * Update run counts.
91447636 454 */
2d21ac55 455 sched_run_incr();
91447636 456 if (thread->sched_mode & TH_MODE_TIMESHARE)
2d21ac55 457 sched_share_incr();
1c79356b 458 }
2d21ac55
A
459 else {
460 /*
461 * Signal if idling on another processor.
462 */
463 if (thread->state & TH_IDLE) {
464 processor_t processor = thread->last_processor;
465
466 if (processor != current_processor())
467 machine_signal_idle(processor);
468 }
469
91447636 470 result = TRUE;
2d21ac55 471 }
1c79356b 472
91447636
A
473 /*
474 * Calculate deadline for real-time threads.
475 */
476 if (thread->sched_mode & TH_MODE_REALTIME) {
477 thread->realtime.deadline = mach_absolute_time();
478 thread->realtime.deadline += thread->realtime.constraint;
0b4e3aa0
A
479 }
480
91447636
A
481 /*
482 * Clear old quantum, fail-safe computation, etc.
483 */
484 thread->current_quantum = 0;
485 thread->computation_metered = 0;
486 thread->reason = AST_NONE;
1c79356b 487
91447636
A
488 KERNEL_DEBUG_CONSTANT(
489 MACHDBG_CODE(DBG_MACH_SCHED,MACH_MAKE_RUNNABLE) | DBG_FUNC_NONE,
b0d623f7
A
490 (uintptr_t)thread_tid(thread), thread->sched_pri, 0, 0, 0);
491
492 DTRACE_SCHED2(wakeup, struct thread *, thread, struct proc *, thread->task->bsd_info);
91447636
A
493
494 return (result);
1c79356b
A
495}
496
497/*
91447636 498 * Routine: thread_go
1c79356b 499 * Purpose:
91447636 500 * Unblock and dispatch thread.
1c79356b
A
501 * Conditions:
502 * thread lock held, IPC locks may be held.
503 * thread must have been pulled from wait queue under same lock hold.
9bccf70c
A
504 * Returns:
505 * KERN_SUCCESS - Thread was set running
506 * KERN_NOT_WAITING - Thread was not waiting
1c79356b 507 */
9bccf70c 508kern_return_t
91447636 509thread_go(
1c79356b 510 thread_t thread,
55e303ae 511 wait_result_t wresult)
1c79356b 512{
1c79356b 513 assert(thread->at_safe_point == FALSE);
9bccf70c 514 assert(thread->wait_event == NO_EVENT64);
1c79356b
A
515 assert(thread->wait_queue == WAIT_QUEUE_NULL);
516
9bccf70c 517 if ((thread->state & (TH_WAIT|TH_TERMINATE)) == TH_WAIT) {
91447636 518 if (!thread_unblock(thread, wresult))
55e303ae 519 thread_setrun(thread, SCHED_PREEMPT | SCHED_TAILQ);
55e303ae
A
520
521 return (KERN_SUCCESS);
1c79356b 522 }
55e303ae
A
523
524 return (KERN_NOT_WAITING);
1c79356b
A
525}
526
9bccf70c
A
527/*
528 * Routine: thread_mark_wait_locked
529 * Purpose:
530 * Mark a thread as waiting. If, given the circumstances,
531 * it doesn't want to wait (i.e. already aborted), then
532 * indicate that in the return value.
533 * Conditions:
534 * at splsched() and thread is locked.
535 */
536__private_extern__
537wait_result_t
1c79356b 538thread_mark_wait_locked(
9bccf70c
A
539 thread_t thread,
540 wait_interrupt_t interruptible)
1c79356b 541{
55e303ae 542 boolean_t at_safe_point;
1c79356b 543
b0d623f7
A
544 assert(thread == current_thread());
545
9bccf70c
A
546 /*
547 * The thread may have certain types of interrupts/aborts masked
548 * off. Even if the wait location says these types of interrupts
549 * are OK, we have to honor mask settings (outer-scoped code may
550 * not be able to handle aborts at the moment).
551 */
91447636
A
552 if (interruptible > (thread->options & TH_OPT_INTMASK))
553 interruptible = thread->options & TH_OPT_INTMASK;
9bccf70c
A
554
555 at_safe_point = (interruptible == THREAD_ABORTSAFE);
556
55e303ae 557 if ( interruptible == THREAD_UNINT ||
2d21ac55 558 !(thread->sched_mode & TH_MODE_ABORT) ||
55e303ae 559 (!at_safe_point &&
2d21ac55 560 (thread->sched_mode & TH_MODE_ABORTSAFELY))) {
b0d623f7
A
561
562 DTRACE_SCHED(sleep);
563
9bccf70c
A
564 thread->state |= (interruptible) ? TH_WAIT : (TH_WAIT | TH_UNINT);
565 thread->at_safe_point = at_safe_point;
9bccf70c 566 return (thread->wait_result = THREAD_WAITING);
9bccf70c 567 }
55e303ae 568 else
2d21ac55
A
569 if (thread->sched_mode & TH_MODE_ABORTSAFELY)
570 thread->sched_mode &= ~TH_MODE_ISABORTED;
55e303ae 571
9bccf70c 572 return (thread->wait_result = THREAD_INTERRUPTED);
1c79356b
A
573}
574
9bccf70c
A
575/*
576 * Routine: thread_interrupt_level
577 * Purpose:
578 * Set the maximum interruptible state for the
579 * current thread. The effective value of any
580 * interruptible flag passed into assert_wait
581 * will never exceed this.
582 *
583 * Useful for code that must not be interrupted,
584 * but which calls code that doesn't know that.
585 * Returns:
586 * The old interrupt level for the thread.
587 */
588__private_extern__
589wait_interrupt_t
590thread_interrupt_level(
591 wait_interrupt_t new_level)
592{
593 thread_t thread = current_thread();
91447636 594 wait_interrupt_t result = thread->options & TH_OPT_INTMASK;
1c79356b 595
91447636 596 thread->options = (thread->options & ~TH_OPT_INTMASK) | (new_level & TH_OPT_INTMASK);
1c79356b 597
91447636 598 return result;
1c79356b
A
599}
600
601/*
602 * Check to see if an assert wait is possible, without actually doing one.
603 * This is used by debug code in locks and elsewhere to verify that it is
604 * always OK to block when trying to take a blocking lock (since waiting
605 * for the actual assert_wait to catch the case may make it hard to detect
606 * this case.
607 */
608boolean_t
609assert_wait_possible(void)
610{
611
612 thread_t thread;
1c79356b
A
613
614#if DEBUG
615 if(debug_mode) return TRUE; /* Always succeed in debug mode */
616#endif
617
618 thread = current_thread();
619
620 return (thread == NULL || wait_queue_assert_possible(thread));
621}
622
623/*
624 * assert_wait:
625 *
626 * Assert that the current thread is about to go to
627 * sleep until the specified event occurs.
628 */
9bccf70c 629wait_result_t
1c79356b
A
630assert_wait(
631 event_t event,
9bccf70c 632 wait_interrupt_t interruptible)
1c79356b
A
633{
634 register wait_queue_t wq;
635 register int index;
636
637 assert(event != NO_EVENT);
1c79356b
A
638
639 index = wait_hash(event);
640 wq = &wait_queues[index];
91447636 641 return wait_queue_assert_wait(wq, event, interruptible, 0);
9bccf70c
A
642}
643
91447636
A
644wait_result_t
645assert_wait_timeout(
646 event_t event,
647 wait_interrupt_t interruptible,
648 uint32_t interval,
649 uint32_t scale_factor)
55e303ae 650{
91447636
A
651 thread_t thread = current_thread();
652 wait_result_t wresult;
653 wait_queue_t wqueue;
654 uint64_t deadline;
655 spl_t s;
656
55e303ae 657 assert(event != NO_EVENT);
91447636
A
658 wqueue = &wait_queues[wait_hash(event)];
659
660 s = splsched();
661 wait_queue_lock(wqueue);
662 thread_lock(thread);
663
664 clock_interval_to_deadline(interval, scale_factor, &deadline);
b0d623f7 665 wresult = wait_queue_assert_wait64_locked(wqueue, CAST_DOWN(event64_t, event),
91447636
A
666 interruptible, deadline, thread);
667
668 thread_unlock(thread);
669 wait_queue_unlock(wqueue);
670 splx(s);
55e303ae 671
91447636 672 return (wresult);
55e303ae
A
673}
674
675wait_result_t
91447636 676assert_wait_deadline(
55e303ae 677 event_t event,
91447636
A
678 wait_interrupt_t interruptible,
679 uint64_t deadline)
55e303ae
A
680{
681 thread_t thread = current_thread();
91447636
A
682 wait_result_t wresult;
683 wait_queue_t wqueue;
55e303ae
A
684 spl_t s;
685
686 assert(event != NO_EVENT);
91447636 687 wqueue = &wait_queues[wait_hash(event)];
55e303ae
A
688
689 s = splsched();
91447636 690 wait_queue_lock(wqueue);
55e303ae
A
691 thread_lock(thread);
692
b0d623f7 693 wresult = wait_queue_assert_wait64_locked(wqueue, CAST_DOWN(event64_t,event),
91447636 694 interruptible, deadline, thread);
55e303ae
A
695
696 thread_unlock(thread);
91447636 697 wait_queue_unlock(wqueue);
55e303ae
A
698 splx(s);
699
700 return (wresult);
701}
9bccf70c
A
702
703/*
704 * thread_sleep_fast_usimple_lock:
705 *
706 * Cause the current thread to wait until the specified event
707 * occurs. The specified simple_lock is unlocked before releasing
708 * the cpu and re-acquired as part of waking up.
709 *
710 * This is the simple lock sleep interface for components that use a
711 * faster version of simple_lock() than is provided by usimple_lock().
712 */
713__private_extern__ wait_result_t
714thread_sleep_fast_usimple_lock(
715 event_t event,
716 simple_lock_t lock,
717 wait_interrupt_t interruptible)
718{
719 wait_result_t res;
720
721 res = assert_wait(event, interruptible);
722 if (res == THREAD_WAITING) {
723 simple_unlock(lock);
724 res = thread_block(THREAD_CONTINUE_NULL);
725 simple_lock(lock);
726 }
727 return res;
1c79356b
A
728}
729
9bccf70c
A
730
731/*
732 * thread_sleep_usimple_lock:
733 *
734 * Cause the current thread to wait until the specified event
735 * occurs. The specified usimple_lock is unlocked before releasing
736 * the cpu and re-acquired as part of waking up.
737 *
738 * This is the simple lock sleep interface for components where
739 * simple_lock() is defined in terms of usimple_lock().
740 */
741wait_result_t
742thread_sleep_usimple_lock(
743 event_t event,
744 usimple_lock_t lock,
745 wait_interrupt_t interruptible)
746{
747 wait_result_t res;
748
749 res = assert_wait(event, interruptible);
750 if (res == THREAD_WAITING) {
751 usimple_unlock(lock);
752 res = thread_block(THREAD_CONTINUE_NULL);
753 usimple_lock(lock);
754 }
755 return res;
756}
757
9bccf70c
A
758/*
759 * thread_sleep_lock_write:
760 *
761 * Cause the current thread to wait until the specified event
762 * occurs. The specified (write) lock is unlocked before releasing
763 * the cpu. The (write) lock will be re-acquired before returning.
9bccf70c
A
764 */
765wait_result_t
766thread_sleep_lock_write(
767 event_t event,
768 lock_t *lock,
769 wait_interrupt_t interruptible)
770{
771 wait_result_t res;
772
773 res = assert_wait(event, interruptible);
774 if (res == THREAD_WAITING) {
775 lock_write_done(lock);
776 res = thread_block(THREAD_CONTINUE_NULL);
777 lock_write(lock);
778 }
779 return res;
780}
781
1c79356b 782/*
91447636 783 * thread_stop:
1c79356b 784 *
91447636
A
785 * Force a preemption point for a thread and wait
786 * for it to stop running. Arbitrates access among
787 * multiple stop requests. (released by unstop)
1c79356b 788 *
91447636
A
789 * The thread must enter a wait state and stop via a
790 * separate means.
1c79356b 791 *
91447636 792 * Returns FALSE if interrupted.
1c79356b
A
793 */
794boolean_t
795thread_stop(
91447636 796 thread_t thread)
1c79356b 797{
91447636 798 wait_result_t wresult;
2d21ac55 799 spl_t s = splsched();
1c79356b 800
1c79356b 801 wake_lock(thread);
2d21ac55 802 thread_lock(thread);
1c79356b
A
803
804 while (thread->state & TH_SUSP) {
805 thread->wake_active = TRUE;
2d21ac55
A
806 thread_unlock(thread);
807
91447636 808 wresult = assert_wait(&thread->wake_active, THREAD_ABORTSAFE);
1c79356b
A
809 wake_unlock(thread);
810 splx(s);
811
91447636
A
812 if (wresult == THREAD_WAITING)
813 wresult = thread_block(THREAD_CONTINUE_NULL);
9bccf70c 814
91447636 815 if (wresult != THREAD_AWAKENED)
1c79356b
A
816 return (FALSE);
817
818 s = splsched();
819 wake_lock(thread);
2d21ac55 820 thread_lock(thread);
1c79356b 821 }
9bccf70c 822
1c79356b 823 thread->state |= TH_SUSP;
1c79356b 824
9bccf70c 825 while (thread->state & TH_RUN) {
9bccf70c
A
826 processor_t processor = thread->last_processor;
827
2d21ac55 828 if (processor != PROCESSOR_NULL && processor->active_thread == thread)
9bccf70c 829 cause_ast_check(processor);
9bccf70c
A
830
831 thread->wake_active = TRUE;
2d21ac55
A
832 thread_unlock(thread);
833
91447636 834 wresult = assert_wait(&thread->wake_active, THREAD_ABORTSAFE);
9bccf70c
A
835 wake_unlock(thread);
836 splx(s);
837
91447636
A
838 if (wresult == THREAD_WAITING)
839 wresult = thread_block(THREAD_CONTINUE_NULL);
9bccf70c 840
91447636 841 if (wresult != THREAD_AWAKENED) {
9bccf70c
A
842 thread_unstop(thread);
843 return (FALSE);
844 }
845
846 s = splsched();
847 wake_lock(thread);
848 thread_lock(thread);
849 }
850
851 thread_unlock(thread);
1c79356b
A
852 wake_unlock(thread);
853 splx(s);
854
855 return (TRUE);
856}
857
858/*
91447636
A
859 * thread_unstop:
860 *
861 * Release a previous stop request and set
862 * the thread running if appropriate.
863 *
864 * Use only after a successful stop operation.
1c79356b
A
865 */
866void
867thread_unstop(
9bccf70c 868 thread_t thread)
1c79356b 869{
9bccf70c 870 spl_t s = splsched();
1c79356b 871
1c79356b
A
872 wake_lock(thread);
873 thread_lock(thread);
874
9bccf70c 875 if ((thread->state & (TH_RUN|TH_WAIT|TH_SUSP)) == TH_SUSP) {
0b4e3aa0 876 thread->state &= ~TH_SUSP;
91447636 877 thread_unblock(thread, THREAD_AWAKENED);
55e303ae
A
878
879 thread_setrun(thread, SCHED_PREEMPT | SCHED_TAILQ);
1c79356b
A
880 }
881 else
882 if (thread->state & TH_SUSP) {
883 thread->state &= ~TH_SUSP;
884
885 if (thread->wake_active) {
886 thread->wake_active = FALSE;
887 thread_unlock(thread);
2d21ac55
A
888
889 thread_wakeup(&thread->wake_active);
1c79356b
A
890 wake_unlock(thread);
891 splx(s);
1c79356b
A
892
893 return;
894 }
895 }
896
897 thread_unlock(thread);
898 wake_unlock(thread);
899 splx(s);
900}
901
902/*
91447636
A
903 * thread_wait:
904 *
905 * Wait for a thread to stop running. (non-interruptible)
906 *
1c79356b 907 */
91447636 908void
1c79356b 909thread_wait(
91447636 910 thread_t thread)
1c79356b 911{
91447636
A
912 wait_result_t wresult;
913 spl_t s = splsched();
1c79356b 914
1c79356b 915 wake_lock(thread);
9bccf70c 916 thread_lock(thread);
1c79356b 917
9bccf70c 918 while (thread->state & TH_RUN) {
9bccf70c 919 processor_t processor = thread->last_processor;
e7c99d92 920
2d21ac55 921 if (processor != PROCESSOR_NULL && processor->active_thread == thread)
9bccf70c 922 cause_ast_check(processor);
1c79356b
A
923
924 thread->wake_active = TRUE;
2d21ac55
A
925 thread_unlock(thread);
926
91447636 927 wresult = assert_wait(&thread->wake_active, THREAD_UNINT);
1c79356b
A
928 wake_unlock(thread);
929 splx(s);
930
91447636
A
931 if (wresult == THREAD_WAITING)
932 thread_block(THREAD_CONTINUE_NULL);
1c79356b
A
933
934 s = splsched();
935 wake_lock(thread);
9bccf70c 936 thread_lock(thread);
1c79356b 937 }
0b4e3aa0 938
9bccf70c 939 thread_unlock(thread);
1c79356b
A
940 wake_unlock(thread);
941 splx(s);
1c79356b
A
942}
943
1c79356b
A
944/*
945 * Routine: clear_wait_internal
946 *
947 * Clear the wait condition for the specified thread.
948 * Start the thread executing if that is appropriate.
949 * Arguments:
950 * thread thread to awaken
951 * result Wakeup result the thread should see
952 * Conditions:
953 * At splsched
954 * the thread is locked.
9bccf70c
A
955 * Returns:
956 * KERN_SUCCESS thread was rousted out a wait
957 * KERN_FAILURE thread was waiting but could not be rousted
958 * KERN_NOT_WAITING thread was not waiting
1c79356b 959 */
9bccf70c 960__private_extern__ kern_return_t
1c79356b 961clear_wait_internal(
9bccf70c 962 thread_t thread,
55e303ae 963 wait_result_t wresult)
1c79356b 964{
9bccf70c 965 wait_queue_t wq = thread->wait_queue;
55e303ae 966 int i = LockTimeOut;
9bccf70c 967
9bccf70c 968 do {
55e303ae
A
969 if (wresult == THREAD_INTERRUPTED && (thread->state & TH_UNINT))
970 return (KERN_FAILURE);
9bccf70c
A
971
972 if (wq != WAIT_QUEUE_NULL) {
973 if (wait_queue_lock_try(wq)) {
974 wait_queue_pull_thread_locked(wq, thread, TRUE);
975 /* wait queue unlocked, thread still locked */
55e303ae
A
976 }
977 else {
9bccf70c
A
978 thread_unlock(thread);
979 delay(1);
55e303ae 980
9bccf70c 981 thread_lock(thread);
55e303ae
A
982 if (wq != thread->wait_queue)
983 return (KERN_NOT_WAITING);
9bccf70c 984
9bccf70c
A
985 continue;
986 }
1c79356b 987 }
55e303ae 988
91447636 989 return (thread_go(thread, wresult));
55e303ae
A
990 } while (--i > 0);
991
2d21ac55 992 panic("clear_wait_internal: deadlock: thread=%p, wq=%p, cpu=%d\n",
9bccf70c 993 thread, wq, cpu_number());
55e303ae
A
994
995 return (KERN_FAILURE);
1c79356b
A
996}
997
998
999/*
1000 * clear_wait:
1001 *
1002 * Clear the wait condition for the specified thread. Start the thread
1003 * executing if that is appropriate.
1004 *
1005 * parameters:
1006 * thread thread to awaken
1007 * result Wakeup result the thread should see
1008 */
9bccf70c 1009kern_return_t
1c79356b 1010clear_wait(
9bccf70c
A
1011 thread_t thread,
1012 wait_result_t result)
1c79356b 1013{
9bccf70c 1014 kern_return_t ret;
1c79356b
A
1015 spl_t s;
1016
1017 s = splsched();
1018 thread_lock(thread);
9bccf70c 1019 ret = clear_wait_internal(thread, result);
1c79356b
A
1020 thread_unlock(thread);
1021 splx(s);
9bccf70c 1022 return ret;
1c79356b
A
1023}
1024
1025
1026/*
1027 * thread_wakeup_prim:
1028 *
1029 * Common routine for thread_wakeup, thread_wakeup_with_result,
1030 * and thread_wakeup_one.
1031 *
1032 */
9bccf70c 1033kern_return_t
1c79356b
A
1034thread_wakeup_prim(
1035 event_t event,
1036 boolean_t one_thread,
9bccf70c 1037 wait_result_t result)
1c79356b
A
1038{
1039 register wait_queue_t wq;
1040 register int index;
1041
1042 index = wait_hash(event);
1043 wq = &wait_queues[index];
1044 if (one_thread)
9bccf70c 1045 return (wait_queue_wakeup_one(wq, event, result));
1c79356b 1046 else
9bccf70c 1047 return (wait_queue_wakeup_all(wq, event, result));
1c79356b
A
1048}
1049
1050/*
1051 * thread_bind:
1052 *
2d21ac55 1053 * Force the current thread to execute on the specified processor.
1c79356b 1054 *
55e303ae
A
1055 * Returns the previous binding. PROCESSOR_NULL means
1056 * not bound.
1057 *
1058 * XXX - DO NOT export this to users - XXX
1c79356b 1059 */
55e303ae 1060processor_t
1c79356b 1061thread_bind(
2d21ac55 1062 processor_t processor)
1c79356b 1063{
2d21ac55 1064 thread_t self = current_thread();
55e303ae 1065 processor_t prev;
55e303ae 1066 spl_t s;
1c79356b
A
1067
1068 s = splsched();
2d21ac55 1069 thread_lock(self);
55e303ae 1070
2d21ac55
A
1071 prev = self->bound_processor;
1072 self->bound_processor = processor;
55e303ae 1073
2d21ac55 1074 thread_unlock(self);
1c79356b 1075 splx(s);
55e303ae
A
1076
1077 return (prev);
1c79356b
A
1078}
1079
1080/*
2d21ac55
A
1081 * thread_select:
1082 *
1083 * Select a new thread for the current processor to execute.
55e303ae
A
1084 *
1085 * May select the current thread, which must be locked.
1c79356b 1086 */
2d21ac55 1087static thread_t
1c79356b 1088thread_select(
2d21ac55
A
1089 thread_t thread,
1090 processor_t processor)
1c79356b 1091{
2d21ac55 1092 processor_set_t pset = processor->processor_set;
cf7d32b8 1093 thread_t new_thread = THREAD_NULL;
b0d623f7 1094 boolean_t inactive_state;
1c79356b 1095
2d21ac55
A
1096 do {
1097 /*
1098 * Update the priority.
1099 */
1100 if (thread->sched_stamp != sched_tick)
1101 update_priority(thread);
0b4e3aa0 1102
2d21ac55 1103 processor->current_pri = thread->sched_pri;
1c79356b 1104
2d21ac55
A
1105 pset_lock(pset);
1106
b7266188 1107 inactive_state = processor->state != PROCESSOR_SHUTDOWN && machine_processor_is_inactive(processor);
c910b4d9 1108
2d21ac55
A
1109 simple_lock(&rt_lock);
1110
2d21ac55
A
1111 /*
1112 * Test to see if the current thread should continue
1113 * to run on this processor. Must be runnable, and not
1114 * bound to a different processor, nor be in the wrong
1115 * processor set.
1116 */
d1ecb069
A
1117 if (
1118#if CONFIG_EMBEDDED
1119 ((thread->state & ~TH_SUSP) == TH_RUN) &&
1120#else
1121 thread->state == TH_RUN &&
1122#endif
b0d623f7
A
1123 (thread->sched_pri >= BASEPRI_RTQUEUES ||
1124 processor->processor_meta == PROCESSOR_META_NULL ||
1125 processor->processor_meta->primary == processor) &&
2d21ac55
A
1126 (thread->bound_processor == PROCESSOR_NULL ||
1127 thread->bound_processor == processor) &&
1128 (thread->affinity_set == AFFINITY_SET_NULL ||
1129 thread->affinity_set->aset_pset == pset) ) {
1130 if ( thread->sched_pri >= BASEPRI_RTQUEUES &&
1131 first_timeslice(processor) ) {
1132 if (rt_runq.highq >= BASEPRI_RTQUEUES) {
1133 register run_queue_t runq = &rt_runq;
1134 register queue_t q;
1135
1136 q = runq->queues + runq->highq;
1137 if (((thread_t)q->next)->realtime.deadline <
1138 processor->deadline) {
1139 thread = (thread_t)q->next;
1140 ((queue_entry_t)thread)->next->prev = q;
1141 q->next = ((queue_entry_t)thread)->next;
1142 thread->runq = PROCESSOR_NULL;
2d21ac55 1143 runq->count--; runq->urgency--;
4a3eedf9 1144 assert(runq->urgency >= 0);
2d21ac55
A
1145 if (queue_empty(q)) {
1146 if (runq->highq != IDLEPRI)
1147 clrbit(MAXPRI - runq->highq, runq->bitmap);
1148 runq->highq = MAXPRI - ffsbit(runq->bitmap);
1149 }
55e303ae
A
1150 }
1151 }
2d21ac55
A
1152
1153 simple_unlock(&rt_lock);
1154
1155 processor->deadline = thread->realtime.deadline;
1156
1157 pset_unlock(pset);
1158
1159 return (thread);
55e303ae
A
1160 }
1161
b0d623f7
A
1162 if (!inactive_state && rt_runq.highq < thread->sched_pri &&
1163 (new_thread = choose_thread(processor, thread->sched_pri)) == THREAD_NULL) {
55e303ae 1164
2d21ac55 1165 simple_unlock(&rt_lock);
55e303ae 1166
2d21ac55 1167 /* I am the highest priority runnable (non-idle) thread */
1c79356b 1168
cf7d32b8 1169 pset_pri_hint(pset, processor, processor->current_pri);
1c79356b 1170
c910b4d9
A
1171 pset_count_hint(pset, processor, processor->runq.count);
1172
2d21ac55 1173 processor->deadline = UINT64_MAX;
55e303ae 1174
2d21ac55 1175 pset_unlock(pset);
55e303ae 1176
2d21ac55
A
1177 return (thread);
1178 }
1179 }
1180
b0d623f7
A
1181 if (new_thread != THREAD_NULL ||
1182 (processor->runq.highq >= rt_runq.highq &&
1183 (new_thread = choose_thread(processor, MINPRI)) != THREAD_NULL)) {
c910b4d9
A
1184 simple_unlock(&rt_lock);
1185
c910b4d9 1186 if (!inactive_state) {
b0d623f7 1187 pset_pri_hint(pset, processor, new_thread->sched_pri);
c910b4d9
A
1188
1189 pset_count_hint(pset, processor, processor->runq.count);
1190 }
1191
1192 processor->deadline = UINT64_MAX;
1193 pset_unlock(pset);
1194
b0d623f7
A
1195 return (new_thread);
1196 }
c910b4d9 1197
b0d623f7 1198 if (rt_runq.count > 0) {
c910b4d9
A
1199 thread = run_queue_dequeue(&rt_runq, SCHED_HEADQ);
1200 simple_unlock(&rt_lock);
1201
1202 processor->deadline = thread->realtime.deadline;
1203 pset_unlock(pset);
1204
1205 return (thread);
1206 }
2d21ac55
A
1207
1208 simple_unlock(&rt_lock);
55e303ae 1209
c910b4d9
A
1210 processor->deadline = UINT64_MAX;
1211
b0d623f7
A
1212 /*
1213 * Set processor inactive based on
1214 * indication from the platform code.
1215 */
c910b4d9
A
1216 if (inactive_state) {
1217 if (processor->state == PROCESSOR_RUNNING)
1218 remqueue(&pset->active_queue, (queue_entry_t)processor);
1219 else
1220 if (processor->state == PROCESSOR_IDLE)
1221 remqueue(&pset->idle_queue, (queue_entry_t)processor);
1222
1223 processor->state = PROCESSOR_INACTIVE;
1224
1225 pset_unlock(pset);
1226
1227 return (processor->idle_thread);
1228 }
1229
2d21ac55
A
1230 /*
1231 * No runnable threads, attempt to steal
1232 * from other processors.
1233 */
cf7d32b8
A
1234 new_thread = steal_thread(pset);
1235 if (new_thread != THREAD_NULL)
1236 return (new_thread);
2d21ac55 1237
cf7d32b8
A
1238 /*
1239 * If other threads have appeared, shortcut
1240 * around again.
1241 */
1242 if (processor->runq.count > 0 || rt_runq.count > 0)
1243 continue;
1244
1245 pset_lock(pset);
55e303ae 1246
1c79356b
A
1247 /*
1248 * Nothing is runnable, so set this processor idle if it
2d21ac55 1249 * was running.
1c79356b 1250 */
55e303ae
A
1251 if (processor->state == PROCESSOR_RUNNING) {
1252 remqueue(&pset->active_queue, (queue_entry_t)processor);
1253 processor->state = PROCESSOR_IDLE;
1c79356b 1254
b0d623f7
A
1255 if (processor->processor_meta == PROCESSOR_META_NULL || processor->processor_meta->primary == processor) {
1256 enqueue_head(&pset->idle_queue, (queue_entry_t)processor);
1257 pset->low_pri = pset->low_count = processor;
1258 }
1259 else {
1260 enqueue_head(&processor->processor_meta->idle_queue, (queue_entry_t)processor);
1261
1262 if (thread->sched_pri < BASEPRI_RTQUEUES) {
1263 pset_unlock(pset);
1264
1265 return (processor->idle_thread);
1266 }
1267 }
1c79356b 1268 }
1c79356b 1269
2d21ac55
A
1270 pset_unlock(pset);
1271
1272 /*
1273 * Choose idle thread if fast idle is not possible.
1274 */
1275 if ((thread->state & (TH_IDLE|TH_TERMINATE|TH_SUSP)) || !(thread->state & TH_WAIT) || thread->wake_active)
1276 return (processor->idle_thread);
1277
1278 /*
1279 * Perform idling activities directly without a
1280 * context switch. Return dispatched thread,
1281 * else check again for a runnable thread.
1282 */
1283 new_thread = thread_select_idle(thread, processor);
1284
1285 } while (new_thread == THREAD_NULL);
1286
1287 return (new_thread);
1288}
1289
1290/*
1291 * thread_select_idle:
1292 *
1293 * Idle the processor using the current thread context.
1294 *
1295 * Called with thread locked, then dropped and relocked.
1296 */
1297static thread_t
1298thread_select_idle(
1299 thread_t thread,
1300 processor_t processor)
1301{
1302 thread_t new_thread;
1303
1304 if (thread->sched_mode & TH_MODE_TIMESHARE)
1305 sched_share_decr();
1306 sched_run_decr();
1307
1308 thread->state |= TH_IDLE;
1309 processor->current_pri = IDLEPRI;
1310
1311 thread_unlock(thread);
1312
1313 /*
1314 * Switch execution timing to processor idle thread.
1315 */
1316 processor->last_dispatch = mach_absolute_time();
1317 thread_timer_event(processor->last_dispatch, &processor->idle_thread->system_timer);
1318 PROCESSOR_DATA(processor, kernel_timer) = &processor->idle_thread->system_timer;
1319
1320 /*
1321 * Cancel the quantum timer while idling.
1322 */
1323 timer_call_cancel(&processor->quantum_timer);
1324 processor->timeslice = 0;
1325
1326 (*thread->sched_call)(SCHED_CALL_BLOCK, thread);
1327
1328 /*
1329 * Enable interrupts and perform idling activities. No
1330 * preemption due to TH_IDLE being set.
1331 */
1332 spllo(); new_thread = processor_idle(thread, processor);
1333
cf7d32b8
A
1334 /*
1335 * Return at splsched.
1336 */
2d21ac55
A
1337 (*thread->sched_call)(SCHED_CALL_UNBLOCK, thread);
1338
1339 thread_lock(thread);
1340
1341 /*
1342 * If awakened, switch to thread timer and start a new quantum.
1343 * Otherwise skip; we will context switch to another thread or return here.
1344 */
1345 if (!(thread->state & TH_WAIT)) {
1346 processor->last_dispatch = mach_absolute_time();
1347 thread_timer_event(processor->last_dispatch, &thread->system_timer);
1348 PROCESSOR_DATA(processor, kernel_timer) = &thread->system_timer;
1349
1350 thread_quantum_init(thread);
1351
1352 processor->quantum_end = processor->last_dispatch + thread->current_quantum;
1353 timer_call_enter1(&processor->quantum_timer, thread, processor->quantum_end);
1354 processor->timeslice = 1;
1355
1356 thread->computation_epoch = processor->last_dispatch;
1c79356b
A
1357 }
1358
2d21ac55 1359 thread->state &= ~TH_IDLE;
55e303ae 1360
2d21ac55
A
1361 sched_run_incr();
1362 if (thread->sched_mode & TH_MODE_TIMESHARE)
1363 sched_share_incr();
1364
1365 return (new_thread);
1c79356b
A
1366}
1367
b0d623f7
A
1368/*
1369 * choose_thread:
1370 *
1371 * Locate a thread to execute from the processor run queue
1372 * and return it. Only choose a thread with greater or equal
1373 * priority.
1374 *
1375 * Associated pset must be locked. Returns THREAD_NULL
1376 * on failure.
1377 */
1378static thread_t
1379choose_thread(
1380 processor_t processor,
1381 int priority)
1382{
1383 run_queue_t rq = &processor->runq;
1384 queue_t queue = rq->queues + rq->highq;
1385 int pri = rq->highq, count = rq->count;
1386 thread_t thread;
1387
1388 while (count > 0 && pri >= priority) {
1389 thread = (thread_t)queue_first(queue);
1390 while (!queue_end(queue, (queue_entry_t)thread)) {
1391 if (thread->bound_processor == PROCESSOR_NULL ||
1392 thread->bound_processor == processor) {
1393 remqueue(queue, (queue_entry_t)thread);
1394
1395 thread->runq = PROCESSOR_NULL;
1396 rq->count--;
1397 if (testbit(pri, sched_preempt_pri)) {
1398 rq->urgency--; assert(rq->urgency >= 0);
1399 }
1400 if (queue_empty(queue)) {
1401 if (pri != IDLEPRI)
1402 clrbit(MAXPRI - pri, rq->bitmap);
1403 rq->highq = MAXPRI - ffsbit(rq->bitmap);
1404 }
1405
1406 return (thread);
1407 }
1408 count--;
1409
1410 thread = (thread_t)queue_next((queue_entry_t)thread);
1411 }
1412
1413 queue--; pri--;
1414 }
1415
1416 return (THREAD_NULL);
1417}
1418
1c79356b 1419/*
55e303ae
A
1420 * Perform a context switch and start executing the new thread.
1421 *
91447636 1422 * Returns FALSE on failure, and the thread is re-dispatched.
9bccf70c 1423 *
55e303ae 1424 * Called at splsched.
1c79356b
A
1425 */
1426
55e303ae
A
1427#define funnel_release_check(thread, debug) \
1428MACRO_BEGIN \
1429 if ((thread)->funnel_state & TH_FN_OWNED) { \
1430 (thread)->funnel_state = TH_FN_REFUNNEL; \
1431 KERNEL_DEBUG(0x603242c | DBG_FUNC_NONE, \
1432 (thread)->funnel_lock, (debug), 0, 0, 0); \
1433 funnel_unlock((thread)->funnel_lock); \
1434 } \
1435MACRO_END
1436
1437#define funnel_refunnel_check(thread, debug) \
1438MACRO_BEGIN \
1439 if ((thread)->funnel_state & TH_FN_REFUNNEL) { \
1440 kern_return_t result = (thread)->wait_result; \
1441 \
1442 (thread)->funnel_state = 0; \
1443 KERNEL_DEBUG(0x6032428 | DBG_FUNC_NONE, \
1444 (thread)->funnel_lock, (debug), 0, 0, 0); \
1445 funnel_lock((thread)->funnel_lock); \
1446 KERNEL_DEBUG(0x6032430 | DBG_FUNC_NONE, \
1447 (thread)->funnel_lock, (debug), 0, 0, 0); \
1448 (thread)->funnel_state = TH_FN_OWNED; \
1449 (thread)->wait_result = result; \
1450 } \
1451MACRO_END
1452
2d21ac55 1453static boolean_t
1c79356b 1454thread_invoke(
2d21ac55
A
1455 register thread_t self,
1456 register thread_t thread,
91447636 1457 ast_t reason)
1c79356b 1458{
2d21ac55
A
1459 thread_continue_t continuation = self->continuation;
1460 void *parameter = self->parameter;
9bccf70c 1461 processor_t processor;
1c79356b 1462
b0d623f7
A
1463 if (get_preemption_level() != 0) {
1464 int pl = get_preemption_level();
1465 panic("thread_invoke: preemption_level %d, possible cause: %s",
1466 pl, (pl < 0 ? "unlocking an unlocked mutex or spinlock" :
1467 "blocking while holding a spinlock, or within interrupt context"));
1468 }
0b4e3aa0 1469
2d21ac55 1470 assert(self == current_thread());
91447636 1471
1c79356b 1472 /*
9bccf70c 1473 * Mark thread interruptible.
1c79356b 1474 */
2d21ac55
A
1475 thread_lock(thread);
1476 thread->state &= ~TH_UNINT;
1c79356b 1477
2d21ac55
A
1478#if DEBUG
1479 assert(thread_runnable(thread));
1480#endif
1c79356b 1481
9bccf70c
A
1482 /*
1483 * Allow time constraint threads to hang onto
1484 * a stack.
1485 */
2d21ac55
A
1486 if ((self->sched_mode & TH_MODE_REALTIME) && !self->reserved_stack)
1487 self->reserved_stack = self->kernel_stack;
1c79356b 1488
91447636 1489 if (continuation != NULL) {
2d21ac55 1490 if (!thread->kernel_stack) {
9bccf70c 1491 /*
2d21ac55 1492 * If we are using a privileged stack,
9bccf70c 1493 * check to see whether we can exchange it with
2d21ac55 1494 * that of the other thread.
9bccf70c 1495 */
2d21ac55 1496 if (self->kernel_stack == self->reserved_stack && !thread->reserved_stack)
9bccf70c 1497 goto need_stack;
1c79356b 1498
91447636
A
1499 /*
1500 * Context switch by performing a stack handoff.
1501 */
2d21ac55
A
1502 continuation = thread->continuation;
1503 parameter = thread->parameter;
1c79356b 1504
9bccf70c 1505 processor = current_processor();
2d21ac55
A
1506 processor->active_thread = thread;
1507 processor->current_pri = thread->sched_pri;
1508 if (thread->last_processor != processor && thread->last_processor != NULL) {
1509 if (thread->last_processor->processor_set != processor->processor_set)
1510 thread->ps_switch++;
1511 thread->p_switch++;
1512 }
1513 thread->last_processor = processor;
1514 thread->c_switch++;
1515 ast_context(thread);
1516 thread_unlock(thread);
1c79356b 1517
2d21ac55 1518 self->reason = reason;
91447636
A
1519
1520 processor->last_dispatch = mach_absolute_time();
2d21ac55
A
1521 thread_timer_event(processor->last_dispatch, &thread->system_timer);
1522 PROCESSOR_DATA(processor, kernel_timer) = &thread->system_timer;
1523
1524 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED, MACH_STACK_HANDOFF)|DBG_FUNC_NONE,
b0d623f7 1525 self->reason, (uintptr_t)thread_tid(thread), self->sched_pri, thread->sched_pri, 0);
1c79356b 1526
b0d623f7
A
1527 DTRACE_SCHED2(off__cpu, struct thread *, thread, struct proc *, thread->task->bsd_info);
1528
1529 TLOG(1, "thread_invoke: calling machine_stack_handoff\n");
2d21ac55 1530 machine_stack_handoff(self, thread);
9bccf70c 1531
b0d623f7
A
1532 DTRACE_SCHED(on__cpu);
1533
2d21ac55 1534 thread_dispatch(self, thread);
1c79356b 1535
2d21ac55 1536 thread->continuation = thread->parameter = NULL;
1c79356b 1537
2d21ac55 1538 counter(c_thread_invoke_hits++);
1c79356b 1539
2d21ac55 1540 funnel_refunnel_check(thread, 2);
9bccf70c 1541 (void) spllo();
1c79356b 1542
2d21ac55
A
1543 assert(continuation);
1544 call_continuation(continuation, parameter, thread->wait_result);
9bccf70c 1545 /*NOTREACHED*/
9bccf70c 1546 }
2d21ac55 1547 else if (thread == self) {
9bccf70c 1548 /* same thread but with continuation */
2d21ac55 1549 ast_context(self);
9bccf70c 1550 counter(++c_thread_invoke_same);
2d21ac55 1551 thread_unlock(self);
9bccf70c 1552
2d21ac55
A
1553 self->continuation = self->parameter = NULL;
1554
1555 funnel_refunnel_check(self, 3);
9bccf70c 1556 (void) spllo();
55e303ae 1557
2d21ac55 1558 call_continuation(continuation, parameter, self->wait_result);
9bccf70c
A
1559 /*NOTREACHED*/
1560 }
1c79356b 1561 }
9bccf70c
A
1562 else {
1563 /*
2d21ac55 1564 * Check that the other thread has a stack
9bccf70c 1565 */
2d21ac55 1566 if (!thread->kernel_stack) {
9bccf70c 1567need_stack:
2d21ac55
A
1568 if (!stack_alloc_try(thread)) {
1569 counter(c_thread_invoke_misses++);
1570 thread_unlock(thread);
1571 thread_stack_enqueue(thread);
9bccf70c
A
1572 return (FALSE);
1573 }
9bccf70c 1574 }
2d21ac55
A
1575 else if (thread == self) {
1576 ast_context(self);
9bccf70c 1577 counter(++c_thread_invoke_same);
2d21ac55 1578 thread_unlock(self);
9bccf70c
A
1579 return (TRUE);
1580 }
1581 }
1c79356b
A
1582
1583 /*
91447636 1584 * Context switch by full context save.
1c79356b 1585 */
9bccf70c 1586 processor = current_processor();
2d21ac55
A
1587 processor->active_thread = thread;
1588 processor->current_pri = thread->sched_pri;
1589 if (thread->last_processor != processor && thread->last_processor != NULL) {
1590 if (thread->last_processor->processor_set != processor->processor_set)
1591 thread->ps_switch++;
1592 thread->p_switch++;
1593 }
1594 thread->last_processor = processor;
1595 thread->c_switch++;
1596 ast_context(thread);
1597 thread_unlock(thread);
1c79356b 1598
2d21ac55 1599 counter(c_thread_invoke_csw++);
1c79356b 1600
2d21ac55
A
1601 assert(self->runq == PROCESSOR_NULL);
1602 self->reason = reason;
1c79356b 1603
91447636 1604 processor->last_dispatch = mach_absolute_time();
2d21ac55
A
1605 thread_timer_event(processor->last_dispatch, &thread->system_timer);
1606 PROCESSOR_DATA(processor, kernel_timer) = &thread->system_timer;
91447636 1607
2d21ac55 1608 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED,MACH_SCHED) | DBG_FUNC_NONE,
b0d623f7
A
1609 self->reason, (uintptr_t)thread_tid(thread), self->sched_pri, thread->sched_pri, 0);
1610
1611 DTRACE_SCHED2(off__cpu, struct thread *, thread, struct proc *, thread->task->bsd_info);
1c79356b
A
1612
1613 /*
91447636 1614 * This is where we actually switch register context,
2d21ac55
A
1615 * and address space if required. We will next run
1616 * as a result of a subsequent context switch.
91447636 1617 */
2d21ac55 1618 thread = machine_switch_context(self, continuation, thread);
b0d623f7
A
1619 TLOG(1,"thread_invoke: returning machine_switch_context: self %p continuation %p thread %p\n", self, continuation, thread);
1620
1621 DTRACE_SCHED(on__cpu);
1c79356b
A
1622
1623 /*
2d21ac55 1624 * We have been resumed and are set to run.
1c79356b 1625 */
2d21ac55 1626 thread_dispatch(thread, self);
9bccf70c 1627
91447636 1628 if (continuation) {
2d21ac55
A
1629 self->continuation = self->parameter = NULL;
1630
1631 funnel_refunnel_check(self, 3);
9bccf70c 1632 (void) spllo();
55e303ae 1633
2d21ac55 1634 call_continuation(continuation, parameter, self->wait_result);
9bccf70c 1635 /*NOTREACHED*/
1c79356b
A
1636 }
1637
9bccf70c 1638 return (TRUE);
1c79356b
A
1639}
1640
1641/*
2d21ac55 1642 * thread_dispatch:
1c79356b 1643 *
2d21ac55
A
1644 * Handle threads at context switch. Re-dispatch other thread
1645 * if still running, otherwise update run state and perform
1646 * special actions. Update quantum for other thread and begin
1647 * the quantum for ourselves.
91447636
A
1648 *
1649 * Called at splsched.
1c79356b
A
1650 */
1651void
2d21ac55
A
1652thread_dispatch(
1653 thread_t thread,
1654 thread_t self)
1c79356b 1655{
2d21ac55
A
1656 processor_t processor = self->last_processor;
1657
1658 if (thread != THREAD_NULL) {
91447636 1659 /*
2d21ac55
A
1660 * If blocked at a continuation, discard
1661 * the stack.
91447636 1662 */
2d21ac55
A
1663 if (thread->continuation != NULL && thread->kernel_stack != 0)
1664 stack_free(thread);
1665
1666 if (!(thread->state & TH_IDLE)) {
1667 wake_lock(thread);
1668 thread_lock(thread);
9bccf70c 1669
91447636 1670 /*
2d21ac55 1671 * Compute remainder of current quantum.
91447636 1672 */
2d21ac55
A
1673 if ( first_timeslice(processor) &&
1674 processor->quantum_end > processor->last_dispatch )
b0d623f7 1675 thread->current_quantum = (uint32_t)(processor->quantum_end - processor->last_dispatch);
2d21ac55
A
1676 else
1677 thread->current_quantum = 0;
1678
1679 if (thread->sched_mode & TH_MODE_REALTIME) {
1680 /*
1681 * Cancel the deadline if the thread has
1682 * consumed the entire quantum.
1683 */
1684 if (thread->current_quantum == 0) {
1685 thread->realtime.deadline = UINT64_MAX;
1686 thread->reason |= AST_QUANTUM;
1687 }
b7266188 1688 } else {
2d21ac55
A
1689 /*
1690 * For non-realtime threads treat a tiny
1691 * remaining quantum as an expired quantum
1692 * but include what's left next time.
1693 */
1694 if (thread->current_quantum < min_std_quantum) {
1695 thread->reason |= AST_QUANTUM;
1696 thread->current_quantum += std_quantum;
1697 }
1698 }
1699
91447636 1700 /*
2d21ac55
A
1701 * If we are doing a direct handoff then
1702 * take the remainder of the quantum.
91447636 1703 */
2d21ac55
A
1704 if ((thread->reason & (AST_HANDOFF|AST_QUANTUM)) == AST_HANDOFF) {
1705 self->current_quantum = thread->current_quantum;
1706 thread->reason |= AST_QUANTUM;
1707 thread->current_quantum = 0;
91447636 1708 }
91447636 1709
b0d623f7 1710 thread->computation_metered += (processor->last_dispatch - thread->computation_epoch);
2d21ac55
A
1711
1712 if (!(thread->state & TH_WAIT)) {
1713 /*
1714 * Still running.
1715 */
1716 if (thread->reason & AST_QUANTUM)
1717 thread_setrun(thread, SCHED_TAILQ);
1718 else
1719 if (thread->reason & AST_PREEMPT)
1720 thread_setrun(thread, SCHED_HEADQ);
1721 else
1722 thread_setrun(thread, SCHED_PREEMPT | SCHED_TAILQ);
1723
1724 thread->reason = AST_NONE;
1725
1726 thread_unlock(thread);
1727 wake_unlock(thread);
1728 }
1729 else {
1730 /*
1731 * Waiting.
1732 */
b7266188
A
1733 boolean_t should_terminate = FALSE;
1734
1735 /* Only the first call to thread_dispatch
1736 * after explicit termination should add
1737 * the thread to the termination queue
1738 */
1739 if ((thread->state & (TH_TERMINATE|TH_TERMINATE2)) == TH_TERMINATE) {
1740 should_terminate = TRUE;
1741 thread->state |= TH_TERMINATE2;
1742 }
1743
2d21ac55
A
1744 thread->state &= ~TH_RUN;
1745
1746 if (thread->sched_mode & TH_MODE_TIMESHARE)
1747 sched_share_decr();
1748 sched_run_decr();
1749
b7266188
A
1750 (*thread->sched_call)(SCHED_CALL_BLOCK, thread);
1751
2d21ac55
A
1752 if (thread->wake_active) {
1753 thread->wake_active = FALSE;
1754 thread_unlock(thread);
1755
1756 thread_wakeup(&thread->wake_active);
1757 }
1758 else
1759 thread_unlock(thread);
91447636 1760
2d21ac55 1761 wake_unlock(thread);
91447636 1762
b7266188 1763 if (should_terminate)
2d21ac55
A
1764 thread_terminate_enqueue(thread);
1765 }
1766 }
91447636 1767 }
91447636 1768
2d21ac55 1769 if (!(self->state & TH_IDLE)) {
91447636 1770 /*
2d21ac55 1771 * Get a new quantum if none remaining.
91447636 1772 */
2d21ac55
A
1773 if (self->current_quantum == 0)
1774 thread_quantum_init(self);
91447636
A
1775
1776 /*
2d21ac55 1777 * Set up quantum timer and timeslice.
91447636 1778 */
2d21ac55
A
1779 processor->quantum_end = (processor->last_dispatch + self->current_quantum);
1780 timer_call_enter1(&processor->quantum_timer, self, processor->quantum_end);
91447636 1781
2d21ac55 1782 processor->timeslice = 1;
91447636 1783
b0d623f7 1784 self->computation_epoch = processor->last_dispatch;
91447636
A
1785 }
1786 else {
1787 timer_call_cancel(&processor->quantum_timer);
2d21ac55 1788 processor->timeslice = 0;
91447636
A
1789 }
1790}
1791
b0d623f7
A
1792#include <libkern/OSDebug.h>
1793
1794uint32_t kdebug_thread_block = 0;
1795
1796
91447636 1797/*
2d21ac55 1798 * thread_block_reason:
91447636 1799 *
2d21ac55
A
1800 * Forces a reschedule, blocking the caller if a wait
1801 * has been asserted.
91447636 1802 *
2d21ac55
A
1803 * If a continuation is specified, then thread_invoke will
1804 * attempt to discard the thread's kernel stack. When the
1805 * thread resumes, it will execute the continuation function
1806 * on a new kernel stack.
91447636 1807 */
2d21ac55
A
1808counter(mach_counter_t c_thread_block_calls = 0;)
1809
1810wait_result_t
1811thread_block_reason(
1812 thread_continue_t continuation,
1813 void *parameter,
1814 ast_t reason)
91447636 1815{
2d21ac55
A
1816 register thread_t self = current_thread();
1817 register processor_t processor;
1818 register thread_t new_thread;
1819 spl_t s;
1c79356b
A
1820
1821 counter(++c_thread_block_calls);
1822
1c79356b
A
1823 s = splsched();
1824
55e303ae 1825 if (!(reason & AST_PREEMPT))
91447636 1826 funnel_release_check(self, 2);
1c79356b 1827
55e303ae 1828 processor = current_processor();
1c79356b 1829
9bccf70c
A
1830 /* If we're explicitly yielding, force a subsequent quantum */
1831 if (reason & AST_YIELD)
55e303ae 1832 processor->timeslice = 0;
0b4e3aa0 1833
9bccf70c
A
1834 /* We're handling all scheduling AST's */
1835 ast_off(AST_SCHEDULING);
1c79356b 1836
91447636
A
1837 self->continuation = continuation;
1838 self->parameter = parameter;
1839
b0d623f7
A
1840 if (kdebug_thread_block && kdebug_enable && self->state != TH_RUN) {
1841 uint32_t bt[8];
1842
1843 OSBacktrace((void **)&bt[0], 8);
1844
1845 KERNEL_DEBUG_CONSTANT(0x140004c | DBG_FUNC_START, bt[0], bt[1], bt[2], bt[3], 0);
1846 KERNEL_DEBUG_CONSTANT(0x140004c | DBG_FUNC_END, bt[4], bt[5], bt[6], bt[7], 0);
1847 }
1848
2d21ac55 1849 do {
91447636 1850 thread_lock(self);
2d21ac55 1851 new_thread = thread_select(self, processor);
91447636 1852 thread_unlock(self);
2d21ac55 1853 } while (!thread_invoke(self, new_thread, reason));
1c79356b 1854
91447636 1855 funnel_refunnel_check(self, 5);
1c79356b
A
1856 splx(s);
1857
91447636 1858 return (self->wait_result);
1c79356b
A
1859}
1860
1861/*
1862 * thread_block:
1863 *
9bccf70c 1864 * Block the current thread if a wait has been asserted.
1c79356b 1865 */
91447636 1866wait_result_t
1c79356b 1867thread_block(
9bccf70c 1868 thread_continue_t continuation)
1c79356b 1869{
91447636
A
1870 return thread_block_reason(continuation, NULL, AST_NONE);
1871}
1872
1873wait_result_t
1874thread_block_parameter(
1875 thread_continue_t continuation,
1876 void *parameter)
1877{
1878 return thread_block_reason(continuation, parameter, AST_NONE);
1c79356b
A
1879}
1880
1881/*
1882 * thread_run:
1883 *
91447636 1884 * Switch directly from the current thread to the
55e303ae 1885 * new thread, handing off our quantum if appropriate.
9bccf70c
A
1886 *
1887 * New thread must be runnable, and not on a run queue.
1c79356b 1888 *
55e303ae 1889 * Called at splsched.
1c79356b
A
1890 */
1891int
1892thread_run(
91447636 1893 thread_t self,
9bccf70c 1894 thread_continue_t continuation,
91447636 1895 void *parameter,
9bccf70c 1896 thread_t new_thread)
1c79356b 1897{
9bccf70c
A
1898 ast_t handoff = AST_HANDOFF;
1899
91447636 1900 funnel_release_check(self, 3);
9bccf70c 1901
91447636
A
1902 self->continuation = continuation;
1903 self->parameter = parameter;
9bccf70c 1904
91447636 1905 while (!thread_invoke(self, new_thread, handoff)) {
2d21ac55 1906 processor_t processor = current_processor();
9bccf70c 1907
91447636 1908 thread_lock(self);
2d21ac55 1909 new_thread = thread_select(self, processor);
91447636 1910 thread_unlock(self);
9bccf70c
A
1911 handoff = AST_NONE;
1912 }
1913
91447636 1914 funnel_refunnel_check(self, 6);
9bccf70c 1915
91447636 1916 return (self->wait_result);
1c79356b
A
1917}
1918
1919/*
91447636 1920 * thread_continue:
55e303ae 1921 *
91447636
A
1922 * Called at splsched when a thread first receives
1923 * a new stack after a continuation.
1c79356b
A
1924 */
1925void
91447636 1926thread_continue(
2d21ac55 1927 register thread_t thread)
1c79356b 1928{
91447636
A
1929 register thread_t self = current_thread();
1930 register thread_continue_t continuation;
1931 register void *parameter;
b0d623f7
A
1932
1933 DTRACE_SCHED(on__cpu);
1934
91447636 1935 continuation = self->continuation;
91447636 1936 parameter = self->parameter;
9bccf70c 1937
2d21ac55 1938 thread_dispatch(thread, self);
9bccf70c 1939
2d21ac55 1940 self->continuation = self->parameter = NULL;
1c79356b 1941
91447636 1942 funnel_refunnel_check(self, 4);
1c79356b 1943
2d21ac55 1944 if (thread != THREAD_NULL)
91447636 1945 (void)spllo();
9bccf70c 1946
2d21ac55 1947 TLOG(1, "thread_continue: calling call_continuation \n");
91447636
A
1948 call_continuation(continuation, parameter, self->wait_result);
1949 /*NOTREACHED*/
1c79356b
A
1950}
1951
1952/*
2d21ac55 1953 * run_queue_init:
55e303ae 1954 *
2d21ac55 1955 * Initialize a run queue before first use.
1c79356b 1956 */
2d21ac55
A
1957void
1958run_queue_init(
1959 run_queue_t rq)
1960{
1961 int i;
1962
1963 rq->highq = IDLEPRI;
1964 for (i = 0; i < NRQBM; i++)
1965 rq->bitmap[i] = 0;
1966 setbit(MAXPRI - IDLEPRI, rq->bitmap);
1967 rq->urgency = rq->count = 0;
1968 for (i = 0; i < NRQS; i++)
1969 queue_init(&rq->queues[i]);
1970}
1c79356b 1971
2d21ac55
A
1972/*
1973 * run_queue_dequeue:
1974 *
1975 * Perform a dequeue operation on a run queue,
1976 * and return the resulting thread.
1977 *
1978 * The run queue must be locked (see run_queue_remove()
1979 * for more info), and not empty.
1980 */
1981static thread_t
1982run_queue_dequeue(
1983 run_queue_t rq,
1984 integer_t options)
1985{
1986 thread_t thread;
1987 queue_t queue = rq->queues + rq->highq;
9bccf70c 1988
2d21ac55
A
1989 if (options & SCHED_HEADQ) {
1990 thread = (thread_t)queue->next;
1991 ((queue_entry_t)thread)->next->prev = queue;
1992 queue->next = ((queue_entry_t)thread)->next;
1993 }
1994 else {
1995 thread = (thread_t)queue->prev;
1996 ((queue_entry_t)thread)->prev->next = queue;
1997 queue->prev = ((queue_entry_t)thread)->prev;
9bccf70c 1998 }
1c79356b 1999
2d21ac55
A
2000 thread->runq = PROCESSOR_NULL;
2001 rq->count--;
4a3eedf9
A
2002 if (testbit(rq->highq, sched_preempt_pri)) {
2003 rq->urgency--; assert(rq->urgency >= 0);
2004 }
2d21ac55
A
2005 if (queue_empty(queue)) {
2006 if (rq->highq != IDLEPRI)
2007 clrbit(MAXPRI - rq->highq, rq->bitmap);
2008 rq->highq = MAXPRI - ffsbit(rq->bitmap);
2009 }
1c79356b 2010
2d21ac55 2011 return (thread);
1c79356b
A
2012}
2013
2014/*
2d21ac55
A
2015 * realtime_queue_insert:
2016 *
2017 * Enqueue a thread for realtime execution.
1c79356b 2018 */
2d21ac55
A
2019static boolean_t
2020realtime_queue_insert(
2021 thread_t thread)
1c79356b 2022{
2d21ac55
A
2023 run_queue_t rq = &rt_runq;
2024 queue_t queue = rq->queues + thread->sched_pri;
2025 uint64_t deadline = thread->realtime.deadline;
2026 boolean_t preempt = FALSE;
1c79356b 2027
2d21ac55 2028 simple_lock(&rt_lock);
1c79356b 2029
55e303ae
A
2030 if (queue_empty(queue)) {
2031 enqueue_tail(queue, (queue_entry_t)thread);
2032
2d21ac55
A
2033 setbit(MAXPRI - thread->sched_pri, rq->bitmap);
2034 if (thread->sched_pri > rq->highq)
2035 rq->highq = thread->sched_pri;
2036 preempt = TRUE;
55e303ae
A
2037 }
2038 else {
2039 register thread_t entry = (thread_t)queue_first(queue);
2040
2041 while (TRUE) {
2042 if ( queue_end(queue, (queue_entry_t)entry) ||
2043 deadline < entry->realtime.deadline ) {
2044 entry = (thread_t)queue_prev((queue_entry_t)entry);
2045 break;
2046 }
2047
2048 entry = (thread_t)queue_next((queue_entry_t)entry);
2049 }
2050
2051 if ((queue_entry_t)entry == queue)
2d21ac55 2052 preempt = TRUE;
55e303ae
A
2053
2054 insque((queue_entry_t)thread, (queue_entry_t)entry);
2055 }
2056
2d21ac55 2057 thread->runq = RT_RUNQ;
55e303ae
A
2058 rq->count++; rq->urgency++;
2059
2d21ac55 2060 simple_unlock(&rt_lock);
55e303ae 2061
2d21ac55
A
2062 return (preempt);
2063}
55e303ae 2064
2d21ac55
A
2065/*
2066 * realtime_setrun:
2067 *
2068 * Dispatch a thread for realtime execution.
2069 *
2070 * Thread must be locked. Associated pset must
2071 * be locked, and is returned unlocked.
2072 */
2073static void
2074realtime_setrun(
2075 processor_t processor,
2076 thread_t thread)
2077{
2078 processor_set_t pset = processor->processor_set;
55e303ae 2079
2d21ac55
A
2080 /*
2081 * Dispatch directly onto idle processor.
2082 */
2083 if (processor->state == PROCESSOR_IDLE) {
2084 remqueue(&pset->idle_queue, (queue_entry_t)processor);
cf7d32b8 2085 enqueue_tail(&pset->active_queue, (queue_entry_t)processor);
55e303ae 2086
2d21ac55
A
2087 processor->next_thread = thread;
2088 processor->deadline = thread->realtime.deadline;
2089 processor->state = PROCESSOR_DISPATCHING;
2090 pset_unlock(pset);
55e303ae 2091
2d21ac55
A
2092 if (processor != current_processor())
2093 machine_signal_idle(processor);
2094 return;
2095 }
55e303ae 2096
2d21ac55
A
2097 if (realtime_queue_insert(thread)) {
2098 if (processor == current_processor())
2099 ast_on(AST_PREEMPT | AST_URGENT);
2100 else
2101 cause_ast_check(processor);
2102 }
2103
2104 pset_unlock(pset);
2105}
2106
2107/*
2108 * processor_enqueue:
2109 *
2110 * Enqueue thread on a processor run queue. Thread must be locked,
2111 * and not already be on a run queue.
2112 *
2113 * Returns TRUE if a preemption is indicated based on the state
2114 * of the run queue.
2115 *
2116 * The run queue must be locked (see run_queue_remove()
2117 * for more info).
2118 */
2119static boolean_t
2120processor_enqueue(
2121 processor_t processor,
2122 thread_t thread,
2123 integer_t options)
2124{
2125 run_queue_t rq = &processor->runq;
2126 queue_t queue = rq->queues + thread->sched_pri;
2127 boolean_t result = FALSE;
2128
2129 if (queue_empty(queue)) {
2130 enqueue_tail(queue, (queue_entry_t)thread);
2131
2132 setbit(MAXPRI - thread->sched_pri, rq->bitmap);
2133 if (thread->sched_pri > rq->highq) {
2134 rq->highq = thread->sched_pri;
2135 result = TRUE;
55e303ae
A
2136 }
2137 }
2d21ac55
A
2138 else
2139 if (options & SCHED_TAILQ)
2140 enqueue_tail(queue, (queue_entry_t)thread);
2141 else
2142 enqueue_head(queue, (queue_entry_t)thread);
55e303ae 2143
2d21ac55 2144 thread->runq = processor;
4a3eedf9 2145 if (testbit(thread->sched_pri, sched_preempt_pri))
2d21ac55
A
2146 rq->urgency++;
2147 rq->count++;
2148
2149 return (result);
55e303ae
A
2150}
2151
2152/*
2d21ac55 2153 * processor_setrun:
55e303ae 2154 *
2d21ac55
A
2155 * Dispatch a thread for execution on a
2156 * processor.
55e303ae 2157 *
2d21ac55
A
2158 * Thread must be locked. Associated pset must
2159 * be locked, and is returned unlocked.
55e303ae 2160 */
2d21ac55
A
2161static void
2162processor_setrun(
2163 processor_t processor,
2164 thread_t thread,
2165 integer_t options)
55e303ae 2166{
2d21ac55
A
2167 processor_set_t pset = processor->processor_set;
2168 ast_t preempt;
55e303ae 2169
55e303ae 2170 /*
2d21ac55 2171 * Dispatch directly onto idle processor.
55e303ae 2172 */
2d21ac55
A
2173 if (processor->state == PROCESSOR_IDLE) {
2174 remqueue(&pset->idle_queue, (queue_entry_t)processor);
cf7d32b8 2175 enqueue_tail(&pset->active_queue, (queue_entry_t)processor);
2d21ac55
A
2176
2177 processor->next_thread = thread;
2178 processor->deadline = UINT64_MAX;
2179 processor->state = PROCESSOR_DISPATCHING;
2180 pset_unlock(pset);
2181
2182 if (processor != current_processor())
2183 machine_signal_idle(processor);
2184 return;
2185 }
55e303ae
A
2186
2187 /*
2d21ac55 2188 * Set preemption mode.
1c79356b 2189 */
4a3eedf9 2190 if (testbit(thread->sched_pri, sched_preempt_pri))
55e303ae 2191 preempt = (AST_PREEMPT | AST_URGENT);
2d21ac55 2192 else
c910b4d9 2193 if (thread->sched_mode & TH_MODE_TIMESHARE && thread->sched_pri < thread->priority)
2d21ac55
A
2194 preempt = AST_NONE;
2195 else
2196 preempt = (options & SCHED_PREEMPT)? AST_PREEMPT: AST_NONE;
9bccf70c 2197
2d21ac55
A
2198 if (!processor_enqueue(processor, thread, options))
2199 preempt = AST_NONE;
9bccf70c 2200
2d21ac55
A
2201 if (preempt != AST_NONE) {
2202 if (processor == current_processor()) {
c910b4d9 2203 if (csw_check(processor) != AST_NONE)
2d21ac55 2204 ast_on(preempt);
9bccf70c
A
2205 }
2206 else
2d21ac55
A
2207 if ( (processor->state == PROCESSOR_RUNNING ||
2208 processor->state == PROCESSOR_SHUTDOWN) &&
2209 thread->sched_pri >= processor->current_pri ) {
2210 cause_ast_check(processor);
2211 }
2212 }
2213 else
2214 if ( processor->state == PROCESSOR_SHUTDOWN &&
2215 thread->sched_pri >= processor->current_pri ) {
2216 cause_ast_check(processor);
2217 }
2218
2219 pset_unlock(pset);
2220}
9bccf70c 2221
2d21ac55
A
2222#define next_pset(p) (((p)->pset_list != PROCESSOR_SET_NULL)? (p)->pset_list: (p)->node->psets)
2223
2224/*
2225 * choose_next_pset:
2226 *
2227 * Return the next sibling pset containing
2228 * available processors.
2229 *
2230 * Returns the original pset if none other is
2231 * suitable.
2232 */
2233static processor_set_t
2234choose_next_pset(
2235 processor_set_t pset)
2236{
2237 processor_set_t nset = pset;
2238
2239 do {
2240 nset = next_pset(nset);
2241 } while (nset->processor_count < 1 && nset != pset);
2242
cf7d32b8 2243 return (nset);
2d21ac55
A
2244}
2245
2246/*
2247 * choose_processor:
2248 *
2249 * Choose a processor for the thread, beginning at
b7266188 2250 * the pset. Accepts an optional processor hint in
2d21ac55
A
2251 * the pset.
2252 *
2253 * Returns a processor, possibly from a different pset.
2254 *
2255 * The thread must be locked. The pset must be locked,
2256 * and the resulting pset is locked on return.
2257 */
2258static processor_t
2259choose_processor(
2260 processor_set_t pset,
b7266188 2261 processor_t processor,
2d21ac55
A
2262 thread_t thread)
2263{
2264 processor_set_t nset, cset = pset;
b0d623f7 2265 processor_meta_t pmeta = PROCESSOR_META_NULL;
cf7d32b8
A
2266
2267 /*
b7266188 2268 * Prefer the hinted processor, when appropriate.
cf7d32b8
A
2269 */
2270 if (processor != PROCESSOR_NULL) {
b7266188
A
2271 processor_t mprocessor;
2272
7e4a7d39 2273 if (processor->processor_meta != PROCESSOR_META_NULL)
b0d623f7
A
2274 processor = processor->processor_meta->primary;
2275
b7266188
A
2276 mprocessor = machine_choose_processor(pset, processor);
2277 if (mprocessor != PROCESSOR_NULL)
2278 processor = mprocessor;
2279
c910b4d9 2280 if (processor->processor_set != pset || processor->state == PROCESSOR_INACTIVE ||
cf7d32b8
A
2281 processor->state == PROCESSOR_SHUTDOWN || processor->state == PROCESSOR_OFF_LINE)
2282 processor = PROCESSOR_NULL;
2283 else
7e4a7d39 2284 if (processor->state == PROCESSOR_IDLE)
cf7d32b8
A
2285 return (processor);
2286 }
b7266188
A
2287 else {
2288 processor = machine_choose_processor(pset, processor);
2289
2290 if (processor != PROCESSOR_NULL) {
2291 if (processor->processor_set != pset || processor->state == PROCESSOR_INACTIVE ||
2292 processor->state == PROCESSOR_SHUTDOWN || processor->state == PROCESSOR_OFF_LINE)
2293 processor = PROCESSOR_NULL;
2294 else
2295 if (processor->state == PROCESSOR_IDLE)
2296 return (processor);
2297 }
2298 }
2d21ac55
A
2299
2300 /*
2301 * Iterate through the processor sets to locate
2302 * an appropriate processor.
2303 */
2304 do {
9bccf70c 2305 /*
2d21ac55 2306 * Choose an idle processor.
9bccf70c 2307 */
2d21ac55
A
2308 if (!queue_empty(&cset->idle_queue))
2309 return ((processor_t)queue_first(&cset->idle_queue));
1c79356b 2310
2d21ac55
A
2311 if (thread->sched_pri >= BASEPRI_RTQUEUES) {
2312 /*
2313 * For an RT thread, iterate through active processors, first fit.
2314 */
2315 processor = (processor_t)queue_first(&cset->active_queue);
2316 while (!queue_end(&cset->active_queue, (queue_entry_t)processor)) {
2317 if (thread->sched_pri > processor->current_pri ||
2318 thread->realtime.deadline < processor->deadline)
2319 return (processor);
2320
b0d623f7
A
2321 if (pmeta == PROCESSOR_META_NULL) {
2322 if (processor->processor_meta != PROCESSOR_META_NULL &&
2323 !queue_empty(&processor->processor_meta->idle_queue))
2324 pmeta = processor->processor_meta;
2325 }
2326
2d21ac55
A
2327 processor = (processor_t)queue_next((queue_entry_t)processor);
2328 }
cf7d32b8 2329
b0d623f7
A
2330 if (pmeta != PROCESSOR_META_NULL)
2331 return ((processor_t)queue_first(&pmeta->idle_queue));
2332
cf7d32b8 2333 processor = PROCESSOR_NULL;
2d21ac55 2334 }
55e303ae 2335 else {
2d21ac55 2336 /*
c910b4d9 2337 * Check any hinted processors in the processor set if available.
2d21ac55 2338 */
c910b4d9
A
2339 if (cset->low_pri != PROCESSOR_NULL && cset->low_pri->state != PROCESSOR_INACTIVE &&
2340 cset->low_pri->state != PROCESSOR_SHUTDOWN && cset->low_pri->state != PROCESSOR_OFF_LINE &&
2341 (processor == PROCESSOR_NULL ||
2342 (thread->sched_pri > BASEPRI_DEFAULT && cset->low_pri->current_pri < thread->sched_pri))) {
2343 processor = cset->low_pri;
2344 }
2345 else
2346 if (cset->low_count != PROCESSOR_NULL && cset->low_count->state != PROCESSOR_INACTIVE &&
2347 cset->low_count->state != PROCESSOR_SHUTDOWN && cset->low_count->state != PROCESSOR_OFF_LINE &&
b0d623f7
A
2348 (processor == PROCESSOR_NULL || (thread->sched_pri <= BASEPRI_DEFAULT &&
2349 cset->low_count->runq.count < processor->runq.count))) {
c910b4d9 2350 processor = cset->low_count;
cf7d32b8 2351 }
9bccf70c 2352
9bccf70c 2353 /*
cf7d32b8 2354 * Otherwise, choose an available processor in the set.
1c79356b 2355 */
cf7d32b8
A
2356 if (processor == PROCESSOR_NULL) {
2357 processor = (processor_t)dequeue_head(&cset->active_queue);
2358 if (processor != PROCESSOR_NULL)
2359 enqueue_tail(&cset->active_queue, (queue_entry_t)processor);
2d21ac55 2360 }
b0d623f7
A
2361
2362 if (processor != PROCESSOR_NULL && pmeta == PROCESSOR_META_NULL) {
2363 if (processor->processor_meta != PROCESSOR_META_NULL &&
2364 !queue_empty(&processor->processor_meta->idle_queue))
2365 pmeta = processor->processor_meta;
2366 }
2d21ac55
A
2367 }
2368
2369 /*
2370 * Move onto the next processor set.
2371 */
2372 nset = next_pset(cset);
2373
2374 if (nset != pset) {
2375 pset_unlock(cset);
2376
2377 cset = nset;
2378 pset_lock(cset);
2379 }
2380 } while (nset != pset);
2381
2382 /*
cf7d32b8
A
2383 * Make sure that we pick a running processor,
2384 * and that the correct processor set is locked.
2d21ac55 2385 */
cf7d32b8 2386 do {
b0d623f7
A
2387 if (pmeta != PROCESSOR_META_NULL) {
2388 if (cset != pmeta->primary->processor_set) {
2389 pset_unlock(cset);
2390
2391 cset = pmeta->primary->processor_set;
2392 pset_lock(cset);
2393 }
2394
2395 if (!queue_empty(&pmeta->idle_queue))
2396 return ((processor_t)queue_first(&pmeta->idle_queue));
2397
2398 pmeta = PROCESSOR_META_NULL;
2399 }
2400
cf7d32b8
A
2401 /*
2402 * If we haven't been able to choose a processor,
c910b4d9 2403 * pick the boot processor and return it.
cf7d32b8
A
2404 */
2405 if (processor == PROCESSOR_NULL) {
c910b4d9 2406 processor = master_processor;
2d21ac55 2407
cf7d32b8
A
2408 /*
2409 * Check that the correct processor set is
2410 * returned locked.
2411 */
2412 if (cset != processor->processor_set) {
2413 pset_unlock(cset);
2414
2415 cset = processor->processor_set;
2416 pset_lock(cset);
2417 }
2418
2419 return (processor);
2420 }
2421
2422 /*
2423 * Check that the processor set for the chosen
2424 * processor is locked.
2425 */
2426 if (cset != processor->processor_set) {
2427 pset_unlock(cset);
2428
2429 cset = processor->processor_set;
2430 pset_lock(cset);
2431 }
2432
2433 /*
2434 * We must verify that the chosen processor is still available.
2435 */
c910b4d9
A
2436 if (processor->state == PROCESSOR_INACTIVE ||
2437 processor->state == PROCESSOR_SHUTDOWN || processor->state == PROCESSOR_OFF_LINE)
cf7d32b8
A
2438 processor = PROCESSOR_NULL;
2439 } while (processor == PROCESSOR_NULL);
2d21ac55
A
2440
2441 return (processor);
2442}
2443
2444/*
2445 * thread_setrun:
2446 *
2447 * Dispatch thread for execution, onto an idle
2448 * processor or run queue, and signal a preemption
2449 * as appropriate.
2450 *
2451 * Thread must be locked.
2452 */
2453void
2454thread_setrun(
2455 thread_t thread,
2456 integer_t options)
2457{
2458 processor_t processor;
2459 processor_set_t pset;
2460
2461#if DEBUG
2462 assert(thread_runnable(thread));
2463#endif
55e303ae 2464
2d21ac55
A
2465 /*
2466 * Update priority if needed.
2467 */
2468 if (thread->sched_stamp != sched_tick)
2469 update_priority(thread);
2470
2471 assert(thread->runq == PROCESSOR_NULL);
2472
2473 if (thread->bound_processor == PROCESSOR_NULL) {
2474 /*
2475 * Unbound case.
2476 */
2477 if (thread->affinity_set != AFFINITY_SET_NULL) {
2478 /*
2479 * Use affinity set policy hint.
2480 */
2481 pset = thread->affinity_set->aset_pset;
2482 pset_lock(pset);
2483
b7266188 2484 processor = choose_processor(pset, PROCESSOR_NULL, thread);
2d21ac55
A
2485 }
2486 else
2487 if (thread->last_processor != PROCESSOR_NULL) {
2488 /*
2489 * Simple (last processor) affinity case.
2490 */
2491 processor = thread->last_processor;
2492 pset = processor->processor_set;
2493 pset_lock(pset);
2494
9bccf70c 2495 /*
2d21ac55 2496 * Choose a different processor in certain cases.
9bccf70c 2497 */
2d21ac55 2498 if (thread->sched_pri >= BASEPRI_RTQUEUES) {
9bccf70c 2499 /*
2d21ac55
A
2500 * If the processor is executing an RT thread with
2501 * an earlier deadline, choose another.
9bccf70c 2502 */
2d21ac55
A
2503 if (thread->sched_pri <= processor->current_pri ||
2504 thread->realtime.deadline >= processor->deadline)
b7266188 2505 processor = choose_processor(pset, PROCESSOR_NULL, thread);
2d21ac55
A
2506 }
2507 else
b7266188 2508 processor = choose_processor(pset, processor, thread);
2d21ac55
A
2509 }
2510 else {
2511 /*
2512 * No Affinity case:
2513 *
cf7d32b8
A
2514 * Utilitize a per task hint to spread threads
2515 * among the available processor sets.
2d21ac55 2516 */
cf7d32b8
A
2517 task_t task = thread->task;
2518
2519 pset = task->pset_hint;
2520 if (pset == PROCESSOR_SET_NULL)
2521 pset = current_processor()->processor_set;
2522
2523 pset = choose_next_pset(pset);
2d21ac55 2524 pset_lock(pset);
9bccf70c 2525
b7266188 2526 processor = choose_processor(pset, PROCESSOR_NULL, thread);
cf7d32b8 2527 task->pset_hint = processor->processor_set;
55e303ae 2528 }
1c79356b
A
2529 }
2530 else {
2d21ac55
A
2531 /*
2532 * Bound case:
2533 *
2534 * Unconditionally dispatch on the processor.
2535 */
2536 processor = thread->bound_processor;
55e303ae 2537 pset = processor->processor_set;
2d21ac55
A
2538 pset_lock(pset);
2539 }
2540
2541 /*
2542 * Dispatch the thread on the choosen processor.
2543 */
2544 if (thread->sched_pri >= BASEPRI_RTQUEUES)
2545 realtime_setrun(processor, thread);
2546 else
2547 processor_setrun(processor, thread, options);
2548}
2549
b0d623f7
A
2550processor_set_t
2551task_choose_pset(
2552 task_t task)
2553{
2554 processor_set_t pset = task->pset_hint;
2555
2556 if (pset != PROCESSOR_SET_NULL)
2557 pset = choose_next_pset(pset);
2558
2559 return (pset);
2560}
2561
2d21ac55
A
2562/*
2563 * processor_queue_shutdown:
2564 *
c910b4d9
A
2565 * Shutdown a processor run queue by
2566 * re-dispatching non-bound threads.
2d21ac55
A
2567 *
2568 * Associated pset must be locked, and is
2569 * returned unlocked.
2570 */
2571void
2572processor_queue_shutdown(
2573 processor_t processor)
2574{
2575 processor_set_t pset = processor->processor_set;
2576 run_queue_t rq = &processor->runq;
2577 queue_t queue = rq->queues + rq->highq;
2578 int pri = rq->highq, count = rq->count;
2579 thread_t next, thread;
2580 queue_head_t tqueue;
2581
2582 queue_init(&tqueue);
2583
2584 while (count > 0) {
2585 thread = (thread_t)queue_first(queue);
2586 while (!queue_end(queue, (queue_entry_t)thread)) {
2587 next = (thread_t)queue_next((queue_entry_t)thread);
2588
b0d623f7 2589 if (thread->bound_processor == PROCESSOR_NULL) {
2d21ac55
A
2590 remqueue(queue, (queue_entry_t)thread);
2591
2592 thread->runq = PROCESSOR_NULL;
2593 rq->count--;
4a3eedf9
A
2594 if (testbit(pri, sched_preempt_pri)) {
2595 rq->urgency--; assert(rq->urgency >= 0);
2596 }
2d21ac55
A
2597 if (queue_empty(queue)) {
2598 if (pri != IDLEPRI)
2599 clrbit(MAXPRI - pri, rq->bitmap);
2600 rq->highq = MAXPRI - ffsbit(rq->bitmap);
9bccf70c 2601 }
2d21ac55
A
2602
2603 enqueue_tail(&tqueue, (queue_entry_t)thread);
9bccf70c 2604 }
2d21ac55
A
2605 count--;
2606
2607 thread = next;
9bccf70c 2608 }
55e303ae 2609
2d21ac55
A
2610 queue--; pri--;
2611 }
2612
2613 pset_unlock(pset);
2614
2d21ac55
A
2615 while ((thread = (thread_t)dequeue_head(&tqueue)) != THREAD_NULL) {
2616 thread_lock(thread);
55e303ae 2617
c910b4d9 2618 thread_setrun(thread, SCHED_TAILQ);
2d21ac55
A
2619
2620 thread_unlock(thread);
9bccf70c
A
2621 }
2622}
2623
2624/*
c910b4d9
A
2625 * Check for a preemption point in
2626 * the current context.
55e303ae
A
2627 *
2628 * Called at splsched.
9bccf70c
A
2629 */
2630ast_t
2631csw_check(
9bccf70c
A
2632 processor_t processor)
2633{
9bccf70c
A
2634 ast_t result = AST_NONE;
2635 run_queue_t runq;
2636
55e303ae 2637 if (first_timeslice(processor)) {
2d21ac55 2638 runq = &rt_runq;
55e303ae
A
2639 if (runq->highq >= BASEPRI_RTQUEUES)
2640 return (AST_PREEMPT | AST_URGENT);
2641
c910b4d9 2642 if (runq->highq > processor->current_pri) {
9bccf70c 2643 if (runq->urgency > 0)
55e303ae 2644 return (AST_PREEMPT | AST_URGENT);
9bccf70c 2645
55e303ae 2646 result |= AST_PREEMPT;
9bccf70c
A
2647 }
2648
2649 runq = &processor->runq;
c910b4d9 2650 if (runq->highq > processor->current_pri) {
9bccf70c 2651 if (runq->urgency > 0)
55e303ae 2652 return (AST_PREEMPT | AST_URGENT);
9bccf70c 2653
55e303ae 2654 result |= AST_PREEMPT;
9bccf70c
A
2655 }
2656 }
2657 else {
2d21ac55 2658 runq = &rt_runq;
c910b4d9 2659 if (runq->highq >= processor->current_pri) {
9bccf70c 2660 if (runq->urgency > 0)
55e303ae 2661 return (AST_PREEMPT | AST_URGENT);
9bccf70c 2662
55e303ae 2663 result |= AST_PREEMPT;
9bccf70c
A
2664 }
2665
2666 runq = &processor->runq;
c910b4d9 2667 if (runq->highq >= processor->current_pri) {
9bccf70c 2668 if (runq->urgency > 0)
55e303ae 2669 return (AST_PREEMPT | AST_URGENT);
9bccf70c 2670
55e303ae 2671 result |= AST_PREEMPT;
9bccf70c 2672 }
1c79356b 2673 }
9bccf70c
A
2674
2675 if (result != AST_NONE)
2676 return (result);
2677
b0d623f7
A
2678 if (processor->current_pri < BASEPRI_RTQUEUES && processor->processor_meta != PROCESSOR_META_NULL &&
2679 processor->processor_meta->primary != processor)
2680 return (AST_PREEMPT);
2681
b7266188 2682 if (machine_processor_is_inactive(processor))
c910b4d9 2683 return (AST_PREEMPT);
9bccf70c 2684
c910b4d9
A
2685 if (processor->active_thread->state & TH_SUSP)
2686 return (AST_PREEMPT);
2687
2688 return (AST_NONE);
1c79356b
A
2689}
2690
2691/*
9bccf70c 2692 * set_sched_pri:
1c79356b 2693 *
55e303ae
A
2694 * Set the scheduled priority of the specified thread.
2695 *
9bccf70c 2696 * This may cause the thread to change queues.
1c79356b 2697 *
55e303ae 2698 * Thread must be locked.
1c79356b
A
2699 */
2700void
9bccf70c 2701set_sched_pri(
2d21ac55
A
2702 thread_t thread,
2703 int priority)
1c79356b 2704{
2d21ac55 2705 boolean_t removed = run_queue_remove(thread);
9bccf70c 2706
9bccf70c 2707 thread->sched_pri = priority;
2d21ac55 2708 if (removed)
55e303ae 2709 thread_setrun(thread, SCHED_PREEMPT | SCHED_TAILQ);
9bccf70c 2710 else
55e303ae 2711 if (thread->state & TH_RUN) {
9bccf70c
A
2712 processor_t processor = thread->last_processor;
2713
2714 if (thread == current_thread()) {
c910b4d9 2715 ast_t preempt;
9bccf70c 2716
9bccf70c 2717 processor->current_pri = priority;
c910b4d9
A
2718 if ((preempt = csw_check(processor)) != AST_NONE)
2719 ast_on(preempt);
9bccf70c
A
2720 }
2721 else
2722 if ( processor != PROCESSOR_NULL &&
55e303ae 2723 processor->active_thread == thread )
9bccf70c 2724 cause_ast_check(processor);
1c79356b
A
2725 }
2726}
2727
91447636
A
2728#if 0
2729
2730static void
2731run_queue_check(
2732 run_queue_t rq,
2733 thread_t thread)
2734{
2735 queue_t q;
2736 queue_entry_t qe;
2737
2738 if (rq != thread->runq)
2739 panic("run_queue_check: thread runq");
2740
2741 if (thread->sched_pri > MAXPRI || thread->sched_pri < MINPRI)
2742 panic("run_queue_check: thread sched_pri");
2743
2744 q = &rq->queues[thread->sched_pri];
2745 qe = queue_first(q);
2746 while (!queue_end(q, qe)) {
2747 if (qe == (queue_entry_t)thread)
2748 return;
2749
2750 qe = queue_next(qe);
2751 }
2752
2753 panic("run_queue_check: end");
2754}
2755
2756#endif /* DEBUG */
2757
1c79356b 2758/*
55e303ae 2759 * run_queue_remove:
1c79356b 2760 *
2d21ac55
A
2761 * Remove a thread from a current run queue and
2762 * return TRUE if successful.
55e303ae
A
2763 *
2764 * Thread must be locked.
1c79356b 2765 */
2d21ac55 2766boolean_t
55e303ae 2767run_queue_remove(
2d21ac55 2768 thread_t thread)
1c79356b 2769{
2d21ac55 2770 processor_t processor = thread->runq;
1c79356b 2771
1c79356b 2772 /*
2d21ac55 2773 * If processor is PROCESSOR_NULL, the thread will stay out of the
55e303ae
A
2774 * run queues because the caller locked the thread. Otherwise
2775 * the thread is on a run queue, but could be chosen for dispatch
2776 * and removed.
1c79356b 2777 */
2d21ac55
A
2778 if (processor != PROCESSOR_NULL) {
2779 void * rqlock;
2780 run_queue_t rq;
55e303ae
A
2781
2782 /*
2d21ac55
A
2783 * The processor run queues are locked by the
2784 * processor set. Real-time priorities use a
2785 * global queue with a dedicated lock.
55e303ae 2786 */
2d21ac55
A
2787 if (thread->sched_pri < BASEPRI_RTQUEUES) {
2788 rqlock = &processor->processor_set->sched_lock;
2789 rq = &processor->runq;
2790 }
2791 else {
2792 rqlock = &rt_lock; rq = &rt_runq;
55e303ae
A
2793 }
2794
2d21ac55 2795 simple_lock(rqlock);
55e303ae 2796
2d21ac55 2797 if (processor == thread->runq) {
1c79356b 2798 /*
55e303ae
A
2799 * Thread is on a run queue and we have a lock on
2800 * that run queue.
1c79356b 2801 */
1c79356b
A
2802 remqueue(&rq->queues[0], (queue_entry_t)thread);
2803 rq->count--;
4a3eedf9
A
2804 if (testbit(thread->sched_pri, sched_preempt_pri)) {
2805 rq->urgency--; assert(rq->urgency >= 0);
2806 }
1c79356b
A
2807
2808 if (queue_empty(rq->queues + thread->sched_pri)) {
2809 /* update run queue status */
2810 if (thread->sched_pri != IDLEPRI)
2811 clrbit(MAXPRI - thread->sched_pri, rq->bitmap);
2812 rq->highq = MAXPRI - ffsbit(rq->bitmap);
2813 }
55e303ae 2814
2d21ac55 2815 thread->runq = PROCESSOR_NULL;
1c79356b
A
2816 }
2817 else {
2818 /*
55e303ae
A
2819 * The thread left the run queue before we could
2820 * lock the run queue.
1c79356b 2821 */
2d21ac55
A
2822 assert(thread->runq == PROCESSOR_NULL);
2823 processor = PROCESSOR_NULL;
1c79356b 2824 }
55e303ae 2825
2d21ac55 2826 simple_unlock(rqlock);
1c79356b
A
2827 }
2828
2d21ac55 2829 return (processor != PROCESSOR_NULL);
1c79356b
A
2830}
2831
2d21ac55 2832/*
cf7d32b8 2833 * steal_processor_thread:
2d21ac55 2834 *
cf7d32b8
A
2835 * Locate a thread to steal from the processor and
2836 * return it.
2d21ac55
A
2837 *
2838 * Associated pset must be locked. Returns THREAD_NULL
2839 * on failure.
2840 */
2841static thread_t
cf7d32b8 2842steal_processor_thread(
2d21ac55 2843 processor_t processor)
91447636 2844{
2d21ac55
A
2845 run_queue_t rq = &processor->runq;
2846 queue_t queue = rq->queues + rq->highq;
2847 int pri = rq->highq, count = rq->count;
cf7d32b8 2848 thread_t thread;
2d21ac55
A
2849
2850 while (count > 0) {
2851 thread = (thread_t)queue_first(queue);
2852 while (!queue_end(queue, (queue_entry_t)thread)) {
b0d623f7 2853 if (thread->bound_processor == PROCESSOR_NULL) {
2d21ac55
A
2854 remqueue(queue, (queue_entry_t)thread);
2855
2856 thread->runq = PROCESSOR_NULL;
2857 rq->count--;
4a3eedf9
A
2858 if (testbit(pri, sched_preempt_pri)) {
2859 rq->urgency--; assert(rq->urgency >= 0);
2860 }
2d21ac55
A
2861 if (queue_empty(queue)) {
2862 if (pri != IDLEPRI)
2863 clrbit(MAXPRI - pri, rq->bitmap);
2864 rq->highq = MAXPRI - ffsbit(rq->bitmap);
2865 }
91447636 2866
2d21ac55
A
2867 return (thread);
2868 }
2869 count--;
91447636 2870
2d21ac55 2871 thread = (thread_t)queue_next((queue_entry_t)thread);
91447636 2872 }
91447636 2873
2d21ac55
A
2874 queue--; pri--;
2875 }
91447636 2876
2d21ac55 2877 return (THREAD_NULL);
91447636
A
2878}
2879
cf7d32b8
A
2880/*
2881 * Locate and steal a thread, beginning
2882 * at the pset.
2883 *
2884 * The pset must be locked, and is returned
2885 * unlocked.
2886 *
2887 * Returns the stolen thread, or THREAD_NULL on
2888 * failure.
2889 */
2890static thread_t
2891steal_thread(
2892 processor_set_t pset)
2893{
2894 processor_set_t nset, cset = pset;
2895 processor_t processor;
2896 thread_t thread;
2897
2898 do {
2899 processor = (processor_t)queue_first(&cset->active_queue);
2900 while (!queue_end(&cset->active_queue, (queue_entry_t)processor)) {
2901 if (processor->runq.count > 0) {
2902 thread = steal_processor_thread(processor);
2903 if (thread != THREAD_NULL) {
2904 remqueue(&cset->active_queue, (queue_entry_t)processor);
2905 enqueue_tail(&cset->active_queue, (queue_entry_t)processor);
2906
cf7d32b8
A
2907 pset_unlock(cset);
2908
2909 return (thread);
2910 }
2911 }
2912
2913 processor = (processor_t)queue_next((queue_entry_t)processor);
2914 }
2915
2916 nset = next_pset(cset);
2917
2918 if (nset != pset) {
2919 pset_unlock(cset);
2920
2921 cset = nset;
2922 pset_lock(cset);
2923 }
2924 } while (nset != pset);
2925
2926 pset_unlock(cset);
2927
2928 return (THREAD_NULL);
2929}
2930
1c79356b 2931/*
2d21ac55
A
2932 * This is the processor idle loop, which just looks for other threads
2933 * to execute. Processor idle threads invoke this without supplying a
2934 * current thread to idle without an asserted wait state.
2935 *
2936 * Returns a the next thread to execute if dispatched directly.
1c79356b 2937 */
2d21ac55
A
2938static thread_t
2939processor_idle(
2940 thread_t thread,
2941 processor_t processor)
1c79356b 2942{
2d21ac55
A
2943 processor_set_t pset = processor->processor_set;
2944 thread_t new_thread;
2945 int state;
1c79356b 2946
2d21ac55 2947 (void)splsched();
1c79356b 2948
2d21ac55 2949 KERNEL_DEBUG_CONSTANT(
b0d623f7 2950 MACHDBG_CODE(DBG_MACH_SCHED,MACH_IDLE) | DBG_FUNC_START, (uintptr_t)thread_tid(thread), 0, 0, 0, 0);
3a60a9f5 2951
2d21ac55
A
2952 timer_switch(&PROCESSOR_DATA(processor, system_state),
2953 mach_absolute_time(), &PROCESSOR_DATA(processor, idle_state));
2954 PROCESSOR_DATA(processor, current_state) = &PROCESSOR_DATA(processor, idle_state);
3a60a9f5 2955
cf7d32b8 2956 while (processor->next_thread == THREAD_NULL && processor->runq.count == 0 && rt_runq.count == 0 &&
2d21ac55 2957 (thread == THREAD_NULL || ((thread->state & (TH_WAIT|TH_SUSP)) == TH_WAIT && !thread->wake_active))) {
2d21ac55 2958 machine_idle();
55e303ae
A
2959
2960 (void)splsched();
c910b4d9 2961
b7266188 2962 if (processor->state == PROCESSOR_INACTIVE && !machine_processor_is_inactive(processor))
c910b4d9 2963 break;
55e303ae
A
2964 }
2965
2d21ac55
A
2966 timer_switch(&PROCESSOR_DATA(processor, idle_state),
2967 mach_absolute_time(), &PROCESSOR_DATA(processor, system_state));
2968 PROCESSOR_DATA(processor, current_state) = &PROCESSOR_DATA(processor, system_state);
1c79356b 2969
2d21ac55
A
2970 pset_lock(pset);
2971
55e303ae
A
2972 state = processor->state;
2973 if (state == PROCESSOR_DISPATCHING) {
1c79356b 2974 /*
55e303ae 2975 * Commmon case -- cpu dispatched.
1c79356b 2976 */
2d21ac55
A
2977 new_thread = processor->next_thread;
2978 processor->next_thread = THREAD_NULL;
55e303ae 2979 processor->state = PROCESSOR_RUNNING;
1c79356b 2980
4a3eedf9
A
2981 if ( processor->runq.highq > new_thread->sched_pri ||
2982 (rt_runq.highq > 0 && rt_runq.highq >= new_thread->sched_pri) ) {
2d21ac55 2983 processor->deadline = UINT64_MAX;
55e303ae 2984
2d21ac55 2985 pset_unlock(pset);
1c79356b 2986
2d21ac55
A
2987 thread_lock(new_thread);
2988 thread_setrun(new_thread, SCHED_HEADQ);
2989 thread_unlock(new_thread);
55e303ae 2990
4a3eedf9 2991 KERNEL_DEBUG_CONSTANT(
b0d623f7 2992 MACHDBG_CODE(DBG_MACH_SCHED,MACH_IDLE) | DBG_FUNC_END, (uintptr_t)thread_tid(thread), state, 0, 0, 0);
4a3eedf9 2993
2d21ac55 2994 return (THREAD_NULL);
1c79356b 2995 }
1c79356b 2996
2d21ac55
A
2997 pset_unlock(pset);
2998
4a3eedf9 2999 KERNEL_DEBUG_CONSTANT(
b0d623f7 3000 MACHDBG_CODE(DBG_MACH_SCHED,MACH_IDLE) | DBG_FUNC_END, (uintptr_t)thread_tid(thread), state, (uintptr_t)thread_tid(new_thread), 0, 0);
4a3eedf9 3001
2d21ac55 3002 return (new_thread);
55e303ae
A
3003 }
3004 else
3005 if (state == PROCESSOR_IDLE) {
55e303ae 3006 remqueue(&pset->idle_queue, (queue_entry_t)processor);
1c79356b 3007
2d21ac55 3008 processor->state = PROCESSOR_RUNNING;
cf7d32b8 3009 enqueue_tail(&pset->active_queue, (queue_entry_t)processor);
1c79356b 3010 }
55e303ae 3011 else
c910b4d9
A
3012 if (state == PROCESSOR_INACTIVE) {
3013 processor->state = PROCESSOR_RUNNING;
3014 enqueue_tail(&pset->active_queue, (queue_entry_t)processor);
3015 }
3016 else
55e303ae
A
3017 if (state == PROCESSOR_SHUTDOWN) {
3018 /*
3019 * Going off-line. Force a
3020 * reschedule.
3021 */
2d21ac55
A
3022 if ((new_thread = processor->next_thread) != THREAD_NULL) {
3023 processor->next_thread = THREAD_NULL;
55e303ae 3024 processor->deadline = UINT64_MAX;
2d21ac55
A
3025
3026 pset_unlock(pset);
55e303ae
A
3027
3028 thread_lock(new_thread);
3029 thread_setrun(new_thread, SCHED_HEADQ);
3030 thread_unlock(new_thread);
55e303ae 3031
4a3eedf9 3032 KERNEL_DEBUG_CONSTANT(
b0d623f7 3033 MACHDBG_CODE(DBG_MACH_SCHED,MACH_IDLE) | DBG_FUNC_END, (uintptr_t)thread_tid(thread), state, 0, 0, 0);
4a3eedf9 3034
2d21ac55
A
3035 return (THREAD_NULL);
3036 }
55e303ae
A
3037 }
3038
2d21ac55
A
3039 pset_unlock(pset);
3040
4a3eedf9 3041 KERNEL_DEBUG_CONSTANT(
b0d623f7 3042 MACHDBG_CODE(DBG_MACH_SCHED,MACH_IDLE) | DBG_FUNC_END, (uintptr_t)thread_tid(thread), state, 0, 0, 0);
4a3eedf9 3043
2d21ac55
A
3044 return (THREAD_NULL);
3045}
3046
cf7d32b8
A
3047/*
3048 * Each processor has a dedicated thread which
3049 * executes the idle loop when there is no suitable
3050 * previous context.
3051 */
2d21ac55
A
3052void
3053idle_thread(void)
3054{
3055 processor_t processor = current_processor();
3056 thread_t new_thread;
3057
3058 new_thread = processor_idle(THREAD_NULL, processor);
3059 if (new_thread != THREAD_NULL) {
3060 thread_run(processor->idle_thread, (thread_continue_t)idle_thread, NULL, new_thread);
3061 /*NOTREACHED*/
3062 }
55e303ae 3063
2d21ac55 3064 thread_block((thread_continue_t)idle_thread);
55e303ae 3065 /*NOTREACHED*/
1c79356b
A
3066}
3067
91447636
A
3068kern_return_t
3069idle_thread_create(
3070 processor_t processor)
1c79356b 3071{
91447636
A
3072 kern_return_t result;
3073 thread_t thread;
3074 spl_t s;
3075
3076 result = kernel_thread_create((thread_continue_t)idle_thread, NULL, MAXPRI_KERNEL, &thread);
3077 if (result != KERN_SUCCESS)
3078 return (result);
3079
3080 s = splsched();
3081 thread_lock(thread);
3082 thread->bound_processor = processor;
3083 processor->idle_thread = thread;
3084 thread->sched_pri = thread->priority = IDLEPRI;
3085 thread->state = (TH_RUN | TH_IDLE);
3086 thread_unlock(thread);
3087 splx(s);
3088
3089 thread_deallocate(thread);
3090
3091 return (KERN_SUCCESS);
1c79356b
A
3092}
3093
55e303ae 3094static uint64_t sched_tick_deadline;
0b4e3aa0 3095
91447636
A
3096/*
3097 * sched_startup:
3098 *
3099 * Kicks off scheduler services.
3100 *
3101 * Called at splsched.
3102 */
0b4e3aa0 3103void
91447636 3104sched_startup(void)
0b4e3aa0 3105{
91447636
A
3106 kern_return_t result;
3107 thread_t thread;
3108
3109 result = kernel_thread_start_priority((thread_continue_t)sched_tick_thread, NULL, MAXPRI_KERNEL, &thread);
3110 if (result != KERN_SUCCESS)
3111 panic("sched_startup");
3112
3113 thread_deallocate(thread);
3114
3115 /*
3116 * Yield to the sched_tick_thread while it times
3117 * a series of context switches back. It stores
3118 * the baseline value in sched_cswtime.
3119 *
3120 * The current thread is the only other thread
3121 * active at this point.
3122 */
3123 while (sched_cswtime == 0)
3124 thread_block(THREAD_CONTINUE_NULL);
3125
3126 thread_daemon_init();
3127
3128 thread_call_initialize();
0b4e3aa0 3129}
1c79356b
A
3130
3131/*
91447636 3132 * sched_tick_thread:
1c79356b 3133 *
55e303ae
A
3134 * Perform periodic bookkeeping functions about ten
3135 * times per second.
1c79356b 3136 */
91447636
A
3137static void
3138sched_tick_continue(void)
1c79356b 3139{
91447636 3140 uint64_t abstime = mach_absolute_time();
1c79356b 3141
91447636 3142 sched_tick++;
1c79356b
A
3143
3144 /*
91447636 3145 * Compute various averages.
1c79356b 3146 */
91447636 3147 compute_averages();
1c79356b
A
3148
3149 /*
91447636
A
3150 * Scan the run queues for threads which
3151 * may need to be updated.
1c79356b 3152 */
91447636 3153 thread_update_scan();
1c79356b
A
3154
3155 clock_deadline_for_periodic_event(sched_tick_interval, abstime,
3156 &sched_tick_deadline);
3157
91447636
A
3158 assert_wait_deadline((event_t)sched_tick_thread, THREAD_UNINT, sched_tick_deadline);
3159 thread_block((thread_continue_t)sched_tick_continue);
1c79356b
A
3160 /*NOTREACHED*/
3161}
3162
91447636
A
3163/*
3164 * Time a series of context switches to determine
3165 * a baseline. Toss the high and low and return
3166 * the one-way value.
3167 */
3168static uint32_t
3169time_cswitch(void)
3170{
3171 uint32_t new, hi, low, accum;
3172 uint64_t abstime;
3173 int i, tries = 7;
3174
3175 accum = hi = low = 0;
3176 for (i = 0; i < tries; ++i) {
3177 abstime = mach_absolute_time();
3178 thread_block(THREAD_CONTINUE_NULL);
3179
b0d623f7 3180 new = (uint32_t)(mach_absolute_time() - abstime);
91447636
A
3181
3182 if (i == 0)
3183 accum = hi = low = new;
3184 else {
3185 if (new < low)
3186 low = new;
3187 else
3188 if (new > hi)
3189 hi = new;
3190 accum += new;
3191 }
3192 }
3193
3194 return ((accum - hi - low) / (2 * (tries - 2)));
3195}
3196
1c79356b
A
3197void
3198sched_tick_thread(void)
3199{
91447636
A
3200 sched_cswtime = time_cswitch();
3201
55e303ae 3202 sched_tick_deadline = mach_absolute_time();
1c79356b 3203
91447636 3204 sched_tick_continue();
1c79356b
A
3205 /*NOTREACHED*/
3206}
3207
1c79356b 3208/*
91447636 3209 * thread_update_scan / runq_scan:
55e303ae 3210 *
91447636
A
3211 * Scan the run queues to account for timesharing threads
3212 * which need to be updated.
1c79356b
A
3213 *
3214 * Scanner runs in two passes. Pass one squirrels likely
91447636 3215 * threads away in an array, pass two does the update.
1c79356b 3216 *
91447636
A
3217 * This is necessary because the run queue is locked for
3218 * the candidate scan, but the thread is locked for the update.
1c79356b 3219 *
91447636
A
3220 * Array should be sized to make forward progress, without
3221 * disabling preemption for long periods.
1c79356b 3222 */
55e303ae 3223
91447636 3224#define THREAD_UPDATE_SIZE 128
55e303ae 3225
91447636
A
3226static thread_t thread_update_array[THREAD_UPDATE_SIZE];
3227static int thread_update_count = 0;
1c79356b
A
3228
3229/*
91447636
A
3230 * Scan a runq for candidate threads.
3231 *
3232 * Returns TRUE if retry is needed.
1c79356b 3233 */
55e303ae 3234static boolean_t
91447636 3235runq_scan(
1c79356b
A
3236 run_queue_t runq)
3237{
91447636 3238 register int count;
1c79356b
A
3239 register queue_t q;
3240 register thread_t thread;
1c79356b 3241
1c79356b
A
3242 if ((count = runq->count) > 0) {
3243 q = runq->queues + runq->highq;
3244 while (count > 0) {
3245 queue_iterate(q, thread, thread_t, links) {
55e303ae 3246 if ( thread->sched_stamp != sched_tick &&
0b4e3aa0 3247 (thread->sched_mode & TH_MODE_TIMESHARE) ) {
91447636 3248 if (thread_update_count == THREAD_UPDATE_SIZE)
55e303ae 3249 return (TRUE);
1c79356b 3250
91447636
A
3251 thread_update_array[thread_update_count++] = thread;
3252 thread_reference_internal(thread);
1c79356b
A
3253 }
3254
3255 count--;
3256 }
3257
3258 q--;
3259 }
3260 }
1c79356b 3261
91447636 3262 return (FALSE);
1c79356b
A
3263}
3264
55e303ae 3265static void
91447636 3266thread_update_scan(void)
1c79356b 3267{
2d21ac55
A
3268 boolean_t restart_needed = FALSE;
3269 processor_t processor = processor_list;
3270 processor_set_t pset;
3271 thread_t thread;
3272 spl_t s;
1c79356b 3273
1c79356b 3274 do {
2d21ac55
A
3275 do {
3276 pset = processor->processor_set;
1c79356b 3277
2d21ac55
A
3278 s = splsched();
3279 pset_lock(pset);
0b4e3aa0 3280
2d21ac55
A
3281 restart_needed = runq_scan(&processor->runq);
3282
3283 pset_unlock(pset);
3284 splx(s);
3285
3286 if (restart_needed)
3287 break;
3288
3289 thread = processor->idle_thread;
3290 if (thread != THREAD_NULL && thread->sched_stamp != sched_tick) {
3291 if (thread_update_count == THREAD_UPDATE_SIZE) {
3292 restart_needed = TRUE;
3293 break;
0b4e3aa0
A
3294 }
3295
2d21ac55
A
3296 thread_update_array[thread_update_count++] = thread;
3297 thread_reference_internal(thread);
1c79356b 3298 }
2d21ac55 3299 } while ((processor = processor->processor_list) != NULL);
1c79356b
A
3300
3301 /*
3302 * Ok, we now have a collection of candidates -- fix them.
3303 */
91447636
A
3304 while (thread_update_count > 0) {
3305 thread = thread_update_array[--thread_update_count];
3306 thread_update_array[thread_update_count] = THREAD_NULL;
55e303ae 3307
1c79356b
A
3308 s = splsched();
3309 thread_lock(thread);
55e303ae
A
3310 if ( !(thread->state & (TH_WAIT|TH_SUSP)) &&
3311 thread->sched_stamp != sched_tick )
3312 update_priority(thread);
1c79356b
A
3313 thread_unlock(thread);
3314 splx(s);
55e303ae 3315
91447636 3316 thread_deallocate(thread);
1c79356b 3317 }
1c79356b
A
3318 } while (restart_needed);
3319}
3320
3321/*
3322 * Just in case someone doesn't use the macro
3323 */
3324#undef thread_wakeup
3325void
3326thread_wakeup(
3327 event_t x);
3328
3329void
3330thread_wakeup(
3331 event_t x)
3332{
3333 thread_wakeup_with_result(x, THREAD_AWAKENED);
3334}
3335
91447636
A
3336boolean_t
3337preemption_enabled(void)
3338{
3339 return (get_preemption_level() == 0 && ml_get_interrupts_enabled());
3340}
9bccf70c 3341
0b4e3aa0 3342#if DEBUG
0b4e3aa0 3343static boolean_t
1c79356b 3344thread_runnable(
0b4e3aa0 3345 thread_t thread)
1c79356b 3346{
0b4e3aa0 3347 return ((thread->state & (TH_RUN|TH_WAIT)) == TH_RUN);
1c79356b 3348}
1c79356b
A
3349#endif /* DEBUG */
3350
3351#if MACH_KDB
3352#include <ddb/db_output.h>
3353#define printf kdbprintf
1c79356b
A
3354void db_sched(void);
3355
3356void
3357db_sched(void)
3358{
3359 iprintf("Scheduling Statistics:\n");
3360 db_indent += 2;
3361 iprintf("Thread invocations: csw %d same %d\n",
3362 c_thread_invoke_csw, c_thread_invoke_same);
3363#if MACH_COUNTERS
3364 iprintf("Thread block: calls %d\n",
3365 c_thread_block_calls);
2d21ac55 3366 iprintf("Idle thread:\n\thandoff %d block %d\n",
1c79356b 3367 c_idle_thread_handoff,
2d21ac55 3368 c_idle_thread_block);
1c79356b
A
3369 iprintf("Sched thread blocks: %d\n", c_sched_thread_block);
3370#endif /* MACH_COUNTERS */
3371 db_indent -= 2;
3372}
55e303ae
A
3373
3374#include <ddb/db_output.h>
3375void db_show_thread_log(void);
3376
3377void
3378db_show_thread_log(void)
3379{
3380}
1c79356b 3381#endif /* MACH_KDB */