|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University.
4: * Copyright (c) 1993,1994 The University of Utah and
5: * the Computer Systems Laboratory (CSL).
6: * All rights reserved.
7: *
8: * Permission to use, copy, modify and distribute this software and its
9: * documentation is hereby granted, provided that both the copyright
10: * notice and this permission notice appear in all copies of the
11: * software, derivative works or modified versions, and any portions
12: * thereof, and that both notices appear in supporting documentation.
13: *
14: * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
15: * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
16: * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
17: * THIS SOFTWARE.
18: *
19: * Carnegie Mellon requests users of this software to return to
20: *
21: * Software Distribution Coordinator or [email protected]
22: * School of Computer Science
23: * Carnegie Mellon University
24: * Pittsburgh PA 15213-3890
25: *
26: * any improvements or extensions that they make and grant Carnegie Mellon
27: * the rights to redistribute these changes.
28: */
29: /*
30: *
31: * This file contains routines to check whether an ast is needed.
32: *
33: * ast_check() - check whether ast is needed for interrupt or context
34: * switch. Usually called by clock interrupt handler.
35: *
36: */
37:
38: #include <kern/ast.h>
39: #include <kern/counters.h>
1.1.1.3 ! root 40: #include <kern/debug.h>
1.1 root 41: #include "cpu_number.h"
42: #include <kern/queue.h>
43: #include <kern/sched.h>
44: #include <kern/sched_prim.h>
45: #include <kern/thread.h>
46: #include <kern/processor.h>
1.1.1.3 ! root 47: #include <device/net_io.h>
1.1 root 48:
49: #include <machine/machspl.h> /* for splsched */
50:
51: #if MACH_FIXPRI
52: #include <mach/policy.h>
1.1.1.2 root 53: #endif /* MACH_FIXPRI */
1.1 root 54:
55:
56: volatile ast_t need_ast[NCPUS];
57:
58: void
59: ast_init()
60: {
61: #ifndef MACHINE_AST
62: register int i;
63:
64: for (i=0; i<NCPUS; i++)
65: need_ast[i] = 0;
1.1.1.2 root 66: #endif /* MACHINE_AST */
1.1 root 67: }
68:
69: void
1.1.1.3 ! root 70: ast_taken(void)
1.1 root 71: {
72: register thread_t self = current_thread();
73: register ast_t reasons;
74:
75: /*
76: * Interrupts are still disabled.
77: * We must clear need_ast and then enable interrupts.
78: */
79:
80: reasons = need_ast[cpu_number()];
81: need_ast[cpu_number()] = AST_ZILCH;
82: (void) spl0();
83:
84: /*
85: * These actions must not block.
86: */
87:
88: if (reasons & AST_NETWORK)
89: net_ast();
90:
91: /*
92: * Make darn sure that we don't call thread_halt_self
93: * or thread_block from the idle thread.
94: */
95:
96: if (self != current_processor()->idle_thread) {
97: #ifndef MIGRATING_THREADS
98: while (thread_should_halt(self))
99: thread_halt_self();
100: #endif
101:
102: /*
103: * One of the previous actions might well have
104: * woken a high-priority thread, so we use
105: * csw_needed in addition to AST_BLOCK.
106: */
107:
108: if ((reasons & AST_BLOCK) ||
109: csw_needed(self, current_processor())) {
110: counter(c_ast_taken_block++);
111: thread_block(thread_exception_return);
112: }
113: }
114: }
115:
116: void
117: ast_check()
118: {
119: register int mycpu = cpu_number();
120: register processor_t myprocessor;
121: register thread_t thread = current_thread();
122: register run_queue_t rq;
123: spl_t s = splsched();
124:
125: /*
126: * Check processor state for ast conditions.
127: */
128: myprocessor = cpu_to_processor(mycpu);
129: switch(myprocessor->state) {
130: case PROCESSOR_OFF_LINE:
131: case PROCESSOR_IDLE:
132: case PROCESSOR_DISPATCHING:
133: /*
134: * No ast.
135: */
136: break;
137:
138: #if NCPUS > 1
139: case PROCESSOR_ASSIGN:
140: case PROCESSOR_SHUTDOWN:
141: /*
142: * Need ast to force action thread onto processor.
143: *
144: * XXX Should check if action thread is already there.
145: */
146: ast_on(mycpu, AST_BLOCK);
147: break;
1.1.1.2 root 148: #endif /* NCPUS > 1 */
1.1 root 149:
150: case PROCESSOR_RUNNING:
151:
152: /*
153: * Propagate thread ast to processor. If we already
154: * need an ast, don't look for more reasons.
155: */
156: ast_propagate(thread, mycpu);
157: if (ast_needed(mycpu))
158: break;
159:
160: /*
161: * Context switch check. The csw_needed macro isn't
162: * used here because the rq->low hint may be wrong,
163: * and fixing it here avoids an extra ast.
164: * First check the easy cases.
165: */
166: if (thread->state & TH_SUSP || myprocessor->runq.count > 0) {
167: ast_on(mycpu, AST_BLOCK);
168: break;
169: }
170:
171: /*
172: * Update lazy evaluated runq->low if only timesharing.
173: */
174: #if MACH_FIXPRI
175: if (myprocessor->processor_set->policies & POLICY_FIXEDPRI) {
176: if (csw_needed(thread,myprocessor)) {
177: ast_on(mycpu, AST_BLOCK);
178: break;
179: }
180: else {
181: /*
182: * For fixed priority threads, set first_quantum
183: * so entire new quantum is used.
184: */
185: if (thread->policy == POLICY_FIXEDPRI)
186: myprocessor->first_quantum = TRUE;
187: }
188: }
189: else {
1.1.1.2 root 190: #endif /* MACH_FIXPRI */
1.1 root 191: rq = &(myprocessor->processor_set->runq);
192: if (!(myprocessor->first_quantum) && (rq->count > 0)) {
193: register queue_t q;
194: /*
195: * This is not the first quantum, and there may
196: * be something in the processor_set runq.
197: * Check whether low hint is accurate.
198: */
199: q = rq->runq + *(volatile int *)&rq->low;
200: if (queue_empty(q)) {
201: register int i;
202:
203: /*
204: * Need to recheck and possibly update hint.
205: */
206: simple_lock(&rq->lock);
207: q = rq->runq + rq->low;
208: if (rq->count > 0) {
209: for (i = rq->low; i < NRQS; i++) {
210: if(!(queue_empty(q)))
211: break;
212: q++;
213: }
214: rq->low = i;
215: }
216: simple_unlock(&rq->lock);
217: }
218:
219: if (rq->low <= thread->sched_pri) {
220: ast_on(mycpu, AST_BLOCK);
221: break;
222: }
223: }
224: #if MACH_FIXPRI
225: }
1.1.1.2 root 226: #endif /* MACH_FIXPRI */
1.1 root 227: break;
228:
229: default:
230: panic("ast_check: Bad processor state (cpu %d processor %08x) state: %d",
231: mycpu, myprocessor, myprocessor->state);
232: }
233:
234: (void) splx(s);
235: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.