]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kern/sched_prim.c
xnu-344.tar.gz
[apple/xnu.git] / osfmk / kern / sched_prim.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * @OSF_FREE_COPYRIGHT@
24 */
25/*
26 * Mach Operating System
27 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
28 * All Rights Reserved.
29 *
30 * Permission to use, copy, modify and distribute this software and its
31 * documentation is hereby granted, provided that both the copyright
32 * notice and this permission notice appear in all copies of the
33 * software, derivative works or modified versions, and any portions
34 * thereof, and that both notices appear in supporting documentation.
35 *
36 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
39 *
40 * Carnegie Mellon requests users of this software to return to
41 *
42 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
43 * School of Computer Science
44 * Carnegie Mellon University
45 * Pittsburgh PA 15213-3890
46 *
47 * any improvements or extensions that they make and grant Carnegie Mellon
48 * the rights to redistribute these changes.
49 */
50/*
51 */
52/*
53 * File: sched_prim.c
54 * Author: Avadis Tevanian, Jr.
55 * Date: 1986
56 *
57 * Scheduling primitives
58 *
59 */
60
61#include <debug.h>
62#include <cpus.h>
63#include <mach_kdb.h>
64#include <simple_clock.h>
65#include <power_save.h>
66#include <task_swapper.h>
67
68#include <ddb/db_output.h>
69#include <mach/machine.h>
70#include <machine/machine_routines.h>
71#include <machine/sched_param.h>
72#include <kern/ast.h>
73#include <kern/clock.h>
74#include <kern/counters.h>
75#include <kern/cpu_number.h>
76#include <kern/cpu_data.h>
77#include <kern/etap_macros.h>
78#include <kern/lock.h>
79#include <kern/macro_help.h>
80#include <kern/machine.h>
81#include <kern/misc_protos.h>
82#include <kern/processor.h>
83#include <kern/queue.h>
84#include <kern/sched.h>
85#include <kern/sched_prim.h>
86#include <kern/syscall_subr.h>
87#include <kern/task.h>
88#include <kern/thread.h>
89#include <kern/thread_swap.h>
90#include <vm/pmap.h>
91#include <vm/vm_kern.h>
92#include <vm/vm_map.h>
93#include <mach/policy.h>
94#include <mach/sync_policy.h>
1c79356b
A
95#include <kern/mk_sp.h> /*** ??? fix so this can be removed ***/
96#include <sys/kdebug.h>
97
98#if TASK_SWAPPER
99#include <kern/task_swap.h>
100extern int task_swap_on;
101#endif /* TASK_SWAPPER */
102
103extern int hz;
104
0b4e3aa0 105#define DEFAULT_PREEMPTION_RATE 100 /* (1/s) */
1c79356b
A
106int default_preemption_rate = DEFAULT_PREEMPTION_RATE;
107
0b4e3aa0
A
108#define MAX_UNSAFE_QUANTA 800
109int max_unsafe_quanta = MAX_UNSAFE_QUANTA;
110
111#define MAX_POLL_QUANTA 2
112int max_poll_quanta = MAX_POLL_QUANTA;
113
114#define SCHED_POLL_YIELD_SHIFT 4 /* 1/16 */
115int sched_poll_yield_shift = SCHED_POLL_YIELD_SHIFT;
116
0b4e3aa0 117uint32_t std_quantum_us;
1c79356b
A
118
119unsigned sched_tick;
120
121#if SIMPLE_CLOCK
122int sched_usec;
123#endif /* SIMPLE_CLOCK */
124
125/* Forwards */
1c79356b
A
126void wait_queues_init(void);
127
1c79356b
A
128thread_t choose_pset_thread(
129 processor_t myprocessor,
130 processor_set_t pset);
131
132thread_t choose_thread(
133 processor_t myprocessor);
134
9bccf70c 135boolean_t run_queue_enqueue(
1c79356b
A
136 run_queue_t runq,
137 thread_t thread,
138 boolean_t tail);
139
1c79356b
A
140void do_thread_scan(void);
141
1c79356b
A
142#if DEBUG
143void dump_run_queues(
144 run_queue_t rq);
145void dump_run_queue_struct(
146 run_queue_t rq);
147void dump_processor(
148 processor_t p);
149void dump_processor_set(
150 processor_set_t ps);
151
152void checkrq(
153 run_queue_t rq,
154 char *msg);
155
156void thread_check(
157 thread_t thread,
158 run_queue_t runq);
1c79356b 159
0b4e3aa0 160static
1c79356b
A
161boolean_t thread_runnable(
162 thread_t thread);
163
0b4e3aa0
A
164#endif /*DEBUG*/
165
166
1c79356b
A
167/*
168 * State machine
169 *
170 * states are combinations of:
171 * R running
172 * W waiting (or on wait queue)
173 * N non-interruptible
174 * O swapped out
175 * I being swapped in
176 *
177 * init action
178 * assert_wait thread_block clear_wait swapout swapin
179 *
180 * R RW, RWN R; setrun - -
181 * RN RWN RN; setrun - -
182 *
183 * RW W R -
184 * RWN WN RN -
185 *
186 * W R; setrun WO
187 * WN RN; setrun -
188 *
189 * RO - - R
190 *
191 */
192
193/*
194 * Waiting protocols and implementation:
195 *
196 * Each thread may be waiting for exactly one event; this event
197 * is set using assert_wait(). That thread may be awakened either
198 * by performing a thread_wakeup_prim() on its event,
199 * or by directly waking that thread up with clear_wait().
200 *
201 * The implementation of wait events uses a hash table. Each
202 * bucket is queue of threads having the same hash function
203 * value; the chain for the queue (linked list) is the run queue
204 * field. [It is not possible to be waiting and runnable at the
205 * same time.]
206 *
207 * Locks on both the thread and on the hash buckets govern the
208 * wait event field and the queue chain field. Because wakeup
209 * operations only have the event as an argument, the event hash
210 * bucket must be locked before any thread.
211 *
212 * Scheduling operations may also occur at interrupt level; therefore,
213 * interrupts below splsched() must be prevented when holding
214 * thread or hash bucket locks.
215 *
216 * The wait event hash table declarations are as follows:
217 */
218
219#define NUMQUEUES 59
220
221struct wait_queue wait_queues[NUMQUEUES];
222
223#define wait_hash(event) \
224 ((((int)(event) < 0)? ~(int)(event): (int)(event)) % NUMQUEUES)
225
226void
227sched_init(void)
228{
229 /*
0b4e3aa0
A
230 * Calculate the timeslicing quantum
231 * in us.
1c79356b
A
232 */
233 if (default_preemption_rate < 1)
234 default_preemption_rate = DEFAULT_PREEMPTION_RATE;
0b4e3aa0 235 std_quantum_us = (1000 * 1000) / default_preemption_rate;
1c79356b 236
0b4e3aa0 237 printf("standard timeslicing quantum is %d us\n", std_quantum_us);
1c79356b
A
238
239 wait_queues_init();
240 pset_sys_bootstrap(); /* initialize processor mgmt. */
241 processor_action();
242 sched_tick = 0;
243#if SIMPLE_CLOCK
244 sched_usec = 0;
245#endif /* SIMPLE_CLOCK */
246 ast_init();
1c79356b
A
247}
248
249void
250wait_queues_init(void)
251{
252 register int i;
253
254 for (i = 0; i < NUMQUEUES; i++) {
255 wait_queue_init(&wait_queues[i], SYNC_POLICY_FIFO);
256 }
257}
258
259/*
0b4e3aa0 260 * Thread wait timer expiration.
1c79356b
A
261 */
262void
263thread_timer_expire(
264 timer_call_param_t p0,
265 timer_call_param_t p1)
266{
267 thread_t thread = p0;
268 spl_t s;
269
270 s = splsched();
271 wake_lock(thread);
0b4e3aa0
A
272 if (--thread->wait_timer_active == 1) {
273 if (thread->wait_timer_is_set) {
274 thread->wait_timer_is_set = FALSE;
275 thread_lock(thread);
276 if (thread->active)
277 clear_wait_internal(thread, THREAD_TIMED_OUT);
278 thread_unlock(thread);
279 }
1c79356b
A
280 }
281 else
0b4e3aa0 282 if (thread->wait_timer_active == 0)
1c79356b
A
283 thread_wakeup_one(&thread->wait_timer_active);
284 wake_unlock(thread);
285 splx(s);
286}
287
288/*
289 * thread_set_timer:
290 *
291 * Set a timer for the current thread, if the thread
292 * is ready to wait. Must be called between assert_wait()
293 * and thread_block().
294 */
295void
296thread_set_timer(
0b4e3aa0
A
297 uint32_t interval,
298 uint32_t scale_factor)
1c79356b
A
299{
300 thread_t thread = current_thread();
0b4e3aa0 301 uint64_t deadline;
1c79356b
A
302 spl_t s;
303
304 s = splsched();
305 wake_lock(thread);
306 thread_lock(thread);
307 if ((thread->state & TH_WAIT) != 0) {
308 clock_interval_to_deadline(interval, scale_factor, &deadline);
309 timer_call_enter(&thread->wait_timer, deadline);
310 assert(!thread->wait_timer_is_set);
311 thread->wait_timer_active++;
312 thread->wait_timer_is_set = TRUE;
313 }
314 thread_unlock(thread);
315 wake_unlock(thread);
316 splx(s);
317}
318
319void
320thread_set_timer_deadline(
0b4e3aa0 321 uint64_t deadline)
1c79356b
A
322{
323 thread_t thread = current_thread();
324 spl_t s;
325
326 s = splsched();
327 wake_lock(thread);
328 thread_lock(thread);
329 if ((thread->state & TH_WAIT) != 0) {
330 timer_call_enter(&thread->wait_timer, deadline);
331 assert(!thread->wait_timer_is_set);
332 thread->wait_timer_active++;
333 thread->wait_timer_is_set = TRUE;
334 }
335 thread_unlock(thread);
336 wake_unlock(thread);
337 splx(s);
338}
339
340void
341thread_cancel_timer(void)
342{
343 thread_t thread = current_thread();
344 spl_t s;
345
346 s = splsched();
347 wake_lock(thread);
348 if (thread->wait_timer_is_set) {
349 if (timer_call_cancel(&thread->wait_timer))
350 thread->wait_timer_active--;
351 thread->wait_timer_is_set = FALSE;
352 }
353 wake_unlock(thread);
354 splx(s);
355}
356
1c79356b
A
357/*
358 * Set up thread timeout element when thread is created.
359 */
360void
361thread_timer_setup(
362 thread_t thread)
363{
0b4e3aa0
A
364 extern void thread_depress_expire(
365 timer_call_param_t p0,
366 timer_call_param_t p1);
367
1c79356b
A
368 timer_call_setup(&thread->wait_timer, thread_timer_expire, thread);
369 thread->wait_timer_is_set = FALSE;
370 thread->wait_timer_active = 1;
1c79356b 371
0b4e3aa0
A
372 timer_call_setup(&thread->depress_timer, thread_depress_expire, thread);
373 thread->depress_timer_active = 1;
374
375 thread->ref_count++;
1c79356b
A
376}
377
378void
379thread_timer_terminate(void)
380{
381 thread_t thread = current_thread();
9bccf70c 382 wait_result_t res;
1c79356b
A
383 spl_t s;
384
385 s = splsched();
386 wake_lock(thread);
387 if (thread->wait_timer_is_set) {
388 if (timer_call_cancel(&thread->wait_timer))
389 thread->wait_timer_active--;
390 thread->wait_timer_is_set = FALSE;
391 }
392
393 thread->wait_timer_active--;
394
395 while (thread->wait_timer_active > 0) {
9bccf70c
A
396 res = assert_wait((event_t)&thread->wait_timer_active, THREAD_UNINT);
397 assert(res == THREAD_WAITING);
1c79356b
A
398 wake_unlock(thread);
399 splx(s);
400
9bccf70c
A
401 res = thread_block(THREAD_CONTINUE_NULL);
402 assert(res == THREAD_AWAKENED);
1c79356b
A
403
404 s = splsched();
405 wake_lock(thread);
406 }
407
0b4e3aa0
A
408 thread->depress_timer_active--;
409
410 while (thread->depress_timer_active > 0) {
9bccf70c
A
411 res = assert_wait((event_t)&thread->depress_timer_active, THREAD_UNINT);
412 assert(res == THREAD_WAITING);
0b4e3aa0
A
413 wake_unlock(thread);
414 splx(s);
415
9bccf70c
A
416 res = thread_block(THREAD_CONTINUE_NULL);
417 assert(res == THREAD_AWAKENED);
0b4e3aa0
A
418
419 s = splsched();
420 wake_lock(thread);
421 }
422
1c79356b
A
423 wake_unlock(thread);
424 splx(s);
425
426 thread_deallocate(thread);
427}
428
429/*
430 * Routine: thread_go_locked
431 * Purpose:
432 * Start a thread running.
433 * Conditions:
434 * thread lock held, IPC locks may be held.
435 * thread must have been pulled from wait queue under same lock hold.
9bccf70c
A
436 * Returns:
437 * KERN_SUCCESS - Thread was set running
438 * KERN_NOT_WAITING - Thread was not waiting
1c79356b 439 */
9bccf70c 440kern_return_t
1c79356b
A
441thread_go_locked(
442 thread_t thread,
9bccf70c 443 wait_result_t result)
1c79356b 444{
1c79356b 445 assert(thread->at_safe_point == FALSE);
9bccf70c 446 assert(thread->wait_event == NO_EVENT64);
1c79356b
A
447 assert(thread->wait_queue == WAIT_QUEUE_NULL);
448
9bccf70c 449 if ((thread->state & (TH_WAIT|TH_TERMINATE)) == TH_WAIT) {
1c79356b
A
450 thread->state &= ~(TH_WAIT|TH_UNINT);
451 if (!(thread->state & TH_RUN)) {
452 thread->state |= TH_RUN;
0b4e3aa0 453
9bccf70c
A
454 if (thread->active_callout)
455 call_thread_unblock();
456
457 if (!(thread->state & TH_IDLE)) {
458 _mk_sp_thread_unblock(thread);
459 hw_atomic_add(&thread->processor_set->run_count, 1);
460 }
1c79356b 461 }
0b4e3aa0 462
1c79356b 463 thread->wait_result = result;
9bccf70c 464 return KERN_SUCCESS;
1c79356b 465 }
9bccf70c 466 return KERN_NOT_WAITING;
1c79356b
A
467}
468
9bccf70c
A
469/*
470 * Routine: thread_mark_wait_locked
471 * Purpose:
472 * Mark a thread as waiting. If, given the circumstances,
473 * it doesn't want to wait (i.e. already aborted), then
474 * indicate that in the return value.
475 * Conditions:
476 * at splsched() and thread is locked.
477 */
478__private_extern__
479wait_result_t
1c79356b 480thread_mark_wait_locked(
9bccf70c
A
481 thread_t thread,
482 wait_interrupt_t interruptible)
1c79356b 483{
9bccf70c
A
484 wait_result_t wait_result;
485 boolean_t at_safe_point;
1c79356b
A
486
487 assert(thread == current_thread());
488
9bccf70c
A
489 /*
490 * The thread may have certain types of interrupts/aborts masked
491 * off. Even if the wait location says these types of interrupts
492 * are OK, we have to honor mask settings (outer-scoped code may
493 * not be able to handle aborts at the moment).
494 */
495 if (interruptible > thread->interrupt_level)
496 interruptible = thread->interrupt_level;
497
498 at_safe_point = (interruptible == THREAD_ABORTSAFE);
499
500 if ((interruptible == THREAD_UNINT) ||
501 !(thread->state & TH_ABORT) ||
502 (!at_safe_point && (thread->state & TH_ABORT_SAFELY))) {
503 thread->state |= (interruptible) ? TH_WAIT : (TH_WAIT | TH_UNINT);
504 thread->at_safe_point = at_safe_point;
505 thread->sleep_stamp = sched_tick;
506 return (thread->wait_result = THREAD_WAITING);
507 } else if (thread->state & TH_ABORT_SAFELY) {
508 thread->state &= ~(TH_ABORT|TH_ABORT_SAFELY);
509 }
510 return (thread->wait_result = THREAD_INTERRUPTED);
1c79356b
A
511}
512
9bccf70c
A
513/*
514 * Routine: thread_interrupt_level
515 * Purpose:
516 * Set the maximum interruptible state for the
517 * current thread. The effective value of any
518 * interruptible flag passed into assert_wait
519 * will never exceed this.
520 *
521 * Useful for code that must not be interrupted,
522 * but which calls code that doesn't know that.
523 * Returns:
524 * The old interrupt level for the thread.
525 */
526__private_extern__
527wait_interrupt_t
528thread_interrupt_level(
529 wait_interrupt_t new_level)
530{
531 thread_t thread = current_thread();
532 wait_interrupt_t result = thread->interrupt_level;
1c79356b 533
9bccf70c
A
534 thread->interrupt_level = new_level;
535 return result;
536}
1c79356b
A
537
538/*
539 * Routine: assert_wait_timeout
540 * Purpose:
541 * Assert that the thread intends to block,
542 * waiting for a timeout (no user known event).
543 */
544unsigned int assert_wait_timeout_event;
545
9bccf70c 546wait_result_t
1c79356b 547assert_wait_timeout(
9bccf70c
A
548 mach_msg_timeout_t msecs,
549 wait_interrupt_t interruptible)
1c79356b 550{
9bccf70c 551 wait_result_t res;
1c79356b 552
9bccf70c
A
553 res = assert_wait((event_t)&assert_wait_timeout_event, interruptible);
554 if (res == THREAD_WAITING)
555 thread_set_timer(msecs, 1000*NSEC_PER_USEC);
556 return res;
1c79356b
A
557}
558
559/*
560 * Check to see if an assert wait is possible, without actually doing one.
561 * This is used by debug code in locks and elsewhere to verify that it is
562 * always OK to block when trying to take a blocking lock (since waiting
563 * for the actual assert_wait to catch the case may make it hard to detect
564 * this case.
565 */
566boolean_t
567assert_wait_possible(void)
568{
569
570 thread_t thread;
571 extern unsigned int debug_mode;
572
573#if DEBUG
574 if(debug_mode) return TRUE; /* Always succeed in debug mode */
575#endif
576
577 thread = current_thread();
578
579 return (thread == NULL || wait_queue_assert_possible(thread));
580}
581
582/*
583 * assert_wait:
584 *
585 * Assert that the current thread is about to go to
586 * sleep until the specified event occurs.
587 */
9bccf70c 588wait_result_t
1c79356b
A
589assert_wait(
590 event_t event,
9bccf70c 591 wait_interrupt_t interruptible)
1c79356b
A
592{
593 register wait_queue_t wq;
594 register int index;
595
596 assert(event != NO_EVENT);
597 assert(assert_wait_possible());
598
599 index = wait_hash(event);
600 wq = &wait_queues[index];
9bccf70c
A
601 return wait_queue_assert_wait(wq, event, interruptible);
602}
603
604
605/*
606 * thread_sleep_fast_usimple_lock:
607 *
608 * Cause the current thread to wait until the specified event
609 * occurs. The specified simple_lock is unlocked before releasing
610 * the cpu and re-acquired as part of waking up.
611 *
612 * This is the simple lock sleep interface for components that use a
613 * faster version of simple_lock() than is provided by usimple_lock().
614 */
615__private_extern__ wait_result_t
616thread_sleep_fast_usimple_lock(
617 event_t event,
618 simple_lock_t lock,
619 wait_interrupt_t interruptible)
620{
621 wait_result_t res;
622
623 res = assert_wait(event, interruptible);
624 if (res == THREAD_WAITING) {
625 simple_unlock(lock);
626 res = thread_block(THREAD_CONTINUE_NULL);
627 simple_lock(lock);
628 }
629 return res;
1c79356b
A
630}
631
9bccf70c
A
632
633/*
634 * thread_sleep_usimple_lock:
635 *
636 * Cause the current thread to wait until the specified event
637 * occurs. The specified usimple_lock is unlocked before releasing
638 * the cpu and re-acquired as part of waking up.
639 *
640 * This is the simple lock sleep interface for components where
641 * simple_lock() is defined in terms of usimple_lock().
642 */
643wait_result_t
644thread_sleep_usimple_lock(
645 event_t event,
646 usimple_lock_t lock,
647 wait_interrupt_t interruptible)
648{
649 wait_result_t res;
650
651 res = assert_wait(event, interruptible);
652 if (res == THREAD_WAITING) {
653 usimple_unlock(lock);
654 res = thread_block(THREAD_CONTINUE_NULL);
655 usimple_lock(lock);
656 }
657 return res;
658}
659
660/*
661 * thread_sleep_mutex:
662 *
663 * Cause the current thread to wait until the specified event
664 * occurs. The specified mutex is unlocked before releasing
665 * the cpu. The mutex will be re-acquired before returning.
666 *
667 * JMM - Add hint to make sure mutex is available before rousting
668 */
669wait_result_t
670thread_sleep_mutex(
671 event_t event,
672 mutex_t *mutex,
673 wait_interrupt_t interruptible)
674{
675 wait_result_t res;
676
677 res = assert_wait(event, interruptible);
678 if (res == THREAD_WAITING) {
679 mutex_unlock(mutex);
680 res = thread_block(THREAD_CONTINUE_NULL);
681 mutex_lock(mutex);
682 }
683 return res;
684}
1c79356b 685
9bccf70c
A
686/*
687 * thread_sleep_mutex_deadline:
688 *
689 * Cause the current thread to wait until the specified event
690 * (or deadline) occurs. The specified mutex is unlocked before
691 * releasing the cpu. The mutex will be re-acquired before returning.
692 *
693 * JMM - Add hint to make sure mutex is available before rousting
694 */
695wait_result_t
696thread_sleep_mutex_deadline(
697 event_t event,
698 mutex_t *mutex,
699 uint64_t deadline,
700 wait_interrupt_t interruptible)
701{
702 wait_result_t res;
703
704 res = assert_wait(event, interruptible);
705 if (res == THREAD_WAITING) {
706 mutex_unlock(mutex);
707 thread_set_timer_deadline(deadline);
708 res = thread_block(THREAD_CONTINUE_NULL);
709 if (res != THREAD_TIMED_OUT)
710 thread_cancel_timer();
711 mutex_lock(mutex);
712 }
713 return res;
714}
715
716/*
717 * thread_sleep_lock_write:
718 *
719 * Cause the current thread to wait until the specified event
720 * occurs. The specified (write) lock is unlocked before releasing
721 * the cpu. The (write) lock will be re-acquired before returning.
722 *
723 * JMM - Add hint to make sure mutex is available before rousting
724 */
725wait_result_t
726thread_sleep_lock_write(
727 event_t event,
728 lock_t *lock,
729 wait_interrupt_t interruptible)
730{
731 wait_result_t res;
732
733 res = assert_wait(event, interruptible);
734 if (res == THREAD_WAITING) {
735 lock_write_done(lock);
736 res = thread_block(THREAD_CONTINUE_NULL);
737 lock_write(lock);
738 }
739 return res;
740}
741
742
743/*
744 * thread_sleep_funnel:
745 *
746 * Cause the current thread to wait until the specified event
747 * occurs. If the thread is funnelled, the funnel will be released
748 * before giving up the cpu. The funnel will be re-acquired before returning.
749 *
750 * JMM - Right now the funnel is dropped and re-acquired inside
751 * thread_block(). At some point, this may give thread_block() a hint.
752 */
753wait_result_t
754thread_sleep_funnel(
755 event_t event,
756 wait_interrupt_t interruptible)
757{
758 wait_result_t res;
759
760 res = assert_wait(event, interruptible);
761 if (res == THREAD_WAITING) {
762 res = thread_block(THREAD_CONTINUE_NULL);
763 }
764 return res;
765}
766
1c79356b
A
767/*
768 * thread_[un]stop(thread)
769 * Once a thread has blocked interruptibly (via assert_wait) prevent
770 * it from running until thread_unstop.
771 *
772 * If someone else has already stopped the thread, wait for the
773 * stop to be cleared, and then stop it again.
774 *
775 * Return FALSE if interrupted.
776 *
777 * NOTE: thread_hold/thread_suspend should be called on the activation
778 * before calling thread_stop. TH_SUSP is only recognized when
779 * a thread blocks and only prevents clear_wait/thread_wakeup
780 * from restarting an interruptible wait. The wake_active flag is
781 * used to indicate that someone is waiting on the thread.
782 */
783boolean_t
784thread_stop(
9bccf70c 785 thread_t thread)
1c79356b 786{
9bccf70c 787 spl_t s = splsched();
1c79356b 788
1c79356b
A
789 wake_lock(thread);
790
791 while (thread->state & TH_SUSP) {
9bccf70c 792 wait_result_t result;
e7c99d92 793
1c79356b 794 thread->wake_active = TRUE;
9bccf70c 795 result = assert_wait(&thread->wake_active, THREAD_ABORTSAFE);
1c79356b
A
796 wake_unlock(thread);
797 splx(s);
798
9bccf70c
A
799 if (result == THREAD_WAITING)
800 result = thread_block(THREAD_CONTINUE_NULL);
801
802 if (result != THREAD_AWAKENED)
1c79356b
A
803 return (FALSE);
804
805 s = splsched();
806 wake_lock(thread);
807 }
9bccf70c 808
1c79356b
A
809 thread_lock(thread);
810 thread->state |= TH_SUSP;
1c79356b 811
9bccf70c
A
812 while (thread->state & TH_RUN) {
813 wait_result_t result;
814 processor_t processor = thread->last_processor;
815
816 if ( processor != PROCESSOR_NULL &&
817 processor->state == PROCESSOR_RUNNING &&
818 processor->cpu_data->active_thread == thread )
819 cause_ast_check(processor);
820 thread_unlock(thread);
821
822 thread->wake_active = TRUE;
823 result = assert_wait(&thread->wake_active, THREAD_ABORTSAFE);
824 wake_unlock(thread);
825 splx(s);
826
827 if (result == THREAD_WAITING)
828 result = thread_block(THREAD_CONTINUE_NULL);
829
830 if (result != THREAD_AWAKENED) {
831 thread_unstop(thread);
832 return (FALSE);
833 }
834
835 s = splsched();
836 wake_lock(thread);
837 thread_lock(thread);
838 }
839
840 thread_unlock(thread);
1c79356b
A
841 wake_unlock(thread);
842 splx(s);
843
844 return (TRUE);
845}
846
847/*
848 * Clear TH_SUSP and if the thread has been stopped and is now runnable,
849 * put it back on the run queue.
850 */
851void
852thread_unstop(
9bccf70c 853 thread_t thread)
1c79356b 854{
9bccf70c 855 spl_t s = splsched();
1c79356b 856
1c79356b
A
857 wake_lock(thread);
858 thread_lock(thread);
859
9bccf70c 860 if ((thread->state & (TH_RUN|TH_WAIT|TH_SUSP)) == TH_SUSP) {
0b4e3aa0
A
861 thread->state &= ~TH_SUSP;
862 thread->state |= TH_RUN;
863
9bccf70c 864 assert(!(thread->state & TH_IDLE));
0b4e3aa0 865 _mk_sp_thread_unblock(thread);
9bccf70c 866 hw_atomic_add(&thread->processor_set->run_count, 1);
1c79356b
A
867 }
868 else
869 if (thread->state & TH_SUSP) {
870 thread->state &= ~TH_SUSP;
871
872 if (thread->wake_active) {
873 thread->wake_active = FALSE;
874 thread_unlock(thread);
875 wake_unlock(thread);
876 splx(s);
1c79356b 877
9bccf70c 878 thread_wakeup(&thread->wake_active);
1c79356b
A
879 return;
880 }
881 }
882
883 thread_unlock(thread);
884 wake_unlock(thread);
885 splx(s);
886}
887
888/*
889 * Wait for the thread's RUN bit to clear
890 */
891boolean_t
892thread_wait(
9bccf70c 893 thread_t thread)
1c79356b 894{
9bccf70c 895 spl_t s = splsched();
1c79356b 896
1c79356b 897 wake_lock(thread);
9bccf70c 898 thread_lock(thread);
1c79356b 899
9bccf70c
A
900 while (thread->state & TH_RUN) {
901 wait_result_t result;
902 processor_t processor = thread->last_processor;
e7c99d92 903
9bccf70c
A
904 if ( processor != PROCESSOR_NULL &&
905 processor->state == PROCESSOR_RUNNING &&
906 processor->cpu_data->active_thread == thread )
907 cause_ast_check(processor);
908 thread_unlock(thread);
1c79356b
A
909
910 thread->wake_active = TRUE;
9bccf70c 911 result = assert_wait(&thread->wake_active, THREAD_ABORTSAFE);
1c79356b
A
912 wake_unlock(thread);
913 splx(s);
914
9bccf70c
A
915 if (result == THREAD_WAITING)
916 result = thread_block(THREAD_CONTINUE_NULL);
917
918 if (result != THREAD_AWAKENED)
919 return (FALSE);
1c79356b
A
920
921 s = splsched();
922 wake_lock(thread);
9bccf70c 923 thread_lock(thread);
1c79356b 924 }
0b4e3aa0 925
9bccf70c 926 thread_unlock(thread);
1c79356b
A
927 wake_unlock(thread);
928 splx(s);
0b4e3aa0
A
929
930 return (TRUE);
1c79356b
A
931}
932
1c79356b
A
933/*
934 * Routine: clear_wait_internal
935 *
936 * Clear the wait condition for the specified thread.
937 * Start the thread executing if that is appropriate.
938 * Arguments:
939 * thread thread to awaken
940 * result Wakeup result the thread should see
941 * Conditions:
942 * At splsched
943 * the thread is locked.
9bccf70c
A
944 * Returns:
945 * KERN_SUCCESS thread was rousted out a wait
946 * KERN_FAILURE thread was waiting but could not be rousted
947 * KERN_NOT_WAITING thread was not waiting
1c79356b 948 */
9bccf70c 949__private_extern__ kern_return_t
1c79356b 950clear_wait_internal(
9bccf70c
A
951 thread_t thread,
952 wait_result_t result)
1c79356b 953{
9bccf70c
A
954 wait_queue_t wq = thread->wait_queue;
955 kern_return_t ret;
956 int loop_count;
957
958 loop_count = 0;
959 do {
960 if ((result == THREAD_INTERRUPTED) && (thread->state & TH_UNINT))
961 return KERN_FAILURE;
962
963 if (wq != WAIT_QUEUE_NULL) {
964 if (wait_queue_lock_try(wq)) {
965 wait_queue_pull_thread_locked(wq, thread, TRUE);
966 /* wait queue unlocked, thread still locked */
967 } else {
968 thread_unlock(thread);
969 delay(1);
970 thread_lock(thread);
971
972 if (wq != thread->wait_queue) {
973 return KERN_NOT_WAITING; /* we know it moved */
974 }
975 continue;
976 }
1c79356b 977 }
9bccf70c
A
978 ret = thread_go_locked(thread, result);
979 return ret;
980 } while (++loop_count < LockTimeOut);
981 panic("clear_wait_internal: deadlock: thread=0x%x, wq=0x%x, cpu=%d\n",
982 thread, wq, cpu_number());
983 return KERN_FAILURE;
1c79356b
A
984}
985
986
987/*
988 * clear_wait:
989 *
990 * Clear the wait condition for the specified thread. Start the thread
991 * executing if that is appropriate.
992 *
993 * parameters:
994 * thread thread to awaken
995 * result Wakeup result the thread should see
996 */
9bccf70c 997kern_return_t
1c79356b 998clear_wait(
9bccf70c
A
999 thread_t thread,
1000 wait_result_t result)
1c79356b 1001{
9bccf70c 1002 kern_return_t ret;
1c79356b
A
1003 spl_t s;
1004
1005 s = splsched();
1006 thread_lock(thread);
9bccf70c 1007 ret = clear_wait_internal(thread, result);
1c79356b
A
1008 thread_unlock(thread);
1009 splx(s);
9bccf70c 1010 return ret;
1c79356b
A
1011}
1012
1013
1014/*
1015 * thread_wakeup_prim:
1016 *
1017 * Common routine for thread_wakeup, thread_wakeup_with_result,
1018 * and thread_wakeup_one.
1019 *
1020 */
9bccf70c 1021kern_return_t
1c79356b
A
1022thread_wakeup_prim(
1023 event_t event,
1024 boolean_t one_thread,
9bccf70c 1025 wait_result_t result)
1c79356b
A
1026{
1027 register wait_queue_t wq;
1028 register int index;
1029
1030 index = wait_hash(event);
1031 wq = &wait_queues[index];
1032 if (one_thread)
9bccf70c 1033 return (wait_queue_wakeup_one(wq, event, result));
1c79356b 1034 else
9bccf70c 1035 return (wait_queue_wakeup_all(wq, event, result));
1c79356b
A
1036}
1037
1038/*
1039 * thread_bind:
1040 *
1041 * Force a thread to execute on the specified processor.
1042 * If the thread is currently executing, it may wait until its
1043 * time slice is up before switching onto the specified processor.
1044 *
1045 * A processor of PROCESSOR_NULL causes the thread to be unbound.
1046 * xxx - DO NOT export this to users.
1047 */
1048void
1049thread_bind(
1050 register thread_t thread,
1051 processor_t processor)
1052{
1053 spl_t s;
1054
1055 s = splsched();
1056 thread_lock(thread);
1057 thread_bind_locked(thread, processor);
1058 thread_unlock(thread);
1059 splx(s);
1060}
1061
1062/*
1063 * Select a thread for this processor (the current processor) to run.
1064 * May select the current thread, which must already be locked.
1065 */
1066thread_t
1067thread_select(
1068 register processor_t myprocessor)
1069{
1070 register thread_t thread;
1071 processor_set_t pset;
1072 register run_queue_t runq = &myprocessor->runq;
1073 boolean_t other_runnable;
1c79356b
A
1074
1075 /*
1076 * Check for other non-idle runnable threads.
1077 */
1c79356b 1078 pset = myprocessor->processor_set;
9bccf70c 1079 thread = myprocessor->cpu_data->active_thread;
0b4e3aa0
A
1080
1081 /* Update the thread's priority */
1082 if (thread->sched_stamp != sched_tick)
1083 update_priority(thread);
1c79356b 1084
9bccf70c
A
1085 myprocessor->current_pri = thread->sched_pri;
1086
1c79356b
A
1087 simple_lock(&runq->lock);
1088 simple_lock(&pset->runq.lock);
1089
1090 other_runnable = runq->count > 0 || pset->runq.count > 0;
1091
1092 if ( thread->state == TH_RUN &&
1093 (!other_runnable ||
1094 (runq->highq < thread->sched_pri &&
1095 pset->runq.highq < thread->sched_pri)) &&
1096 thread->processor_set == pset &&
1097 (thread->bound_processor == PROCESSOR_NULL ||
1098 thread->bound_processor == myprocessor) ) {
1099
1100 /* I am the highest priority runnable (non-idle) thread */
1101 simple_unlock(&pset->runq.lock);
1102 simple_unlock(&runq->lock);
1103
0b4e3aa0
A
1104 myprocessor->slice_quanta =
1105 (thread->sched_mode & TH_MODE_TIMESHARE)? pset->set_quanta: 1;
1c79356b
A
1106 }
1107 else
9bccf70c 1108 if (other_runnable)
1c79356b 1109 thread = choose_thread(myprocessor);
1c79356b
A
1110 else {
1111 simple_unlock(&pset->runq.lock);
1112 simple_unlock(&runq->lock);
1113
1114 /*
1115 * Nothing is runnable, so set this processor idle if it
1116 * was running. If it was in an assignment or shutdown,
1117 * leave it alone. Return its idle thread.
1118 */
9bccf70c 1119 simple_lock(&pset->sched_lock);
1c79356b 1120 if (myprocessor->state == PROCESSOR_RUNNING) {
9bccf70c 1121 remqueue(&pset->active_queue, (queue_entry_t)myprocessor);
1c79356b 1122 myprocessor->state = PROCESSOR_IDLE;
9bccf70c 1123
1c79356b 1124 if (myprocessor == master_processor)
9bccf70c 1125 enqueue_tail(&pset->idle_queue, (queue_entry_t)myprocessor);
1c79356b 1126 else
9bccf70c 1127 enqueue_head(&pset->idle_queue, (queue_entry_t)myprocessor);
1c79356b
A
1128
1129 pset->idle_count++;
1130 }
9bccf70c 1131 simple_unlock(&pset->sched_lock);
1c79356b
A
1132
1133 thread = myprocessor->idle_thread;
1134 }
1135
1136 return (thread);
1137}
1138
1139
1140/*
1141 * Stop running the current thread and start running the new thread.
1142 * If continuation is non-zero, and the current thread is blocked,
1143 * then it will resume by executing continuation on a new stack.
1144 * Returns TRUE if the hand-off succeeds.
9bccf70c 1145 *
1c79356b
A
1146 * Assumes splsched.
1147 */
1148
1c79356b
A
1149static thread_t
1150__current_thread(void)
1151{
1152 return (current_thread());
1153}
1154
1155boolean_t
1156thread_invoke(
1157 register thread_t old_thread,
1158 register thread_t new_thread,
1159 int reason,
9bccf70c 1160 thread_continue_t old_cont)
1c79356b 1161{
9bccf70c
A
1162 thread_continue_t new_cont;
1163 processor_t processor;
1c79356b 1164
9bccf70c 1165 if (get_preemption_level() != 0)
0b4e3aa0 1166 panic("thread_invoke: preemption_level %d\n",
9bccf70c 1167 get_preemption_level());
0b4e3aa0 1168
1c79356b 1169 /*
9bccf70c 1170 * Mark thread interruptible.
1c79356b
A
1171 */
1172 thread_lock(new_thread);
1173 new_thread->state &= ~TH_UNINT;
1174
1c79356b
A
1175 assert(thread_runnable(new_thread));
1176
9bccf70c 1177 assert(old_thread->continuation == NULL);
1c79356b 1178
9bccf70c
A
1179 /*
1180 * Allow time constraint threads to hang onto
1181 * a stack.
1182 */
0b4e3aa0
A
1183 if ( (old_thread->sched_mode & TH_MODE_REALTIME) &&
1184 !old_thread->stack_privilege ) {
1185 old_thread->stack_privilege = old_thread->kernel_stack;
1c79356b
A
1186 }
1187
9bccf70c
A
1188 if (old_cont != NULL) {
1189 if (new_thread->state & TH_STACK_HANDOFF) {
1190 /*
1191 * If the old thread is using a privileged stack,
1192 * check to see whether we can exchange it with
1193 * that of the new thread.
1194 */
1195 if ( old_thread->kernel_stack == old_thread->stack_privilege &&
1196 !new_thread->stack_privilege)
1197 goto need_stack;
1c79356b 1198
9bccf70c
A
1199 new_thread->state &= ~TH_STACK_HANDOFF;
1200 new_cont = new_thread->continuation;
1201 new_thread->continuation = NULL;
1c79356b 1202
9bccf70c
A
1203 /*
1204 * Set up ast context of new thread and switch
1205 * to its timer.
1206 */
1207 processor = current_processor();
1208 new_thread->last_processor = processor;
1209 processor->current_pri = new_thread->sched_pri;
1210 ast_context(new_thread->top_act, processor->slot_num);
1211 timer_switch(&new_thread->system_timer);
1212 thread_unlock(new_thread);
0b4e3aa0 1213
9bccf70c 1214 current_task()->csw++;
1c79356b 1215
9bccf70c
A
1216 old_thread->reason = reason;
1217 old_thread->continuation = old_cont;
0b4e3aa0 1218
9bccf70c 1219 _mk_sp_thread_done(old_thread, new_thread, processor);
1c79356b 1220
9bccf70c
A
1221 stack_handoff(old_thread, new_thread);
1222
1223 _mk_sp_thread_begin(new_thread, processor);
1c79356b 1224
1c79356b
A
1225 wake_lock(old_thread);
1226 thread_lock(old_thread);
1c79356b 1227
9bccf70c
A
1228 /*
1229 * Inline thread_dispatch but
1230 * don't free stack.
1231 */
1232
1233 switch (old_thread->state & (TH_RUN|TH_WAIT|TH_UNINT|TH_IDLE)) {
1234
1235 case TH_RUN | TH_UNINT:
1236 case TH_RUN:
1237 /*
1238 * Still running, put back
1239 * onto a run queue.
1240 */
1241 old_thread->state |= TH_STACK_HANDOFF;
1242 _mk_sp_thread_dispatch(old_thread);
1243
1244 thread_unlock(old_thread);
1245 wake_unlock(old_thread);
1246 break;
1c79356b 1247
9bccf70c
A
1248 case TH_RUN | TH_WAIT | TH_UNINT:
1249 case TH_RUN | TH_WAIT:
1250 {
1251 boolean_t reap, wake, callblock;
1c79356b 1252
9bccf70c
A
1253 /*
1254 * Waiting.
1255 */
1256 old_thread->sleep_stamp = sched_tick;
1257 old_thread->state |= TH_STACK_HANDOFF;
1258 old_thread->state &= ~TH_RUN;
1259 hw_atomic_sub(&old_thread->processor_set->run_count, 1);
1260 callblock = old_thread->active_callout;
1261 wake = old_thread->wake_active;
1262 old_thread->wake_active = FALSE;
1263 reap = (old_thread->state & TH_TERMINATE)? TRUE: FALSE;
1264
1265 thread_unlock(old_thread);
1266 wake_unlock(old_thread);
1267
1268 if (callblock)
1269 call_thread_block();
1270
1271 if (wake)
1272 thread_wakeup((event_t)&old_thread->wake_active);
1273
1274 if (reap)
1275 thread_reaper_enqueue(old_thread);
1276 break;
1277 }
1c79356b 1278
9bccf70c
A
1279 case TH_RUN | TH_IDLE:
1280 /*
1281 * The idle threads don't go
1282 * onto a run queue.
1283 */
1284 old_thread->state |= TH_STACK_HANDOFF;
1285 thread_unlock(old_thread);
1286 wake_unlock(old_thread);
1287 break;
1c79356b 1288
9bccf70c
A
1289 default:
1290 panic("thread_invoke: state 0x%x\n", old_thread->state);
1291 }
1c79356b 1292
9bccf70c 1293 counter_always(c_thread_invoke_hits++);
1c79356b 1294
9bccf70c
A
1295 if (new_thread->funnel_state & TH_FN_REFUNNEL) {
1296 kern_return_t wait_result = new_thread->wait_result;
1c79356b 1297
9bccf70c
A
1298 new_thread->funnel_state = 0;
1299 KERNEL_DEBUG(0x6032428 | DBG_FUNC_NONE,
1300 new_thread->funnel_lock, 2, 0, 0, 0);
1301 funnel_lock(new_thread->funnel_lock);
1302 KERNEL_DEBUG(0x6032430 | DBG_FUNC_NONE,
1303 new_thread->funnel_lock, 2, 0, 0, 0);
1304 new_thread->funnel_state = TH_FN_OWNED;
1305 new_thread->wait_result = wait_result;
1306 }
1307 (void) spllo();
1c79356b 1308
9bccf70c
A
1309 assert(new_cont);
1310 call_continuation(new_cont);
1311 /*NOTREACHED*/
1312 return (TRUE);
1c79356b 1313 }
9bccf70c
A
1314 else
1315 if (new_thread->state & TH_STACK_ALLOC) {
1316 /*
1317 * Waiting for a stack
1318 */
1c79356b 1319 counter_always(c_thread_invoke_misses++);
9bccf70c
A
1320 thread_unlock(new_thread);
1321 return (FALSE);
1322 }
1323 else
1324 if (new_thread == old_thread) {
1325 /* same thread but with continuation */
1326 counter(++c_thread_invoke_same);
1327 thread_unlock(new_thread);
1328
1329 if (new_thread->funnel_state & TH_FN_REFUNNEL) {
1330 kern_return_t wait_result = new_thread->wait_result;
1331
1332 new_thread->funnel_state = 0;
1333 KERNEL_DEBUG(0x6032428 | DBG_FUNC_NONE,
1334 new_thread->funnel_lock, 3, 0, 0, 0);
1335 funnel_lock(new_thread->funnel_lock);
1336 KERNEL_DEBUG(0x6032430 | DBG_FUNC_NONE,
1337 new_thread->funnel_lock, 3, 0, 0, 0);
1338 new_thread->funnel_state = TH_FN_OWNED;
1339 new_thread->wait_result = wait_result;
1340 }
1341 (void) spllo();
1342 call_continuation(old_cont);
1343 /*NOTREACHED*/
1344 }
1c79356b 1345 }
9bccf70c
A
1346 else {
1347 /*
1348 * Check that the new thread has a stack
1349 */
1350 if (new_thread->state & TH_STACK_HANDOFF) {
1351need_stack:
1352 if (!stack_alloc_try(new_thread, thread_continue)) {
1353 counter_always(c_thread_invoke_misses++);
1354 thread_swapin(new_thread);
1355 return (FALSE);
1356 }
1c79356b 1357
9bccf70c
A
1358 new_thread->state &= ~TH_STACK_HANDOFF;
1359 }
1360 else
1361 if (new_thread->state & TH_STACK_ALLOC) {
1362 /*
1363 * Waiting for a stack
1364 */
1365 counter_always(c_thread_invoke_misses++);
1366 thread_unlock(new_thread);
1367 return (FALSE);
1368 }
1369 else
1370 if (old_thread == new_thread) {
1371 counter(++c_thread_invoke_same);
1372 thread_unlock(new_thread);
1373 return (TRUE);
1374 }
1375 }
1c79356b
A
1376
1377 /*
9bccf70c 1378 * Set up ast context of new thread and switch to its timer.
1c79356b 1379 */
9bccf70c
A
1380 processor = current_processor();
1381 new_thread->last_processor = processor;
1382 processor->current_pri = new_thread->sched_pri;
1383 ast_context(new_thread->top_act, processor->slot_num);
1c79356b
A
1384 timer_switch(&new_thread->system_timer);
1385 assert(thread_runnable(new_thread));
1c79356b
A
1386 thread_unlock(new_thread);
1387
1388 counter_always(c_thread_invoke_csw++);
1389 current_task()->csw++;
1390
1c79356b 1391 assert(old_thread->runq == RUN_QUEUE_NULL);
9bccf70c
A
1392 old_thread->reason = reason;
1393 old_thread->continuation = old_cont;
1c79356b 1394
9bccf70c 1395 _mk_sp_thread_done(old_thread, new_thread, processor);
1c79356b
A
1396
1397 /*
1398 * switch_context is machine-dependent. It does the
1399 * machine-dependent components of a context-switch, like
1400 * changing address spaces. It updates active_threads.
1401 */
9bccf70c 1402 old_thread = switch_context(old_thread, old_cont, new_thread);
1c79356b
A
1403
1404 /* Now on new thread's stack. Set a local variable to refer to it. */
1405 new_thread = __current_thread();
1406 assert(old_thread != new_thread);
1407
1c79356b 1408 assert(thread_runnable(new_thread));
9bccf70c 1409 _mk_sp_thread_begin(new_thread, new_thread->last_processor);
1c79356b
A
1410
1411 /*
1412 * We're back. Now old_thread is the thread that resumed
1413 * us, and we have to dispatch it.
1414 */
1c79356b 1415 thread_dispatch(old_thread);
9bccf70c
A
1416
1417 if (old_cont) {
1418 if (new_thread->funnel_state & TH_FN_REFUNNEL) {
1419 kern_return_t wait_result = new_thread->wait_result;
1420
1421 new_thread->funnel_state = 0;
1422 KERNEL_DEBUG(0x6032428 | DBG_FUNC_NONE,
1423 new_thread->funnel_lock, 3, 0, 0, 0);
1424 funnel_lock(new_thread->funnel_lock);
1425 KERNEL_DEBUG(0x6032430 | DBG_FUNC_NONE,
1426 new_thread->funnel_lock, 3, 0, 0, 0);
1427 new_thread->funnel_state = TH_FN_OWNED;
1428 new_thread->wait_result = wait_result;
1429 }
1430 (void) spllo();
1431 call_continuation(old_cont);
1432 /*NOTREACHED*/
1c79356b
A
1433 }
1434
9bccf70c 1435 return (TRUE);
1c79356b
A
1436}
1437
1438/*
1439 * thread_continue:
1440 *
9bccf70c 1441 * Called when a thread gets a new stack, at splsched();
1c79356b
A
1442 */
1443void
1444thread_continue(
0b4e3aa0 1445 register thread_t old_thread)
1c79356b 1446{
9bccf70c
A
1447 register thread_t self = current_thread();
1448 register thread_continue_t continuation;
1449
1450 continuation = self->continuation;
1451 self->continuation = NULL;
1452
1453 _mk_sp_thread_begin(self, self->last_processor);
1c79356b
A
1454
1455 /*
1456 * We must dispatch the old thread and then
1457 * call the current thread's continuation.
1458 * There might not be an old thread, if we are
1459 * the first thread to run on this processor.
1460 */
0b4e3aa0 1461 if (old_thread != THREAD_NULL)
1c79356b 1462 thread_dispatch(old_thread);
1c79356b
A
1463
1464 if (self->funnel_state & TH_FN_REFUNNEL) {
9bccf70c 1465 kern_return_t wait_result = self->wait_result;
0b4e3aa0
A
1466
1467 self->funnel_state = 0;
0b4e3aa0
A
1468 KERNEL_DEBUG(0x6032428 | DBG_FUNC_NONE, self->funnel_lock, 4, 0, 0, 0);
1469 funnel_lock(self->funnel_lock);
1470 KERNEL_DEBUG(0x6032430 | DBG_FUNC_NONE, self->funnel_lock, 4, 0, 0, 0);
0b4e3aa0 1471 self->funnel_state = TH_FN_OWNED;
9bccf70c 1472 self->wait_result = wait_result;
1c79356b 1473 }
9bccf70c 1474 (void)spllo();
1c79356b 1475 assert(continuation);
9bccf70c 1476 call_continuation(continuation);
1c79356b
A
1477 /*NOTREACHED*/
1478}
1479
1480#if MACH_LDEBUG || MACH_KDB
1481
1482#define THREAD_LOG_SIZE 300
1483
1484struct t64 {
1485 unsigned long h;
1486 unsigned long l;
1487};
1488
1489struct {
1490 struct t64 stamp;
1491 thread_t thread;
1492 long info1;
1493 long info2;
1494 long info3;
1495 char * action;
1496} thread_log[THREAD_LOG_SIZE];
1497
1498int thread_log_index;
1499
1500void check_thread_time(long n);
1501
1502
1503int check_thread_time_crash;
1504
1505#if 0
1506void
1507check_thread_time(long us)
1508{
1509 struct t64 temp;
1510
1511 if (!check_thread_time_crash)
1512 return;
1513
1514 temp = thread_log[0].stamp;
1515 cyctm05_diff (&thread_log[1].stamp, &thread_log[0].stamp, &temp);
1516
1517 if (temp.l >= us && thread_log[1].info != 0x49) /* HACK!!! */
1518 panic ("check_thread_time");
1519}
1520#endif
1521
1522void
1523log_thread_action(char * action, long info1, long info2, long info3)
1524{
1525 int i;
1526 spl_t x;
1527 static unsigned int tstamp;
1528
1529 x = splhigh();
1530
1531 for (i = THREAD_LOG_SIZE-1; i > 0; i--) {
1532 thread_log[i] = thread_log[i-1];
1533 }
1534
1535 thread_log[0].stamp.h = 0;
1536 thread_log[0].stamp.l = tstamp++;
1537 thread_log[0].thread = current_thread();
1538 thread_log[0].info1 = info1;
1539 thread_log[0].info2 = info2;
1540 thread_log[0].info3 = info3;
1541 thread_log[0].action = action;
1542/* strcpy (&thread_log[0].action[0], action);*/
1543
1544 splx(x);
1545}
1546#endif /* MACH_LDEBUG || MACH_KDB */
1547
1548#if MACH_KDB
1549#include <ddb/db_output.h>
1550void db_show_thread_log(void);
1551
1552void
1553db_show_thread_log(void)
1554{
1555 int i;
1556
1557 db_printf ("%s %s %s %s %s %s\n", " Thread ", " Info1 ", " Info2 ",
1558 " Info3 ", " Timestamp ", "Action");
1559
1560 for (i = 0; i < THREAD_LOG_SIZE; i++) {
1561 db_printf ("%08x %08x %08x %08x %08x/%08x %s\n",
1562 thread_log[i].thread,
1563 thread_log[i].info1,
1564 thread_log[i].info2,
1565 thread_log[i].info3,
1566 thread_log[i].stamp.h,
1567 thread_log[i].stamp.l,
1568 thread_log[i].action);
1569 }
1570}
1571#endif /* MACH_KDB */
1572
1573/*
1574 * thread_block_reason:
1575 *
0b4e3aa0
A
1576 * Block the current thread if a wait has been asserted,
1577 * otherwise unconditionally yield the remainder of the
1578 * current quantum unless reason contains AST_BLOCK.
1579 *
1c79356b
A
1580 * If a continuation is specified, then thread_block will
1581 * attempt to discard the thread's kernel stack. When the
1582 * thread resumes, it will execute the continuation function
1583 * on a new kernel stack.
1584 */
1585counter(mach_counter_t c_thread_block_calls = 0;)
1586
1587int
1588thread_block_reason(
9bccf70c
A
1589 thread_continue_t continuation,
1590 ast_t reason)
1c79356b
A
1591{
1592 register thread_t thread = current_thread();
1593 register processor_t myprocessor;
1594 register thread_t new_thread;
1595 spl_t s;
1596
1597 counter(++c_thread_block_calls);
1598
1599 check_simple_locks();
1600
1601 machine_clock_assist();
1602
1603 s = splsched();
1604
1605 if ((thread->funnel_state & TH_FN_OWNED) && !(reason & AST_PREEMPT)) {
9bccf70c
A
1606 thread->funnel_state = TH_FN_REFUNNEL;
1607 KERNEL_DEBUG(
1608 0x603242c | DBG_FUNC_NONE, thread->funnel_lock, 2, 0, 0, 0);
1609 funnel_unlock(thread->funnel_lock);
1c79356b
A
1610 }
1611
1612 myprocessor = current_processor();
1613
9bccf70c
A
1614 /* If we're explicitly yielding, force a subsequent quantum */
1615 if (reason & AST_YIELD)
0b4e3aa0
A
1616 myprocessor->slice_quanta = 0;
1617
9bccf70c
A
1618 /* We're handling all scheduling AST's */
1619 ast_off(AST_SCHEDULING);
1c79356b 1620
9bccf70c 1621 thread_lock(thread);
1c79356b 1622 new_thread = thread_select(myprocessor);
9bccf70c 1623 assert(new_thread && thread_runnable(new_thread));
1c79356b
A
1624 thread_unlock(thread);
1625 while (!thread_invoke(thread, new_thread, reason, continuation)) {
1626 thread_lock(thread);
1627 new_thread = thread_select(myprocessor);
9bccf70c 1628 assert(new_thread && thread_runnable(new_thread));
1c79356b
A
1629 thread_unlock(thread);
1630 }
1631
1632 if (thread->funnel_state & TH_FN_REFUNNEL) {
9bccf70c 1633 kern_return_t wait_result = thread->wait_result;
1c79356b 1634
1c79356b 1635 thread->funnel_state = 0;
9bccf70c
A
1636 KERNEL_DEBUG(
1637 0x6032428 | DBG_FUNC_NONE, thread->funnel_lock, 5, 0, 0, 0);
1c79356b 1638 funnel_lock(thread->funnel_lock);
9bccf70c
A
1639 KERNEL_DEBUG(
1640 0x6032430 | DBG_FUNC_NONE, thread->funnel_lock, 5, 0, 0, 0);
1c79356b 1641 thread->funnel_state = TH_FN_OWNED;
9bccf70c 1642 thread->wait_result = wait_result;
1c79356b
A
1643 }
1644
1645 splx(s);
1646
9bccf70c 1647 return (thread->wait_result);
1c79356b
A
1648}
1649
1650/*
1651 * thread_block:
1652 *
9bccf70c 1653 * Block the current thread if a wait has been asserted.
1c79356b
A
1654 */
1655int
1656thread_block(
9bccf70c 1657 thread_continue_t continuation)
1c79356b 1658{
0b4e3aa0 1659 return thread_block_reason(continuation, AST_NONE);
1c79356b
A
1660}
1661
1662/*
1663 * thread_run:
1664 *
9bccf70c
A
1665 * Switch directly from the current (old) thread to the
1666 * specified thread, handing off our quantum if possible.
1667 *
1668 * New thread must be runnable, and not on a run queue.
1c79356b
A
1669 *
1670 * Assumption:
1671 * at splsched.
1672 */
1673int
1674thread_run(
9bccf70c
A
1675 thread_t old_thread,
1676 thread_continue_t continuation,
1677 thread_t new_thread)
1c79356b 1678{
9bccf70c
A
1679 ast_t handoff = AST_HANDOFF;
1680
1681 assert(old_thread == current_thread());
1682
1683 machine_clock_assist();
1684
1685 if (old_thread->funnel_state & TH_FN_OWNED) {
1686 old_thread->funnel_state = TH_FN_REFUNNEL;
1687 KERNEL_DEBUG(
1688 0x603242c | DBG_FUNC_NONE, old_thread->funnel_lock, 3, 0, 0, 0);
1689 funnel_unlock(old_thread->funnel_lock);
1690 }
1691
1692 while (!thread_invoke(old_thread, new_thread, handoff, continuation)) {
1693 register processor_t myprocessor = current_processor();
1694
1c79356b
A
1695 thread_lock(old_thread);
1696 new_thread = thread_select(myprocessor);
1697 thread_unlock(old_thread);
9bccf70c
A
1698 handoff = AST_NONE;
1699 }
1700
1701 /* if we fell thru */
1702 if (old_thread->funnel_state & TH_FN_REFUNNEL) {
1703 kern_return_t wait_result = old_thread->wait_result;
1704
1705 old_thread->funnel_state = 0;
1706 KERNEL_DEBUG(
1707 0x6032428 | DBG_FUNC_NONE, old_thread->funnel_lock, 6, 0, 0, 0);
1708 funnel_lock(old_thread->funnel_lock);
1709 KERNEL_DEBUG(
1710 0x6032430 | DBG_FUNC_NONE, old_thread->funnel_lock, 6, 0, 0, 0);
1711 old_thread->funnel_state = TH_FN_OWNED;
1712 old_thread->wait_result = wait_result;
1c79356b 1713 }
9bccf70c
A
1714
1715 return (old_thread->wait_result);
1c79356b
A
1716}
1717
1718/*
1719 * Dispatches a running thread that is not on a runq.
1720 * Called at splsched.
1721 */
1722void
1723thread_dispatch(
1724 register thread_t thread)
1725{
9bccf70c
A
1726 wake_lock(thread);
1727 thread_lock(thread);
1728
1c79356b
A
1729 /*
1730 * If we are discarding the thread's stack, we must do it
1731 * before the thread has a chance to run.
1732 */
1c79356b 1733#ifndef i386
9bccf70c
A
1734 if (thread->continuation != NULL) {
1735 assert((thread->state & TH_STACK_STATE) == 0);
1736 thread->state |= TH_STACK_HANDOFF;
1737 stack_free(thread);
1738 }
1c79356b
A
1739#endif
1740
1741 switch (thread->state & (TH_RUN|TH_WAIT|TH_UNINT|TH_IDLE)) {
1742
1743 case TH_RUN | TH_UNINT:
1744 case TH_RUN:
1745 /*
1746 * No reason to stop. Put back on a run queue.
1747 */
0b4e3aa0 1748 _mk_sp_thread_dispatch(thread);
1c79356b
A
1749 break;
1750
1751 case TH_RUN | TH_WAIT | TH_UNINT:
1752 case TH_RUN | TH_WAIT:
9bccf70c
A
1753 {
1754 boolean_t reap, wake, callblock;
1c79356b
A
1755
1756 /*
1757 * Waiting
1758 */
9bccf70c 1759 thread->sleep_stamp = sched_tick;
1c79356b 1760 thread->state &= ~TH_RUN;
9bccf70c
A
1761 hw_atomic_sub(&thread->processor_set->run_count, 1);
1762 callblock = thread->active_callout;
1763 wake = thread->wake_active;
1764 thread->wake_active = FALSE;
1765 reap = (thread->state & TH_TERMINATE)? TRUE: FALSE;
1c79356b 1766
9bccf70c
A
1767 thread_unlock(thread);
1768 wake_unlock(thread);
1769
1770 if (callblock)
1771 call_thread_block();
1772
1773 if (wake)
1c79356b 1774 thread_wakeup((event_t)&thread->wake_active);
9bccf70c
A
1775
1776 if (reap)
1777 thread_reaper_enqueue(thread);
1778
1779 return;
1780 }
1c79356b
A
1781
1782 case TH_RUN | TH_IDLE:
1783 /*
9bccf70c
A
1784 * The idle threads don't go
1785 * onto a run queue.
1c79356b
A
1786 */
1787 break;
1788
1789 default:
9bccf70c 1790 panic("thread_dispatch: bad thread state 0x%x\n", thread->state);
1c79356b 1791 }
9bccf70c 1792
1c79356b
A
1793 thread_unlock(thread);
1794 wake_unlock(thread);
1795}
1796
1797/*
1798 * Enqueue thread on run queue. Thread must be locked,
9bccf70c
A
1799 * and not already be on a run queue. Returns TRUE iff
1800 * the particular queue level was empty beforehand.
1c79356b 1801 */
9bccf70c 1802boolean_t
1c79356b
A
1803run_queue_enqueue(
1804 register run_queue_t rq,
1805 register thread_t thread,
1806 boolean_t tail)
1807{
9bccf70c
A
1808 register int whichq = thread->sched_pri;
1809 register queue_t queue = &rq->queues[whichq];
1810 boolean_t result = FALSE;
1c79356b 1811
1c79356b
A
1812 assert(whichq >= MINPRI && whichq <= MAXPRI);
1813
9bccf70c 1814 simple_lock(&rq->lock);
1c79356b 1815 assert(thread->runq == RUN_QUEUE_NULL);
9bccf70c
A
1816 if (queue_empty(queue)) {
1817 enqueue_tail(queue, (queue_entry_t)thread);
1818
1819 setbit(MAXPRI - whichq, rq->bitmap);
1820 if (whichq > rq->highq)
1821 rq->highq = whichq;
1822 result = TRUE;
1823 }
1824 else
1c79356b 1825 if (tail)
9bccf70c 1826 enqueue_tail(queue, (queue_entry_t)thread);
1c79356b 1827 else
9bccf70c 1828 enqueue_head(queue, (queue_entry_t)thread);
1c79356b 1829
1c79356b 1830 thread->runq = rq;
9bccf70c
A
1831 if (thread->sched_mode & TH_MODE_PREEMPT)
1832 rq->urgency++;
1833 rq->count++;
1c79356b
A
1834#if DEBUG
1835 thread_check(thread, rq);
1836#endif /* DEBUG */
1837 simple_unlock(&rq->lock);
1838
9bccf70c 1839 return (result);
1c79356b
A
1840}
1841
9bccf70c
A
1842struct {
1843 uint32_t pset_idle_last,
1844 pset_idle_any,
1845 pset_self,
1846 pset_last,
1847 pset_other,
1848 bound_idle,
1849 bound_self,
1850 bound_other;
1851} dispatch_counts;
1852
1c79356b
A
1853/*
1854 * thread_setrun:
1855 *
9bccf70c
A
1856 * Dispatch thread for execution, directly onto an idle
1857 * processor if possible. Else put on appropriate run
1858 * queue. (local if bound, else processor set)
1859 *
1860 * Thread must be locked.
1861 *
1862 * The tail parameter indicates the proper placement of
1863 * the thread on a run queue.
1c79356b
A
1864 */
1865void
1866thread_setrun(
1867 register thread_t new_thread,
1c79356b
A
1868 boolean_t tail)
1869{
1870 register processor_t processor;
1c79356b 1871 register processor_set_t pset;
9bccf70c
A
1872 register thread_t thread;
1873 boolean_t try_preempt = FALSE;
1874 ast_t preempt = AST_BLOCK;
1c79356b 1875
1c79356b
A
1876 assert(thread_runnable(new_thread));
1877
1878 /*
1879 * Update priority if needed.
1880 */
1881 if (new_thread->sched_stamp != sched_tick)
1882 update_priority(new_thread);
1883
1c79356b 1884 /*
9bccf70c 1885 * Check for urgent preemption.
1c79356b 1886 */
9bccf70c
A
1887 if (new_thread->sched_mode & TH_MODE_PREEMPT)
1888 preempt |= AST_URGENT;
1889
1890 assert(new_thread->runq == RUN_QUEUE_NULL);
1891
1c79356b
A
1892 if ((processor = new_thread->bound_processor) == PROCESSOR_NULL) {
1893 /*
9bccf70c
A
1894 * First try to dispatch on
1895 * the last processor.
1c79356b
A
1896 */
1897 pset = new_thread->processor_set;
9bccf70c
A
1898 processor = new_thread->last_processor;
1899 if ( pset->processor_count > 1 &&
1900 processor != PROCESSOR_NULL &&
1901 processor->state == PROCESSOR_IDLE ) {
1902 simple_lock(&processor->lock);
1903 simple_lock(&pset->sched_lock);
1904 if ( processor->processor_set == pset &&
1905 processor->state == PROCESSOR_IDLE ) {
1906 remqueue(&pset->idle_queue, (queue_entry_t)processor);
1c79356b
A
1907 pset->idle_count--;
1908 processor->next_thread = new_thread;
1909 processor->state = PROCESSOR_DISPATCHING;
9bccf70c
A
1910 simple_unlock(&pset->sched_lock);
1911 simple_unlock(&processor->lock);
1912 if (processor != current_processor())
1c79356b 1913 machine_signal_idle(processor);
9bccf70c 1914 dispatch_counts.pset_idle_last++;
1c79356b
A
1915 return;
1916 }
9bccf70c
A
1917 simple_unlock(&processor->lock);
1918 }
1919 else
1920 simple_lock(&pset->sched_lock);
1921
1922 /*
1923 * Next pick any idle processor
1924 * in the processor set.
1925 */
1926 if (pset->idle_count > 0) {
1927 processor = (processor_t)dequeue_head(&pset->idle_queue);
1928 pset->idle_count--;
1929 processor->next_thread = new_thread;
1930 processor->state = PROCESSOR_DISPATCHING;
1931 simple_unlock(&pset->sched_lock);
1932 if (processor != current_processor())
1933 machine_signal_idle(processor);
1934 dispatch_counts.pset_idle_any++;
1935 return;
1936 }
1c79356b 1937
0b4e3aa0 1938 /*
9bccf70c 1939 * Place thread on run queue.
0b4e3aa0 1940 */
9bccf70c
A
1941 if (run_queue_enqueue(&pset->runq, new_thread, tail))
1942 try_preempt = TRUE;
1943
1944 /*
1945 * Update the timesharing quanta.
1946 */
1947 pset_quanta_update(pset);
0b4e3aa0 1948
1c79356b 1949 /*
9bccf70c 1950 * Preempt check.
1c79356b 1951 */
1c79356b 1952 processor = current_processor();
9bccf70c
A
1953 thread = processor->cpu_data->active_thread;
1954 if (try_preempt) {
1955 /*
1956 * First try the current processor
1957 * if it is a member of the correct
1958 * processor set.
1c79356b 1959 */
9bccf70c
A
1960 if ( pset == processor->processor_set &&
1961 csw_needed(thread, processor) ) {
1962 simple_unlock(&pset->sched_lock);
1963
1964 ast_on(preempt);
1965 dispatch_counts.pset_self++;
1966 return;
1967 }
1968
1969 /*
1970 * If that failed and we have other
1971 * processors available keep trying.
1972 */
1973 if ( pset->processor_count > 1 ||
1974 pset != processor->processor_set ) {
1975 queue_t active = &pset->active_queue;
1976 processor_t myprocessor, lastprocessor;
1977 queue_entry_t next;
1978
1979 /*
1980 * Next try the last processor
1981 * dispatched on.
1982 */
1983 myprocessor = processor;
1984 processor = new_thread->last_processor;
1985 if ( processor != myprocessor &&
1986 processor != PROCESSOR_NULL &&
1987 processor->processor_set == pset &&
1988 processor->state == PROCESSOR_RUNNING &&
1989 new_thread->sched_pri > processor->current_pri ) {
1990 cause_ast_check(processor);
1991 simple_unlock(&pset->sched_lock);
1992 dispatch_counts.pset_last++;
1993 return;
1994 }
1995
1996 /*
1997 * Lastly, pick any other
1998 * available processor.
1999 */
2000 lastprocessor = processor;
2001 processor = (processor_t)queue_first(active);
2002 while (!queue_end(active, (queue_entry_t)processor)) {
2003 next = queue_next((queue_entry_t)processor);
2004
2005 if ( processor != myprocessor &&
2006 processor != lastprocessor &&
2007 new_thread->sched_pri > processor->current_pri ) {
2008 if (!queue_end(active, next)) {
2009 remqueue(active, (queue_entry_t)processor);
2010 enqueue_tail(active, (queue_entry_t)processor);
2011 }
2012 cause_ast_check(processor);
2013 simple_unlock(&pset->sched_lock);
2014 dispatch_counts.pset_other++;
2015 return;
2016 }
2017
2018 processor = (processor_t)next;
2019 }
2020 }
1c79356b 2021 }
9bccf70c
A
2022
2023 simple_unlock(&pset->sched_lock);
1c79356b
A
2024 }
2025 else {
2026 /*
2027 * Bound, can only run on bound processor. Have to lock
2028 * processor here because it may not be the current one.
2029 */
9bccf70c 2030 if (processor->state == PROCESSOR_IDLE) {
1c79356b
A
2031 simple_lock(&processor->lock);
2032 pset = processor->processor_set;
9bccf70c 2033 simple_lock(&pset->sched_lock);
1c79356b 2034 if (processor->state == PROCESSOR_IDLE) {
9bccf70c 2035 remqueue(&pset->idle_queue, (queue_entry_t)processor);
1c79356b
A
2036 pset->idle_count--;
2037 processor->next_thread = new_thread;
2038 processor->state = PROCESSOR_DISPATCHING;
9bccf70c 2039 simple_unlock(&pset->sched_lock);
1c79356b 2040 simple_unlock(&processor->lock);
9bccf70c 2041 if (processor != current_processor())
1c79356b 2042 machine_signal_idle(processor);
9bccf70c 2043 dispatch_counts.bound_idle++;
1c79356b
A
2044 return;
2045 }
9bccf70c 2046 simple_unlock(&pset->sched_lock);
1c79356b
A
2047 simple_unlock(&processor->lock);
2048 }
2049
9bccf70c
A
2050 if (run_queue_enqueue(&processor->runq, new_thread, tail))
2051 try_preempt = TRUE;
2052
2053 if (processor == current_processor()) {
2054 if (try_preempt) {
2055 thread = processor->cpu_data->active_thread;
2056 if (csw_needed(thread, processor)) {
2057 ast_on(preempt);
2058 dispatch_counts.bound_self++;
2059 }
2060 }
2061 }
1c79356b 2062 else {
9bccf70c
A
2063 if (try_preempt) {
2064 if ( processor->state == PROCESSOR_RUNNING &&
2065 new_thread->sched_pri > processor->current_pri ) {
2066 cause_ast_check(processor);
2067 dispatch_counts.bound_other++;
2068 return;
2069 }
2070 }
2071
2072 if (processor->state == PROCESSOR_IDLE) {
2073 machine_signal_idle(processor);
2074 dispatch_counts.bound_idle++;
2075 }
2076 }
2077 }
2078}
2079
2080/*
2081 * Called at splsched by a thread on itself.
2082 */
2083ast_t
2084csw_check(
2085 thread_t thread,
2086 processor_t processor)
2087{
2088 int current_pri = thread->sched_pri;
2089 ast_t result = AST_NONE;
2090 run_queue_t runq;
2091
2092 if (first_quantum(processor)) {
2093 runq = &processor->processor_set->runq;
2094 if (runq->highq > current_pri) {
2095 if (runq->urgency > 0)
2096 return (AST_BLOCK | AST_URGENT);
2097
2098 result |= AST_BLOCK;
2099 }
2100
2101 runq = &processor->runq;
2102 if (runq->highq > current_pri) {
2103 if (runq->urgency > 0)
2104 return (AST_BLOCK | AST_URGENT);
2105
2106 result |= AST_BLOCK;
2107 }
2108 }
2109 else {
2110 runq = &processor->processor_set->runq;
2111 if (runq->highq >= current_pri) {
2112 if (runq->urgency > 0)
2113 return (AST_BLOCK | AST_URGENT);
2114
2115 result |= AST_BLOCK;
2116 }
2117
2118 runq = &processor->runq;
2119 if (runq->highq >= current_pri) {
2120 if (runq->urgency > 0)
2121 return (AST_BLOCK | AST_URGENT);
2122
2123 result |= AST_BLOCK;
2124 }
1c79356b 2125 }
9bccf70c
A
2126
2127 if (result != AST_NONE)
2128 return (result);
2129
2130 if (thread->state & TH_SUSP)
2131 result |= AST_BLOCK;
2132
2133 return (result);
1c79356b
A
2134}
2135
2136/*
9bccf70c 2137 * set_sched_pri:
1c79356b 2138 *
9bccf70c
A
2139 * Set the current scheduled priority of the specified thread.
2140 * This may cause the thread to change queues.
1c79356b
A
2141 *
2142 * The thread *must* be locked by the caller.
2143 */
2144void
9bccf70c 2145set_sched_pri(
1c79356b 2146 thread_t thread,
9bccf70c 2147 int priority)
1c79356b 2148{
9bccf70c
A
2149 register struct run_queue *rq = rem_runq(thread);
2150
2151 if ( !(thread->sched_mode & TH_MODE_TIMESHARE) &&
2152 (priority >= BASEPRI_PREEMPT ||
2153 (thread->task_priority < MINPRI_KERNEL &&
2154 thread->task_priority >= BASEPRI_BACKGROUND &&
2155 priority > thread->task_priority) ||
2156 (thread->sched_mode & TH_MODE_FORCEDPREEMPT) ) )
2157 thread->sched_mode |= TH_MODE_PREEMPT;
2158 else
2159 thread->sched_mode &= ~TH_MODE_PREEMPT;
1c79356b 2160
9bccf70c
A
2161 thread->sched_pri = priority;
2162 if (rq != RUN_QUEUE_NULL)
2163 thread_setrun(thread, TAIL_Q);
2164 else
2165 if ((thread->state & (TH_RUN|TH_WAIT)) == TH_RUN) {
2166 processor_t processor = thread->last_processor;
2167
2168 if (thread == current_thread()) {
2169 ast_t preempt = csw_check(thread, processor);
2170
2171 if (preempt != AST_NONE)
2172 ast_on(preempt);
2173 processor->current_pri = priority;
2174 }
2175 else
2176 if ( processor != PROCESSOR_NULL &&
2177 processor->cpu_data->active_thread == thread )
2178 cause_ast_check(processor);
1c79356b
A
2179 }
2180}
2181
2182/*
2183 * rem_runq:
2184 *
2185 * Remove a thread from its run queue.
2186 * The run queue that the process was on is returned
2187 * (or RUN_QUEUE_NULL if not on a run queue). Thread *must* be locked
2188 * before calling this routine. Unusual locking protocol on runq
2189 * field in thread structure makes this code interesting; see thread.h.
2190 */
2191run_queue_t
2192rem_runq(
2193 thread_t thread)
2194{
2195 register struct run_queue *rq;
2196
2197 rq = thread->runq;
2198 /*
2199 * If rq is RUN_QUEUE_NULL, the thread will stay out of the
2200 * run_queues because the caller locked the thread. Otherwise
2201 * the thread is on a runq, but could leave.
2202 */
2203 if (rq != RUN_QUEUE_NULL) {
2204 simple_lock(&rq->lock);
2205 if (rq == thread->runq) {
2206 /*
2207 * Thread is in a runq and we have a lock on
2208 * that runq.
2209 */
2210#if DEBUG
2211 thread_check(thread, rq);
2212#endif /* DEBUG */
2213 remqueue(&rq->queues[0], (queue_entry_t)thread);
2214 rq->count--;
9bccf70c
A
2215 if (thread->sched_mode & TH_MODE_PREEMPT)
2216 rq->urgency--;
2217 assert(rq->urgency >= 0);
1c79356b
A
2218
2219 if (queue_empty(rq->queues + thread->sched_pri)) {
2220 /* update run queue status */
2221 if (thread->sched_pri != IDLEPRI)
2222 clrbit(MAXPRI - thread->sched_pri, rq->bitmap);
2223 rq->highq = MAXPRI - ffsbit(rq->bitmap);
2224 }
2225 thread->runq = RUN_QUEUE_NULL;
2226 simple_unlock(&rq->lock);
2227 }
2228 else {
2229 /*
2230 * The thread left the runq before we could
2231 * lock the runq. It is not on a runq now, and
2232 * can't move again because this routine's
2233 * caller locked the thread.
2234 */
2235 assert(thread->runq == RUN_QUEUE_NULL);
2236 simple_unlock(&rq->lock);
2237 rq = RUN_QUEUE_NULL;
2238 }
2239 }
2240
2241 return (rq);
2242}
2243
1c79356b
A
2244/*
2245 * choose_thread:
2246 *
2247 * Choose a thread to execute. The thread chosen is removed
2248 * from its run queue. Note that this requires only that the runq
2249 * lock be held.
2250 *
2251 * Strategy:
2252 * Check processor runq first; if anything found, run it.
2253 * Else check pset runq; if nothing found, return idle thread.
2254 *
2255 * Second line of strategy is implemented by choose_pset_thread.
9bccf70c
A
2256 *
2257 * Called with both the local & pset run queues locked, returned
2258 * unlocked.
1c79356b
A
2259 */
2260thread_t
2261choose_thread(
2262 processor_t myprocessor)
2263{
2264 thread_t thread;
2265 register queue_t q;
2266 register run_queue_t runq;
2267 processor_set_t pset;
2268
2269 runq = &myprocessor->runq;
2270 pset = myprocessor->processor_set;
2271
1c79356b 2272 if (runq->count > 0 && runq->highq >= pset->runq.highq) {
9bccf70c 2273 simple_unlock(&pset->runq.lock);
1c79356b
A
2274 q = runq->queues + runq->highq;
2275#if MACH_ASSERT
2276 if (!queue_empty(q)) {
2277#endif /*MACH_ASSERT*/
2278 thread = (thread_t)q->next;
2279 ((queue_entry_t)thread)->next->prev = q;
2280 q->next = ((queue_entry_t)thread)->next;
2281 thread->runq = RUN_QUEUE_NULL;
2282 runq->count--;
9bccf70c
A
2283 if (thread->sched_mode & TH_MODE_PREEMPT)
2284 runq->urgency--;
2285 assert(runq->urgency >= 0);
1c79356b
A
2286 if (queue_empty(q)) {
2287 if (runq->highq != IDLEPRI)
2288 clrbit(MAXPRI - runq->highq, runq->bitmap);
2289 runq->highq = MAXPRI - ffsbit(runq->bitmap);
2290 }
2291 simple_unlock(&runq->lock);
2292 return (thread);
2293#if MACH_ASSERT
2294 }
2295 panic("choose_thread");
2296#endif /*MACH_ASSERT*/
2297 /*NOTREACHED*/
2298 }
9bccf70c 2299 simple_unlock(&myprocessor->runq.lock);
1c79356b 2300
1c79356b
A
2301 return (choose_pset_thread(myprocessor, pset));
2302}
2303
1c79356b
A
2304/*
2305 * choose_pset_thread: choose a thread from processor_set runq or
2306 * set processor idle and choose its idle thread.
2307 *
1c79356b
A
2308 * This routine chooses and removes a thread from the runq if there
2309 * is one (and returns it), else it sets the processor idle and
2310 * returns its idle thread.
9bccf70c
A
2311 *
2312 * Called with both local & pset run queues locked, returned
2313 * unlocked.
1c79356b
A
2314 */
2315thread_t
2316choose_pset_thread(
2317 register processor_t myprocessor,
2318 processor_set_t pset)
2319{
2320 register run_queue_t runq;
2321 register thread_t thread;
2322 register queue_t q;
2323
2324 runq = &pset->runq;
2325 if (runq->count > 0) {
2326 q = runq->queues + runq->highq;
2327#if MACH_ASSERT
2328 if (!queue_empty(q)) {
2329#endif /*MACH_ASSERT*/
2330 thread = (thread_t)q->next;
2331 ((queue_entry_t)thread)->next->prev = q;
2332 q->next = ((queue_entry_t)thread)->next;
2333 thread->runq = RUN_QUEUE_NULL;
2334 runq->count--;
9bccf70c
A
2335 if (thread->sched_mode & TH_MODE_PREEMPT)
2336 runq->urgency--;
2337 assert(runq->urgency >= 0);
1c79356b
A
2338 if (queue_empty(q)) {
2339 if (runq->highq != IDLEPRI)
2340 clrbit(MAXPRI - runq->highq, runq->bitmap);
2341 runq->highq = MAXPRI - ffsbit(runq->bitmap);
2342 }
9bccf70c 2343 pset_quanta_update(pset);
1c79356b
A
2344 simple_unlock(&runq->lock);
2345 return (thread);
2346#if MACH_ASSERT
2347 }
2348 panic("choose_pset_thread");
2349#endif /*MACH_ASSERT*/
2350 /*NOTREACHED*/
2351 }
2352 simple_unlock(&runq->lock);
2353
2354 /*
2355 * Nothing is runnable, so set this processor idle if it
2356 * was running. If it was in an assignment or shutdown,
2357 * leave it alone. Return its idle thread.
2358 */
9bccf70c 2359 simple_lock(&pset->sched_lock);
1c79356b 2360 if (myprocessor->state == PROCESSOR_RUNNING) {
9bccf70c 2361 remqueue(&pset->active_queue, (queue_entry_t)myprocessor);
1c79356b 2362 myprocessor->state = PROCESSOR_IDLE;
9bccf70c 2363
1c79356b 2364 if (myprocessor == master_processor)
9bccf70c 2365 enqueue_tail(&pset->idle_queue, (queue_entry_t)myprocessor);
1c79356b 2366 else
9bccf70c 2367 enqueue_head(&pset->idle_queue, (queue_entry_t)myprocessor);
1c79356b
A
2368
2369 pset->idle_count++;
2370 }
9bccf70c 2371 simple_unlock(&pset->sched_lock);
1c79356b
A
2372
2373 return (myprocessor->idle_thread);
2374}
2375
2376/*
2377 * no_dispatch_count counts number of times processors go non-idle
2378 * without being dispatched. This should be very rare.
2379 */
2380int no_dispatch_count = 0;
2381
2382/*
2383 * This is the idle thread, which just looks for other threads
2384 * to execute.
2385 */
2386void
2387idle_thread_continue(void)
2388{
2389 register processor_t myprocessor;
2390 register volatile thread_t *threadp;
2391 register volatile int *gcount;
2392 register volatile int *lcount;
2393 register thread_t new_thread;
2394 register int state;
2395 register processor_set_t pset;
2396 int mycpu;
2397
2398 mycpu = cpu_number();
9bccf70c 2399 myprocessor = cpu_to_processor(mycpu);
1c79356b
A
2400 threadp = (volatile thread_t *) &myprocessor->next_thread;
2401 lcount = (volatile int *) &myprocessor->runq.count;
2402
2403 for (;;) {
1c79356b
A
2404 gcount = (volatile int *)&myprocessor->processor_set->runq.count;
2405
2406 (void)splsched();
2407 while ( (*threadp == (volatile thread_t)THREAD_NULL) &&
2408 (*gcount == 0) && (*lcount == 0) ) {
2409
2410 /* check for ASTs while we wait */
9bccf70c 2411 if (need_ast[mycpu] &~ ( AST_SCHEDULING | AST_BSD )) {
1c79356b 2412 /* don't allow scheduling ASTs */
9bccf70c 2413 need_ast[mycpu] &= ~( AST_SCHEDULING | AST_BSD );
0b4e3aa0 2414 ast_taken(AST_ALL, TRUE); /* back at spllo */
1c79356b
A
2415 }
2416 else
2417#ifdef __ppc__
2418 machine_idle();
2419#else
2420 (void)spllo();
2421#endif
2422 machine_clock_assist();
2423
2424 (void)splsched();
2425 }
2426
1c79356b
A
2427 /*
2428 * This is not a switch statement to avoid the
2429 * bounds checking code in the common case.
2430 */
2431 pset = myprocessor->processor_set;
9bccf70c 2432 simple_lock(&pset->sched_lock);
1c79356b
A
2433retry:
2434 state = myprocessor->state;
2435 if (state == PROCESSOR_DISPATCHING) {
2436 /*
2437 * Commmon case -- cpu dispatched.
2438 */
2439 new_thread = *threadp;
2440 *threadp = (volatile thread_t) THREAD_NULL;
2441 myprocessor->state = PROCESSOR_RUNNING;
9bccf70c
A
2442 enqueue_tail(&pset->active_queue, (queue_entry_t)myprocessor);
2443 simple_unlock(&pset->sched_lock);
1c79356b 2444
1c79356b
A
2445 if ( myprocessor->runq.highq > new_thread->sched_pri ||
2446 pset->runq.highq > new_thread->sched_pri ) {
9bccf70c
A
2447 thread_lock(new_thread);
2448 thread_setrun(new_thread, HEAD_Q);
1c79356b
A
2449 thread_unlock(new_thread);
2450
2451 counter(c_idle_thread_block++);
2452 thread_block(idle_thread_continue);
9bccf70c 2453 /* NOTREACHED */
1c79356b
A
2454 }
2455 else {
1c79356b
A
2456 counter(c_idle_thread_handoff++);
2457 thread_run(myprocessor->idle_thread,
2458 idle_thread_continue, new_thread);
9bccf70c 2459 /* NOTREACHED */
1c79356b
A
2460 }
2461 }
2462 else
2463 if (state == PROCESSOR_IDLE) {
2464 if (myprocessor->state != PROCESSOR_IDLE) {
2465 /*
2466 * Something happened, try again.
2467 */
2468 goto retry;
2469 }
2470 /*
2471 * Processor was not dispatched (Rare).
2472 * Set it running again.
2473 */
2474 no_dispatch_count++;
2475 pset->idle_count--;
9bccf70c 2476 remqueue(&pset->idle_queue, (queue_entry_t)myprocessor);
1c79356b 2477 myprocessor->state = PROCESSOR_RUNNING;
9bccf70c
A
2478 enqueue_tail(&pset->active_queue, (queue_entry_t)myprocessor);
2479 simple_unlock(&pset->sched_lock);
1c79356b
A
2480
2481 counter(c_idle_thread_block++);
2482 thread_block(idle_thread_continue);
9bccf70c 2483 /* NOTREACHED */
1c79356b
A
2484 }
2485 else
2486 if ( state == PROCESSOR_ASSIGN ||
2487 state == PROCESSOR_SHUTDOWN ) {
2488 /*
2489 * Changing processor sets, or going off-line.
2490 * Release next_thread if there is one. Actual
2491 * thread to run is on a runq.
2492 */
2493 if ((new_thread = (thread_t)*threadp) != THREAD_NULL) {
2494 *threadp = (volatile thread_t) THREAD_NULL;
9bccf70c
A
2495 simple_unlock(&pset->sched_lock);
2496
1c79356b 2497 thread_lock(new_thread);
9bccf70c 2498 thread_setrun(new_thread, TAIL_Q);
1c79356b 2499 thread_unlock(new_thread);
9bccf70c
A
2500 }
2501 else
2502 simple_unlock(&pset->sched_lock);
1c79356b
A
2503
2504 counter(c_idle_thread_block++);
2505 thread_block(idle_thread_continue);
9bccf70c 2506 /* NOTREACHED */
1c79356b
A
2507 }
2508 else {
9bccf70c 2509 simple_unlock(&pset->sched_lock);
1c79356b 2510
9bccf70c 2511 panic("idle_thread: bad processor state %d\n", cpu_state(mycpu));
1c79356b
A
2512 }
2513
2514 (void)spllo();
2515 }
2516}
2517
2518void
2519idle_thread(void)
2520{
2521 thread_t self = current_thread();
2522 spl_t s;
2523
2524 stack_privilege(self);
1c79356b
A
2525
2526 s = splsched();
2527 thread_lock(self);
1c79356b 2528 self->priority = IDLEPRI;
9bccf70c 2529 set_sched_pri(self, self->priority);
1c79356b
A
2530 thread_unlock(self);
2531 splx(s);
2532
2533 counter(c_idle_thread_block++);
9bccf70c 2534 thread_block(idle_thread_continue);
1c79356b
A
2535 /*NOTREACHED*/
2536}
2537
0b4e3aa0
A
2538static uint64_t sched_tick_interval, sched_tick_deadline;
2539
2540void sched_tick_thread(void);
2541
2542void
2543sched_tick_init(void)
2544{
2545 kernel_thread_with_priority(
2546 kernel_task, MAXPRI_STANDARD,
2547 sched_tick_thread, TRUE, TRUE);
2548}
1c79356b
A
2549
2550/*
2551 * sched_tick_thread
2552 *
2553 * Update the priorities of all threads periodically.
2554 */
2555void
2556sched_tick_thread_continue(void)
2557{
0b4e3aa0 2558 uint64_t abstime;
1c79356b
A
2559#if SIMPLE_CLOCK
2560 int new_usec;
2561#endif /* SIMPLE_CLOCK */
2562
2563 clock_get_uptime(&abstime);
2564
2565 sched_tick++; /* age usage one more time */
2566#if SIMPLE_CLOCK
2567 /*
2568 * Compensate for clock drift. sched_usec is an
2569 * exponential average of the number of microseconds in
2570 * a second. It decays in the same fashion as cpu_usage.
2571 */
2572 new_usec = sched_usec_elapsed();
2573 sched_usec = (5*sched_usec + 3*new_usec)/8;
2574#endif /* SIMPLE_CLOCK */
2575
2576 /*
2577 * Compute the scheduler load factors.
2578 */
2579 compute_mach_factor();
2580
2581 /*
2582 * Scan the run queues for runnable threads that need to
2583 * have their priorities recalculated.
2584 */
2585 do_thread_scan();
2586
2587 clock_deadline_for_periodic_event(sched_tick_interval, abstime,
2588 &sched_tick_deadline);
2589
2590 assert_wait((event_t)sched_tick_thread_continue, THREAD_INTERRUPTIBLE);
2591 thread_set_timer_deadline(sched_tick_deadline);
2592 thread_block(sched_tick_thread_continue);
2593 /*NOTREACHED*/
2594}
2595
2596void
2597sched_tick_thread(void)
2598{
2599 thread_t self = current_thread();
2600 natural_t rate;
2601 spl_t s;
2602
2603 stack_privilege(self);
1c79356b
A
2604
2605 rate = (1000 >> SCHED_TICK_SHIFT);
2606 clock_interval_to_absolutetime_interval(rate, USEC_PER_SEC,
2607 &sched_tick_interval);
2608 clock_get_uptime(&sched_tick_deadline);
2609
2610 thread_block(sched_tick_thread_continue);
2611 /*NOTREACHED*/
2612}
2613
2614#define MAX_STUCK_THREADS 128
2615
2616/*
2617 * do_thread_scan: scan for stuck threads. A thread is stuck if
2618 * it is runnable but its priority is so low that it has not
2619 * run for several seconds. Its priority should be higher, but
2620 * won't be until it runs and calls update_priority. The scanner
2621 * finds these threads and does the updates.
2622 *
2623 * Scanner runs in two passes. Pass one squirrels likely
2624 * thread ids away in an array (takes out references for them).
2625 * Pass two does the priority updates. This is necessary because
2626 * the run queue lock is required for the candidate scan, but
9bccf70c 2627 * cannot be held during updates.
1c79356b
A
2628 *
2629 * Array length should be enough so that restart isn't necessary,
9bccf70c 2630 * but restart logic is included.
1c79356b
A
2631 *
2632 */
2633thread_t stuck_threads[MAX_STUCK_THREADS];
2634int stuck_count = 0;
2635
2636/*
2637 * do_runq_scan is the guts of pass 1. It scans a runq for
2638 * stuck threads. A boolean is returned indicating whether
2639 * a retry is needed.
2640 */
2641boolean_t
2642do_runq_scan(
2643 run_queue_t runq)
2644{
2645 register queue_t q;
2646 register thread_t thread;
2647 register int count;
2648 spl_t s;
2649 boolean_t result = FALSE;
2650
2651 s = splsched();
2652 simple_lock(&runq->lock);
2653 if ((count = runq->count) > 0) {
2654 q = runq->queues + runq->highq;
2655 while (count > 0) {
2656 queue_iterate(q, thread, thread_t, links) {
0b4e3aa0
A
2657 if ( !(thread->state & (TH_WAIT|TH_SUSP)) &&
2658 (thread->sched_mode & TH_MODE_TIMESHARE) ) {
1c79356b
A
2659 if (thread->sched_stamp != sched_tick) {
2660 /*
2661 * Stuck, save its id for later.
2662 */
2663 if (stuck_count == MAX_STUCK_THREADS) {
2664 /*
2665 * !@#$% No more room.
2666 */
2667 simple_unlock(&runq->lock);
2668 splx(s);
2669
2670 return (TRUE);
2671 }
2672
2673 /*
2674 * Inline version of thread_reference
2675 * XXX - lock ordering problem here:
2676 * thread locks should be taken before runq
2677 * locks: just try and get the thread's locks
2678 * and ignore this thread if we fail, we might
2679 * have better luck next time.
2680 */
9bccf70c 2681 if (thread_lock_try(thread)) {
1c79356b
A
2682 thread->ref_count++;
2683 thread_unlock(thread);
2684 stuck_threads[stuck_count++] = thread;
2685 }
2686 else
2687 result = TRUE;
2688 }
2689 }
2690
2691 count--;
2692 }
2693
2694 q--;
2695 }
2696 }
2697 simple_unlock(&runq->lock);
2698 splx(s);
2699
2700 return (result);
2701}
2702
2703boolean_t thread_scan_enabled = TRUE;
2704
2705void
2706do_thread_scan(void)
2707{
2708 register boolean_t restart_needed = FALSE;
2709 register thread_t thread;
2710 register processor_set_t pset = &default_pset;
2711 register processor_t processor;
2712 spl_t s;
2713
2714 if (!thread_scan_enabled)
2715 return;
2716
2717 do {
2718 restart_needed = do_runq_scan(&pset->runq);
2719 if (!restart_needed) {
2720 simple_lock(&pset->processors_lock);
2721 processor = (processor_t)queue_first(&pset->processors);
2722 while (!queue_end(&pset->processors, (queue_entry_t)processor)) {
2723 if (restart_needed = do_runq_scan(&processor->runq))
2724 break;
2725
0b4e3aa0
A
2726 thread = processor->idle_thread;
2727 if (thread->sched_stamp != sched_tick) {
2728 if (stuck_count == MAX_STUCK_THREADS) {
2729 restart_needed = TRUE;
2730 break;
2731 }
2732
2733 stuck_threads[stuck_count++] = thread;
2734 }
2735
1c79356b
A
2736 processor = (processor_t)queue_next(&processor->processors);
2737 }
2738 simple_unlock(&pset->processors_lock);
2739 }
2740
2741 /*
2742 * Ok, we now have a collection of candidates -- fix them.
2743 */
2744 while (stuck_count > 0) {
2745 thread = stuck_threads[--stuck_count];
2746 stuck_threads[stuck_count] = THREAD_NULL;
2747 s = splsched();
2748 thread_lock(thread);
0b4e3aa0
A
2749 if ( (thread->sched_mode & TH_MODE_TIMESHARE) ||
2750 (thread->state & TH_IDLE) ) {
1c79356b 2751 if ( !(thread->state & (TH_WAIT|TH_SUSP)) &&
0b4e3aa0 2752 thread->sched_stamp != sched_tick )
1c79356b
A
2753 update_priority(thread);
2754 }
2755 thread_unlock(thread);
2756 splx(s);
0b4e3aa0
A
2757 if (!(thread->state & TH_IDLE))
2758 thread_deallocate(thread);
1c79356b 2759 }
9bccf70c
A
2760
2761 if (restart_needed)
2762 delay(1); /* XXX */
1c79356b
A
2763
2764 } while (restart_needed);
2765}
2766
2767/*
2768 * Just in case someone doesn't use the macro
2769 */
2770#undef thread_wakeup
2771void
2772thread_wakeup(
2773 event_t x);
2774
2775void
2776thread_wakeup(
2777 event_t x)
2778{
2779 thread_wakeup_with_result(x, THREAD_AWAKENED);
2780}
2781
9bccf70c 2782
0b4e3aa0
A
2783#if DEBUG
2784
2785static boolean_t
1c79356b 2786thread_runnable(
0b4e3aa0 2787 thread_t thread)
1c79356b 2788{
0b4e3aa0 2789 return ((thread->state & (TH_RUN|TH_WAIT)) == TH_RUN);
1c79356b
A
2790}
2791
1c79356b
A
2792void
2793dump_processor_set(
2794 processor_set_t ps)
2795{
2796 printf("processor_set: %08x\n",ps);
2797 printf("idle_queue: %08x %08x, idle_count: 0x%x\n",
2798 ps->idle_queue.next,ps->idle_queue.prev,ps->idle_count);
2799 printf("processors: %08x %08x, processor_count: 0x%x\n",
2800 ps->processors.next,ps->processors.prev,ps->processor_count);
2801 printf("tasks: %08x %08x, task_count: 0x%x\n",
2802 ps->tasks.next,ps->tasks.prev,ps->task_count);
2803 printf("threads: %08x %08x, thread_count: 0x%x\n",
2804 ps->threads.next,ps->threads.prev,ps->thread_count);
2805 printf("ref_count: 0x%x, active: %x\n",
2806 ps->ref_count,ps->active);
2807 printf("pset_self: %08x, pset_name_self: %08x\n",ps->pset_self, ps->pset_name_self);
0b4e3aa0 2808 printf("set_quanta: 0x%x\n", ps->set_quanta);
1c79356b
A
2809}
2810
2811#define processor_state(s) (((s)>PROCESSOR_SHUTDOWN)?"*unknown*":states[s])
2812
2813void
2814dump_processor(
2815 processor_t p)
2816{
2817 char *states[]={"OFF_LINE","RUNNING","IDLE","DISPATCHING",
2818 "ASSIGN","SHUTDOWN"};
2819
2820 printf("processor: %08x\n",p);
2821 printf("processor_queue: %08x %08x\n",
2822 p->processor_queue.next,p->processor_queue.prev);
2823 printf("state: %8s, next_thread: %08x, idle_thread: %08x\n",
2824 processor_state(p->state), p->next_thread, p->idle_thread);
0b4e3aa0 2825 printf("slice_quanta: %x\n", p->slice_quanta);
1c79356b
A
2826 printf("processor_set: %08x, processor_set_next: %08x\n",
2827 p->processor_set, p->processor_set_next);
2828 printf("processors: %08x %08x\n", p->processors.next,p->processors.prev);
2829 printf("processor_self: %08x, slot_num: 0x%x\n", p->processor_self, p->slot_num);
2830}
2831
2832void
2833dump_run_queue_struct(
2834 run_queue_t rq)
2835{
2836 char dump_buf[80];
2837 int i;
2838
2839 for( i=0; i < NRQS; ) {
2840 int j;
2841
2842 printf("%6s",(i==0)?"runq:":"");
2843 for( j=0; (j<8) && (i < NRQS); j++,i++ ) {
2844 if( rq->queues[i].next == &rq->queues[i] )
2845 printf( " --------");
2846 else
2847 printf(" %08x",rq->queues[i].next);
2848 }
2849 printf("\n");
2850 }
2851 for( i=0; i < NRQBM; ) {
2852 register unsigned int mask;
2853 char *d=dump_buf;
2854
2855 mask = ~0;
2856 mask ^= (mask>>1);
2857
2858 do {
2859 *d++ = ((rq->bitmap[i]&mask)?'r':'e');
2860 mask >>=1;
2861 } while( mask );
2862 *d = '\0';
2863 printf("%8s%s\n",((i==0)?"bitmap:":""),dump_buf);
2864 i++;
2865 }
2866 printf("highq: 0x%x, count: %u\n", rq->highq, rq->count);
2867}
2868
2869void
2870dump_run_queues(
2871 run_queue_t runq)
2872{
2873 register queue_t q1;
2874 register int i;
2875 register queue_entry_t e;
2876
2877 q1 = runq->queues;
2878 for (i = 0; i < NRQS; i++) {
2879 if (q1->next != q1) {
2880 int t_cnt;
2881
2882 printf("[%u]",i);
2883 for (t_cnt=0, e = q1->next; e != q1; e = e->next) {
2884 printf("\t0x%08x",e);
2885 if( (t_cnt = ++t_cnt%4) == 0 )
2886 printf("\n");
2887 }
2888 if( t_cnt )
2889 printf("\n");
2890 }
2891 /* else
2892 printf("[%u]\t<empty>\n",i);
2893 */
2894 q1++;
2895 }
2896}
2897
2898void
2899checkrq(
2900 run_queue_t rq,
2901 char *msg)
2902{
2903 register queue_t q1;
2904 register int i, j;
2905 register queue_entry_t e;
2906 register int highq;
2907
2908 highq = NRQS;
2909 j = 0;
2910 q1 = rq->queues;
2911 for (i = MAXPRI; i >= 0; i--) {
2912 if (q1->next == q1) {
2913 if (q1->prev != q1) {
2914 panic("checkrq: empty at %s", msg);
2915 }
2916 }
2917 else {
2918 if (highq == -1)
2919 highq = i;
2920
2921 for (e = q1->next; e != q1; e = e->next) {
2922 j++;
2923 if (e->next->prev != e)
2924 panic("checkrq-2 at %s", msg);
2925 if (e->prev->next != e)
2926 panic("checkrq-3 at %s", msg);
2927 }
2928 }
2929 q1++;
2930 }
2931 if (j != rq->count)
2932 panic("checkrq: count wrong at %s", msg);
2933 if (rq->count != 0 && highq > rq->highq)
2934 panic("checkrq: highq wrong at %s", msg);
2935}
2936
2937void
2938thread_check(
2939 register thread_t thread,
2940 register run_queue_t rq)
2941{
2942 register int whichq = thread->sched_pri;
2943 register queue_entry_t queue, entry;
2944
2945 if (whichq < MINPRI || whichq > MAXPRI)
2946 panic("thread_check: bad pri");
2947
1c79356b
A
2948 queue = &rq->queues[whichq];
2949 entry = queue_first(queue);
2950 while (!queue_end(queue, entry)) {
2951 if (entry == (queue_entry_t)thread)
2952 return;
2953
2954 entry = queue_next(entry);
2955 }
2956
2957 panic("thread_check: not found");
2958}
2959
2960#endif /* DEBUG */
2961
2962#if MACH_KDB
2963#include <ddb/db_output.h>
2964#define printf kdbprintf
2965extern int db_indent;
2966void db_sched(void);
2967
2968void
2969db_sched(void)
2970{
2971 iprintf("Scheduling Statistics:\n");
2972 db_indent += 2;
2973 iprintf("Thread invocations: csw %d same %d\n",
2974 c_thread_invoke_csw, c_thread_invoke_same);
2975#if MACH_COUNTERS
2976 iprintf("Thread block: calls %d\n",
2977 c_thread_block_calls);
2978 iprintf("Idle thread:\n\thandoff %d block %d no_dispatch %d\n",
2979 c_idle_thread_handoff,
2980 c_idle_thread_block, no_dispatch_count);
2981 iprintf("Sched thread blocks: %d\n", c_sched_thread_block);
2982#endif /* MACH_COUNTERS */
2983 db_indent -= 2;
2984}
2985#endif /* MACH_KDB */