|
|
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_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: /*
54: *
55: * This file contains routines to check whether an ast is needed.
56: *
57: * ast_check() - check whether ast is needed for interrupt or context
58: * switch. Usually called by clock interrupt handler.
59: *
60: */
61:
62: #include <cputypes.h>
63: #include <cpus.h>
64: #include <platforms.h>
65: #include <dipc.h>
66: #include <task_swapper.h>
67:
68: #include <kern/ast.h>
69: #include <kern/counters.h>
70: #include <kern/cpu_number.h>
71: #include <kern/misc_protos.h>
72: #include <kern/queue.h>
73: #include <kern/sched.h>
74: #include <kern/sched_prim.h>
75: #include <kern/thread.h>
76: #include <kern/thread_act.h>
77: #include <kern/thread_swap.h>
78: #include <kern/processor.h>
79: #include <kern/spl.h>
80: #include <mach/policy.h>
81: #if DIPC
82: #include <dipc/dipc_funcs.h>
83: #endif /* DIPC */
84: #if TASK_SWAPPER
85: #include <kern/task_swap.h>
86: #endif /* TASK_SWAPPER */
87:
88: volatile ast_t need_ast[NCPUS];
89:
90: void
91: ast_init(void)
92: {
93: #ifndef MACHINE_AST
94: register int i;
95:
96: for (i=0; i<NCPUS; i++) {
97: need_ast[i] = AST_NONE;
98: }
99: #endif /* MACHINE_AST */
100: }
101:
102: void
103: ast_taken(
104: boolean_t preemption,
105: ast_t mask,
106: boolean_t interrupt
107: )
108: {
109: register thread_t self = current_thread();
110: register processor_t mypr;
111: register ast_t reasons;
112: register int mycpu;
113: thread_act_t act = self->top_act;
114: #ifdef MACH_BSD
115: extern void bsd_ast(thread_act_t);
116: #endif
117:
118: mp_disable_preemption();
119: mycpu = cpu_number();
120: reasons = need_ast[mycpu] & mask;
121: need_ast[mycpu] &= ~reasons;
122: mp_enable_preemption();
123:
124: ml_set_interrupts_enabled(interrupt);
125:
126: /*
127: * These actions must not block.
128: */
129:
130: #if DIPC
131: if (reasons & AST_DIPC)
132: dipc_ast();
133: #endif /* DIPC */
134:
135: #ifdef MACH_BSD
136: if (reasons & AST_BSD)
137: bsd_ast(act);
138: if (reasons & AST_BSD_INIT) {
139: thread_ast_clear(act,AST_BSD_INIT);
140: bsdinit_task();
141: }
142: #endif
143:
144: /*
145: * Make darn sure that we don't call thread_halt_self
146: * or thread_block from the idle thread.
147: */
148:
149: /* XXX - this isn't currently right for the HALT case... */
150:
151: mp_disable_preemption();
152: mypr = current_processor();
153: if (self == mypr->idle_thread) {
154: #if NCPUS == 1
155: if (reasons & AST_URGENT) {
156: if (!preemption)
157: panic("ast_taken: AST_URGENT for idle_thr w/o preemption");
158: }
159: #endif
160: mp_enable_preemption();
161: return;
162: }
163: mp_enable_preemption();
164:
165: #if TASK_SWAPPER
166: /* must be before AST_APC */
167: if (reasons & AST_SWAPOUT) {
168: spl_t s;
169: swapout_ast();
170: s = splsched();
171: mp_disable_preemption();
172: mycpu = cpu_number();
173: if (need_ast[mycpu] & AST_APC) {
174: /* generated in swapout_ast() to get suspended */
175: reasons |= AST_APC; /* process now ... */
176: need_ast[mycpu] &= ~AST_APC; /* ... and not later */
177: }
178: mp_enable_preemption();
179: splx(s);
180: }
181: #endif /* TASK_SWAPPER */
182:
183: /* migration APC hook */
184: if (reasons & AST_APC) {
185: act_execute_returnhandlers();
186: return; /* auto-retry will catch anything new */
187: }
188:
189: /*
190: * thread_block needs to know if the thread's quantum
191: * expired so the thread can be put on the tail of
192: * run queue. One of the previous actions might well
193: * have woken a high-priority thread, so we also use
194: * csw_needed check.
195: */
196: {
197: if ((reasons &= AST_PREEMPT) == 0) {
198: mp_disable_preemption();
199: mypr = current_processor();
200: if (csw_needed(self, mypr)) {
201: reasons = (mypr->first_quantum
202: ? AST_BLOCK
203: : AST_QUANTUM);
204: }
205: mp_enable_preemption();
206: }
207: if (reasons) {
208: counter(c_ast_taken_block++);
209: thread_block_reason((void (*)(void))0, reasons);
210: }
211: }
212: }
213:
214: void
215: ast_check(void)
216: {
217: register int mycpu;
218: register processor_t myprocessor;
219: register thread_t thread = current_thread();
220: spl_t s = splsched();
221:
222: mp_disable_preemption();
223: mycpu = cpu_number();
224:
225: /*
226: * Check processor state for ast conditions.
227: */
228: myprocessor = cpu_to_processor(mycpu);
229: switch(myprocessor->state) {
230: case PROCESSOR_OFF_LINE:
231: case PROCESSOR_IDLE:
232: case PROCESSOR_DISPATCHING:
233: /*
234: * No ast.
235: */
236: break;
237:
238: #if NCPUS > 1
239: case PROCESSOR_ASSIGN:
240: case PROCESSOR_SHUTDOWN:
241: /*
242: * Need ast to force action thread onto processor.
243: *
244: * XXX Should check if action thread is already there.
245: */
246: ast_on(AST_BLOCK);
247: break;
248: #endif /* NCPUS > 1 */
249:
250: case PROCESSOR_RUNNING:
251: /*
252: * Propagate thread ast to processor. If we already
253: * need an ast, don't look for more reasons.
254: */
255: ast_propagate(current_act()->ast);
256: if (ast_needed(mycpu))
257: break;
258:
259: /*
260: * Context switch check.
261: */
262: if (csw_needed(thread, myprocessor)) {
263: ast_on((myprocessor->first_quantum ?
264: AST_BLOCK : AST_QUANTUM));
265: }
266: break;
267:
268: default:
269: panic("ast_check: Bad processor state");
270: }
271: mp_enable_preemption();
272: splx(s);
273: }
274:
275: /*
276: * JMM - Temporary exports to other components
277: */
278: #undef ast_on
279: #undef ast_off
280:
281: void
282: ast_on(ast_t reason)
283: {
284: ast_on_fast(reason);
285: }
286:
287: void
288: ast_off(ast_t reason)
289: {
290: ast_off_fast(reason);
291: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.