|
|
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: * File: clock_prim.c
31: * Author: Avadis Tevanian, Jr.
32: * Date: 1986
33: *
34: * Clock primitives.
35: */
36:
37: #include <cpus.h>
38:
39: #include <mach/boolean.h>
40: #include <mach/kern_return.h>
41: #include <mach/machine.h>
42: #include <kern/host.h>
43: #include <kern/mach_param.h>
44: #include <kern/sched.h>
45: #include <kern/thread.h>
46: #include <kern/processor.h>
47: #include <kern/timer.h>
48: #include <kern/time_out.h>
49: #include <kern/time_stamp.h>
50: #include <machine/machspl.h>
51:
52:
53:
54: /*
55: * USAGE_THRESHOLD is the amount by which usage must change to
56: * cause a priority shift that moves a thread between run queues.
57: */
58:
59: #ifdef PRI_SHIFT_2
60: #if PRI_SHIFT_2 > 0
61: #define USAGE_THRESHOLD (((1 << PRI_SHIFT) + (1 << PRI_SHIFT_2)) << (2 + SCHED_SHIFT))
62: #else /* PRI_SHIFT_2 > 0 */
63: #define USAGE_THRESHOLD (((1 << PRI_SHIFT) - (1 << -(PRI_SHIFT_2))) << (2 + SCHED_SHIFT))
64: #endif /* PRI_SHIFT_2 > 0 */
65: #else /* PRI_SHIFT_2 */
66: #define USAGE_THRESHOLD (1 << (PRI_SHIFT + 2 + SCHED_SHIFT))
67: #endif /* PRI_SHIFT_2 */
68:
69: /*
70: * thread_quantum_update:
71: *
72: * Recalculate the quantum and priority for a thread.
73: * The number of ticks that has elapsed since we were last called
74: * is passed as "nticks."
75: *
76: * Called only from clock_interrupt().
77: */
78:
79: void thread_quantum_update(mycpu, thread, nticks, state)
80: register int mycpu;
81: register thread_t thread;
82: int nticks;
83: int state;
84: {
85: register int quantum;
86: register processor_t myprocessor;
87: #if NCPUS > 1
88: register processor_set_t pset;
89: #endif
90: spl_t s;
91:
92: myprocessor = cpu_to_processor(mycpu);
93: #if NCPUS > 1
94: pset = myprocessor->processor_set;
95: if (pset == 0) {
96: /*
97: * Processor is being reassigned.
98: * Should rewrite processor assignment code to
99: * block clock interrupts.
100: */
101: return;
102: }
103: #endif /* NCPUS > 1 */
104:
105: /*
106: * Account for thread's utilization of these ticks.
107: * This assumes that there is *always* a current thread.
108: * When the processor is idle, it should be the idle thread.
109: */
110:
111: /*
112: * Update set_quantum and calculate the current quantum.
113: */
114: #if NCPUS > 1
115: pset->set_quantum = pset->machine_quantum[
116: ((pset->runq.count > pset->processor_count) ?
117: pset->processor_count : pset->runq.count)];
118:
119: if (myprocessor->runq.count != 0)
120: quantum = min_quantum;
121: else
122: quantum = pset->set_quantum;
123: #else /* NCPUS > 1 */
124: quantum = min_quantum;
125: default_pset.set_quantum = quantum;
126: #endif /* NCPUS > 1 */
127:
128: /*
129: * Now recompute the priority of the thread if appropriate.
130: */
131:
132: if (state != CPU_STATE_IDLE) {
133: myprocessor->quantum -= nticks;
134: #if NCPUS > 1
135: /*
136: * Runtime quantum adjustment. Use quantum_adj_index
137: * to avoid synchronizing quantum expirations.
138: */
139: if ((quantum != myprocessor->last_quantum) &&
140: (pset->processor_count > 1)) {
141: myprocessor->last_quantum = quantum;
142: simple_lock(&pset->quantum_adj_lock);
143: quantum = min_quantum + (pset->quantum_adj_index *
144: (quantum - min_quantum)) /
145: (pset->processor_count - 1);
146: if (++(pset->quantum_adj_index) >=
147: pset->processor_count)
148: pset->quantum_adj_index = 0;
149: simple_unlock(&pset->quantum_adj_lock);
150: }
151: #endif /* NCPUS > 1 */
152: if (myprocessor->quantum <= 0) {
153: s = splsched();
154: thread_lock(thread);
155: if (thread->sched_stamp != sched_tick) {
156: update_priority(thread);
157: }
158: else {
159: if (
160: #if MACH_FIXPRI
161: (thread->policy == POLICY_TIMESHARE) &&
162: #endif /* MACH_FIXPRI */
163: (thread->depress_priority < 0)) {
164: thread_timer_delta(thread);
165: thread->sched_usage +=
166: thread->sched_delta;
167: thread->sched_delta = 0;
168: compute_my_priority(thread);
169: }
170: }
171: thread_unlock(thread);
172: (void) splx(s);
173: /*
174: * This quantum is up, give this thread another.
175: */
176: myprocessor->first_quantum = FALSE;
177: #if MACH_FIXPRI
178: if (thread->policy == POLICY_TIMESHARE) {
179: #endif /* MACH_FIXPRI */
180: myprocessor->quantum += quantum;
181: #if MACH_FIXPRI
182: }
183: else {
184: /*
185: * Fixed priority has per-thread quantum.
186: *
187: */
188: myprocessor->quantum += thread->sched_data;
189: }
190: #endif /* MACH_FIXPRI */
191: }
192: /*
193: * Recompute priority if appropriate.
194: */
195: else {
196: s = splsched();
197: thread_lock(thread);
198: if (thread->sched_stamp != sched_tick) {
199: update_priority(thread);
200: }
201: else {
202: if (
203: #if MACH_FIXPRI
204: (thread->policy == POLICY_TIMESHARE) &&
205: #endif /* MACH_FIXPRI */
206: (thread->depress_priority < 0)) {
207: thread_timer_delta(thread);
208: if (thread->sched_delta >= USAGE_THRESHOLD) {
209: thread->sched_usage +=
210: thread->sched_delta;
211: thread->sched_delta = 0;
212: compute_my_priority(thread);
213: }
214: }
215: }
216: thread_unlock(thread);
217: (void) splx(s);
218: }
219: /*
220: * Check for and schedule ast if needed.
221: */
222: ast_check();
223: }
224: }
225:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.