|
|
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 <cpus.h>
39: #include <mach_fixpri.h>
40: #include <norma_ipc.h>
41:
42: #include <kern/ast.h>
43: #include <kern/counters.h>
44: #include "cpu_number.h"
45: #include <kern/queue.h>
46: #include <kern/sched.h>
47: #include <kern/sched_prim.h>
48: #include <kern/thread.h>
49: #include <kern/processor.h>
50:
51: #include <machine/machspl.h> /* for splsched */
52:
53: #if MACH_FIXPRI
54: #include <mach/policy.h>
55: #endif /* MACH_FIXPRI */
56:
57:
58: volatile ast_t need_ast[NCPUS];
59:
60: void
61: ast_init()
62: {
63: #ifndef MACHINE_AST
64: register int i;
65:
66: for (i=0; i<NCPUS; i++)
67: need_ast[i] = 0;
68: #endif /* MACHINE_AST */
69: }
70:
71: void
72: ast_taken()
73: {
74: register thread_t self = current_thread();
75: register ast_t reasons;
76:
77: /*
78: * Interrupts are still disabled.
79: * We must clear need_ast and then enable interrupts.
80: */
81:
82: reasons = need_ast[cpu_number()];
83: need_ast[cpu_number()] = AST_ZILCH;
84: (void) spl0();
85:
86: /*
87: * These actions must not block.
88: */
89:
90: if (reasons & AST_NETWORK)
91: net_ast();
92:
93: #if NORMA_IPC
94: if (reasons & AST_NETIPC)
95: netipc_ast();
96: #endif /* NORMA_IPC */
97:
98: /*
99: * Make darn sure that we don't call thread_halt_self
100: * or thread_block from the idle thread.
101: */
102:
103: if (self != current_processor()->idle_thread) {
104: #ifndef MIGRATING_THREADS
105: while (thread_should_halt(self))
106: thread_halt_self();
107: #endif
108:
109: /*
110: * One of the previous actions might well have
111: * woken a high-priority thread, so we use
112: * csw_needed in addition to AST_BLOCK.
113: */
114:
115: if ((reasons & AST_BLOCK) ||
116: csw_needed(self, current_processor())) {
117: counter(c_ast_taken_block++);
118: thread_block(thread_exception_return);
119: }
120: }
121: }
122:
123: void
124: ast_check()
125: {
126: register int mycpu = cpu_number();
127: register processor_t myprocessor;
128: register thread_t thread = current_thread();
129: register run_queue_t rq;
130: spl_t s = splsched();
131:
132: /*
133: * Check processor state for ast conditions.
134: */
135: myprocessor = cpu_to_processor(mycpu);
136: switch(myprocessor->state) {
137: case PROCESSOR_OFF_LINE:
138: case PROCESSOR_IDLE:
139: case PROCESSOR_DISPATCHING:
140: /*
141: * No ast.
142: */
143: break;
144:
145: #if NCPUS > 1
146: case PROCESSOR_ASSIGN:
147: case PROCESSOR_SHUTDOWN:
148: /*
149: * Need ast to force action thread onto processor.
150: *
151: * XXX Should check if action thread is already there.
152: */
153: ast_on(mycpu, AST_BLOCK);
154: break;
155: #endif /* NCPUS > 1 */
156:
157: case PROCESSOR_RUNNING:
158:
159: /*
160: * Propagate thread ast to processor. If we already
161: * need an ast, don't look for more reasons.
162: */
163: ast_propagate(thread, mycpu);
164: if (ast_needed(mycpu))
165: break;
166:
167: /*
168: * Context switch check. The csw_needed macro isn't
169: * used here because the rq->low hint may be wrong,
170: * and fixing it here avoids an extra ast.
171: * First check the easy cases.
172: */
173: if (thread->state & TH_SUSP || myprocessor->runq.count > 0) {
174: ast_on(mycpu, AST_BLOCK);
175: break;
176: }
177:
178: /*
179: * Update lazy evaluated runq->low if only timesharing.
180: */
181: #if MACH_FIXPRI
182: if (myprocessor->processor_set->policies & POLICY_FIXEDPRI) {
183: if (csw_needed(thread,myprocessor)) {
184: ast_on(mycpu, AST_BLOCK);
185: break;
186: }
187: else {
188: /*
189: * For fixed priority threads, set first_quantum
190: * so entire new quantum is used.
191: */
192: if (thread->policy == POLICY_FIXEDPRI)
193: myprocessor->first_quantum = TRUE;
194: }
195: }
196: else {
197: #endif /* MACH_FIXPRI */
198: rq = &(myprocessor->processor_set->runq);
199: if (!(myprocessor->first_quantum) && (rq->count > 0)) {
200: register queue_t q;
201: /*
202: * This is not the first quantum, and there may
203: * be something in the processor_set runq.
204: * Check whether low hint is accurate.
205: */
206: q = rq->runq + *(volatile int *)&rq->low;
207: if (queue_empty(q)) {
208: register int i;
209:
210: /*
211: * Need to recheck and possibly update hint.
212: */
213: simple_lock(&rq->lock);
214: q = rq->runq + rq->low;
215: if (rq->count > 0) {
216: for (i = rq->low; i < NRQS; i++) {
217: if(!(queue_empty(q)))
218: break;
219: q++;
220: }
221: rq->low = i;
222: }
223: simple_unlock(&rq->lock);
224: }
225:
226: if (rq->low <= thread->sched_pri) {
227: ast_on(mycpu, AST_BLOCK);
228: break;
229: }
230: }
231: #if MACH_FIXPRI
232: }
233: #endif /* MACH_FIXPRI */
234: break;
235:
236: default:
237: panic("ast_check: Bad processor state (cpu %d processor %08x) state: %d",
238: mycpu, myprocessor, myprocessor->state);
239: }
240:
241: (void) splx(s);
242: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.