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