FreeBSD/Linux Kernel Cross Reference
sys/kern/quantum.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1993-1987 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: quantum.c,v $
29 * Revision 2.2 93/11/17 17:19:04 dbg
30 * Separated quantum calculation code from clock update routines
31 * and moved into this file.
32 * [93/05/11 dbg]
33 *
34 */
35
36 #include <mach/boolean.h>
37
38 #include <kern/processor.h>
39 #include <kern/sched_policy.h>
40 #include <kern/thread.h>
41
42 /*
43 * Quantum adjustment.
44 */
45
46 /*
47 * Max context switch rate, in microseconds.
48 */
49 int min_quantum = 100 * 1000; /* 10/second = 100 milliseconds */
50
51 /*
52 * Precalculate the appropriate system quanta based on load. The
53 * index into machine_quantum is the number of threads on the
54 * processor set queue. It is limited to the number of processors in
55 * the set.
56 */
57
58 void quantum_set(
59 processor_set_t pset)
60 {
61 #if NCPUS > 1
62 register int i,ncpus;
63
64 ncpus = pset->processor_count;
65
66 for (i = 1; i <= ncpus; i++) {
67 pset->machine_quantum[i] = ((min_quantum * ncpus) + (i/2)) / i ;
68 }
69 pset->machine_quantum[0] = 2 * pset->machine_quantum[1];
70
71 i = (pset->runq.count > pset->processor_count)
72 ? pset->processor_count
73 : pset->runq.count;
74 pset->set_quantum = pset->machine_quantum[i];
75 #else /* NCPUS > 1 */
76 default_pset.set_quantum = min_quantum;
77 #endif /* NCPUS > 1 */
78 }
79
80 /*
81 * clock_quantum_update:
82 *
83 * Recalculate the quantum and priority for a thread.
84 * The number of microseconds that has elapsed since
85 * we were last called is passed in.
86 */
87
88 void
89 clock_quantum_update(
90 thread_t thread,
91 int mycpu,
92 unsigned int usecs)
93 {
94 int quantum;
95 processor_t myprocessor = cpu_to_processor(mycpu);
96 boolean_t end_quantum;
97
98 #if NCPUS > 1
99 /*
100 * Update set_quantum.
101 */
102 {
103 processor_set_t pset = myprocessor->processor_set;
104
105 if (pset == 0) {
106 /*
107 * Processor is being reassigned.
108 *
109 * Should rewrite processor assignment code to
110 * block clock interrupts.
111 */
112 return;
113 }
114
115 if (pset->runq.count > pset->processor_count)
116 pset->set_quantum = pset->machine_quantum[pset->processor_count];
117 else
118 pset->set_quantum = pset->machine_quantum[pset->runq.count];
119
120 if (myprocessor->state == PROCESSOR_IDLE)
121 return;
122
123 #if MACH_IO_BINDING
124 if (myprocessor->runq.count != 0)
125 quantum = min_quantum;
126 else
127 #endif
128 quantum = pset->set_quantum;
129
130 /*
131 * Runtime quantum adjustment. Use quantum_adj_index
132 * to avoid synchronizing quantum expirations.
133 */
134 if (quantum != myprocessor->last_quantum &&
135 pset->processor_count > 1)
136 {
137 myprocessor->last_quantum = quantum;
138 simple_lock(&pset->quantum_adj_lock);
139 quantum = min_quantum +
140 (pset->quantum_adj_index * (quantum - min_quantum))
141 / (pset->processor_count - 1);
142 if (++pset->quantum_adj_index >= pset->processor_count)
143 pset->quantum_adj_index = 0;
144 simple_unlock(&pset->quantum_adj_lock);
145 }
146 }
147
148 #else /* NCPUS > 1 */
149 quantum = min_quantum;
150
151 if (myprocessor->state == PROCESSOR_IDLE)
152 return;
153 #endif /* NCPUS > 1 */
154
155 /*
156 * Decrement quantum
157 */
158 myprocessor->quantum -= usecs;
159 if (myprocessor->quantum <= 0) {
160 /*
161 * The quantum is up. Give the thread another.
162 */
163 myprocessor->first_quantum = FALSE;
164 myprocessor->quantum += quantum;
165 end_quantum = TRUE;
166 }
167 else {
168 end_quantum = FALSE;
169 }
170
171 CLOCK_SCHED(thread, end_quantum);
172 }
Cache object: bd3f43f955f4fcae8c65c994a5fac613
|