|
|
1.1 root 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 [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: */
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 <mach_host.h>
66: #include <power_save.h>
67: #include <task_swapper.h>
68:
69: #include <ddb/db_output.h>
70: #include <mach/machine.h>
71: #include <machine/machine_routines.h>
72: #include <machine/sched_param.h>
73: #include <kern/ast.h>
74: #include <kern/clock.h>
75: #include <kern/counters.h>
76: #include <kern/cpu_number.h>
77: #include <kern/cpu_data.h>
78: #include <kern/etap_macros.h>
79: #include <kern/lock.h>
80: #include <kern/macro_help.h>
81: #include <kern/machine.h>
82: #include <kern/misc_protos.h>
83: #include <kern/processor.h>
84: #include <kern/queue.h>
85: #include <kern/sched.h>
86: #include <kern/sched_prim.h>
87: #include <kern/syscall_subr.h>
88: #include <kern/task.h>
89: #include <kern/thread.h>
90: #include <kern/thread_swap.h>
91: #include <vm/pmap.h>
92: #include <vm/vm_kern.h>
93: #include <vm/vm_map.h>
94: #include <mach/policy.h>
95: #include <mach/sync_policy.h>
96: #include <kern/sf.h>
97: #include <kern/mk_sp.h> /*** ??? fix so this can be removed ***/
98: #include <sys/kdebug.h>
99:
100: #if TASK_SWAPPER
101: #include <kern/task_swap.h>
102: extern int task_swap_on;
103: #endif /* TASK_SWAPPER */
104:
105: extern int hz;
106:
107: #define DEFAULT_PREEMPTION_RATE 100 /* (1/s) */
108: int default_preemption_rate = DEFAULT_PREEMPTION_RATE;
109: int min_quantum;
110:
111: unsigned sched_tick;
112:
113: #if SIMPLE_CLOCK
114: int sched_usec;
115: #endif /* SIMPLE_CLOCK */
116:
117: /* Forwards */
118: void thread_continue(thread_t);
119:
120: void wait_queues_init(void);
121:
122: void set_pri(
123: thread_t thread,
124: int pri,
125: int resched);
126:
127: thread_t choose_pset_thread(
128: processor_t myprocessor,
129: processor_set_t pset);
130:
131: thread_t choose_thread(
132: processor_t myprocessor);
133:
134: int run_queue_enqueue(
135: run_queue_t runq,
136: thread_t thread,
137: boolean_t tail);
138:
139: void idle_thread_continue(void);
140: void do_thread_scan(void);
141:
142: static
143: void clear_wait_internal(
144: thread_t thread,
145: int result);
146:
147:
148: void dump_run_queues(run_queue_t);
149: void dump_run_queue_struct( run_queue_t );
150: void dump_processor( processor_t );
151: void dump_processor_set( processor_set_t );
152:
153: #if DEBUG
154: void checkrq(
155: run_queue_t rq,
156: char *msg);
157:
158: void thread_check(
159: thread_t thread,
160: run_queue_t runq);
161: #endif /*DEBUG*/
162:
163: boolean_t thread_runnable(
164: thread_t thread);
165:
166: /*
167: * State machine
168: *
169: * states are combinations of:
170: * R running
171: * W waiting (or on wait queue)
172: * N non-interruptible
173: * O swapped out
174: * I being swapped in
175: *
176: * init action
177: * assert_wait thread_block clear_wait swapout swapin
178: *
179: * R RW, RWN R; setrun - -
180: * RN RWN RN; setrun - -
181: *
182: * RW W R -
183: * RWN WN RN -
184: *
185: * W R; setrun WO
186: * WN RN; setrun -
187: *
188: * RO - - R
189: *
190: */
191:
192: /*
193: * Waiting protocols and implementation:
194: *
195: * Each thread may be waiting for exactly one event; this event
196: * is set using assert_wait(). That thread may be awakened either
197: * by performing a thread_wakeup_prim() on its event,
198: * or by directly waking that thread up with clear_wait().
199: *
200: * The implementation of wait events uses a hash table. Each
201: * bucket is queue of threads having the same hash function
202: * value; the chain for the queue (linked list) is the run queue
203: * field. [It is not possible to be waiting and runnable at the
204: * same time.]
205: *
206: * Locks on both the thread and on the hash buckets govern the
207: * wait event field and the queue chain field. Because wakeup
208: * operations only have the event as an argument, the event hash
209: * bucket must be locked before any thread.
210: *
211: * Scheduling operations may also occur at interrupt level; therefore,
212: * interrupts below splsched() must be prevented when holding
213: * thread or hash bucket locks.
214: *
215: * The wait event hash table declarations are as follows:
216: */
217:
218: #define NUMQUEUES 59
219:
220: struct wait_queue wait_queues[NUMQUEUES];
221:
222: #define wait_hash(event) \
223: ((((int)(event) < 0)? ~(int)(event): (int)(event)) % NUMQUEUES)
224:
225: void
226: sched_init(void)
227: {
228: /*
229: * Calculate the minimum quantum
230: * in ticks.
231: */
232: if (default_preemption_rate < 1)
233: default_preemption_rate = DEFAULT_PREEMPTION_RATE;
234: min_quantum = hz / default_preemption_rate;
235: /*
236: * Round up result (4/5) to an
237: * integral number of ticks.
238: */
239: if (((hz * 10) / default_preemption_rate) - (min_quantum * 10) >= 5)
240: min_quantum++;
241: if (min_quantum < 1)
242: min_quantum = 1;
243: printf("minimum scheduling quantum is %d ms\n", (1000 / hz) * min_quantum);
244:
245: wait_queues_init();
246: pset_sys_bootstrap(); /* initialize processer mgmt. */
247: queue_init(&action_queue);
248: simple_lock_init(&action_lock, ETAP_THREAD_ACTION);
249: sched_tick = 0;
250: #if SIMPLE_CLOCK
251: sched_usec = 0;
252: #endif /* SIMPLE_CLOCK */
253: ast_init();
254: /*** ??? is this the right place?***/
255: sf_init();
256: }
257:
258: void
259: wait_queues_init(void)
260: {
261: register int i;
262:
263: for (i = 0; i < NUMQUEUES; i++) {
264: wait_queue_init(&wait_queues[i], SYNC_POLICY_FIFO);
265: }
266: }
267:
268: /*
269: * Thread timeout routine, called when timer expires.
270: */
271: void
272: thread_timer_expire(
273: thread_t thread)
274: {
275: spl_t s;
276:
277: s = splsched();
278: thread_lock(thread);
279: if ( thread->wait_timer_is_set &&
280: !thread_call_is_delayed(&thread->wait_timer, NULL) ) {
281: thread->wait_timer_is_set = FALSE;
282: if (thread->active)
283: clear_wait_internal(thread, THREAD_TIMED_OUT);
284: }
285: thread_unlock(thread);
286: splx(s);
287:
288: thread_deallocate(thread);
289: }
290:
291: /*
292: * thread_set_timer:
293: *
294: * Set a timer for the current thread, if the thread
295: * is ready to wait. Must be called between assert_wait()
296: * and thread_block().
297: */
298: void
299: thread_set_timer(
300: natural_t interval,
301: natural_t scale_factor)
302: {
303: thread_t thread = current_thread();
304: AbsoluteTime deadline;
305: spl_t s;
306:
307: s = splsched();
308: thread_lock(thread);
309: if ((thread->state & TH_WAIT) != 0) {
310: clock_interval_to_deadline(interval, scale_factor, &deadline);
311: thread_call_enter_delayed(&thread->wait_timer, deadline);
312: assert(!thread->wait_timer_is_set);
313: thread->ref_count++;
314: thread->wait_timer_is_set = TRUE;
315: }
316: thread_unlock(thread);
317: splx(s);
318: }
319:
320: void
321: thread_set_timer_deadline(
322: AbsoluteTime deadline)
323: {
324: thread_t thread = current_thread();
325: spl_t s;
326:
327: s = splsched();
328: thread_lock(thread);
329: if ((thread->state & TH_WAIT) != 0) {
330: thread_call_enter_delayed(&thread->wait_timer, deadline);
331: assert(!thread->wait_timer_is_set);
332: thread->ref_count++;
333: thread->wait_timer_is_set = TRUE;
334: }
335: thread_unlock(thread);
336: splx(s);
337: }
338:
339: void
340: thread_cancel_timer(void)
341: {
342: thread_t thread = current_thread();
343: boolean_t release = FALSE;
344: spl_t s;
345:
346: s = splsched();
347: thread_lock(thread);
348: if (thread->wait_timer_is_set) {
349: if (thread_call_cancel(&thread->wait_timer))
350: release = TRUE;
351: thread->wait_timer_is_set = FALSE;
352: }
353: thread_unlock(thread);
354: splx(s);
355:
356: if (release)
357: thread_deallocate(thread);
358: }
359:
360: /*
361: * thread_depress_timeout:
362: *
363: * Timeout routine for priority depression.
364: */
365: void
366: thread_depress_timeout(
367: thread_t thread)
368: {
369: sched_policy_t *policy;
370: spl_t s;
371:
372: s = splsched();
373: thread_lock(thread);
374: policy = policy_id_to_sched_policy(thread->policy);
375: thread_unlock(thread);
376: splx(s);
377:
378: if (policy != SCHED_POLICY_NULL)
379: policy->sp_ops.sp_thread_depress_timeout(policy, thread);
380:
381: thread_deallocate(thread);
382: }
383:
384: /*
385: * Set up thread timeout element when thread is created.
386: */
387: void
388: thread_timer_setup(
389: thread_t thread)
390: {
391: thread_call_setup(&thread->wait_timer, thread_timer_expire, thread);
392: thread->wait_timer_is_set = FALSE;
393: thread_call_setup(&thread->depress_timer, thread_depress_timeout, thread);
394: }
395:
396: /*
397: * Routine: thread_go_locked
398: * Purpose:
399: * Start a thread running.
400: * Conditions:
401: * thread lock held, IPC locks may be held.
402: * thread must have been pulled from wait queue under same lock hold.
403: */
404: void
405: thread_go_locked(
406: thread_t thread,
407: int result)
408: {
409: int state;
410: sched_policy_t *policy;
411: sf_return_t sfr;
412:
413: assert(thread->at_safe_point == FALSE);
414: assert(thread->wait_event == NO_EVENT);
415: assert(thread->wait_queue == WAIT_QUEUE_NULL);
416:
417: if (thread->state & TH_WAIT) {
418:
419: thread->state &= ~TH_WAIT;
420: if (!(thread->state & TH_RUN)) {
421: thread->state |= TH_RUN;
422: #if THREAD_SWAPPER
423: if (thread->state & TH_SWAPPED_OUT)
424: thread_swapin(thread->top_act, FALSE);
425: else
426: #endif /* THREAD_SWAPPER */
427: {
428: policy = &sched_policy[thread->policy];
429: sfr = policy->sp_ops.sp_thread_unblock(policy, thread);
430: assert(sfr == SF_SUCCESS);
431: }
432: }
433: thread->wait_result = result;
434: }
435:
436:
437: /*
438: * The next few lines are a major hack. Hopefully this will get us
439: * around all of the scheduling framework hooha. We can't call
440: * sp_thread_unblock yet because we could still be finishing up the
441: * durn two stage block on another processor and thread_setrun
442: * could be called by s_t_u and we'll really be messed up then.
443: */
444: /* Don't mess with this if we are still swapped out */
445: if (!(thread->state & TH_SWAPPED_OUT))
446: ((mk_sp_info_t)thread->sp_info)->th_state = MK_SP_RUNNABLE;
447:
448: }
449:
450: void
451: thread_mark_wait_locked(
452: thread_t thread,
453: int interruptible)
454: {
455:
456: assert(thread == current_thread());
457:
458: thread->wait_result = -1; /* JMM - Needed for non-assert kernel */
459: thread->state |= (interruptible) ? TH_WAIT : (TH_WAIT | TH_UNINT);
460: thread->at_safe_point = (interruptible == THREAD_ABORTSAFE);
461: thread->sleep_stamp = sched_tick;
462: }
463:
464:
465:
466: /*
467: * Routine: assert_wait_timeout
468: * Purpose:
469: * Assert that the thread intends to block,
470: * waiting for a timeout (no user known event).
471: */
472: unsigned int assert_wait_timeout_event;
473:
474: void
475: assert_wait_timeout(
476: mach_msg_timeout_t msecs,
477: int interruptible)
478: {
479: spl_t s;
480:
481: assert_wait((event_t)&assert_wait_timeout_event, interruptible);
482: thread_set_timer(msecs, 1000*NSEC_PER_USEC);
483: }
484:
485: /*
486: * Check to see if an assert wait is possible, without actually doing one.
487: * This is used by debug code in locks and elsewhere to verify that it is
488: * always OK to block when trying to take a blocking lock (since waiting
489: * for the actual assert_wait to catch the case may make it hard to detect
490: * this case.
491: */
492: boolean_t
493: assert_wait_possible(void)
494: {
495: thread_t thread = current_thread();
496:
497: return (thread == NULL || wait_queue_assert_possible(thread));
498: }
499:
500: /*
501: * assert_wait:
502: *
503: * Assert that the current thread is about to go to
504: * sleep until the specified event occurs.
505: */
506: void
507: assert_wait(
508: event_t event,
509: int interruptible)
510: {
511: register wait_queue_t wq;
512: register int index;
513:
514: assert(event != NO_EVENT);
515: assert(assert_wait_possible());
516:
517: index = wait_hash(event);
518: wq = &wait_queues[index];
519: wait_queue_assert_wait(wq,
520: event,
521: interruptible);
522: }
523:
524:
525: /*
526: * thread_[un]stop(thread)
527: * Once a thread has blocked interruptibly (via assert_wait) prevent
528: * it from running until thread_unstop.
529: *
530: * If someone else has already stopped the thread, wait for the
531: * stop to be cleared, and then stop it again.
532: *
533: * Return FALSE if interrupted.
534: *
535: * NOTE: thread_hold/thread_suspend should be called on the activation
536: * before calling thread_stop. TH_SUSP is only recognized when
537: * a thread blocks and only prevents clear_wait/thread_wakeup
538: * from restarting an interruptible wait. The wake_active flag is
539: * used to indicate that someone is waiting on the thread.
540: */
541: boolean_t
542: thread_stop(
543: thread_t thread)
544: {
545: spl_t s;
546:
547: s = splsched();
548: wake_lock(thread);
549:
550: while (thread->state & TH_SUSP) {
551: thread->wake_active = TRUE;
552: assert_wait((event_t)&thread->wake_active, THREAD_ABORTSAFE);
553: wake_unlock(thread);
554: splx(s);
555:
556: thread_block((void (*)(void)) 0);
557: if (current_thread()->wait_result != THREAD_AWAKENED)
558: return (FALSE);
559:
560: s = splsched();
561: wake_lock(thread);
562: }
563: thread_lock(thread);
564: thread->state |= TH_SUSP;
565: thread_unlock(thread);
566:
567: wake_unlock(thread);
568: splx(s);
569:
570: return (TRUE);
571: }
572:
573: /*
574: * Clear TH_SUSP and if the thread has been stopped and is now runnable,
575: * put it back on the run queue.
576: */
577: void
578: thread_unstop(
579: thread_t thread)
580: {
581: sched_policy_t *policy;
582: sf_return_t sfr;
583: spl_t s;
584:
585: s = splsched();
586: wake_lock(thread);
587: thread_lock(thread);
588:
589: if ((thread->state & (TH_RUN|TH_WAIT|TH_SUSP/*|TH_UNINT*/)) == TH_SUSP) {
590: thread->state = (thread->state & ~TH_SUSP) | TH_RUN;
591: #if THREAD_SWAPPER
592: if (thread->state & TH_SWAPPED_OUT)
593: thread_swapin(thread->top_act, FALSE);
594: else
595: #endif /* THREAD_SWAPPER */
596: {
597: policy = &sched_policy[thread->policy];
598: sfr = policy->sp_ops.sp_thread_unblock(policy, thread);
599: assert(sfr == SF_SUCCESS);
600: }
601: }
602: else
603: if (thread->state & TH_SUSP) {
604: thread->state &= ~TH_SUSP;
605:
606: if (thread->wake_active) {
607: thread->wake_active = FALSE;
608: thread_unlock(thread);
609: wake_unlock(thread);
610: splx(s);
611: thread_wakeup((event_t)&thread->wake_active);
612:
613: return;
614: }
615: }
616:
617: thread_unlock(thread);
618: wake_unlock(thread);
619: splx(s);
620: }
621:
622: /*
623: * Wait for the thread's RUN bit to clear
624: */
625: boolean_t
626: thread_wait(
627: thread_t thread)
628: {
629: spl_t s;
630:
631: s = splsched();
632: wake_lock(thread);
633:
634: while (thread->state & (TH_RUN/*|TH_UNINT*/)) {
635: if (thread->last_processor != PROCESSOR_NULL)
636: cause_ast_check(thread->last_processor);
637:
638: thread->wake_active = TRUE;
639: assert_wait((event_t)&thread->wake_active, THREAD_ABORTSAFE);
640: wake_unlock(thread);
641: splx(s);
642:
643: thread_block((void (*)(void))0);
644: if (current_thread()->wait_result != THREAD_AWAKENED)
645: return (FALSE);
646:
647: s = splsched();
648: wake_lock(thread);
649: }
650:
651: wake_unlock(thread);
652: splx(s);
653:
654: return (TRUE);
655: }
656:
657:
658: /*
659: * thread_stop_wait(thread)
660: * Stop the thread then wait for it to block interruptibly
661: */
662: boolean_t
663: thread_stop_wait(
664: thread_t thread)
665: {
666: if (thread_stop(thread)) {
667: if (thread_wait(thread))
668: return (TRUE);
669:
670: thread_unstop(thread);
671: }
672:
673: return (FALSE);
674: }
675:
676:
677: static
678: void
679: clear_wait_internal(
680: thread_t thread,
681: int result)
682: {
683: register int index;
684: register queue_t q;
685: register event_t event;
686: register simple_lock_t lock;
687: sched_policy_t *policy;
688: sf_return_t sfr;
689:
690: /*
691: * If the thread isn't in a wait queue, just set it running. Otherwise,
692: * try to remove it from the queue and, if successful, then set it
693: * running.
694: */
695: if (wait_queue_assert_possible(thread) ||
696: (wait_queue_remove(thread) == KERN_SUCCESS)) {
697: thread_go_locked(thread, result);
698: }
699: }
700:
701: /*
702: * clear_wait:
703: *
704: * Clear the wait condition for the specified thread. Start the thread
705: * executing if that is appropriate.
706: *
707: * parameters:
708: * thread thread to awaken
709: * result Wakeup result the thread should see
710: * interruptible Don't wake up the thread if it isn't interruptible.
711: */
712: void
713: clear_wait(
714: thread_t thread,
715: int result,
716: boolean_t interruptible)
717: {
718: spl_t s;
719:
720: s = splsched();
721: thread_lock(thread);
722: if (!interruptible || !(thread->state & TH_UNINT))
723: clear_wait_internal(thread, result);
724: thread_unlock(thread);
725: splx(s);
726: }
727:
728:
729: /*
730: * thread_wakeup_prim:
731: *
732: * Common routine for thread_wakeup, thread_wakeup_with_result,
733: * and thread_wakeup_one.
734: *
735: */
736: void
737: thread_wakeup_prim(
738: event_t event,
739: boolean_t one_thread,
740: int result)
741: {
742: register wait_queue_t wq;
743: register int index;
744:
745: index = wait_hash(event);
746: wq = &wait_queues[index];
747: if (one_thread)
748: wait_queue_wakeup_one(wq, event, result);
749: else
750: wait_queue_wakeup_all(wq, event, result);
751: }
752:
753: /*
754: * thread_bind:
755: *
756: * Force a thread to execute on the specified processor.
757: * If the thread is currently executing, it may wait until its
758: * time slice is up before switching onto the specified processor.
759: *
760: * A processor of PROCESSOR_NULL causes the thread to be unbound.
761: * xxx - DO NOT export this to users.
762: */
763: void
764: thread_bind(
765: register thread_t thread,
766: processor_t processor)
767: {
768: spl_t s;
769:
770: s = splsched();
771: thread_lock(thread);
772: thread_bind_locked(thread, processor);
773: thread_unlock(thread);
774: splx(s);
775: }
776:
777: /*
778: * Select a thread for this processor (the current processor) to run.
779: * May select the current thread.
780: * Assumes splsched.
781: */
782: thread_t
783: thread_select(
784: register processor_t myprocessor)
785: {
786: register thread_t thread;
787: processor_set_t pset;
788: register run_queue_t runq = &myprocessor->runq;
789: boolean_t other_runnable;
790: sched_policy_t *policy;
791: sf_return_t sfr;
792:
793: /*
794: * Check for other non-idle runnable threads.
795: */
796: myprocessor->first_quantum = TRUE;
797: pset = myprocessor->processor_set;
798: thread = current_thread();
799:
800: #if 0 /* CHECKME! */
801: thread->unconsumed_quantum = myprocessor->quantum;
802: #endif
803:
804: simple_lock(&runq->lock);
805: simple_lock(&pset->runq.lock);
806:
807: other_runnable = runq->count > 0 || pset->runq.count > 0;
808:
809: if ( (!other_runnable ||
810: (runq->highq < thread->sched_pri &&
811: pset->runq.highq < thread->sched_pri)) &&
812: #if MACH_HOST
813: thread->processor_set == pset &&
814: #endif /* MACH_HOST */
815: (thread->bound_processor == PROCESSOR_NULL ||
816: thread->bound_processor == myprocessor) &&
817: thread->state == TH_RUN &&
818: thread->pending_policy == POLICY_NULL ) {
819:
820: /* I am the highest priority runnable thread: */
821: simple_unlock(&pset->runq.lock);
822: simple_unlock(&runq->lock);
823:
824: /* Update the thread's meta-priority */
825: policy = &sched_policy[thread->policy];
826: /*** ??? maybe use a macro ***/
827: sfr = policy->sp_ops.sp_thread_update_mpri(policy, thread);
828: assert(sfr == SF_SUCCESS);
829: }
830: else if (other_runnable) {
831: simple_unlock(&pset->runq.lock);
832: simple_unlock(&runq->lock);
833: thread = choose_thread(myprocessor);
834: }
835: else {
836: simple_unlock(&runq->lock);
837:
838: /*
839: * Nothing non-idle runnable, including myself.
840: * Return if this
841: * thread is still runnable on this processor.
842: * Check for priority update if required.
843: */
844: /* get an idle thread to run */
845: thread = choose_pset_thread(myprocessor, pset);
846: }
847:
848: if (thread->policy & (POLICY_RR|POLICY_FIFO))
849: #if 1 /* CHECKME! */
850: myprocessor->quantum = pset->set_quantum;
851: #else
852: myprocessor->quantum = thread->unconsumed_quantum;
853: #endif
854: else
855: myprocessor->quantum = thread->bound_processor?
856: min_quantum : pset->set_quantum;
857:
858: return (thread);
859: }
860:
861:
862: /*
863: * Stop running the current thread and start running the new thread.
864: * If continuation is non-zero, and the current thread is blocked,
865: * then it will resume by executing continuation on a new stack.
866: * Returns TRUE if the hand-off succeeds.
867: * The reason parameter == AST_QUANTUM if the thread blocked
868: * because its quantum expired.
869: * Assumes splsched.
870: */
871:
872:
873: static thread_t
874: __current_thread(void)
875: {
876: return (current_thread());
877: }
878:
879:
880: boolean_t
881: thread_invoke(
882: register thread_t old_thread,
883: register thread_t new_thread,
884: int reason,
885: void (*continuation)(void))
886: {
887: sched_policy_t *policy;
888: sf_return_t sfr;
889: thread_t old_thread_hold;
890: void (*lcont)(void);
891:
892: /*
893: * Mark thread interruptible.
894: */
895: thread_lock(new_thread);
896: new_thread->state &= ~TH_UNINT;
897:
898: assert(thread_runnable(new_thread));
899:
900: /*
901: * Check for invoking the same thread.
902: */
903: if (old_thread == new_thread) {
904: counter(++c_thread_invoke_same);
905: thread_unlock(new_thread);
906: if (continuation != (void (*)()) 0) {
907: if (old_thread->funnel_state & TH_FN_REFUNNEL) {
908: kern_return_t save_wait_result;
909: old_thread->funnel_state = 0;
910: save_wait_result = old_thread->wait_result;
911: mutex_lock(&funnel_lock);
912: old_thread->funnel_state = TH_FN_OWNED;
913: old_thread->wait_result = save_wait_result;
914: }
915: (void) spllo();
916: call_continuation(continuation);
917: /*NOTREACHED*/
918: }
919: return TRUE;
920: }
921:
922: if ((old_thread->stack_privilege != current_stack()) &&
923: (continuation != (void (*)()) 0))
924: {
925: switch (new_thread->state & TH_STACK_STATE) {
926: case TH_STACK_HANDOFF:
927: new_thread->state &= ~(TH_STACK_HANDOFF|TH_UNINT);
928: thread_unlock(new_thread);
929:
930: mp_disable_preemption();
931: new_thread->last_processor = current_processor();
932: mp_enable_preemption();
933:
934: /*
935: * Set up ast context of new thread and switch to its timer.
936: */
937: mp_disable_preemption();
938: ast_context(new_thread->top_act, cpu_number());
939: mp_enable_preemption();
940: timer_switch(&new_thread->system_timer);
941:
942: old_thread->continuation = continuation;
943: stack_handoff(old_thread, new_thread);
944: act_machine_sv_free(old_thread->top_act);
945:
946: thread_lock(old_thread);
947:
948: /*
949: * inline thread_dispatch but don't free stack
950: */
951:
952: switch (old_thread->state & (TH_RUN|TH_WAIT|TH_UNINT|TH_IDLE)) {
953: sched_policy_t *policy;
954: sf_return_t sfr;
955:
956: case TH_RUN | TH_UNINT:
957: case TH_RUN:
958: /*
959: * No reason to stop. Put back on a run queue.
960: */
961: old_thread->state |= TH_STACK_HANDOFF;
962:
963: /* Get pointer to scheduling policy "object" */
964: policy = &sched_policy[old_thread->policy];
965:
966: /* Leave enqueueing thread up to scheduling policy */
967: sfr = policy->sp_ops.sp_thread_dispatch(policy,
968: old_thread);
969: assert(sfr == SF_SUCCESS);
970:
971: break;
972:
973: case TH_RUN | TH_WAIT | TH_UNINT:
974: case TH_RUN | TH_WAIT:
975: old_thread->sleep_stamp = sched_tick;
976:
977: /* fallthrough */
978: case TH_WAIT: /* this happens! */
979:
980: /*
981: * Waiting
982: */
983: old_thread->state |= TH_STACK_HANDOFF;
984: old_thread->state &= ~TH_RUN;
985: if (old_thread->state & TH_TERMINATE)
986: thread_reaper_enqueue(old_thread);
987:
988: if (old_thread->wake_active) {
989: old_thread->wake_active = FALSE;
990: thread_unlock(old_thread);
991: thread_wakeup((event_t)&old_thread->wake_active);
992: goto after_old_thread;
993: }
994: break;
995:
996: case TH_RUN | TH_IDLE:
997: /*
998: * Drop idle thread -- it is already in
999: * idle_thread_array.
1000: */
1001: old_thread->state |= TH_STACK_HANDOFF;
1002:
1003: break;
1004:
1005: default:
1006: panic("State 0x%x \n",old_thread->state);
1007: }
1008:
1009: thread_unlock(old_thread);
1010: after_old_thread:
1011: /*
1012: * call_continuation calls the continuation after
1013: resetting the current stack pointer to recover
1014: stack space. without this we could stack overflow
1015: */
1016: disable_preemption();
1017:
1018: thread_lock(old_thread);
1019:
1020: /* Get pointer to scheduling policy "object" */
1021: policy = &sched_policy[old_thread->policy];
1022:
1023: /* Indicate to sched policy that old thread has stopped execution */
1024: /*** ??? maybe use a macro -- rkc, 1/4/96 ***/
1025: sfr = policy->sp_ops.sp_thread_done(policy,
1026: old_thread);
1027: assert(sfr == SF_SUCCESS);
1028:
1029: /* Process any pending scheduling policy change */
1030: if (old_thread->pending_policy != POLICY_NULL) {
1031: sched_policy_t *policy;
1032: sf_return_t sfr;
1033: if (old_thread->policy != old_thread->pending_policy) {
1034: /* Detach thread from current scheduling policy */
1035: sfr = policy->sp_ops.sp_thread_detach(
1036: policy,
1037: old_thread);
1038: assert(sfr == SF_SUCCESS);
1039:
1040: /* Attach to the pending policy */
1041: policy = &sched_policy[old_thread->pending_policy];
1042: sfr = policy->sp_ops.sp_thread_attach(
1043: policy,
1044: old_thread);
1045:
1046: /* Save result for issuer of policy change */
1047: old_thread->change_sfr = (kern_return_t)sfr;
1048:
1049: /* If successful so far, set up sched attributes */
1050: if (sfr == SF_SUCCESS) {
1051: sfr = policy->sp_ops.sp_thread_set(
1052: policy,
1053: old_thread,
1054: old_thread->pending_sched_attr);
1055:
1056: /* Save result for issuer of policy change */
1057: old_thread->change_sfr = (kern_return_t)sfr;
1058: }
1059: }
1060:
1061: /* Indicate change has been done */
1062: old_thread->pending_policy = POLICY_NULL;
1063: }
1064: thread_unlock(old_thread);
1065: thread_lock(new_thread);
1066:
1067: assert(thread_runnable(new_thread));
1068:
1069: /* Get pointer to scheduling policy "object" */
1070: policy = &sched_policy[new_thread->policy];
1071:
1072: /* Indicate to sched policy that new thread has started execution */
1073: /*** ??? maybe use a macro ***/
1074: sfr = policy->sp_ops.sp_thread_begin(policy, new_thread);
1075: assert(sfr == SF_SUCCESS);
1076: thread_unlock(new_thread);
1077: enable_preemption();
1078:
1079: counter_always(c_thread_invoke_hits++);
1080: (void) spllo();
1081: lcont = new_thread->continuation;
1082: assert(lcont);
1083: if (new_thread->funnel_state & TH_FN_REFUNNEL) {
1084: kern_return_t save_wait_result;
1085: new_thread->funnel_state = 0;
1086: save_wait_result = new_thread->wait_result;
1087: mutex_lock(&funnel_lock);
1088: new_thread->funnel_state = TH_FN_OWNED;
1089: new_thread->wait_result = save_wait_result;
1090: }
1091: assert(lcont);
1092: call_continuation(lcont);
1093: /*NOTREACHED*/
1094: return TRUE;
1095:
1096: case TH_STACK_COMING_IN:
1097: /*
1098: * waiting for a stack
1099: */
1100: thread_swapin(new_thread);
1101: thread_unlock(new_thread);
1102: counter_always(c_thread_invoke_misses++);
1103: return FALSE;
1104:
1105: case 0:
1106: /*
1107: * already has a stack - can't handoff
1108: */
1109:
1110: break;
1111: }
1112: }
1113: else
1114: {
1115: /*
1116: * check that the new thread has a stack
1117: */
1118: if (new_thread->state & TH_STACK_HANDOFF) {
1119: /* has no stack. if not already waiting for one try to get one */
1120: if ((new_thread->state & TH_STACK_COMING_IN) ||
1121: /* not already waiting. nonblocking try to get one */
1122: !stack_alloc_try(new_thread, thread_continue))
1123: {
1124: /* couldn't get one. schedule new thread to get a stack and
1125: return failure so we can try another thread. */
1126: thread_swapin(new_thread);
1127: thread_unlock(new_thread);
1128: counter_always(c_thread_invoke_misses++);
1129: return FALSE;
1130: }
1131: }
1132: /* new thread now has a stack. it has been setup to resume in
1133: thread_continue so it can dispatch the old thread, deal with
1134: funnelling and then go to it's true continuation point */
1135: }
1136:
1137: new_thread->state &= ~(TH_STACK_HANDOFF | TH_UNINT);
1138:
1139: /*
1140: * Thread is now interruptible.
1141: */
1142: mp_disable_preemption();
1143: new_thread->last_processor = current_processor();
1144: mp_enable_preemption();
1145:
1146: thread_unlock(new_thread);
1147:
1148: /*
1149: * Set up ast context of new thread and switch to its timer.
1150: */
1151: mp_disable_preemption();
1152: ast_context(new_thread->top_act, cpu_number());
1153: mp_enable_preemption();
1154: timer_switch(&new_thread->system_timer);
1155:
1156: /*
1157: * switch_context is machine-dependent. It does the
1158: * machine-dependent components of a context-switch, like
1159: * changing address spaces. It updates active_threads.
1160: */
1161: old_thread->reason = reason;
1162: counter_always(c_thread_invoke_csw++);
1163: current_task()->csw++;
1164:
1165: /*
1166: * N.B. On return from the call to switch_context, 'old_thread'
1167: * points at the thread that yielded to us. Unfortunately, at
1168: * this point, there are no simple_locks held, so if we are preempted
1169: * before the call to thread_dispatch blocks preemption, it is
1170: * possible for 'old_thread' to terminate, leaving us with a
1171: * stale thread pointer.
1172: */
1173: assert(thread_runnable(new_thread));
1174: assert(old_thread->runq == RUN_QUEUE_NULL);
1175:
1176: disable_preemption();
1177:
1178: thread_lock(old_thread);
1179:
1180: /* Indicate to sched policy that old thread has stopped execution */
1181: policy = &sched_policy[old_thread->policy];
1182: /*** ??? maybe use a macro -- ***/
1183: sfr = policy->sp_ops.sp_thread_done(policy, old_thread);
1184: assert(sfr == SF_SUCCESS);
1185:
1186: /* Process any pending scheduling policy change */
1187: if (old_thread->pending_policy != POLICY_NULL) {
1188: if (old_thread->policy != old_thread->pending_policy) {
1189: /* Detach thread from current scheduling policy */
1190: sfr = policy->sp_ops.sp_thread_detach(policy, old_thread);
1191: assert(sfr == SF_SUCCESS);
1192:
1193: /* Attach to the pending policy */
1194: policy = &sched_policy[old_thread->pending_policy];
1195: sfr = policy->sp_ops.sp_thread_attach(policy, old_thread);
1196:
1197: /* Save result for issuer of policy change */
1198: old_thread->change_sfr = (kern_return_t)sfr;
1199:
1200: /* If successful so far, set up sched attributes */
1201: if (sfr == SF_SUCCESS) {
1202: sfr = policy->sp_ops.sp_thread_set(policy, old_thread,
1203: old_thread->pending_sched_attr);
1204:
1205: /* Save result for issuer of policy change */
1206: old_thread->change_sfr = (kern_return_t)sfr;
1207: }
1208: }
1209:
1210: /* Indicate change has been done */
1211: old_thread->pending_policy = POLICY_NULL;
1212: }
1213:
1214: thread_unlock(old_thread);
1215: old_thread_hold = old_thread;
1216:
1217: /* SWITCH CONTEXT HERE */
1218:
1219: old_thread = switch_context(old_thread, continuation, new_thread);
1220:
1221: /* Now on new thread's stack. Set a local variable to refer to it. */
1222: new_thread = __current_thread();
1223: assert(old_thread != new_thread);
1224:
1225: assert(thread_runnable(new_thread));
1226:
1227: thread_lock(new_thread);
1228: assert(thread_runnable(new_thread));
1229: /* Indicate to sched policy that new thread has started execution */
1230: policy = &sched_policy[new_thread->policy];
1231: /*** ??? maybe use a macro -- rkc, 1/4/96 ***/
1232: sfr = policy->sp_ops.sp_thread_begin(policy, new_thread);
1233: assert(sfr == SF_SUCCESS);
1234: thread_unlock(new_thread);
1235:
1236: /*
1237: * We're back. Now old_thread is the thread that resumed
1238: * us, and we have to dispatch it.
1239: */
1240: /* CHECKME! */
1241: // Code from OSF in Grenoble deleted the following fields. They were
1242: // used in HPPA and 386 code, but not in the PPC for other than
1243: // just setting and resetting. They didn't delete these lines from
1244: // the MACH_RT builds, though, causing compile errors. I'm going
1245: // to make a wild guess and assume we can just delete these.
1246: #if 0
1247: if (old_thread->preempt == TH_NOT_PREEMPTABLE) {
1248: /*
1249: * Mark that we have been really preempted
1250: */
1251: old_thread->preempt = TH_PREEMPTED;
1252: }
1253: #endif
1254: thread_dispatch(old_thread);
1255: enable_preemption();
1256: return TRUE;
1257: }
1258:
1259: /*
1260: * thread_continue:
1261: *
1262: * Called when the launching a new thread, at splsched();
1263: */
1264: void
1265: thread_continue(
1266: register thread_t old_thread)
1267: {
1268: register thread_t self;
1269: register void (*continuation)();
1270: sched_policy_t *policy;
1271: sf_return_t sfr;
1272:
1273: self = current_thread();
1274: continuation = self->continuation;
1275:
1276: /*
1277: * We must dispatch the old thread and then
1278: * call the current thread's continuation.
1279: * There might not be an old thread, if we are
1280: * the first thread to run on this processor.
1281: */
1282: if (old_thread != THREAD_NULL) {
1283: thread_dispatch(old_thread);
1284: thread_lock(self);
1285:
1286: /* Get pointer to scheduling policy "object" */
1287: policy = &sched_policy[self->policy];
1288:
1289: /* Indicate to sched policy that new thread has started execution */
1290: /*** ??? maybe use a macro -- rkc, 1/4/96 ***/
1291: sfr = policy->sp_ops.sp_thread_begin(policy,self);
1292: assert(sfr == SF_SUCCESS);
1293: thread_unlock(self);
1294: }
1295:
1296: /*
1297: * N.B. - the following is necessary, since thread_invoke()
1298: * inhibits preemption on entry and reenables before it
1299: * returns. Unfortunately, the first time a newly-created
1300: * thread executes, it magically appears here, and never
1301: * executes the enable_preemption() call in thread_invoke().
1302: */
1303: enable_preemption();
1304: if (self->funnel_state & TH_FN_REFUNNEL) {
1305: kern_return_t save_wait_result;
1306: self->funnel_state = 0;
1307: save_wait_result = self->wait_result;
1308: mutex_lock(&funnel_lock);
1309: self->wait_result = save_wait_result;
1310: self->funnel_state = TH_FN_OWNED;
1311: }
1312: spllo();
1313:
1314: assert(continuation);
1315: (*continuation)();
1316: /*NOTREACHED*/
1317: }
1318:
1319: #if MACH_LDEBUG || MACH_KDB
1320:
1321: #define THREAD_LOG_SIZE 300
1322:
1323: struct t64 {
1324: unsigned long h;
1325: unsigned long l;
1326: };
1327:
1328: struct {
1329: struct t64 stamp;
1330: thread_t thread;
1331: long info1;
1332: long info2;
1333: long info3;
1334: char * action;
1335: } thread_log[THREAD_LOG_SIZE];
1336:
1337: int thread_log_index;
1338:
1339: void check_thread_time(long n);
1340:
1341:
1342: int check_thread_time_crash;
1343:
1344: #if 0
1345: void
1346: check_thread_time(long us)
1347: {
1348: struct t64 temp;
1349:
1350: if (!check_thread_time_crash)
1351: return;
1352:
1353: temp = thread_log[0].stamp;
1354: cyctm05_diff (&thread_log[1].stamp, &thread_log[0].stamp, &temp);
1355:
1356: if (temp.l >= us && thread_log[1].info != 0x49) /* HACK!!! */
1357: panic ("check_thread_time");
1358: }
1359: #endif
1360:
1361: void
1362: log_thread_action(char * action, long info1, long info2, long info3)
1363: {
1364: int i;
1365: spl_t x;
1366: static unsigned int tstamp;
1367:
1368: x = splhigh();
1369:
1370: for (i = THREAD_LOG_SIZE-1; i > 0; i--) {
1371: thread_log[i] = thread_log[i-1];
1372: }
1373:
1374: thread_log[0].stamp.h = 0;
1375: thread_log[0].stamp.l = tstamp++;
1376: thread_log[0].thread = current_thread();
1377: thread_log[0].info1 = info1;
1378: thread_log[0].info2 = info2;
1379: thread_log[0].info3 = info3;
1380: thread_log[0].action = action;
1381: /* strcpy (&thread_log[0].action[0], action);*/
1382:
1383: splx(x);
1384: }
1385: #endif /* MACH_LDEBUG || MACH_KDB */
1386:
1387: #if MACH_KDB
1388: #include <ddb/db_output.h>
1389: void db_show_thread_log(void);
1390:
1391: void
1392: db_show_thread_log(void)
1393: {
1394: int i;
1395:
1396: db_printf ("%s %s %s %s %s %s\n", " Thread ", " Info1 ", " Info2 ",
1397: " Info3 ", " Timestamp ", "Action");
1398:
1399: for (i = 0; i < THREAD_LOG_SIZE; i++) {
1400: db_printf ("%08x %08x %08x %08x %08x/%08x %s\n",
1401: thread_log[i].thread,
1402: thread_log[i].info1,
1403: thread_log[i].info2,
1404: thread_log[i].info3,
1405: thread_log[i].stamp.h,
1406: thread_log[i].stamp.l,
1407: thread_log[i].action);
1408: }
1409: }
1410: #endif /* MACH_KDB */
1411:
1412: /*
1413: * thread_block_reason:
1414: *
1415: * Block the current thread. If the thread is runnable
1416: * then someone must have woken it up between its request
1417: * to sleep and now. In this case, it goes back on a
1418: * run queue.
1419: *
1420: * If a continuation is specified, then thread_block will
1421: * attempt to discard the thread's kernel stack. When the
1422: * thread resumes, it will execute the continuation function
1423: * on a new kernel stack.
1424: */
1425: counter(mach_counter_t c_thread_block_calls = 0;)
1426:
1427: int
1428: thread_block_reason(
1429: void (*continuation)(void),
1430: int reason)
1431: {
1432: register thread_t thread = current_thread();
1433: register processor_t myprocessor;
1434: register thread_t new_thread;
1435: register int aborted;
1436: spl_t s;
1437:
1438: counter(++c_thread_block_calls);
1439:
1440: check_simple_locks();
1441:
1442: if (thread->funnel_state & TH_FN_OWNED) {
1443: thread->funnel_state = TH_FN_REFUNNEL;
1444: mutex_unlock(&funnel_lock);
1445: }
1446:
1447: machine_clock_assist();
1448:
1449: s = splsched();
1450: mp_disable_preemption();
1451: myprocessor = current_processor();
1452:
1453: thread_lock(thread);
1454: aborted = (thread->state & TH_ABORT);
1455: if (aborted)
1456: clear_wait_internal(thread, THREAD_INTERRUPTED);
1457:
1458: /* Unconditionally remove either | both */
1459: ast_off(AST_QUANTUM|AST_BLOCK|AST_URGENT);
1460:
1461: mp_enable_preemption();
1462:
1463: new_thread = thread_select(myprocessor);
1464: assert(new_thread);
1465: assert(thread_runnable(new_thread));
1466: thread_unlock(thread);
1467: while (!thread_invoke(thread, new_thread, reason, continuation)) {
1468: thread_lock(thread);
1469: new_thread = thread_select(myprocessor);
1470: assert(new_thread);
1471: assert(thread_runnable(new_thread));
1472: thread_unlock(thread);
1473: }
1474:
1475: splx(s);
1476:
1477: if (thread->funnel_state & TH_FN_REFUNNEL) {
1478: kern_return_t save_wait_result;
1479:
1480: save_wait_result = thread->wait_result;
1481: thread->funnel_state = 0;
1482: mutex_lock(&funnel_lock);
1483: thread->funnel_state = TH_FN_OWNED;
1484: thread->wait_result = save_wait_result;
1485: }
1486:
1487: return thread->wait_result;
1488: }
1489:
1490: /*
1491: * thread_block:
1492: *
1493: * Now calls thread_block_reason() which forwards the
1494: * the reason parameter to thread_invoke() so it can
1495: * do the right thing if the thread's quantum expired.
1496: */
1497: int
1498: thread_block(
1499: void (*continuation)(void))
1500: {
1501: return thread_block_reason(continuation, 0);
1502: }
1503:
1504: /*
1505: * thread_run:
1506: *
1507: * Switch directly from the current thread to a specified
1508: * thread. Both the current and new threads must be
1509: * runnable.
1510: */
1511: void
1512: thread_run(
1513: void (*continuation)(void),
1514: register thread_t new_thread)
1515: {
1516: register thread_t thread = current_thread();
1517: spl_t s;
1518:
1519: s = splsched();
1520: while (!thread_invoke(thread, new_thread, 0, continuation)) {
1521: register processor_t myprocessor = current_processor();
1522: thread_lock(thread);
1523: new_thread = thread_select(myprocessor);
1524: thread_unlock(thread);
1525: }
1526: splx(s);
1527: }
1528:
1529: /*
1530: * Dispatches a running thread that is not on a runq.
1531: * Called at splsched.
1532: */
1533: void
1534: thread_dispatch(
1535: register thread_t thread)
1536: {
1537: sched_policy_t *policy;
1538: sf_return_t sfr;
1539:
1540: /*
1541: * If we are discarding the thread's stack, we must do it
1542: * before the thread has a chance to run.
1543: */
1544: wake_lock(thread);
1545: thread_lock(thread);
1546:
1547: if (thread->continuation != (void (*)())0) {
1548: assert((thread->state & TH_STACK_STATE) == 0);
1549: thread->state |= TH_STACK_HANDOFF;
1550:
1551: stack_free(thread);
1552: if (thread->top_act) {
1553: act_machine_sv_free(thread->top_act);
1554: }
1555: }
1556:
1557: switch (thread->state & (TH_RUN|TH_WAIT|TH_UNINT|TH_IDLE)) {
1558:
1559: case TH_RUN | TH_UNINT:
1560: case TH_RUN:
1561: /*
1562: * No reason to stop. Put back on a run queue.
1563: */
1564: /* Leave enqueueing thread up to scheduling policy */
1565: policy = &sched_policy[thread->policy];
1566: /*** ??? maybe use a macro ***/
1567: sfr = policy->sp_ops.sp_thread_dispatch(policy, thread);
1568: assert(sfr == SF_SUCCESS);
1569: break;
1570:
1571: case TH_RUN | TH_WAIT | TH_UNINT:
1572: case TH_RUN | TH_WAIT:
1573: thread->sleep_stamp = sched_tick;
1574: /* fallthrough */
1575: case TH_WAIT: /* this happens! */
1576:
1577: /*
1578: * Waiting
1579: */
1580: thread->state &= ~TH_RUN;
1581: if (thread->state & TH_TERMINATE)
1582: thread_reaper_enqueue(thread);
1583:
1584: if (thread->wake_active) {
1585: thread->wake_active = FALSE;
1586: thread_unlock(thread);
1587: wake_unlock(thread);
1588: thread_wakeup((event_t)&thread->wake_active);
1589: return;
1590: }
1591: break;
1592:
1593: case TH_RUN | TH_IDLE:
1594: /*
1595: * Drop idle thread -- it is already in
1596: * idle_thread_array.
1597: */
1598: break;
1599:
1600: default:
1601: panic("State 0x%x \n",thread->state);
1602: }
1603: thread_unlock(thread);
1604: wake_unlock(thread);
1605: }
1606:
1607: /*
1608: * Enqueue thread on run_queue.
1609: */
1610: int
1611: run_queue_enqueue(
1612: register run_queue_t rq,
1613: register thread_t thread,
1614: boolean_t tail)
1615: {
1616: register int whichq;
1617: int oldrqcount;
1618:
1619: whichq = thread->sched_pri;
1620: if (whichq > MAXPRI || whichq < MINPRI) {
1621: panic("run_queue_enqueue: bad pri (%d)\n", whichq);
1622: }
1623:
1624: simple_lock(&rq->lock); /* lock the run queue */
1625: assert(thread->runq == RUN_QUEUE_NULL);
1626: if (tail)
1627: enqueue_tail(&rq->runq[whichq], (queue_entry_t)thread);
1628: else
1629: enqueue_head(&rq->runq[whichq], (queue_entry_t)thread);
1630:
1631: setbit(MAXPRI - whichq, rq->bitmap);
1632: if (whichq > rq->highq) {
1633: rq->highq = whichq;
1634: }
1635: oldrqcount = rq->count++;
1636: if (whichq == DEPRESSPRI)
1637: rq->depress_count++;
1638: thread->runq = rq;
1639: thread->whichq = whichq;
1640: #if DEBUG
1641: thread_check(thread, rq);
1642: #endif /* DEBUG */
1643: simple_unlock(&rq->lock);
1644:
1645: return (oldrqcount);
1646: }
1647:
1648: /*
1649: * thread_setrun:
1650: *
1651: * Make thread runnable; dispatch directly onto an idle processor
1652: * if possible. Else put on appropriate run queue (processor
1653: * if bound, else processor set. Caller must have lock on thread.
1654: * This is always called at splsched.
1655: * The tail parameter, if TRUE || TAIL_Q, indicates that the
1656: * thread should be placed at the tail of the runq. If
1657: * FALSE || HEAD_Q the thread will be placed at the head of the
1658: * appropriate runq.
1659: */
1660: void
1661: thread_setrun(
1662: register thread_t new_thread,
1663: boolean_t may_preempt,
1664: boolean_t tail)
1665: {
1666: register processor_t processor;
1667: register run_queue_t runq;
1668: register processor_set_t pset;
1669: thread_t thread;
1670: ast_t ast_flags = AST_BLOCK;
1671:
1672: mp_disable_preemption();
1673:
1674: assert(!(new_thread->state & TH_SWAPPED_OUT));
1675: assert(thread_runnable(new_thread));
1676:
1677: /*
1678: * Update priority if needed.
1679: */
1680: /*** ??? fix me ***/
1681: if (new_thread->policy & (POLICY_TIMESHARE|POLICY_RR|POLICY_FIFO)) {
1682: mk_sp_info_t sp_info = new_thread->sp_info;
1683:
1684: assert(sp_info != SP_INFO_NULL);
1685: if (sp_info->sched_stamp != sched_tick)
1686: update_priority(new_thread);
1687:
1688: #if 0 /* TEMPORARILY DISABLE PREEMPTION */
1689: if ( (new_thread->policy & (POLICY_FIFO|POLICY_RR)) &&
1690: sp_info->priority > BASEPRI_SYSTEM )
1691: ast_flags |= AST_URGENT;
1692: #endif /* TEMPORARILY DISABLE PREEMPTION */
1693: }
1694:
1695: assert(new_thread->runq == RUN_QUEUE_NULL);
1696:
1697: /*** ??? fix me ***/
1698: assert(new_thread->sp_info != SP_INFO_NULL);
1699:
1700: /*
1701: * Try to dispatch the thread directly onto an idle processor.
1702: */
1703: if ((processor = new_thread->bound_processor) == PROCESSOR_NULL) {
1704: /*
1705: * Not bound, any processor in the processor set is ok.
1706: */
1707: pset = new_thread->processor_set;
1708: if (pset->idle_count > 0) {
1709: simple_lock(&pset->idle_lock);
1710: if (pset->idle_count > 0) {
1711: processor = (processor_t) queue_first(&pset->idle_queue);
1712: queue_remove(&(pset->idle_queue), processor, processor_t,
1713: processor_queue);
1714: pset->idle_count--;
1715: processor->next_thread = new_thread;
1716: processor->state = PROCESSOR_DISPATCHING;
1717: simple_unlock(&pset->idle_lock);
1718:
1719: mp_enable_preemption();
1720: return;
1721: }
1722: simple_unlock(&pset->idle_lock);
1723: }
1724:
1725:
1726: /*
1727: * Preempt check
1728: */
1729: runq = &pset->runq;
1730: thread = current_thread();
1731: processor = current_processor();
1732: if ( may_preempt &&
1733: #if MACH_HOST
1734: pset == processor->processor_set &&
1735: #endif /* MACH_HOST */
1736: thread->sched_pri < new_thread->sched_pri ) {
1737: simple_lock(&processor->lock);
1738: pset = processor->processor_set;
1739: simple_lock(&pset->idle_lock);
1740:
1741: /*
1742: * XXX if we have a non-empty local runq or are
1743: * XXX running a bound thread, ought to check for
1744: * XXX another cpu running lower-pri thread to preempt.
1745: *
1746: * Turn off first_quantum to allow csw.
1747: */
1748: if (processor->state == PROCESSOR_DISPATCHING) {
1749: thread = processor->next_thread;
1750: processor->next_thread = new_thread;
1751: simple_unlock(&pset->idle_lock);
1752: simple_unlock(&processor->lock);
1753: new_thread = thread;
1754: }
1755: else {
1756: simple_unlock(&pset->idle_lock);
1757: simple_unlock(&processor->lock);
1758: processor->first_quantum = FALSE;
1759: ast_on(ast_flags);
1760: }
1761: }
1762:
1763: /*
1764: * Put us on the end of the runq, if we are not preempting
1765: * or the guy we are preempting.
1766: */
1767: run_queue_enqueue(runq, new_thread, tail);
1768: }
1769: else {
1770: /*
1771: * Bound, can only run on bound processor. Have to lock
1772: * processor here because it may not be the current one.
1773: */
1774: if (processor->state == PROCESSOR_IDLE) {
1775: simple_lock(&processor->lock);
1776: pset = processor->processor_set;
1777: simple_lock(&pset->idle_lock);
1778: if (processor->state == PROCESSOR_IDLE) {
1779: queue_remove(&pset->idle_queue, processor,
1780: processor_t, processor_queue);
1781: pset->idle_count--;
1782: processor->next_thread = new_thread;
1783: processor->state = PROCESSOR_DISPATCHING;
1784: simple_unlock(&pset->idle_lock);
1785: simple_unlock(&processor->lock);
1786:
1787: mp_enable_preemption();
1788: return;
1789: }
1790: simple_unlock(&pset->idle_lock);
1791: simple_unlock(&processor->lock);
1792: }
1793:
1794: /*
1795: * Cause ast on processor if processor is on line, and the
1796: * currently executing thread is not bound to that processor
1797: * (bound threads have implicit priority over non-bound threads).
1798: * We also avoid sending the AST to the idle thread (if it got
1799: * scheduled in the window between the 'if' above and here),
1800: * since the idle_thread is bound.
1801: */
1802: runq = &processor->runq;
1803: thread = current_thread();
1804: if (processor == current_processor()) {
1805: if ( thread->bound_processor == PROCESSOR_NULL ||
1806: thread->sched_pri > new_thread->sched_pri ) {
1807: if (processor->state == PROCESSOR_DISPATCHING) {
1808: thread = processor->next_thread;
1809: processor->next_thread = new_thread;
1810: new_thread = thread;
1811: }
1812: else {
1813: processor->first_quantum = FALSE;
1814: ast_on(ast_flags);
1815: }
1816: }
1817:
1818: run_queue_enqueue(runq, new_thread, tail);
1819: }
1820: else {
1821: thread = cpu_data[processor->slot_num].active_thread;
1822: if ( run_queue_enqueue(runq, new_thread, tail) == 0 &&
1823: processor->state != PROCESSOR_OFF_LINE &&
1824: thread && thread->bound_processor != processor )
1825: cause_ast_check(processor);
1826: }
1827: }
1828:
1829: mp_enable_preemption();
1830: }
1831:
1832: /*
1833: * set_pri:
1834: *
1835: * Set the priority of the specified thread to the specified
1836: * priority. This may cause the thread to change queues.
1837: *
1838: * The thread *must* be locked by the caller.
1839: */
1840: void
1841: set_pri(
1842: thread_t thread,
1843: int pri,
1844: boolean_t resched)
1845: {
1846: register struct run_queue *rq;
1847:
1848: rq = rem_runq(thread);
1849: assert(thread->runq == RUN_QUEUE_NULL);
1850: thread->sched_pri = pri;
1851: if (rq != RUN_QUEUE_NULL) {
1852: if (resched)
1853: thread_setrun(thread, TRUE, TAIL_Q);
1854: else
1855: run_queue_enqueue(rq, thread, TAIL_Q);
1856: }
1857: }
1858:
1859: /*
1860: * rem_runq:
1861: *
1862: * Remove a thread from its run queue.
1863: * The run queue that the process was on is returned
1864: * (or RUN_QUEUE_NULL if not on a run queue). Thread *must* be locked
1865: * before calling this routine. Unusual locking protocol on runq
1866: * field in thread structure makes this code interesting; see thread.h.
1867: */
1868: run_queue_t
1869: rem_runq(
1870: thread_t thread)
1871: {
1872: register struct run_queue *rq;
1873:
1874: rq = thread->runq;
1875: /*
1876: * If rq is RUN_QUEUE_NULL, the thread will stay out of the
1877: * run_queues because the caller locked the thread. Otherwise
1878: * the thread is on a runq, but could leave.
1879: */
1880: if (rq != RUN_QUEUE_NULL) {
1881: #if DEBUG
1882: thread_t t;
1883: int whichq;
1884: #endif
1885: simple_lock(&rq->lock);
1886: if (rq == thread->runq) {
1887: /*
1888: * Thread is in a runq and we have a lock on
1889: * that runq.
1890: */
1891: #if DEBUG
1892: thread_check(thread, rq);
1893: #endif /* DEBUG */
1894: remqueue(&rq->runq[0], (queue_entry_t)thread);
1895: rq->count--;
1896:
1897: if (thread->whichq == DEPRESSPRI)
1898: rq->depress_count--;
1899:
1900: if (queue_empty(rq->runq + thread->sched_pri)) {
1901: /* update run queue status */
1902: clrbit(MAXPRI - thread->sched_pri, rq->bitmap);
1903: rq->highq = MAXPRI - ffsbit(rq->bitmap);
1904: }
1905: thread->runq = RUN_QUEUE_NULL;
1906: simple_unlock(&rq->lock);
1907: }
1908: else {
1909: /*
1910: * The thread left the runq before we could
1911: * lock the runq. It is not on a runq now, and
1912: * can't move again because this routine's
1913: * caller locked the thread.
1914: */
1915: assert(thread->runq == RUN_QUEUE_NULL);
1916: simple_unlock(&rq->lock);
1917: rq = RUN_QUEUE_NULL;
1918: }
1919: }
1920:
1921: return (rq);
1922: }
1923:
1924:
1925: /*
1926: * choose_thread:
1927: *
1928: * Choose a thread to execute. The thread chosen is removed
1929: * from its run queue. Note that this requires only that the runq
1930: * lock be held.
1931: *
1932: * Strategy:
1933: * Check processor runq first; if anything found, run it.
1934: * Else check pset runq; if nothing found, return idle thread.
1935: *
1936: * Second line of strategy is implemented by choose_pset_thread.
1937: * This is only called on processor startup and when thread_block
1938: * thinks there's something in the processor runq.
1939: */
1940: thread_t
1941: choose_thread(
1942: processor_t myprocessor)
1943: {
1944: thread_t thread;
1945: register queue_t q;
1946: register run_queue_t runq;
1947: processor_set_t pset;
1948:
1949: runq = &myprocessor->runq;
1950: pset = myprocessor->processor_set;
1951:
1952: simple_lock(&runq->lock);
1953: if (runq->count > 0 && runq->highq >= pset->runq.highq) {
1954: q = runq->runq + runq->highq;
1955: #if MACH_ASSERT
1956: if (!queue_empty(q)) {
1957: #endif /*MACH_ASSERT*/
1958: thread = (thread_t)q->next;
1959: ((queue_entry_t)thread)->next->prev = q;
1960: q->next = ((queue_entry_t)thread)->next;
1961: thread->runq = RUN_QUEUE_NULL;
1962: runq->count--;
1963: if (thread->whichq == DEPRESSPRI)
1964: runq->depress_count--;
1965: if (queue_empty(q)) {
1966: clrbit(MAXPRI - runq->highq, runq->bitmap);
1967: runq->highq = MAXPRI - ffsbit(runq->bitmap);
1968: }
1969: simple_unlock(&runq->lock);
1970: return (thread);
1971: #if MACH_ASSERT
1972: }
1973: panic("choose_thread");
1974: #endif /*MACH_ASSERT*/
1975: /*NOTREACHED*/
1976: }
1977:
1978: simple_unlock(&runq->lock);
1979: simple_lock(&pset->runq.lock);
1980: return (choose_pset_thread(myprocessor, pset));
1981: }
1982:
1983:
1984: /*
1985: * choose_pset_thread: choose a thread from processor_set runq or
1986: * set processor idle and choose its idle thread.
1987: *
1988: * Caller must be at splsched and have a lock on the runq. This
1989: * lock is released by this routine. myprocessor is always the current
1990: * processor, and pset must be its processor set.
1991: * This routine chooses and removes a thread from the runq if there
1992: * is one (and returns it), else it sets the processor idle and
1993: * returns its idle thread.
1994: */
1995: thread_t
1996: choose_pset_thread(
1997: register processor_t myprocessor,
1998: processor_set_t pset)
1999: {
2000: register run_queue_t runq;
2001: register thread_t thread;
2002: register queue_t q;
2003:
2004: runq = &pset->runq;
2005: if (runq->count > 0) {
2006: q = runq->runq + runq->highq;
2007: #if MACH_ASSERT
2008: if (!queue_empty(q)) {
2009: #endif /*MACH_ASSERT*/
2010: thread = (thread_t)q->next;
2011: ((queue_entry_t)thread)->next->prev = q;
2012: q->next = ((queue_entry_t)thread)->next;
2013: thread->runq = RUN_QUEUE_NULL;
2014: runq->count--;
2015: if (thread->whichq == DEPRESSPRI)
2016: runq->depress_count--;
2017: if (queue_empty(q)) {
2018: clrbit(MAXPRI - runq->highq, runq->bitmap);
2019: runq->highq = MAXPRI - ffsbit(runq->bitmap);
2020: }
2021: simple_unlock(&runq->lock);
2022: return (thread);
2023: #if MACH_ASSERT
2024: }
2025: panic("choose_pset_thread");
2026: #endif /*MACH_ASSERT*/
2027: /*NOTREACHED*/
2028: }
2029: simple_unlock(&runq->lock);
2030:
2031: /*
2032: * Nothing is runnable, so set this processor idle if it
2033: * was running. If it was in an assignment or shutdown,
2034: * leave it alone. Return its idle thread.
2035: */
2036: simple_lock(&pset->idle_lock);
2037: if (myprocessor->state == PROCESSOR_RUNNING) {
2038: myprocessor->state = PROCESSOR_IDLE;
2039: /*
2040: * XXX Until it goes away, put master on end of queue, others
2041: * XXX on front so master gets used last.
2042: */
2043: if (myprocessor == master_processor)
2044: queue_enter(&(pset->idle_queue), myprocessor,
2045: processor_t, processor_queue);
2046: else
2047: queue_enter_first(&(pset->idle_queue), myprocessor,
2048: processor_t, processor_queue);
2049:
2050: pset->idle_count++;
2051: }
2052: simple_unlock(&pset->idle_lock);
2053:
2054: return (myprocessor->idle_thread);
2055: }
2056:
2057: /*
2058: * no_dispatch_count counts number of times processors go non-idle
2059: * without being dispatched. This should be very rare.
2060: */
2061: int no_dispatch_count = 0;
2062:
2063: /*
2064: * This is the idle thread, which just looks for other threads
2065: * to execute.
2066: */
2067: void
2068: idle_thread_continue(void)
2069: {
2070: register processor_t myprocessor;
2071: register volatile thread_t *threadp;
2072: register volatile int *gcount;
2073: register volatile int *lcount;
2074: register thread_t new_thread;
2075: register int state;
2076: register processor_set_t pset;
2077: int mycpu;
2078: spl_t s;
2079:
2080: mycpu = cpu_number();
2081: myprocessor = current_processor();
2082: threadp = (volatile thread_t *) &myprocessor->next_thread;
2083: lcount = (volatile int *) &myprocessor->runq.count;
2084:
2085: for (;;) {
2086: #ifdef MARK_CPU_IDLE
2087: MARK_CPU_IDLE(mycpu);
2088: #endif /* MARK_CPU_IDLE */
2089:
2090: #if MACH_HOST
2091: gcount = (volatile int *)&myprocessor->processor_set->runq.count;
2092: #else /* MACH_HOST */
2093: gcount = (volatile int *)&default_pset.runq.count;
2094: #endif /* MACH_HOST */
2095:
2096: /*
2097: * This cpu will be dispatched (by thread_setrun) by setting next_thread
2098: * to the value of the thread to run next. Also check runq counts.
2099: */
2100: s = splsched();
2101: while ((*threadp == (volatile thread_t)THREAD_NULL) && (*gcount == 0) && (*lcount == 0)) {
2102:
2103: /* check for ASTs while we wait */
2104:
2105: if (need_ast[mycpu] &~ (AST_SCHEDULING|AST_BSD|AST_BSD_INIT)) {
2106: /* don't allow scheduling ASTs */
2107: need_ast[mycpu] &= ~(AST_SCHEDULING|AST_BSD|AST_BSD_INIT);
2108: splx(s);
2109: ast_taken(FALSE, AST_ALL, s);
2110: /* back at spllo */
2111: }
2112: else
2113: splx(s);
2114:
2115: machine_clock_assist();
2116:
2117: /*
2118: * machine_idle is a machine dependent function,
2119: * to conserve power.
2120: */
2121: #if POWER_SAVE
2122: machine_idle(mycpu);
2123: #endif /* POWER_SAVE */
2124: s = splsched();
2125: }
2126:
2127: #ifdef MARK_CPU_ACTIVE
2128: splx(s);
2129: MARK_CPU_ACTIVE(mycpu);
2130: s = splsched();
2131: #endif /* MARK_CPU_ACTIVE */
2132:
2133: /*
2134: * This is not a switch statement to avoid the
2135: * bounds checking code in the common case.
2136: */
2137: pset = myprocessor->processor_set;
2138: simple_lock(&pset->idle_lock);
2139: retry:
2140: state = myprocessor->state;
2141: if (state == PROCESSOR_DISPATCHING) {
2142: /*
2143: * Commmon case -- cpu dispatched.
2144: */
2145: new_thread = *threadp;
2146: *threadp = (volatile thread_t) THREAD_NULL;
2147: myprocessor->state = PROCESSOR_RUNNING;
2148:
2149: simple_unlock(&pset->idle_lock);
2150: thread_lock(new_thread);
2151:
2152: /*
2153: * set up quantum for new thread.
2154: */
2155: if (new_thread->policy == POLICY_TIMESHARE) {
2156: /*
2157: * Just use set quantum. No point in
2158: * checking for shorter local runq quantum;
2159: * csw_needed will handle correctly.
2160: */
2161: #if MACH_HOST
2162: myprocessor->quantum = new_thread->processor_set->set_quantum;
2163: #else /* MACH_HOST */
2164: myprocessor->quantum = default_pset.set_quantum;
2165: #endif /* MACH_HOST */
2166: }
2167: else
2168: if (new_thread->policy & (POLICY_RR|POLICY_FIFO)) {
2169: mk_sp_info_t sp_info = (mk_sp_info_t)new_thread->sp_info;
2170:
2171: assert(sp_info != SP_INFO_NULL);
2172: myprocessor->quantum = sp_info->unconsumed_quantum;
2173: }
2174:
2175: thread_unlock(new_thread);
2176:
2177: myprocessor->first_quantum = TRUE;
2178: counter(c_idle_thread_handoff++);
2179: thread_run((void(*)(void))0, new_thread);
2180: }
2181: else
2182: if (state == PROCESSOR_IDLE) {
2183:
2184: if (myprocessor->state != PROCESSOR_IDLE) {
2185: /*
2186: * Something happened, try again.
2187: */
2188: goto retry;
2189: }
2190: /*
2191: * Processor was not dispatched (Rare).
2192: * Set it running again.
2193: */
2194: no_dispatch_count++;
2195: pset->idle_count--;
2196: queue_remove(&pset->idle_queue, myprocessor,
2197: processor_t, processor_queue);
2198: myprocessor->state = PROCESSOR_RUNNING;
2199: simple_unlock(&pset->idle_lock);
2200: counter(c_idle_thread_block++);
2201: thread_block((void(*)(void))0);
2202: }
2203: else
2204: if ( state == PROCESSOR_ASSIGN ||
2205: state == PROCESSOR_SHUTDOWN ) {
2206: /*
2207: * Changing processor sets, or going off-line.
2208: * Release next_thread if there is one. Actual
2209: * thread to run in on a runq.
2210: */
2211: if ((new_thread = (thread_t)*threadp)!= THREAD_NULL) {
2212: *threadp = (volatile thread_t) THREAD_NULL;
2213: thread_setrun(new_thread, FALSE, TAIL_Q);
2214: }
2215:
2216: counter(c_idle_thread_block++);
2217: thread_block((void(*)(void))0);
2218: }
2219: else {
2220: simple_unlock(&pset->idle_lock);
2221: printf("Bad processor state %d (Cpu %d)\n",
2222: cpu_state(mycpu), mycpu);
2223: panic("idle_thread");
2224:
2225: }
2226: splx(s);
2227: }
2228: }
2229:
2230: void
2231: idle_thread(void)
2232: {
2233: thread_t self = current_thread();
2234: mk_sp_info_t sp_info;
2235: spl_t s;
2236:
2237: stack_privilege(self);
2238: thread_swappable(current_act(), FALSE);
2239:
2240: s = splsched();
2241: thread_lock(self);
2242:
2243: /*
2244: * Set the idle flag to indicate that this is an idle thread,
2245: * enter ourselves in the idle array, and thread_block() to get
2246: * out of the run queues (and set the processor idle when we
2247: * run next time).
2248: */
2249: self->state |= TH_IDLE;
2250: current_processor()->idle_thread = self;
2251:
2252: /*** ??? fix me ***/
2253: assert(self->policy == POLICY_FIFO);
2254: sp_info = (mk_sp_info_t)self->sp_info;
2255: assert(sp_info != SP_INFO_NULL);
2256: sp_info->priority = IDLEPRI;
2257: self->sched_pri = sp_info->priority;
2258:
2259: thread_unlock(self);
2260: splx(s);
2261:
2262: counter(c_idle_thread_block++);
2263: thread_block((void(*)(void))0);
2264: idle_thread_continue();
2265: /*NOTREACHED*/
2266:
2267: panic("idle_thread_continue!");
2268: }
2269:
2270: static thread_call_t sched_tick_timer;
2271: static thread_call_data_t sched_tick_timer_data;
2272: static AbsoluteTime sched_tick_interval, sched_tick_deadline;
2273:
2274: /*
2275: * recompute_priorities:
2276: *
2277: * Update the priorities of all threads periodically.
2278: */
2279: void
2280: _recompute_priorities(void)
2281: {
2282: AbsoluteTime abstime;
2283: #if SIMPLE_CLOCK
2284: int new_usec;
2285: #endif /* SIMPLE_CLOCK */
2286:
2287: clock_get_uptime(&abstime);
2288:
2289: sched_tick++; /* age usage one more time */
2290: #if SIMPLE_CLOCK
2291: /*
2292: * Compensate for clock drift. sched_usec is an
2293: * exponential average of the number of microseconds in
2294: * a second. It decays in the same fashion as cpu_usage.
2295: */
2296: new_usec = sched_usec_elapsed();
2297: sched_usec = (5*sched_usec + 3*new_usec)/8;
2298: #endif /* SIMPLE_CLOCK */
2299:
2300: /*
2301: * Compute the scheduler load factors.
2302: */
2303: compute_mach_factor();
2304:
2305: /*
2306: * Scan the run queues for runnable threads that need to
2307: * have their priorities recalculated.
2308: */
2309: do_thread_scan();
2310:
2311: clock_deadline_for_periodic_event(sched_tick_interval, abstime,
2312: &sched_tick_deadline);
2313: thread_call_enter_delayed(sched_tick_timer, sched_tick_deadline);
2314: }
2315:
2316: void
2317: recompute_priorities(void)
2318: {
2319: thread_call_setup(&sched_tick_timer_data, _recompute_priorities, NULL);
2320: clock_interval_to_absolutetime_interval(1, NSEC_PER_SEC,
2321: &sched_tick_interval);
2322: clock_get_uptime(&sched_tick_deadline);
2323: sched_tick_timer = &sched_tick_timer_data;
2324:
2325: _recompute_priorities();
2326: }
2327:
2328: #define MAX_STUCK_THREADS 128
2329:
2330: /*
2331: * do_thread_scan: scan for stuck threads. A thread is stuck if
2332: * it is runnable but its priority is so low that it has not
2333: * run for several seconds. Its priority should be higher, but
2334: * won't be until it runs and calls update_priority. The scanner
2335: * finds these threads and does the updates.
2336: *
2337: * Scanner runs in two passes. Pass one squirrels likely
2338: * thread ids away in an array (takes out references for them).
2339: * Pass two does the priority updates. This is necessary because
2340: * the run queue lock is required for the candidate scan, but
2341: * cannot be held during updates [set_pri will deadlock].
2342: *
2343: * Array length should be enough so that restart isn't necessary,
2344: * but restart logic is included. Does not scan processor runqs.
2345: *
2346: */
2347: thread_t stuck_threads[MAX_STUCK_THREADS];
2348: int stuck_count = 0;
2349:
2350: /*
2351: * do_runq_scan is the guts of pass 1. It scans a runq for
2352: * stuck threads. A boolean is returned indicating whether
2353: * a retry is needed.
2354: */
2355: boolean_t
2356: do_runq_scan(
2357: run_queue_t runq,
2358: int *mask)
2359: {
2360: register queue_t q;
2361: register thread_t thread;
2362: register int count;
2363: int qindex;
2364: spl_t s;
2365: boolean_t result = FALSE;
2366:
2367: s = splsched();
2368: simple_lock(&runq->lock);
2369: if ((count = runq->count) > 0) {
2370: q = runq->runq + runq->highq;
2371: qindex = runq->highq;
2372: while (count > 0) {
2373: boolean_t qvalid = testbit(qindex, mask);
2374:
2375: queue_iterate(q, thread, thread_t, links) {
2376: if ( qvalid &&
2377: !(thread->state & (TH_WAIT|TH_SUSP)) &&
2378: thread->policy == POLICY_TIMESHARE ) {
2379: mk_sp_info_t sp_info = thread->sp_info;
2380:
2381: assert(sp_info != SP_INFO_NULL);
2382: /*** ??? fix me ***/
2383: if (sp_info->sched_stamp != sched_tick) {
2384: /*
2385: * Stuck, save its id for later.
2386: */
2387: if (stuck_count == MAX_STUCK_THREADS) {
2388: /*
2389: * !@#$% No more room.
2390: */
2391: simple_unlock(&runq->lock);
2392: splx(s);
2393:
2394: return (TRUE);
2395: }
2396:
2397: /*
2398: * Inline version of thread_reference
2399: * XXX - lock ordering problem here:
2400: * thread locks should be taken before runq
2401: * locks: just try and get the thread's locks
2402: * and ignore this thread if we fail, we might
2403: * have better luck next time.
2404: */
2405: if (simple_lock_try(&thread->lock)) {
2406: thread->ref_count++;
2407: thread_unlock(thread);
2408: stuck_threads[stuck_count++] = thread;
2409: }
2410: else
2411: result = TRUE;
2412: }
2413: }
2414:
2415: count--;
2416: }
2417:
2418: q--;
2419: qindex--;
2420: }
2421: }
2422: simple_unlock(&runq->lock);
2423: splx(s);
2424:
2425: return (result);
2426: }
2427:
2428: boolean_t thread_scan_enabled = TRUE;
2429:
2430: void
2431: do_thread_scan(void)
2432: {
2433: register boolean_t restart_needed = FALSE;
2434: register thread_t thread;
2435: #if MACH_HOST
2436: register processor_set_t pset;
2437: #endif /* MACH_HOST */
2438: int *mask;
2439: spl_t s;
2440:
2441: if (!thread_scan_enabled)
2442: return;
2443:
2444: mask = sched_policy[POLICY_TIMESHARE].priority_mask.bitmap;
2445:
2446: do {
2447: #if MACH_HOST
2448: mutex_lock(&all_psets_lock);
2449: queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
2450: if (restart_needed = do_runq_scan(&pset->runq, mask))
2451: break;
2452: }
2453: mutex_unlock(&all_psets_lock);
2454: #else /* MACH_HOST */
2455: restart_needed = do_runq_scan(&default_pset.runq, mask);
2456: #endif /* MACH_HOST */
2457: if (!restart_needed)
2458: restart_needed = do_runq_scan(&master_processor->runq, mask);
2459:
2460: /*
2461: * Ok, we now have a collection of candidates -- fix them.
2462: */
2463: while (stuck_count > 0) {
2464: thread = stuck_threads[--stuck_count];
2465: stuck_threads[stuck_count] = THREAD_NULL;
2466: s = splsched();
2467: thread_lock(thread);
2468: /*** ??? fix me ***/
2469: if (thread->policy == POLICY_TIMESHARE) {
2470: mk_sp_info_t sp_info = thread->sp_info;
2471:
2472: assert(thread->sp_info != SP_INFO_NULL);
2473: if ( !(thread->state & (TH_WAIT|TH_SUSP)) &&
2474: /*** ??? fix me ***/
2475: sp_info->sched_stamp != sched_tick )
2476: update_priority(thread);
2477: }
2478: thread_unlock(thread);
2479: splx(s);
2480: thread_deallocate(thread);
2481: }
2482:
2483: } while (restart_needed);
2484: }
2485:
2486: /*
2487: * Just in case someone doesn't use the macro
2488: */
2489: #undef thread_wakeup
2490: void
2491: thread_wakeup(
2492: event_t x);
2493:
2494: void
2495: thread_wakeup(
2496: event_t x)
2497: {
2498: thread_wakeup_with_result(x, THREAD_AWAKENED);
2499: }
2500:
2501: boolean_t
2502: thread_runnable(
2503: thread_t thread)
2504: {
2505: sched_policy_t *policy;
2506:
2507: /* Ask sched policy if thread is runnable */
2508: policy = policy_id_to_sched_policy(thread->policy);
2509:
2510: return ((policy != SCHED_POLICY_NULL)?
2511: policy->sp_ops.sp_thread_runnable(policy, thread) : FALSE);
2512: }
2513:
2514: void
2515: dump_processor_set(
2516: processor_set_t ps)
2517: {
2518: printf("processor_set: %08x\n",ps);
2519: printf("idle_queue: %08x %08x, idle_count: 0x%x\n",
2520: ps->idle_queue.next,ps->idle_queue.prev,ps->idle_count);
2521: printf("processors: %08x %08x, processor_count: 0x%x, empty: %x\n",
2522: ps->processors.next,ps->processors.prev,ps->processor_count);
2523: printf("tasks: %08x %08x, task_count: 0x%x\n",
2524: ps->tasks.next,ps->tasks.prev,ps->task_count);
2525: printf("threads: %08x %08x, thread_count: 0x%x\n",
2526: ps->threads.next,ps->threads.prev,ps->thread_count);
2527: printf("ref_count: 0x%x, all_psets: %08x %08x, active: %x\n",
2528: ps->ref_count, ps->all_psets.next,ps->all_psets.prev,ps->active);
2529: printf("pset_self: %08x, pset_name_self: %08x\n",ps->pset_self, ps->pset_name_self);
2530: printf("max_priority: 0x%x, policies: 0x%x, set_quantum: 0x%x\n",
2531: ps->max_priority, ps->policies, ps->set_quantum);
2532: }
2533:
2534: #define processor_state(s) (((s)>PROCESSOR_SHUTDOWN)?"*unknown*":states[s])
2535:
2536: void
2537: dump_processor(
2538: processor_t p)
2539: {
2540: char *states[]={"OFF_LINE","RUNNING","IDLE","DISPATCHING",
2541: "ASSIGN","SHUTDOWN"};
2542:
2543: printf("processor: %08x\n",p);
2544: printf("processor_queue: %08x %08x\n",
2545: p->processor_queue.next,p->processor_queue.prev);
2546: printf("state: %8s, next_thread: %08x, idle_thread: %08x\n",
2547: processor_state(p->state), p->next_thread, p->idle_thread);
2548: printf("quantum: %u, first_quantum: %x, last_quantum: %u\n",
2549: p->quantum, p->first_quantum, p->last_quantum);
2550: printf("processor_set: %08x, processor_set_next: %08x\n",
2551: p->processor_set, p->processor_set_next);
2552: printf("processors: %08x %08x\n", p->processors.next,p->processors.prev);
2553: printf("processor_self: %08x, slot_num: 0x%x\n", p->processor_self, p->slot_num);
2554: }
2555:
2556: void
2557: dump_run_queue_struct(
2558: run_queue_t rq)
2559: {
2560: char dump_buf[80];
2561: int i;
2562:
2563: for( i=0; i < NRQS; ) {
2564: int j;
2565:
2566: printf("%6s",(i==0)?"runq:":"");
2567: for( j=0; (j<8) && (i < NRQS); j++,i++ ) {
2568: if( rq->runq[i].next == &rq->runq[i] )
2569: printf( " --------");
2570: else
2571: printf(" %08x",rq->runq[i].next);
2572: }
2573: printf("\n");
2574: }
2575: for( i=0; i < NRQBM; ) {
2576: register unsigned int mask;
2577: char *d=dump_buf;
2578:
2579: mask = ~0;
2580: mask ^= (mask>>1);
2581:
2582: do {
2583: *d++ = ((rq->bitmap[i]&mask)?'r':'e');
2584: mask >>=1;
2585: } while( mask );
2586: *d = '\0';
2587: printf("%8s%s\n",((i==0)?"bitmap:":""),dump_buf);
2588: i++;
2589: }
2590: printf("highq: 0x%x, count: %u\n", rq->highq, rq->count);
2591: }
2592:
2593: void
2594: dump_run_queues(
2595: run_queue_t runq)
2596: {
2597: register queue_t q1;
2598: register int i;
2599: register queue_entry_t e;
2600:
2601: q1 = runq->runq;
2602: for (i = 0; i < NRQS; i++) {
2603: if (q1->next != q1) {
2604: int t_cnt;
2605:
2606: printf("[%u]",i);
2607: for (t_cnt=0, e = q1->next; e != q1; e = e->next) {
2608: printf("\t0x%08x",e);
2609: if( (t_cnt = ++t_cnt%4) == 0 )
2610: printf("\n");
2611: }
2612: if( t_cnt )
2613: printf("\n");
2614: }
2615: /* else
2616: printf("[%u]\t<empty>\n",i);
2617: */
2618: q1++;
2619: }
2620: }
2621:
2622: #if DEBUG
2623:
2624: void
2625: checkrq(
2626: run_queue_t rq,
2627: char *msg)
2628: {
2629: register queue_t q1;
2630: register int i, j;
2631: register queue_entry_t e;
2632: register int highq;
2633:
2634: highq = NRQS;
2635: j = 0;
2636: q1 = rq->runq;
2637: for (i = MAXPRI; i >= 0; i--) {
2638: if (q1->next == q1) {
2639: if (q1->prev != q1) {
2640: panic("checkrq: empty at %s", msg);
2641: }
2642: }
2643: else {
2644: if (highq == -1)
2645: highq = i;
2646:
2647: for (e = q1->next; e != q1; e = e->next) {
2648: j++;
2649: if (e->next->prev != e)
2650: panic("checkrq-2 at %s", msg);
2651: if (e->prev->next != e)
2652: panic("checkrq-3 at %s", msg);
2653: }
2654: }
2655: q1++;
2656: }
2657: if (j != rq->count)
2658: panic("checkrq: count wrong at %s", msg);
2659: if (rq->count != 0 && highq > rq->highq)
2660: panic("checkrq: highq wrong at %s", msg);
2661: }
2662:
2663: void
2664: thread_check(
2665: register thread_t th,
2666: register run_queue_t rq)
2667: {
2668: register unsigned int whichq;
2669:
2670: whichq = th->sched_pri;
2671: if (whichq < MINPRI) {
2672: printf("thread_check: priority too high\n");
2673: whichq = MINPRI;
2674: }
2675: if ((th->links.next == &rq->runq[whichq]) &&
2676: (rq->runq[whichq].prev != (queue_entry_t)th))
2677: panic("thread_check");
2678: }
2679:
2680: #endif /* DEBUG */
2681:
2682: #if MACH_KDB
2683: #include <ddb/db_output.h>
2684: #define printf kdbprintf
2685: extern int db_indent;
2686: void db_sched(void);
2687:
2688: void
2689: db_sched(void)
2690: {
2691: iprintf("Scheduling Statistics:\n");
2692: db_indent += 2;
2693: iprintf("Thread invocations: csw %d same %d\n",
2694: c_thread_invoke_csw, c_thread_invoke_same);
2695: #if MACH_COUNTERS
2696: iprintf("Thread block: calls %d\n",
2697: c_thread_block_calls);
2698: iprintf("Idle thread:\n\thandoff %d block %d no_dispatch %d\n",
2699: c_idle_thread_handoff,
2700: c_idle_thread_block, no_dispatch_count);
2701: iprintf("Sched thread blocks: %d\n", c_sched_thread_block);
2702: #endif /* MACH_COUNTERS */
2703: db_indent -= 2;
2704: }
2705: #endif /* MACH_KDB */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.