|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * Mach Operating System
27: * Copyright (c) 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: * This file contains routines to check whether an ast is needed.
53: *
54: * ast_check() - check whether ast is needed for interrupt or context
55: * switch. Usually called by clock interrupt handler.
56: *
57: */
58:
59: #include <cpus.h>
60: #include <mach_fixpri.h>
61:
62: #include <kern/ast.h>
63: #include <kern/counters.h>
64: #include <kern/cpu_number.h>
65: #include <kern/queue.h>
66: #include <kern/sched.h>
67: #include <kern/sched_prim.h>
68: #include <kern/thread.h>
69: #include <kern/processor.h>
70: #include <machine/machspl.h> /* for splsched */
71:
72: #include <sys/param.h> /* XXX */
73: #include <sys/proc.h> /* XXX */
74: #include <sys/user.h> /* XXX */
75: #include <sys/signalvar.h>
76:
77: #if MACH_FIXPRI
78: #include <mach/policy.h>
79: #endif MACH_FIXPRI
80:
81:
82: volatile ast_t need_ast[NCPUS];
83:
84: void
85: ast_init()
86: {
87: #ifndef MACHINE_AST
88: register int i;
89:
90: for (i=0; i<NCPUS; i++)
91: need_ast[i] = 0;
92: #endif MACHINE_AST
93: }
94:
95: #ifdef notdef
96: void
97: ast_taken()
98: {
99: register thread_t self = current_thread();
100: register ast_t reasons;
101:
102: /*
103: * Interrupts are still disabled.
104: * We must clear need_ast and then enable interrupts.
105: */
106:
107: reasons = need_ast[cpu_number()];
108: need_ast[cpu_number()] = AST_ZILCH;
109: (void) spl0();
110:
111: /*
112: * These actions must not block.
113: */
114:
115: if (reasons & AST_NETWORK)
116: net_ast();
117:
118: /*
119: * Make darn sure that we don't call thread_halt_self
120: * or thread_block from the idle thread.
121: */
122:
123: if (self != current_processor()->idle_thread) {
124: while (thread_should_halt(self))
125: thread_halt_self();
126:
127: /*
128: * One of the previous actions might well have
129: * woken a high-priority thread, so we use
130: * csw_needed in addition to AST_BLOCK.
131: */
132:
133: if ((reasons & AST_BLOCK) ||
134: csw_needed(self, current_processor())) {
135: counter(c_ast_taken_block++);
136: thread_block_continue(thread_exception_return);
137: }
138: }
139: }
140: #endif
141:
142: void
143: ast_check()
144: {
145: register struct proc *p;
146: register int mycpu = cpu_number();
147: register processor_t myprocessor;
148: register thread_t thread = current_thread();
149: register run_queue_t rq;
150: spl_t s = splsched();
151:
152: /*
153: * Check processor state for ast conditions.
154: */
155: myprocessor = cpu_to_processor(mycpu);
156: switch(myprocessor->state) {
157: case PROCESSOR_OFF_LINE:
158: case PROCESSOR_IDLE:
159: case PROCESSOR_DISPATCHING:
160: /*
161: * No ast.
162: */
163: break;
164:
165: #if NCPUS > 1
166: case PROCESSOR_ASSIGN:
167: case PROCESSOR_SHUTDOWN:
168: /*
169: * Need ast to force action thread onto processor.
170: *
171: * XXX Should check if action thread is already there.
172: */
173: ast_on(mycpu, AST_BLOCK);
174: break;
175: #endif NCPUS > 1
176:
177: case PROCESSOR_RUNNING:
178:
179: /*
180: * XXX Check for signals.
181: */
182: p = thread->task->proc;
183: if (p) {
184: if ((thread != THREAD_NULL && SHOULDissignal(p, thread->_uthread)))
185: ast_on(mycpu, AST_UNIX);
186: }
187:
188: /*
189: * Propagate thread ast to processor. If we already
190: * need an ast, don't look for more reasons.
191: */
192: ast_propagate(thread, mycpu);
193: if (ast_needed(mycpu))
194: break;
195:
196: /*
197: * Context switch check. The csw_needed macro isn't
198: * used here because the rq->low hint may be wrong,
199: * and fixing it here avoids an extra ast.
200: * First check the easy cases.
201: */
202: if (thread->state & TH_SUSP || myprocessor->runq.count > 0) {
203: ast_on(mycpu, AST_BLOCK);
204: break;
205: }
206:
207: /*
208: * Update lazy evaluated runq->low if only timesharing.
209: */
210: #if MACH_FIXPRI
211: if (myprocessor->processor_set->policies & POLICY_FIXEDPRI) {
212: if (csw_needed(thread,myprocessor)) {
213: ast_on(mycpu, AST_BLOCK);
214: break;
215: }
216: else {
217: /*
218: * For fixed priority threads, set first_quantum
219: * so entire new quantum is used.
220: */
221: if (thread->policy == POLICY_FIXEDPRI)
222: myprocessor->first_quantum = TRUE;
223: }
224: }
225: else {
226: #endif MACH_FIXPRI
227: rq = &(myprocessor->processor_set->runq);
228: if (!(myprocessor->first_quantum) && (rq->count > 0)) {
229: register queue_t q;
230: /*
231: * This is not the first quantum, and there may
232: * be something in the processor_set runq.
233: * Check whether low hint is accurate.
234: */
235: q = rq->runq + *(volatile int *)&rq->high;
236: if (queue_empty(q)) {
237: register int i;
238:
239: /*
240: * Need to recheck and possibly update hint.
241: */
242: simple_lock(&rq->lock);
243: q = rq->runq + rq->high;
244: if (rq->count > 0) {
245: for (i = rq->high; i >= 0; i--) {
246: if(!(queue_empty(q)))
247: break;
248: q--;
249: }
250: rq->high = i;
251: }
252: simple_unlock(&rq->lock);
253: }
254:
255: if (rq->high >= thread->sched_pri) {
256: ast_on(mycpu, AST_BLOCK);
257: break;
258: }
259: }
260: #if MACH_FIXPRI
261: }
262: #endif MACH_FIXPRI
263: break;
264:
265: default:
266: panic("ast_check: Bad processor state");
267: }
268:
269: (void) splx(s);
270: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.