]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kern/thread_policy.c
e9eacf91b5588b1315d7ff92ff3021768f2369fe
[apple/xnu.git] / osfmk / kern / thread_policy.c
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 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
24 *
25 * HISTORY
26 *
27 * 15 October 2000 (debo)
28 * Created.
29 */
30
31 #include <kern/thread.h>
32
33 static void
34 thread_recompute_priority(
35 thread_t thread);
36
37 kern_return_t
38 thread_policy_set(
39 thread_act_t act,
40 thread_policy_flavor_t flavor,
41 thread_policy_t policy_info,
42 mach_msg_type_number_t count)
43 {
44 kern_return_t result = KERN_SUCCESS;
45 thread_t thread;
46 spl_t s;
47
48 if (act == THR_ACT_NULL)
49 return (KERN_INVALID_ARGUMENT);
50
51 thread = act_lock_thread(act);
52 if (!act->active) {
53 act_unlock_thread(act);
54
55 return (KERN_TERMINATED);
56 }
57
58 assert(thread != THREAD_NULL);
59
60 switch (flavor) {
61
62 case THREAD_EXTENDED_POLICY:
63 {
64 boolean_t timeshare = TRUE;
65
66 if (count >= THREAD_EXTENDED_POLICY_COUNT) {
67 thread_extended_policy_t info;
68
69 info = (thread_extended_policy_t)policy_info;
70 timeshare = info->timeshare;
71 }
72
73 s = splsched();
74 thread_lock(thread);
75
76 if (!(thread->sched_mode & TH_MODE_FAILSAFE)) {
77 thread->sched_mode &= ~TH_MODE_REALTIME;
78
79 if (timeshare)
80 thread->sched_mode |= TH_MODE_TIMESHARE;
81 else
82 thread->sched_mode &= ~TH_MODE_TIMESHARE;
83
84 thread_recompute_priority(thread);
85 }
86 else {
87 thread->safe_mode &= ~TH_MODE_REALTIME;
88
89 if (timeshare)
90 thread->safe_mode |= TH_MODE_TIMESHARE;
91 else
92 thread->safe_mode &= ~TH_MODE_TIMESHARE;
93 }
94
95 thread_unlock(thread);
96 splx(s);
97
98 break;
99 }
100
101 case THREAD_TIME_CONSTRAINT_POLICY:
102 {
103 thread_time_constraint_policy_t info;
104
105 if (count < THREAD_TIME_CONSTRAINT_POLICY_COUNT) {
106 result = KERN_INVALID_ARGUMENT;
107 break;
108 }
109
110 info = (thread_time_constraint_policy_t)policy_info;
111 if ( info->computation > max_rt_quantum ||
112 info->computation < min_rt_quantum ) {
113 result = KERN_INVALID_ARGUMENT;
114 break;
115 }
116
117 s = splsched();
118 thread_lock(thread);
119
120 thread->realtime.period = info->period;
121 thread->realtime.computation = info->computation;
122 thread->realtime.constraint = info->constraint;
123 thread->realtime.preemptible = info->preemptible;
124
125 if (!(thread->sched_mode & TH_MODE_FAILSAFE)) {
126 thread->sched_mode &= ~TH_MODE_TIMESHARE;
127 thread->sched_mode |= TH_MODE_REALTIME;
128 thread_recompute_priority(thread);
129 }
130 else {
131 thread->safe_mode &= ~TH_MODE_TIMESHARE;
132 thread->safe_mode |= TH_MODE_REALTIME;
133 }
134
135 thread_unlock(thread);
136 splx(s);
137
138 break;
139 }
140
141 case THREAD_PRECEDENCE_POLICY:
142 {
143 thread_precedence_policy_t info;
144
145 if (count < THREAD_PRECEDENCE_POLICY_COUNT) {
146 result = KERN_INVALID_ARGUMENT;
147 break;
148 }
149
150 info = (thread_precedence_policy_t)policy_info;
151
152 s = splsched();
153 thread_lock(thread);
154
155 thread->importance = info->importance;
156
157 thread_recompute_priority(thread);
158
159 thread_unlock(thread);
160 splx(s);
161
162 break;
163 }
164
165 default:
166 result = KERN_INVALID_ARGUMENT;
167 break;
168 }
169
170 act_unlock_thread(act);
171
172 return (result);
173 }
174
175 static void
176 thread_recompute_priority(
177 thread_t thread)
178 {
179 integer_t priority;
180
181 if (thread->sched_mode & TH_MODE_REALTIME)
182 priority = BASEPRI_REALTIME;
183 else {
184 if (thread->importance > MAXPRI)
185 priority = MAXPRI;
186 else
187 if (thread->importance < -MAXPRI)
188 priority = -MAXPRI;
189 else
190 priority = thread->importance;
191
192 priority += thread->task_priority;
193
194 if (priority > thread->max_priority)
195 priority = thread->max_priority;
196 else
197 if (priority < MINPRI)
198 priority = MINPRI;
199 }
200
201 if (thread->depress_priority >= 0)
202 thread->depress_priority = priority;
203 else {
204 thread->priority = priority;
205 compute_priority(thread, TRUE);
206
207 if (thread == current_thread())
208 ast_on(AST_BLOCK);
209 }
210 }
211
212 void
213 thread_task_priority(
214 thread_t thread,
215 integer_t priority,
216 integer_t max_priority)
217 {
218 spl_t s;
219
220 assert(thread != THREAD_NULL);
221
222 s = splsched();
223 thread_lock(thread);
224
225 thread->task_priority = priority;
226 thread->max_priority = max_priority;
227
228 thread_recompute_priority(thread);
229
230 thread_unlock(thread);
231 splx(s);
232 }
233
234 kern_return_t
235 thread_policy_get(
236 thread_act_t act,
237 thread_policy_flavor_t flavor,
238 thread_policy_t policy_info,
239 mach_msg_type_number_t *count,
240 boolean_t *get_default)
241 {
242 kern_return_t result = KERN_SUCCESS;
243 thread_t thread;
244 spl_t s;
245
246 if (act == THR_ACT_NULL)
247 return (KERN_INVALID_ARGUMENT);
248
249 thread = act_lock_thread(act);
250 if (!act->active) {
251 act_unlock_thread(act);
252
253 return (KERN_TERMINATED);
254 }
255
256 assert(thread != THREAD_NULL);
257
258 switch (flavor) {
259
260 case THREAD_EXTENDED_POLICY:
261 {
262 boolean_t timeshare = TRUE;
263
264 if (!(*get_default)) {
265 s = splsched();
266 thread_lock(thread);
267
268 if ( !(thread->sched_mode & TH_MODE_REALTIME) &&
269 !(thread->safe_mode & TH_MODE_REALTIME) ) {
270 if (!(thread->sched_mode & TH_MODE_FAILSAFE))
271 timeshare = (thread->sched_mode & TH_MODE_TIMESHARE) != 0;
272 else
273 timeshare = (thread->safe_mode & TH_MODE_TIMESHARE) != 0;
274 }
275 else
276 *get_default = TRUE;
277
278 thread_unlock(thread);
279 splx(s);
280 }
281
282 if (*count >= THREAD_EXTENDED_POLICY_COUNT) {
283 thread_extended_policy_t info;
284
285 info = (thread_extended_policy_t)policy_info;
286 info->timeshare = timeshare;
287 }
288
289 break;
290 }
291
292 case THREAD_TIME_CONSTRAINT_POLICY:
293 {
294 thread_time_constraint_policy_t info;
295
296 if (*count < THREAD_TIME_CONSTRAINT_POLICY_COUNT) {
297 result = KERN_INVALID_ARGUMENT;
298 break;
299 }
300
301 info = (thread_time_constraint_policy_t)policy_info;
302
303 if (!(*get_default)) {
304 s = splsched();
305 thread_lock(thread);
306
307 if ( (thread->sched_mode & TH_MODE_REALTIME) ||
308 (thread->safe_mode & TH_MODE_REALTIME) ) {
309 info->period = thread->realtime.period;
310 info->computation = thread->realtime.computation;
311 info->constraint = thread->realtime.constraint;
312 info->preemptible = thread->realtime.preemptible;
313 }
314 else
315 *get_default = TRUE;
316
317 thread_unlock(thread);
318 splx(s);
319 }
320
321 if (*get_default) {
322 info->period = 0;
323 info->computation = std_quantum / 2;
324 info->constraint = std_quantum;
325 info->preemptible = TRUE;
326 }
327
328 break;
329 }
330
331 case THREAD_PRECEDENCE_POLICY:
332 {
333 thread_precedence_policy_t info;
334
335 if (*count < THREAD_PRECEDENCE_POLICY_COUNT) {
336 result = KERN_INVALID_ARGUMENT;
337 break;
338 }
339
340 info = (thread_precedence_policy_t)policy_info;
341
342 if (!(*get_default)) {
343 s = splsched();
344 thread_lock(thread);
345
346 info->importance = thread->importance;
347
348 thread_unlock(thread);
349 splx(s);
350 }
351 else
352 info->importance = 0;
353
354 break;
355 }
356
357 default:
358 result = KERN_INVALID_ARGUMENT;
359 break;
360 }
361
362 act_unlock_thread(act);
363
364 return (result);
365 }