|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * Mach Operating System
27: * Copyright (c) 1993-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 [email protected]
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: * File: sched_prim.c
52: * Author: Avadis Tevanian, Jr.
53: * Date: 1986
54: *
55: * Scheduling primitives
56: *
57: */
58:
59: #include <cpus.h>
60: #include <simple_clock.h>
61: #include <mach_fixpri.h>
62: #include <mach_host.h>
63: #include <hw_footprint.h>
64:
65: #include <mach/machine.h>
66: #include <kern/ast.h>
67: #include <kern/counters.h>
68: #include <kern/cpu_number.h>
69: #include <kern/lock.h>
70: #include <kern/macro_help.h>
71: #include <kern/processor.h>
72: #include <kern/queue.h>
73: #include <kern/sched.h>
74: #include <kern/sched_prim.h>
75: #include <kern/syscall_subr.h>
76: #include <kern/thread.h>
77: #include <kern/thread_swap.h>
78: #include <kern/time_out.h>
79: #include <vm/pmap.h>
80: #include <vm/vm_kern.h>
81: #include <vm/vm_map.h>
82: #include <machine/machspl.h> /* For def'n of splsched() */
83:
84: #if MACH_FIXPRI
85: #include <mach/policy.h>
86: #endif /* MACH_FIXPRI */
87:
88: #import <kern/assert.h>
89: #import <kern/power.h>
90:
91: extern int hz;
92:
93: #define DEFAULT_PREEMPTION_RATE 100 /* (1/s) */
94: int default_preemption_rate = DEFAULT_PREEMPTION_RATE;
95: int min_quantum;
96:
97: unsigned sched_tick;
98:
99: #if SIMPLE_CLOCK
100: int sched_usec;
101: #endif /* SIMPLE_CLOCK */
102:
103: thread_t sched_thread_id;
104:
105: void recompute_priorities(void); /* forward */
106: void update_priority(thread_t);
107: void set_pri(thread_t, int, boolean_t);
108: void do_thread_scan(void);
109:
110: thread_t choose_pset_thread();
111:
112: #define RUNQ_DEBUG 0
113:
114: #if RUNQ_DEBUG
115: int runq_debug = 0;
116:
117: #define CHECKRQ(rq, s) \
118: if (runq_debug) checkrq((rq), (s))
119:
120: #define THREAD_CHECK(th, rq) \
121: if (runq_debug) thread_check((th), (rq))
122:
123: void checkrq(run_queue_t, char *);
124: void thread_check(thread_t, run_queue_t);
125: #endif
126:
127: /*
128: * State machine
129: *
130: * states are combinations of:
131: * R running
132: * W waiting (or on wait queue)
133: * S suspended (or will suspend)
134: * N non-interruptible
135: *
136: * init action
137: * assert_wait thread_block clear_wait suspend resume
138: *
139: * R RW, RWN R; setrun - RS -
140: * RS RWS, RWNS S; wake_active - - R
141: * RN RWN RN; setrun - RNS -
142: * RNS RWNS RNS; setrun - - RN
143: *
144: * RW W R RWS -
145: * RWN WN RN RWNS -
146: * RWS WS; wake_active RS - RW
147: * RWNS WNS RNS - RWN
148: *
149: * W R; setrun WS -
150: * WN RN; setrun WNS -
151: * WNS RNS; setrun - WN
152: *
153: * S - - R
154: * WS S - W
155: *
156: */
157:
158: /*
159: * Waiting protocols and implementation:
160: *
161: * Each thread may be waiting for exactly one event; this event
162: * is set using assert_wait(). That thread may be awakened either
163: * by performing a thread_wakeup_prim() on its event,
164: * or by directly waking that thread up with clear_wait().
165: *
166: * The implementation of wait events uses a hash table. Each
167: * bucket is queue of threads having the same hash function
168: * value; the chain for the queue (linked list) is the run queue
169: * field. [It is not possible to be waiting and runnable at the
170: * same time.]
171: *
172: * Locks on both the thread and on the hash buckets govern the
173: * wait event field and the queue chain field. Because wakeup
174: * operations only have the event as an argument, the event hash
175: * bucket must be locked before any thread.
176: *
177: * Scheduling operations may also occur at interrupt level; therefore,
178: * interrupts below splsched() must be prevented when holding
179: * thread or hash bucket locks.
180: *
181: * The wait event hash table declarations are as follows:
182: */
183:
184: #define NUMQUEUES 59
185:
186: queue_head_t wait_queue[NUMQUEUES];
187: decl_simple_lock_data(, wait_lock[NUMQUEUES])
188:
189: /* NOTE: we want a small positive integer out of this */
190: #define wait_hash(event) \
191: ((((int)(event) < 0) ? ~(int)(event) : (int)(event)) % NUMQUEUES)
192:
193: void wait_queue_init(void)
194: {
195: register int i;
196:
197: for (i = 0; i < NUMQUEUES; i++) {
198: queue_init(&wait_queue[i]);
199: simple_lock_init(&wait_lock[i]);
200: }
201: }
202:
203: void sched_init(void)
204: {
205: /*
206: * Calculate the minimum quantum
207: * in ticks.
208: */
209: if (default_preemption_rate < 1)
210: default_preemption_rate = DEFAULT_PREEMPTION_RATE;
211: min_quantum = hz / default_preemption_rate;
212: /*
213: * Round up result (4/5) to an
214: * integral number of ticks.
215: */
216: if (((hz * 10) / default_preemption_rate) - (min_quantum * 10) >= 5)
217: min_quantum++;
218: if (min_quantum < 1)
219: min_quantum = 1;
220:
221: wait_queue_init();
222: pset_sys_bootstrap(); /* initialize processer mgmt. */
223: queue_init(&action_queue);
224: simple_lock_init(&action_lock);
225: sched_tick = 0;
226: #if SIMPLE_CLOCK
227: sched_usec = 0;
228: #endif /* SIMPLE_CLOCK */
229: ast_init();
230: }
231:
232: /*
233: * Thread timeout routine, called when timer expires.
234: * Called at splsoftclock.
235: */
236: void thread_timeout(
237: thread_t thread)
238: {
239: assert(thread->timer.set == TELT_UNSET);
240:
241: clear_wait(thread, THREAD_TIMED_OUT, FALSE);
242: }
243:
244: /*
245: * thread_set_timeout:
246: *
247: * Set a timer for the current thread, if the thread
248: * is ready to wait. Must be called between assert_wait()
249: * and thread_block().
250: */
251:
252: void thread_set_timeout(
253: int t) /* timeout interval in ticks */
254: {
255: register thread_t thread = current_thread();
256: register spl_t s;
257:
258: s = splsched();
259: thread_lock(thread);
260: if ((thread->state & TH_WAIT) != 0) {
261: set_timeout(&thread->timer, t);
262: }
263: thread_unlock(thread);
264: splx(s);
265: }
266:
267: /*
268: * Set up thread timeout element when thread is created.
269: */
270: void thread_timeout_setup(
271: register thread_t thread)
272: {
273: thread->timer.fcn = (int (*)())thread_timeout;
274: thread->timer.param = (char *)thread;
275: thread->depress_timer.fcn = (int (*)())thread_depress_timeout;
276: thread->depress_timer.param = (char *)thread;
277: }
278:
279: /*
280: * assert_wait:
281: *
282: * Assert that the current thread is about to go to
283: * sleep until the specified event occurs.
284: */
285: void assert_wait(
286: event_t event,
287: boolean_t interruptible)
288: {
289: register queue_t q;
290: register int index;
291: register thread_t thread;
292: #if MACH_SLOCKS
293: register simple_lock_t lock;
294: #endif /* MACH_SLOCKS */
295: spl_t s;
296:
297: thread = current_thread();
298: if (thread->wait_event != 0) {
299: printf("assert_wait: already asserted event 0x%x\n",
300: thread->wait_event);
301: panic("assert_wait");
302: }
303: s = splsched();
304: if (event != 0) {
305: index = wait_hash(event);
306: q = &wait_queue[index];
307: #if MACH_SLOCKS
308: lock = &wait_lock[index];
309: #endif /* MACH_SLOCKS */
310: simple_lock(lock);
311: thread_lock(thread);
312: enqueue_tail(q, (queue_entry_t) thread);
313: thread->wait_event = event;
314: if (interruptible)
315: thread->state |= TH_WAIT;
316: else
317: thread->state |= TH_WAIT | TH_UNINT;
318: thread_unlock(thread);
319: simple_unlock(lock);
320: }
321: else {
322: thread_lock(thread);
323: if (interruptible)
324: thread->state |= TH_WAIT;
325: else
326: thread->state |= TH_WAIT | TH_UNINT;
327: thread_unlock(thread);
328: }
329: splx(s);
330: }
331:
332: /*
333: * clear_wait:
334: *
335: * Clear the wait condition for the specified thread. Start the thread
336: * executing if that is appropriate.
337: *
338: * parameters:
339: * thread thread to awaken
340: * result Wakeup result the thread should see
341: * interrupt_only Don't wake up the thread if it isn't
342: * interruptible.
343: */
344: void clear_wait(
345: register thread_t thread,
346: int result,
347: boolean_t interrupt_only)
348: {
349: register int index;
350: register queue_t q;
351: #if MACH_SLOCKS
352: register simple_lock_t lock;
353: #endif /* MACH_SLOCKS */
354: register event_t event;
355: spl_t s;
356:
357: s = splsched();
358: thread_lock(thread);
359: if (interrupt_only && (thread->state & TH_UNINT)) {
360: /*
361: * can`t interrupt thread
362: */
363: thread_unlock(thread);
364: splx(s);
365: return;
366: }
367:
368: event = thread->wait_event;
369: if (event != 0) {
370: thread_unlock(thread);
371: index = wait_hash(event);
372: q = &wait_queue[index];
373: #if MACH_SLOCKS
374: lock = &wait_lock[index];
375: #endif /* MACH_SLOCKS */
376: simple_lock(lock);
377: /*
378: * If the thread is still waiting on that event,
379: * then remove it from the list. If it is waiting
380: * on a different event, or no event at all, then
381: * someone else did our job for us.
382: */
383: thread_lock(thread);
384: if (thread->wait_event == event) {
385: remqueue(q, (queue_entry_t)thread);
386: thread->wait_event = 0;
387: event = 0; /* cause to run below */
388: }
389: simple_unlock(lock);
390: }
391: if (event == 0) {
392: register int state = thread->state;
393:
394: reset_timeout_check(&thread->timer);
395:
396: switch (state & TH_SCHED_STATE) {
397: case TH_WAIT | TH_SUSP | TH_UNINT:
398: case TH_WAIT | TH_UNINT:
399: case TH_WAIT:
400: /*
401: * Sleeping and not suspendable - put
402: * on run queue.
403: */
404: thread->state = (state &~ TH_WAIT) | TH_RUN;
405: thread->wait_result = result;
406: thread_setrun(thread, TRUE);
407: break;
408:
409: case TH_WAIT | TH_SUSP:
410: case TH_RUN | TH_WAIT:
411: case TH_RUN | TH_WAIT | TH_SUSP:
412: case TH_RUN | TH_WAIT | TH_UNINT:
413: case TH_RUN | TH_WAIT | TH_SUSP | TH_UNINT:
414: /*
415: * Either already running, or suspended.
416: */
417: thread->state = state &~ TH_WAIT;
418: thread->wait_result = result;
419: break;
420:
421: default:
422: /*
423: * Not waiting.
424: */
425: break;
426: }
427: }
428: thread_unlock(thread);
429: splx(s);
430: }
431:
432: /*
433: * thread_wakeup_prim:
434: *
435: * Common routine for thread_wakeup, thread_wakeup_with_result,
436: * and thread_wakeup_one.
437: *
438: */
439: void thread_wakeup_prim(
440: event_t event,
441: boolean_t one_thread,
442: int result)
443: {
444: register queue_t q;
445: register int index;
446: register thread_t thread, next_th;
447: #if MACH_SLOCKS
448: register simple_lock_t lock;
449: #endif /* MACH_SLOCKS */
450: spl_t s;
451: register int state;
452:
453: index = wait_hash(event);
454: q = &wait_queue[index];
455: s = splsched();
456: #if MACH_SLOCKS
457: lock = &wait_lock[index];
458: #endif /* MACH_SLOCKS */
459: simple_lock(lock);
460: thread = (thread_t) queue_first(q);
461: while (!queue_end(q, (queue_entry_t)thread)) {
462: next_th = (thread_t) queue_next((queue_t) thread);
463:
464: if (thread->wait_event == event) {
465: thread_lock(thread);
466: remqueue(q, (queue_entry_t) thread);
467: thread->wait_event = 0;
468: reset_timeout_check(&thread->timer);
469:
470: state = thread->state;
471: switch (state & TH_SCHED_STATE) {
472:
473: case TH_WAIT | TH_SUSP | TH_UNINT:
474: case TH_WAIT | TH_UNINT:
475: case TH_WAIT:
476: /*
477: * Sleeping and not suspendable - put
478: * on run queue.
479: */
480: thread->state = (state &~ TH_WAIT) | TH_RUN;
481: thread->wait_result = result;
482: thread_setrun(thread, TRUE);
483: break;
484:
485: case TH_WAIT | TH_SUSP:
486: case TH_RUN | TH_WAIT:
487: case TH_RUN | TH_WAIT | TH_SUSP:
488: case TH_RUN | TH_WAIT | TH_UNINT:
489: case TH_RUN | TH_WAIT | TH_SUSP | TH_UNINT:
490: /*
491: * Either already running, or suspended.
492: */
493: thread->state = state &~ TH_WAIT;
494: thread->wait_result = result;
495: break;
496:
497: default:
498: panic("thread_wakeup");
499: break;
500: }
501: thread_unlock(thread);
502: if (one_thread)
503: break;
504: }
505: thread = next_th;
506: }
507: simple_unlock(lock);
508: splx(s);
509: }
510:
511: /*
512: * thread_sleep:
513: *
514: * Cause the current thread to wait until the specified event
515: * occurs. The specified lock is unlocked before releasing
516: * the cpu. (This is a convenient way to sleep without manually
517: * calling assert_wait).
518: */
519: void thread_sleep(
520: event_t event,
521: simple_lock_t lock,
522: boolean_t interruptible)
523: {
524: assert_wait(event, interruptible); /* assert event */
525: simple_unlock(lock); /* release the lock */
526: thread_block_with_continuation((void (*)()) 0); /* block ourselves */
527: }
528:
529: /*
530: * thread_bind:
531: *
532: * Force a thread to execute on the specified processor.
533: * If the thread is currently executing, it may wait until its
534: * time slice is up before switching onto the specified processor.
535: *
536: * A processor of PROCESSOR_NULL causes the thread to be unbound.
537: * xxx - DO NOT export this to users.
538: */
539: void thread_bind(
540: register thread_t thread,
541: processor_t processor)
542: {
543: spl_t s;
544:
545: s = splsched();
546: thread_lock(thread);
547: thread->bound_processor = processor;
548: thread_unlock(thread);
549: (void) splx(s);
550: }
551:
552: /*
553: * Select a thread for this processor (the current processor) to run.
554: * May select the current thread.
555: * Assumes splsched.
556: */
557:
558: thread_t thread_select(
559: register processor_t myprocessor)
560: {
561: register thread_t thread = current_thread();
562:
563: myprocessor->first_quantum = TRUE;
564: /*
565: * Check for obvious simple case; local runq is
566: * empty and global runq has entry at hint.
567: */
568: if (myprocessor->runq.count > 0) {
569: thread = choose_thread(myprocessor);
570: myprocessor->quantum = min_quantum;
571: }
572: else {
573: register processor_set_t pset;
574:
575: #if MACH_HOST
576: pset = myprocessor->processor_set;
577: #else /* MACH_HOST */
578: pset = &default_pset;
579: #endif /* MACH_HOST */
580: simple_lock(&pset->runq.lock);
581: #if RUNQ_DEBUG
582: CHECKRQ(&pset->runq, "thread_select");
583: #endif /* DEBUG */
584: if (pset->runq.count == 0 ||
585: pset->runq.high < thread->sched_pri) {
586: /*
587: * Nothing else runnable. Return if this
588: * thread is still runnable on this processor.
589: * Check for priority update if required.
590: */
591: if ((thread->state == TH_RUN) &&
592: #if MACH_HOST
593: (thread->processor_set == pset) &&
594: #endif /* MACH_HOST */
595: ((thread->bound_processor == PROCESSOR_NULL) ||
596: (thread->bound_processor == myprocessor))) {
597:
598: simple_unlock(&pset->runq.lock);
599: thread_lock(thread);
600: if (thread->sched_stamp != sched_tick)
601: update_priority(thread);
602: thread_unlock(thread);
603: }
604: else {
605: thread = choose_pset_thread(myprocessor, pset);
606: }
607: }
608: else {
609: register queue_t q;
610:
611: /*
612: * If there is a thread at hint, grab it,
613: * else call choose_pset_thread.
614: */
615: q = pset->runq.runq + pset->runq.high;
616:
617: if (queue_empty(q)) {
618: pset->runq.high--;
619: thread = choose_pset_thread(myprocessor, pset);
620: }
621: else {
622: thread = (thread_t) dequeue_head(q);
623: thread->runq = RUN_QUEUE_NULL;
624: pset->runq.count--;
625: #if MACH_FIXPRI
626: /*
627: * Cannot lazy evaluate pset->runq.low for
628: * fixed priority policy
629: */
630: if ((pset->runq.count > 0) &&
631: (pset->policies & POLICY_FIXEDPRI)) {
632: while (queue_empty(q)) {
633: pset->runq.high--;
634: q--;
635: }
636: }
637: #endif /* MACH_FIXPRI */
638: #if RUNQ_DEBUG
639: CHECKRQ(&pset->runq, "thread_select: after");
640: #endif /* DEBUG */
641: simple_unlock(&pset->runq.lock);
642: }
643: }
644:
645: #if MACH_FIXPRI
646: if (thread->policy != POLICY_FIXEDPRI) {
647: #endif /* MACH_FIXPRI */
648: myprocessor->quantum = pset->set_quantum;
649: #if MACH_FIXPRI
650: }
651: else {
652: /*
653: * POLICY_FIXEDPRI
654: */
655: myprocessor->quantum = thread->sched_data;
656: }
657: #endif /* MACH_FIXPRI */
658: }
659:
660: return thread;
661: }
662:
663: /*
664: * Stop running the current thread and start running the new thread.
665: * If continuation is non-zero, and the current thread is blocked,
666: * then it will resume by executing continuation on a new stack.
667: * Returns TRUE if the hand-off succeeds.
668: * Assumes splsched.
669: */
670:
671: boolean_t thread_invoke(
672: register thread_t old_thread,
673: continuation_t continuation,
674: register thread_t new_thread)
675: {
676: /*
677: * Check for invoking the same thread.
678: */
679: if (old_thread == new_thread) {
680: /*
681: * Mark thread interruptible.
682: * Run continuation if there is one.
683: */
684: thread_lock(new_thread);
685: new_thread->state &= ~TH_UNINT;
686: thread_unlock(new_thread);
687:
688: if (continuation != (void (*)()) 0) {
689: (void) spl0();
690: call_continuation(continuation);
691: /*NOTREACHED*/
692: }
693: return TRUE;
694: }
695:
696: /*
697: * Check for stack-handoff.
698: */
699: thread_lock(new_thread);
700: if ((old_thread->stack_privilege != current_stack()) &&
701: (continuation != (void (*)()) 0))
702: {
703: switch (new_thread->state & TH_SWAP_STATE) {
704: case TH_SWAPPED:
705:
706: new_thread->state &= ~(TH_SWAPPED | TH_UNINT);
707: thread_unlock(new_thread);
708:
709: #if NCPUS > 1
710: new_thread->last_processor = current_processor();
711: #endif /* NCPUS > 1 */
712:
713: /*
714: * Set up ast context of new thread and
715: * switch to its timer.
716: */
717: ast_context(new_thread, cpu_number());
718: timer_switch(&new_thread->system_timer);
719:
720: old_thread->swap_func = continuation;
721: stack_handoff(old_thread, new_thread);
722:
723: /*
724: * We can dispatch the old thread now.
725: * This is like thread_dispatch, except
726: * that the old thread is left swapped
727: * *without* freeing its stack.
728: * This path is also much more frequent
729: * than actual calls to thread_dispatch.
730: */
731:
732: thread_lock(old_thread);
733:
734: switch (old_thread->state) {
735: case TH_RUN | TH_SUSP:
736: case TH_RUN | TH_SUSP | TH_HALTED:
737: case TH_RUN | TH_WAIT | TH_SUSP:
738: /*
739: * Suspend the thread
740: */
741: old_thread->state = (old_thread->state & ~TH_RUN)
742: | TH_SWAPPED;
743: if (old_thread->wake_active) {
744: old_thread->wake_active = FALSE;
745: thread_unlock(old_thread);
746: thread_wakeup((event_t)&old_thread->wake_active);
747:
748: goto after_old_thread;
749: }
750: break;
751:
752: case TH_RUN | TH_SUSP | TH_UNINT:
753: case TH_RUN | TH_UNINT:
754: case TH_RUN:
755: /*
756: * We can`t suspend the thread yet,
757: * or it`s still running.
758: * Put back on a run queue.
759: */
760: old_thread->state |= TH_SWAPPED;
761: thread_setrun(old_thread, FALSE);
762: break;
763:
764: case TH_RUN | TH_WAIT | TH_SUSP | TH_UNINT:
765: case TH_RUN | TH_WAIT | TH_UNINT:
766: case TH_RUN | TH_WAIT:
767: /*
768: * Waiting, and not suspendable.
769: */
770: old_thread->state = (old_thread->state & ~TH_RUN)
771: | TH_SWAPPED;
772: break;
773:
774: case TH_RUN | TH_IDLE:
775: /*
776: * Drop idle thread -- it is already in
777: * idle_thread_array.
778: */
779: old_thread->state = TH_RUN | TH_IDLE | TH_SWAPPED;
780: break;
781:
782: default:
783: printf("illegal handoff thread state 0x%x\n",
784: old_thread->state);
785: panic("thread_invoke");
786: }
787: thread_unlock(old_thread);
788: after_old_thread:
789:
790: /*
791: * call_continuation calls the continuation
792: * after resetting the current stack pointer
793: * to recover stack space. If we called
794: * the continuation directly, we would risk
795: * running out of stack.
796: */
797:
798: counter_always(c_thread_invoke_hits++);
799: (void) spl0();
800: call_continuation(new_thread->swap_func);
801: /*NOTREACHED*/
802: return TRUE; /* help for the compiler */
803:
804: case TH_SW_COMING_IN:
805: /*
806: * Waiting for a stack
807: */
808: thread_swapin(new_thread);
809: thread_unlock(new_thread);
810: counter_always(c_thread_invoke_misses++);
811: return FALSE;
812:
813: case 0:
814: /*
815: * Already has a stack - can`t handoff.
816: */
817: break;
818: }
819: }
820:
821: else {
822: /*
823: * Check that the thread is swapped-in.
824: */
825: if (new_thread->state & TH_SWAPPED) {
826: if ((new_thread->state & TH_SW_COMING_IN) ||
827: !stack_alloc_try(new_thread, thread_continue))
828: {
829: thread_swapin(new_thread);
830: thread_unlock(new_thread);
831: counter_always(c_thread_invoke_misses++);
832: return FALSE;
833: }
834: }
835: }
836:
837: new_thread->state &= ~(TH_SWAPPED | TH_UNINT);
838: thread_unlock(new_thread);
839:
840: /*
841: * Thread is now interruptible.
842: */
843: #if NCPUS > 1
844: new_thread->last_processor = current_processor();
845: #endif /* NCPUS > 1 */
846:
847: /*
848: * Set up ast context of new thread and switch to its timer.
849: */
850: ast_context(new_thread, cpu_number());
851: timer_switch(&new_thread->system_timer);
852:
853: /*
854: * switch_context is machine-dependent. It does the
855: * machine-dependent components of a context-switch, like
856: * changing address spaces. It updates active_threads.
857: * It returns only if a continuation is not supplied.
858: */
859: counter_always(c_thread_invoke_csw++);
860: old_thread = switch_context(old_thread, continuation, new_thread);
861:
862: /*
863: * We're back. Now old_thread is the thread that resumed
864: * us, and we have to dispatch it.
865: */
866: thread_dispatch(old_thread);
867:
868: return TRUE;
869: }
870:
871: /*
872: * thread_continue:
873: *
874: * Called when the current thread is given a new stack.
875: * Called at splsched.
876: */
877: void thread_continue(
878: register thread_t old_thread)
879: {
880: register continuation_t continuation = current_thread()->swap_func;
881:
882: /*
883: * We must dispatch the old thread and then
884: * call the current thread's continuation.
885: * There might not be an old thread, if we are
886: * the first thread to run on this processor.
887: */
888:
889: if (old_thread != THREAD_NULL)
890: thread_dispatch(old_thread);
891: (void) spl0();
892: (*continuation)();
893: /*NOTREACHED*/
894: }
895:
896:
897: /*
898: * thread_block:
899: *
900: * Block the current thread. If the thread is runnable
901: * then someone must have woken it up between its request
902: * to sleep and now. In this case, it goes back on a
903: * run queue.
904: *
905: * If a continuation is specified, then thread_block will
906: * attempt to discard the thread's kernel stack. When the
907: * thread resumes, it will execute the continuation function
908: * on a new kernel stack.
909: */
910:
911: void thread_block_with_continuation(
912: continuation_t continuation)
913: {
914: register thread_t thread = current_thread();
915: register processor_t myprocessor = cpu_to_processor(cpu_number());
916: register thread_t new_thread;
917: spl_t s;
918:
919: s = splsched();
920:
921: #if FAST_TAS
922: {
923: extern void recover_ras();
924:
925: if (csw_needed(thread, myprocessor))
926: recover_ras(thread);
927: }
928: #endif /* FAST_TAS */
929:
930: ast_off(cpu_number(), AST_BLOCK);
931:
932: do
933: new_thread = thread_select(myprocessor);
934: while (!thread_invoke(thread, continuation, new_thread));
935:
936: splx(s);
937: }
938:
939: /*
940: * thread_run:
941: *
942: * Switch directly from the current thread to a specified
943: * thread. Both the current and new threads must be
944: * runnable.
945: *
946: * If a continuation is specified, then thread_block will
947: * attempt to discard the current thread's kernel stack. When the
948: * thread resumes, it will execute the continuation function
949: * on a new kernel stack.
950: */
951: void thread_run(
952: continuation_t continuation,
953: register thread_t new_thread)
954: {
955: register thread_t thread = current_thread();
956: register processor_t myprocessor = cpu_to_processor(cpu_number());
957: spl_t s;
958:
959: s = splsched();
960:
961: while (!thread_invoke(thread, continuation, new_thread))
962: new_thread = thread_select(myprocessor);
963:
964: splx(s);
965: }
966:
967: /*
968: * Dispatches a running thread that is not on a runq.
969: * Called at splsched.
970: */
971:
972: void thread_dispatch(
973: register thread_t thread)
974: {
975: /*
976: * If we are discarding the thread's stack, we must do it
977: * before the thread has a chance to run.
978: */
979:
980: thread_lock(thread);
981:
982: if (thread->swap_func != (void (*)()) 0) {
983: assert((thread->state & TH_SWAP_STATE) == 0);
984: thread->state |= TH_SWAPPED;
985: stack_free(thread);
986: }
987:
988: switch (thread->state &~ TH_SWAP_STATE) {
989: case TH_RUN | TH_SUSP:
990: case TH_RUN | TH_SUSP | TH_HALTED:
991: case TH_RUN | TH_WAIT | TH_SUSP:
992: /*
993: * Suspend the thread
994: */
995: thread->state &= ~TH_RUN;
996: if (thread->wake_active) {
997: thread->wake_active = FALSE;
998: thread_unlock(thread);
999: thread_wakeup((event_t)&thread->wake_active);
1000: return;
1001: }
1002: break;
1003:
1004: case TH_RUN | TH_SUSP | TH_UNINT:
1005: case TH_RUN | TH_UNINT:
1006: case TH_RUN:
1007: /*
1008: * No reason to stop. Put back on a run queue.
1009: */
1010: thread_setrun(thread, FALSE);
1011: break;
1012:
1013: case TH_RUN | TH_WAIT | TH_SUSP | TH_UNINT:
1014: case TH_RUN | TH_WAIT | TH_UNINT:
1015: case TH_RUN | TH_WAIT:
1016: /*
1017: * Waiting, and not suspended.
1018: */
1019: thread->state &= ~TH_RUN;
1020: break;
1021:
1022: case TH_RUN | TH_IDLE:
1023: /*
1024: * Drop idle thread -- it is already in
1025: * idle_thread_array.
1026: */
1027: break;
1028:
1029: default:
1030: panic("thread_dispatch");
1031: }
1032: thread_unlock(thread);
1033: }
1034:
1035:
1036: /*
1037: * Define shifts for simulating (5/8)**n
1038: */
1039:
1040: shift_data_t wait_shift[32] = {
1041: {1,1},{1,3},{1,-3},{2,-7},{3,5},{3,-5},{4,-8},{5,7},
1042: {5,-7},{6,-10},{7,10},{7,-9},{8,-11},{9,12},{9,-11},{10,-13},
1043: {11,14},{11,-13},{12,-15},{13,17},{13,-15},{14,-17},{15,19},{16,18},
1044: {16,-19},{17,22},{18,20},{18,-20},{19,26},{20,22},{20,-22},{21,-27}};
1045:
1046: /*
1047: * do_priority_computation:
1048: *
1049: * Calculate new priority for thread based on its base priority plus
1050: * accumulated usage. PRI_SHIFT and PRI_SHIFT_2 convert from
1051: * usage to priorities. SCHED_SHIFT converts for the scaling
1052: * of the sched_usage field by SCHED_SCALE. This scaling comes
1053: * from the multiplication by sched_load (thread_timer_delta)
1054: * in sched.h. sched_load is calculated as a scaled overload
1055: * factor in compute_mach_factor (mach_factor.c).
1056: */
1057:
1058: #ifdef PRI_SHIFT_2
1059: #if PRI_SHIFT_2 > 0
1060: #define do_priority_computation(th, pri) \
1061: MACRO_BEGIN \
1062: (pri) = (th)->priority /* start with base priority */ \
1063: - ((th)->sched_usage >> (PRI_SHIFT + SCHED_SHIFT)) \
1064: - ((th)->sched_usage >> (PRI_SHIFT_2 + SCHED_SHIFT)); \
1065: if ((pri) < 0) (pri) = 0; \
1066: MACRO_END
1067: #else PRI_SHIFT_2
1068: #define do_priority_computation(th, pri) \
1069: MACRO_BEGIN \
1070: (pri) = (th)->priority /* start with base priority */ \
1071: - ((th)->sched_usage >> (PRI_SHIFT + SCHED_SHIFT)) \
1072: + ((th)->sched_usage >> (SCHED_SHIFT - PRI_SHIFT_2)); \
1073: if ((pri) < 0) (pri) = 0; \
1074: MACRO_END
1075: #endif PRI_SHIFT_2
1076: #else defined(PRI_SHIFT_2)
1077: #define do_priority_computation(th, pri) \
1078: MACRO_BEGIN \
1079: (pri) = (th)->priority /* start with base priority */ \
1080: - ((th)->sched_usage >> (PRI_SHIFT + SCHED_SHIFT)); \
1081: if ((pri) < 0) (pri) = 0; \
1082: MACRO_END
1083: #endif defined(PRI_SHIFT_2)
1084:
1085: /*
1086: * compute_priority:
1087: *
1088: * Compute the effective priority of the specified thread.
1089: * The effective priority computation is as follows:
1090: *
1091: * Take the base priority for this thread and add
1092: * to it an increment derived from its cpu_usage.
1093: *
1094: * The thread *must* be locked by the caller.
1095: */
1096:
1097: void compute_priority(
1098: register thread_t thread,
1099: boolean_t resched)
1100: {
1101: register int pri;
1102:
1103: #if MACH_FIXPRI
1104: if (thread->policy != POLICY_FIXEDPRI) {
1105: #endif /* MACH_FIXPRI */
1106: do_priority_computation(thread, pri);
1107: if (thread->depress_priority < 0)
1108: set_pri(thread, pri, resched);
1109: else
1110: thread->depress_priority = pri;
1111: #if MACH_FIXPRI
1112: }
1113: else {
1114: set_pri(thread, thread->priority, resched);
1115: }
1116: #endif /* MACH_FIXPRI */
1117: }
1118:
1119: /*
1120: * compute_my_priority:
1121: *
1122: * Version of compute priority for current thread or thread
1123: * being manipulated by scheduler (going on or off a runq).
1124: * Only used for priority updates. Policy or priority changes
1125: * must call compute_priority above. Caller must have thread
1126: * locked and know it is timesharing and not depressed.
1127: */
1128:
1129: void compute_my_priority(
1130: register thread_t thread)
1131: {
1132: register int temp_pri;
1133:
1134: do_priority_computation(thread,temp_pri);
1135: thread->sched_pri = temp_pri;
1136: }
1137:
1138: /*
1139: * recompute_priorities:
1140: *
1141: * Update the priorities of all threads periodically.
1142: */
1143: void recompute_priorities(void)
1144: {
1145: static int recompute_priority_ticks;
1146: #if SIMPLE_CLOCK
1147: int new_usec;
1148: #endif /* SIMPLE_CLOCK */
1149:
1150: if (recompute_priority_ticks-- > 0)
1151: return;
1152:
1153: sched_tick++; /* age usage one more time */
1154: #if SIMPLE_CLOCK
1155: /*
1156: * Compensate for clock drift. sched_usec is an
1157: * exponential average of the number of microseconds in
1158: * a second. It decays in the same fashion as cpu_usage.
1159: */
1160: new_usec = sched_usec_elapsed();
1161: sched_usec = (5*sched_usec + 3*new_usec)/8;
1162: #endif /* SIMPLE_CLOCK */
1163: /*
1164: * Wakeup scheduler thread.
1165: */
1166: if (sched_thread_id != THREAD_NULL) {
1167: clear_wait(sched_thread_id, THREAD_AWAKENED, FALSE);
1168: }
1169:
1170: recompute_priority_ticks = hz;
1171: }
1172:
1173: /*
1174: * update_priority
1175: *
1176: * Cause the priority computation of a thread that has been
1177: * sleeping or suspended to "catch up" with the system. Thread
1178: * *MUST* be locked by caller. If thread is running, then this
1179: * can only be called by the thread on itself.
1180: */
1181: void update_priority(
1182: register thread_t thread)
1183: {
1184: register unsigned int ticks;
1185: register shift_t shiftp;
1186: register int temp_pri;
1187:
1188: ticks = sched_tick - thread->sched_stamp;
1189:
1190: assert(ticks != 0);
1191:
1192: if ((thread->state & TH_RUN) == 0)
1193: thread->sleep_time += ticks;
1194: else
1195: thread->sleep_time = 0;
1196:
1197: /*
1198: * If asleep for more than 30 seconds forget all
1199: * cpu_usage, else catch up on missed aging.
1200: * 5/8 ** n is approximated by the two shifts
1201: * in the wait_shift array.
1202: */
1203: thread->sched_stamp += ticks;
1204: thread_timer_delta(thread);
1205: if (ticks > 30) {
1206: thread->cpu_usage = 0;
1207: thread->sched_usage = 0;
1208: }
1209: else {
1210: thread->cpu_usage += thread->cpu_delta;
1211: thread->sched_usage += thread->sched_delta;
1212: shiftp = &wait_shift[ticks];
1213: if (shiftp->shift2 > 0) {
1214: thread->cpu_usage =
1215: (thread->cpu_usage >> shiftp->shift1) +
1216: (thread->cpu_usage >> shiftp->shift2);
1217: thread->sched_usage =
1218: (thread->sched_usage >> shiftp->shift1) +
1219: (thread->sched_usage >> shiftp->shift2);
1220: }
1221: else {
1222: thread->cpu_usage =
1223: (thread->cpu_usage >> shiftp->shift1) -
1224: (thread->cpu_usage >> -(shiftp->shift2));
1225: thread->sched_usage =
1226: (thread->sched_usage >> shiftp->shift1) -
1227: (thread->sched_usage >> -(shiftp->shift2));
1228: }
1229: }
1230: thread->cpu_delta = 0;
1231: thread->sched_delta = 0;
1232: /*
1233: * Recompute priority if appropriate.
1234: */
1235: if (
1236: #if MACH_FIXPRI
1237: (thread->policy != POLICY_FIXEDPRI) &&
1238: #endif /* MACH_FIXPRI */
1239: (thread->depress_priority < 0)) {
1240: do_priority_computation(thread, temp_pri);
1241: thread->sched_pri = temp_pri;
1242: }
1243: }
1244:
1245: /*
1246: * run_queue_enqueue for thread_setrun().
1247: */
1248: run_queue_enqueue(rq, th)
1249: run_queue_t rq;
1250: thread_t th;
1251: {
1252: register unsigned int whichq;
1253:
1254: whichq = th->sched_pri;
1255: if (whichq >= NRQS) {
1256: printf("run_queue_enqueue: pri too high (%d)\n", th->sched_pri);
1257: whichq = NRQS - 1;
1258: }
1259:
1260: simple_lock(&rq->lock); /* lock the run queue */
1261: enqueue_tail(&rq->runq[whichq], (queue_entry_t) th);
1262:
1263: if (whichq > rq->high || rq->count == 0)
1264: rq->high = whichq; /* maximize */
1265:
1266: rq->count++;
1267: th->runq = rq;
1268: #if RUNQ_DEBUG
1269: THREAD_CHECK(th, rq);
1270: CHECKRQ(rq, "run_queue_enqueue");
1271: #endif /* DEBUG */
1272: simple_unlock(&rq->lock);
1273: }
1274:
1275:
1276: /*
1277: * thread_setrun:
1278: *
1279: * Make thread runnable; dispatch directly onto an idle processor
1280: * if possible. Else put on appropriate run queue (processor
1281: * if bound, else processor set. Caller must have lock on thread.
1282: * This is always called at splsched.
1283: */
1284:
1285: void thread_setrun(
1286: register thread_t th,
1287: boolean_t may_preempt)
1288: {
1289: register processor_t processor;
1290: register run_queue_t rq;
1291: #if NCPUS > 1
1292: register processor_set_t pset;
1293: #endif /* NCPUS > 1 */
1294:
1295: /*
1296: * Update priority if needed.
1297: */
1298: if (th->sched_stamp != sched_tick) {
1299: update_priority(th);
1300: }
1301:
1302: assert(th->runq == RUN_QUEUE_NULL);
1303:
1304: #if NCPUS > 1
1305: /*
1306: * Try to dispatch the thread directly onto an idle processor.
1307: */
1308: if ((processor = th->bound_processor) == PROCESSOR_NULL) {
1309: /*
1310: * Not bound, any processor in the processor set is ok.
1311: */
1312: pset = th->processor_set;
1313: #if HW_FOOTPRINT
1314: /*
1315: * But first check the last processor it ran on.
1316: */
1317: processor = th->last_processor;
1318: if (processor->state == PROCESSOR_IDLE) {
1319: simple_lock(&processor->lock);
1320: simple_lock(&pset->idle_lock);
1321: if ((processor->state == PROCESSOR_IDLE)
1322: #if MACH_HOST
1323: && (processor->processor_set == pset)
1324: #endif /* MACH_HOST */
1325: ) {
1326: queue_remove(&pset->idle_queue, processor,
1327: processor_t, processor_queue);
1328: pset->idle_count--;
1329: processor->next_thread = th;
1330: processor->state = PROCESSOR_DISPATCHING;
1331: simple_unlock(&pset->idle_lock);
1332: simple_unlock(&processor->lock);
1333: return;
1334: }
1335: simple_unlock(&pset->idle_lock);
1336: simple_unlock(&processor->lock);
1337: }
1338: #endif /* HW_FOOTPRINT */
1339:
1340: if (pset->idle_count > 0) {
1341: simple_lock(&pset->idle_lock);
1342: if (pset->idle_count > 0) {
1343: processor = (processor_t) queue_first(&pset->idle_queue);
1344: queue_remove(&(pset->idle_queue), processor, processor_t,
1345: processor_queue);
1346: pset->idle_count--;
1347: processor->next_thread = th;
1348: processor->state = PROCESSOR_DISPATCHING;
1349: simple_unlock(&pset->idle_lock);
1350: return;
1351: }
1352: simple_unlock(&pset->idle_lock);
1353: }
1354: rq = &(pset->runq);
1355: run_queue_enqueue(rq,th);
1356: /*
1357: * Preempt check
1358: */
1359: if (may_preempt &&
1360: #if MACH_HOST
1361: (pset == current_processor()->processor_set) &&
1362: #endif /* MACH_HOST */
1363: (current_thread()->sched_pri < th->sched_pri)) {
1364: /*
1365: * Turn off first_quantum to allow csw.
1366: */
1367: current_processor()->first_quantum = FALSE;
1368: ast_on(cpu_number(), AST_BLOCK);
1369: }
1370: }
1371: else {
1372: /*
1373: * Bound, can only run on bound processor. Have to lock
1374: * processor here because it may not be the current one.
1375: */
1376: if (processor->state == PROCESSOR_IDLE) {
1377: simple_lock(&processor->lock);
1378: pset = processor->processor_set;
1379: simple_lock(&pset->idle_lock);
1380: if (processor->state == PROCESSOR_IDLE) {
1381: queue_remove(&pset->idle_queue, processor,
1382: processor_t, processor_queue);
1383: pset->idle_count--;
1384: processor->next_thread = th;
1385: processor->state = PROCESSOR_DISPATCHING;
1386: simple_unlock(&pset->idle_lock);
1387: simple_unlock(&processor->lock);
1388: return;
1389: }
1390: simple_unlock(&pset->idle_lock);
1391: simple_unlock(&processor->lock);
1392: }
1393: rq = &(processor->runq);
1394: run_queue_enqueue(rq,th);
1395:
1396: /*
1397: * Cause ast on processor if processor is on line.
1398: *
1399: * XXX Don't do this remotely to master because this will
1400: * XXX send an interprocessor interrupt, and that's too
1401: * XXX expensive for all the unparallelized U*x code.
1402: */
1403: if (processor == current_processor()) {
1404: ast_on(cpu_number(), AST_BLOCK);
1405: }
1406: else if ((processor != master_processor) &&
1407: (processor->state != PROCESSOR_OFF_LINE)) {
1408: cause_ast_check(processor);
1409: }
1410: }
1411: #else /* NCPUS > 1 */
1412: /*
1413: * XXX should replace queue with a boolean in this case.
1414: */
1415: if (default_pset.idle_count > 0) {
1416: processor = (processor_t) queue_first(&default_pset.idle_queue);
1417: queue_remove(&default_pset.idle_queue, processor,
1418: processor_t, processor_queue);
1419: default_pset.idle_count--;
1420: processor->next_thread = th;
1421: processor->state = PROCESSOR_DISPATCHING;
1422: return;
1423: }
1424: if (th->bound_processor == PROCESSOR_NULL) {
1425: rq = &(default_pset.runq);
1426: }
1427: else {
1428: rq = &(master_processor->runq);
1429: ast_on(cpu_number(), AST_BLOCK);
1430: }
1431: run_queue_enqueue(rq,th);
1432:
1433: /*
1434: * Preempt check
1435: */
1436: if (may_preempt && (current_thread()->sched_pri < th->sched_pri)) {
1437: /*
1438: * Turn off first_quantum to allow context switch.
1439: */
1440: current_processor()->first_quantum = FALSE;
1441: ast_on(cpu_number(), AST_BLOCK);
1442: }
1443: #endif /* NCPUS > 1 */
1444: }
1445:
1446: /*
1447: * set_pri:
1448: *
1449: * Set the priority of the specified thread to the specified
1450: * priority. This may cause the thread to change queues.
1451: *
1452: * The thread *must* be locked by the caller.
1453: */
1454:
1455: void set_pri(
1456: thread_t th,
1457: int pri,
1458: boolean_t resched)
1459: {
1460: register struct run_queue *rq;
1461:
1462: rq = rem_runq(th);
1463: th->sched_pri = pri;
1464: if (rq != RUN_QUEUE_NULL) {
1465: if (resched)
1466: thread_setrun(th, TRUE);
1467: else
1468: run_queue_enqueue(rq, th);
1469: }
1470: }
1471:
1472: /*
1473: * rem_runq:
1474: *
1475: * Remove a thread from its run queue.
1476: * The run queue that the process was on is returned
1477: * (or RUN_QUEUE_NULL if not on a run queue). Thread *must* be locked
1478: * before calling this routine. Unusual locking protocol on runq
1479: * field in thread structure makes this code interesting; see thread.h.
1480: */
1481:
1482: struct run_queue *rem_runq(
1483: thread_t th)
1484: {
1485: register struct run_queue *rq;
1486:
1487: rq = th->runq;
1488: /*
1489: * If rq is RUN_QUEUE_NULL, the thread will stay out of the
1490: * run_queues because the caller locked the thread. Otherwise
1491: * the thread is on a runq, but could leave.
1492: */
1493: if (rq != RUN_QUEUE_NULL) {
1494: simple_lock(&rq->lock);
1495: #if RUNQ_DEBUG
1496: CHECKRQ(rq, "rem_runq: at entry");
1497: #endif /* DEBUG */
1498: if (rq == th->runq) {
1499: /*
1500: * Thread is in a runq and we have a lock on
1501: * that runq.
1502: */
1503: #if RUNQ_DEBUG
1504: CHECKRQ(rq, "rem_runq: before removing thread");
1505: THREAD_CHECK(th, rq);
1506: #endif /* DEBUG */
1507: remqueue(&rq->runq[0], (queue_entry_t) th);
1508: rq->count--;
1509: #if RUNQ_DEBUG
1510: CHECKRQ(rq, "rem_runq: after removing thread");
1511: #endif /* DEBUG */
1512: th->runq = RUN_QUEUE_NULL;
1513: simple_unlock(&rq->lock);
1514: }
1515: else {
1516: /*
1517: * The thread left the runq before we could
1518: * lock the runq. It is not on a runq now, and
1519: * can't move again because this routine's
1520: * caller locked the thread.
1521: */
1522: simple_unlock(&rq->lock);
1523: rq = RUN_QUEUE_NULL;
1524: }
1525: }
1526:
1527: return rq;
1528: }
1529:
1530:
1531: /*
1532: * choose_thread:
1533: *
1534: * Choose a thread to execute. The thread chosen is removed
1535: * from its run queue. Note that this requires only that the runq
1536: * lock be held.
1537: *
1538: * Strategy:
1539: * Check processor runq first; if anything found, run it.
1540: * Else check pset runq; if nothing found, return idle thread.
1541: *
1542: * Second line of strategy is implemented by choose_pset_thread.
1543: * This is only called on processor startup and when thread_block
1544: * thinks there's something in the processor runq.
1545: */
1546:
1547: thread_t choose_thread(
1548: processor_t myprocessor)
1549: {
1550: thread_t th;
1551: register queue_t q;
1552: register run_queue_t runq;
1553: register int i;
1554: register processor_set_t pset;
1555:
1556: runq = &myprocessor->runq;
1557:
1558: simple_lock(&runq->lock);
1559: if (runq->count > 0) {
1560: q = runq->runq + runq->high;
1561: for (i = runq->high; i >= 0 ; i--, q--) {
1562: if (!queue_empty(q)) {
1563: th = (thread_t) dequeue_head(q);
1564: th->runq = RUN_QUEUE_NULL;
1565: runq->count--;
1566: runq->high = i;
1567: simple_unlock(&runq->lock);
1568: return(th);
1569: }
1570: }
1571: panic("choose_thread");
1572: /*NOTREACHED*/
1573: }
1574: simple_unlock(&runq->lock);
1575:
1576: pset = myprocessor->processor_set;
1577:
1578: simple_lock(&pset->runq.lock);
1579: return choose_pset_thread(myprocessor,pset);
1580: }
1581:
1582: /*
1583: * choose_pset_thread: choose a thread from processor_set runq or
1584: * set processor idle and choose its idle thread.
1585: *
1586: * Caller must be at splsched and have a lock on the runq. This
1587: * lock is released by this routine. myprocessor is always the current
1588: * processor, and pset must be its processor set.
1589: * This routine chooses and removes a thread from the runq if there
1590: * is one (and returns it), else it sets the processor idle and
1591: * returns its idle thread.
1592: */
1593:
1594: thread_t choose_pset_thread(
1595: register processor_t myprocessor,
1596: processor_set_t pset)
1597: {
1598: register run_queue_t runq;
1599: register thread_t th;
1600: register queue_t q;
1601: register int i;
1602:
1603: runq = &pset->runq;
1604:
1605: if (runq->count > 0) {
1606: q = runq->runq + runq->high;
1607: for (i = runq->high; i >= 0 ; i--, q--) {
1608: if (!queue_empty(q)) {
1609: th = (thread_t) dequeue_head(q);
1610: th->runq = RUN_QUEUE_NULL;
1611: runq->count--;
1612: /*
1613: * For POLICY_FIXEDPRI, runq->low must be
1614: * accurate!
1615: */
1616: #if MACH_FIXPRI
1617: if ((runq->count > 0) &&
1618: (pset->policies & POLICY_FIXEDPRI)) {
1619: while (queue_empty(q)) {
1620: q--;
1621: i--;
1622: }
1623: }
1624: #endif /* MACH_FIXPRI */
1625: runq->high = i;
1626: #if RUNQ_DEBUG
1627: CHECKRQ(runq, "choose_pset_thread");
1628: #endif /* DEBUG */
1629: simple_unlock(&runq->lock);
1630: return th;
1631: }
1632: }
1633: panic("choose_pset_thread");
1634: /*NOTREACHED*/
1635: }
1636: simple_unlock(&runq->lock);
1637:
1638: /*
1639: * Nothing is runnable, so set this processor idle if it
1640: * was running. If it was in an assignment or shutdown,
1641: * leave it alone. Return its idle thread.
1642: */
1643: simple_lock(&pset->idle_lock);
1644: if (myprocessor->state == PROCESSOR_RUNNING) {
1645: myprocessor->state = PROCESSOR_IDLE;
1646: /*
1647: * XXX Until it goes away, put master on end of queue, others
1648: * XXX on front so master gets used last.
1649: */
1650: if (myprocessor == master_processor) {
1651: queue_enter(&(pset->idle_queue), myprocessor,
1652: processor_t, processor_queue);
1653: }
1654: else {
1655: queue_enter_first(&(pset->idle_queue), myprocessor,
1656: processor_t, processor_queue);
1657: }
1658:
1659: pset->idle_count++;
1660: }
1661: simple_unlock(&pset->idle_lock);
1662:
1663: return myprocessor->idle_thread;
1664: }
1665:
1666: /*
1667: * no_dispatch_count counts number of times processors go non-idle
1668: * without being dispatched. This should be very rare.
1669: */
1670: int no_dispatch_count = 0;
1671:
1672: /*
1673: * This is the idle thread, which just looks for other threads
1674: * to execute.
1675: */
1676:
1677: void idle_thread_continue(void)
1678: {
1679: register processor_t myprocessor;
1680: register volatile thread_t *threadp;
1681: register volatile int *gcount;
1682: register volatile int *lcount;
1683: register thread_t new_thread;
1684: register int state;
1685: int mycpu;
1686: spl_t s;
1687:
1688: mycpu = cpu_number();
1689: myprocessor = current_processor();
1690: threadp = (volatile thread_t *) &myprocessor->next_thread;
1691: lcount = (volatile int *) &myprocessor->runq.count;
1692:
1693: while (TRUE) {
1694: #ifdef MARK_CPU_IDLE
1695: MARK_CPU_IDLE(mycpu);
1696: #endif /* MARK_CPU_IDLE */
1697:
1698: #if MACH_HOST
1699: gcount = (volatile int *)
1700: &myprocessor->processor_set->runq.count;
1701: #else /* MACH_HOST */
1702: gcount = (volatile int *) &default_pset.runq.count;
1703: #endif /* MACH_HOST */
1704:
1705: /*
1706: * This cpu will be dispatched (by thread_setrun) by setting next_thread
1707: * to the value of the thread to run next. Also check runq counts.
1708: */
1709: while ((*threadp == (volatile thread_t)THREAD_NULL) &&
1710: (*gcount == 0) && (*lcount == 0)) {
1711:
1712: /* check for ASTs while we wait */
1713:
1714: if (need_ast[mycpu] &~ AST_SCHEDULING) {
1715: (void) splsched();
1716: /* don't allow scheduling ASTs */
1717: need_ast[mycpu] &= ~AST_SCHEDULING;
1718: (void) spl0();
1719: }
1720:
1721: /*
1722: * machine_idle is a machine dependent function,
1723: * to conserve power.
1724: */
1725: }
1726:
1727: #ifdef MARK_CPU_ACTIVE
1728: MARK_CPU_ACTIVE(mycpu);
1729: #endif /* MARK_CPU_ACTIVE */
1730:
1731: s = splsched();
1732:
1733: /*
1734: * This is not a switch statement to avoid the
1735: * bounds checking code in the common case.
1736: */
1737: retry:
1738: state = myprocessor->state;
1739: if (state == PROCESSOR_DISPATCHING) {
1740: /*
1741: * Commmon case -- cpu dispatched.
1742: */
1743: new_thread = (thread_t) *threadp;
1744: *threadp = (volatile thread_t) THREAD_NULL;
1745: myprocessor->state = PROCESSOR_RUNNING;
1746: /*
1747: * set up quantum for new thread.
1748: */
1749: #if MACH_FIXPRI
1750: if (new_thread->policy != POLICY_FIXEDPRI) {
1751: #endif /* MACH_FIXPRI */
1752: /*
1753: * Just use set quantum. No point in
1754: * checking for shorter local runq quantum;
1755: * csw_needed will handle correctly.
1756: */
1757: #if MACH_HOST
1758: myprocessor->quantum = new_thread->
1759: processor_set->set_quantum;
1760: #else /* MACH_HOST */
1761: myprocessor->quantum =
1762: default_pset.set_quantum;
1763: #endif /* MACH_HOST */
1764:
1765: #if MACH_FIXPRI
1766: }
1767: else {
1768: /*
1769: * POLICY_FIXEDPRI
1770: */
1771: myprocessor->quantum = new_thread->sched_data;
1772: }
1773: #endif /* MACH_FIXPRI */
1774: myprocessor->first_quantum = TRUE;
1775: counter(c_idle_thread_handoff++);
1776: thread_run(idle_thread_continue, new_thread);
1777: }
1778: else if (state == PROCESSOR_IDLE) {
1779: register processor_set_t pset;
1780:
1781: pset = myprocessor->processor_set;
1782: simple_lock(&pset->idle_lock);
1783: if (myprocessor->state != PROCESSOR_IDLE) {
1784: /*
1785: * Something happened, try again.
1786: */
1787: simple_unlock(&pset->idle_lock);
1788: goto retry;
1789: }
1790: /*
1791: * Processor was not dispatched (Rare).
1792: * Set it running again.
1793: */
1794: no_dispatch_count++;
1795: pset->idle_count--;
1796: queue_remove(&pset->idle_queue, myprocessor,
1797: processor_t, processor_queue);
1798: myprocessor->state = PROCESSOR_RUNNING;
1799: simple_unlock(&pset->idle_lock);
1800: counter(c_idle_thread_block++);
1801: thread_block_with_continuation(idle_thread_continue);
1802: }
1803: else if ((state == PROCESSOR_ASSIGN) ||
1804: (state == PROCESSOR_SHUTDOWN)) {
1805: /*
1806: * Changing processor sets, or going off-line.
1807: * Release next_thread if there is one. Actual
1808: * thread to run is on a runq.
1809: */
1810: if ((new_thread = (thread_t)*threadp)!= THREAD_NULL) {
1811: *threadp = (volatile thread_t) THREAD_NULL;
1812: thread_setrun(new_thread, FALSE);
1813: }
1814:
1815: counter(c_idle_thread_block++);
1816: thread_block_with_continuation(idle_thread_continue);
1817: }
1818: else {
1819: printf(" Bad processor state %d (Cpu %d)\n",
1820: cpu_state(mycpu), mycpu);
1821: panic("idle_thread");
1822: }
1823:
1824: (void) splx(s);
1825: }
1826: }
1827:
1828: void idle_thread(void)
1829: {
1830: register thread_t self = current_thread();
1831: spl_t s;
1832:
1833: stack_privilege(self);
1834:
1835: s = splsched();
1836: self->priority = 0;
1837: self->sched_pri = 0;
1838:
1839: /*
1840: * Set the idle flag to indicate that this is an idle thread,
1841: * enter ourselves in the idle array, and thread_block() to get
1842: * out of the run queues (and set the processor idle when we
1843: * run next time).
1844: */
1845: thread_lock(self);
1846: self->state |= TH_IDLE;
1847: thread_unlock(self);
1848: current_processor()->idle_thread = self;
1849: (void) splx(s);
1850:
1851: counter(c_idle_thread_block++);
1852: thread_block_with_continuation(idle_thread_continue);
1853: idle_thread_continue();
1854: /*NOTREACHED*/
1855: }
1856:
1857: /*
1858: * sched_thread: scheduler thread.
1859: *
1860: * This thread handles periodic calculations in the scheduler that
1861: * we don't want to do at interrupt level. This allows us to
1862: * avoid blocking.
1863: */
1864: void sched_thread_continue(void)
1865: {
1866: /*
1867: * Compute the scheduler load factors.
1868: */
1869: compute_mach_factor();
1870:
1871: /*
1872: * Scan the run queues for runnable threads that need to
1873: * have their priorities recalculated.
1874: */
1875: do_thread_scan();
1876:
1877: assert_wait((event_t) 0, FALSE);
1878: counter(c_sched_thread_block++);
1879: thread_block_with_continuation(sched_thread_continue);
1880: /*NOTREACHED*/
1881: }
1882:
1883: void sched_thread(void)
1884: {
1885: sched_thread_id = current_thread();
1886:
1887: /*
1888: * Sleep on event 0, recompute_priorities() will awaken
1889: * us by calling clear_wait().
1890: */
1891: assert_wait((event_t) 0, FALSE);
1892: counter(c_sched_thread_block++);
1893: thread_block_with_continuation(sched_thread_continue);
1894: sched_thread_continue();
1895: /*NOTREACHED*/
1896: }
1897:
1898: #define MAX_STUCK_THREADS 128
1899:
1900: /*
1901: * do_thread_scan: scan for stuck threads. A thread is stuck if
1902: * it is runnable but its priority is so low that it has not
1903: * run for several seconds. Its priority should be higher, but
1904: * won't be until it runs and calls update_priority. The scanner
1905: * finds these threads and does the updates.
1906: *
1907: * Scanner runs in two passes. Pass one squirrels likely
1908: * thread ids away in an array, and removes them from the run queue.
1909: * Pass two does the priority updates. This is necessary because
1910: * the run queue lock is required for the candidate scan, but
1911: * cannot be held during updates [set_pri will deadlock].
1912: *
1913: * Array length should be enough so that restart isn't necessary,
1914: * but restart logic is included. Does not scan processor runqs.
1915: *
1916: */
1917:
1918: boolean_t do_thread_scan_debug = FALSE;
1919:
1920: thread_t stuck_threads[MAX_STUCK_THREADS];
1921: int stuck_count = 0;
1922:
1923: /*
1924: * do_runq_scan is the guts of pass 1. It scans a runq for
1925: * stuck threads. A boolean is returned indicating whether
1926: * it ran out of space.
1927: */
1928:
1929: boolean_t
1930: do_runq_scan(
1931: run_queue_t runq)
1932: {
1933: register spl_t s;
1934: register queue_t q;
1935: register thread_t thread;
1936: register int count;
1937:
1938: s = splsched();
1939: simple_lock(&runq->lock);
1940: if((count = runq->count) > 0) {
1941: q = runq->runq + runq->high;
1942: while (count > 0) {
1943: thread = (thread_t) queue_first(q);
1944: while (!queue_end(q, (queue_entry_t) thread)) {
1945: /*
1946: * Get the next thread now, since we may
1947: * remove this thread from the run queue.
1948: */
1949: thread_t next = (thread_t) queue_next(&thread->links);
1950:
1951: if ((thread->state & TH_SCHED_STATE) == TH_RUN &&
1952: thread->sched_stamp != sched_tick) {
1953: /*
1954: * Stuck, save its id for later.
1955: */
1956: if (stuck_count == MAX_STUCK_THREADS) {
1957: /*
1958: * !@#$% No more room.
1959: */
1960: simple_unlock(&runq->lock);
1961: splx(s);
1962: return TRUE;
1963: }
1964: /*
1965: * We can`t take the thread_lock here,
1966: * since we already have the runq lock.
1967: * So we can`t grab a reference to the
1968: * thread. However, a thread that is
1969: * in RUN state cannot be deallocated
1970: * until it stops running. If it isn`t
1971: * on the runq, then thread_halt cannot
1972: * see it. So we remove the thread
1973: * from the runq to make it safe.
1974: */
1975: remqueue(q, (queue_entry_t) thread);
1976: runq->count--;
1977: thread->runq = RUN_QUEUE_NULL;
1978:
1979: stuck_threads[stuck_count++] = thread;
1980: if (do_thread_scan_debug)
1981: printf("do_runq_scan: adding thread %#x\n", thread);
1982: }
1983: count--;
1984: thread = next;
1985: }
1986: q--;
1987: }
1988: }
1989: simple_unlock(&runq->lock);
1990: splx(s);
1991:
1992: return FALSE;
1993: }
1994:
1995: void do_thread_scan(void)
1996: {
1997: register spl_t s;
1998: register boolean_t restart_needed = 0;
1999: register thread_t thread;
2000: #if MACH_HOST
2001: register processor_set_t pset;
2002: #endif /* MACH_HOST */
2003:
2004: do {
2005: #if MACH_HOST
2006: simple_lock(&all_psets_lock);
2007: queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
2008: if (restart_needed = do_runq_scan(&pset->runq))
2009: break;
2010: }
2011: simple_unlock(&all_psets_lock);
2012: #else /* MACH_HOST */
2013: restart_needed = do_runq_scan(&default_pset.runq);
2014: #endif /* MACH_HOST */
2015: if (!restart_needed)
2016: restart_needed = do_runq_scan(&master_processor->runq);
2017:
2018: /*
2019: * Ok, we now have a collection of candidates -- fix them.
2020: */
2021:
2022: while (stuck_count > 0) {
2023: thread = stuck_threads[--stuck_count];
2024: stuck_threads[stuck_count] = THREAD_NULL;
2025: s = splsched();
2026: thread_lock(thread);
2027: if ((thread->state & TH_SCHED_STATE) == TH_RUN) {
2028: /*
2029: * Do the priority update. Call
2030: * thread_setrun because thread is
2031: * off the run queues.
2032: */
2033: update_priority(thread);
2034: thread_setrun(thread, TRUE);
2035: }
2036: thread_unlock(thread);
2037: splx(s);
2038: }
2039: } while (restart_needed);
2040: }
2041:
2042: /*
2043: * Just in case someone doesn't use the macro
2044: */
2045: #undef thread_wakeup
2046: void thread_wakeup(x)
2047: void *x;
2048: {
2049: thread_wakeup_with_result(x, THREAD_AWAKENED);
2050: }
2051:
2052: #if RUNQ_DEBUG
2053: void checkrq(
2054: run_queue_t rq,
2055: char *msg)
2056: {
2057: register queue_t q1;
2058: register int i, j;
2059: register queue_entry_t e;
2060: register int high;
2061:
2062: high = NRQS;
2063: j = 0;
2064: q1 = &rq->runq[NRQS-1];
2065: for (i = NRQS-1; i >= 0; i--) {
2066: if (q1->next == q1) {
2067: if (q1->prev != q1)
2068: panic("checkrq: empty at %s", msg);
2069: }
2070: else {
2071: if (high == NRQS)
2072: high = i;
2073:
2074: for (e = q1->next; e != q1; e = e->next) {
2075: j++;
2076: if (e->next->prev != e)
2077: panic("checkrq-2 at %s", msg);
2078: if (e->prev->next != e)
2079: panic("checkrq-3 at %s", msg);
2080: }
2081: }
2082: q1--;
2083: }
2084: if (j != rq->count)
2085: panic("checkrq: count %d wrong at %s (should be %d)",
2086: j, msg, rq->count);
2087: if (rq->count != 0 && high > rq->high)
2088: panic("checkrq: high %d wrong at %s (should be %d)",
2089: high, msg, rq->high);
2090: }
2091:
2092: void thread_check(
2093: register thread_t th,
2094: register run_queue_t rq)
2095: {
2096: register unsigned int whichq;
2097:
2098: whichq = th->sched_pri;
2099: if (whichq >= NRQS) {
2100: panic("thread_check: priority %d too high\n", whichq);
2101: whichq = NRQS-1;
2102: }
2103: if ((th->links.next == &rq->runq[whichq]) &&
2104: (rq->runq[whichq].prev != (queue_entry_t)th))
2105: panic("thread_check");
2106: }
2107: #endif /* DEBUG */
2108:
2109: int thread_wait_result()
2110: {
2111: return current_thread()->wait_result;
2112: }
2113:
2114: void thread_block(void)
2115: {
2116: thread_block_with_continuation((continuation_t) 0);
2117: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.