]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kern/thread_policy.c
xnu-792.12.6.tar.gz
[apple/xnu.git] / osfmk / kern / thread_policy.c
CommitLineData
1c79356b 1/*
91447636 2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
1c79356b 3 *
8ad349bb 4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
1c79356b 5 *
8ad349bb
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
1c79356b 29 */
1c79356b 30
91447636
A
31#include <mach/mach_types.h>
32#include <mach/thread_act_server.h>
33
34#include <kern/kern_types.h>
55e303ae 35#include <kern/processor.h>
1c79356b
A
36#include <kern/thread.h>
37
0b4e3aa0
A
38static void
39thread_recompute_priority(
40 thread_t thread);
41
1c79356b
A
42kern_return_t
43thread_policy_set(
91447636 44 thread_t thread,
1c79356b
A
45 thread_policy_flavor_t flavor,
46 thread_policy_t policy_info,
47 mach_msg_type_number_t count)
48{
49 kern_return_t result = KERN_SUCCESS;
1c79356b
A
50 spl_t s;
51
91447636 52 if (thread == THREAD_NULL)
1c79356b
A
53 return (KERN_INVALID_ARGUMENT);
54
91447636
A
55 thread_mtx_lock(thread);
56 if (!thread->active) {
57 thread_mtx_unlock(thread);
1c79356b
A
58
59 return (KERN_TERMINATED);
60 }
61
1c79356b
A
62 switch (flavor) {
63
0b4e3aa0 64 case THREAD_EXTENDED_POLICY:
1c79356b 65 {
0b4e3aa0
A
66 boolean_t timeshare = TRUE;
67
68 if (count >= THREAD_EXTENDED_POLICY_COUNT) {
69 thread_extended_policy_t info;
70
71 info = (thread_extended_policy_t)policy_info;
72 timeshare = info->timeshare;
73 }
1c79356b
A
74
75 s = splsched();
76 thread_lock(thread);
77
0b4e3aa0 78 if (!(thread->sched_mode & TH_MODE_FAILSAFE)) {
55e303ae
A
79 integer_t oldmode = (thread->sched_mode & TH_MODE_TIMESHARE);
80
0b4e3aa0 81 thread->sched_mode &= ~TH_MODE_REALTIME;
1c79356b 82
55e303ae 83 if (timeshare && !oldmode) {
0b4e3aa0 84 thread->sched_mode |= TH_MODE_TIMESHARE;
55e303ae
A
85
86 if (thread->state & TH_RUN)
87 pset_share_incr(thread->processor_set);
88 }
0b4e3aa0 89 else
55e303ae 90 if (!timeshare && oldmode) {
0b4e3aa0 91 thread->sched_mode &= ~TH_MODE_TIMESHARE;
1c79356b 92
55e303ae
A
93 if (thread->state & TH_RUN)
94 pset_share_decr(thread->processor_set);
95 }
96
0b4e3aa0
A
97 thread_recompute_priority(thread);
98 }
99 else {
100 thread->safe_mode &= ~TH_MODE_REALTIME;
1c79356b 101
0b4e3aa0
A
102 if (timeshare)
103 thread->safe_mode |= TH_MODE_TIMESHARE;
104 else
105 thread->safe_mode &= ~TH_MODE_TIMESHARE;
106 }
1c79356b
A
107
108 thread_unlock(thread);
109 splx(s);
110
111 break;
112 }
113
114 case THREAD_TIME_CONSTRAINT_POLICY:
115 {
116 thread_time_constraint_policy_t info;
117
118 if (count < THREAD_TIME_CONSTRAINT_POLICY_COUNT) {
119 result = KERN_INVALID_ARGUMENT;
120 break;
121 }
122
123 info = (thread_time_constraint_policy_t)policy_info;
55e303ae
A
124 if ( info->constraint < info->computation ||
125 info->computation > max_rt_quantum ||
0b4e3aa0
A
126 info->computation < min_rt_quantum ) {
127 result = KERN_INVALID_ARGUMENT;
128 break;
129 }
1c79356b
A
130
131 s = splsched();
132 thread_lock(thread);
133
1c79356b
A
134 thread->realtime.period = info->period;
135 thread->realtime.computation = info->computation;
136 thread->realtime.constraint = info->constraint;
137 thread->realtime.preemptible = info->preemptible;
138
0b4e3aa0 139 if (!(thread->sched_mode & TH_MODE_FAILSAFE)) {
55e303ae
A
140 if (thread->sched_mode & TH_MODE_TIMESHARE) {
141 thread->sched_mode &= ~TH_MODE_TIMESHARE;
142
143 if (thread->state & TH_RUN)
144 pset_share_decr(thread->processor_set);
145 }
0b4e3aa0
A
146 thread->sched_mode |= TH_MODE_REALTIME;
147 thread_recompute_priority(thread);
148 }
149 else {
150 thread->safe_mode &= ~TH_MODE_TIMESHARE;
151 thread->safe_mode |= TH_MODE_REALTIME;
152 }
1c79356b
A
153
154 thread_unlock(thread);
155 splx(s);
156
157 break;
158 }
159
160 case THREAD_PRECEDENCE_POLICY:
161 {
162 thread_precedence_policy_t info;
163
164 if (count < THREAD_PRECEDENCE_POLICY_COUNT) {
165 result = KERN_INVALID_ARGUMENT;
166 break;
167 }
168
169 info = (thread_precedence_policy_t)policy_info;
170
171 s = splsched();
172 thread_lock(thread);
173
174 thread->importance = info->importance;
175
0b4e3aa0 176 thread_recompute_priority(thread);
1c79356b
A
177
178 thread_unlock(thread);
179 splx(s);
180
181 break;
182 }
183
184 default:
185 result = KERN_INVALID_ARGUMENT;
186 break;
187 }
188
91447636 189 thread_mtx_unlock(thread);
1c79356b 190
1c79356b
A
191 return (result);
192}
193
0b4e3aa0
A
194static void
195thread_recompute_priority(
196 thread_t thread)
197{
198 integer_t priority;
199
200 if (thread->sched_mode & TH_MODE_REALTIME)
55e303ae 201 priority = BASEPRI_RTQUEUES;
0b4e3aa0
A
202 else {
203 if (thread->importance > MAXPRI)
204 priority = MAXPRI;
205 else
206 if (thread->importance < -MAXPRI)
207 priority = -MAXPRI;
208 else
209 priority = thread->importance;
210
211 priority += thread->task_priority;
212
213 if (priority > thread->max_priority)
214 priority = thread->max_priority;
215 else
216 if (priority < MINPRI)
217 priority = MINPRI;
218 }
219
9bccf70c 220 set_priority(thread, priority);
0b4e3aa0
A
221}
222
223void
224thread_task_priority(
225 thread_t thread,
226 integer_t priority,
227 integer_t max_priority)
228{
229 spl_t s;
230
231 assert(thread != THREAD_NULL);
232
233 s = splsched();
234 thread_lock(thread);
235
236 thread->task_priority = priority;
237 thread->max_priority = max_priority;
238
239 thread_recompute_priority(thread);
240
241 thread_unlock(thread);
242 splx(s);
243}
244
91447636
A
245void
246thread_policy_reset(
247 thread_t thread)
248{
249 if (!(thread->sched_mode & TH_MODE_FAILSAFE)) {
250 thread->sched_mode &= ~TH_MODE_REALTIME;
251
252 if (!(thread->sched_mode & TH_MODE_TIMESHARE)) {
253 thread->sched_mode |= TH_MODE_TIMESHARE;
254
255 if (thread->state & TH_RUN)
256 pset_share_incr(thread->processor_set);
257 }
258 }
259 else {
260 thread->safe_mode = 0;
261 thread->sched_mode &= ~TH_MODE_FAILSAFE;
262 }
263
264 thread->importance = 0;
265
266 thread_recompute_priority(thread);
267}
268
1c79356b
A
269kern_return_t
270thread_policy_get(
91447636 271 thread_t thread,
1c79356b
A
272 thread_policy_flavor_t flavor,
273 thread_policy_t policy_info,
274 mach_msg_type_number_t *count,
275 boolean_t *get_default)
276{
277 kern_return_t result = KERN_SUCCESS;
1c79356b
A
278 spl_t s;
279
91447636 280 if (thread == THREAD_NULL)
1c79356b
A
281 return (KERN_INVALID_ARGUMENT);
282
91447636
A
283 thread_mtx_lock(thread);
284 if (!thread->active) {
285 thread_mtx_unlock(thread);
1c79356b
A
286
287 return (KERN_TERMINATED);
288 }
289
1c79356b
A
290 switch (flavor) {
291
0b4e3aa0
A
292 case THREAD_EXTENDED_POLICY:
293 {
294 boolean_t timeshare = TRUE;
1c79356b 295
0b4e3aa0
A
296 if (!(*get_default)) {
297 s = splsched();
298 thread_lock(thread);
299
300 if ( !(thread->sched_mode & TH_MODE_REALTIME) &&
301 !(thread->safe_mode & TH_MODE_REALTIME) ) {
302 if (!(thread->sched_mode & TH_MODE_FAILSAFE))
303 timeshare = (thread->sched_mode & TH_MODE_TIMESHARE) != 0;
304 else
305 timeshare = (thread->safe_mode & TH_MODE_TIMESHARE) != 0;
306 }
307 else
308 *get_default = TRUE;
309
310 thread_unlock(thread);
311 splx(s);
312 }
313
314 if (*count >= THREAD_EXTENDED_POLICY_COUNT) {
315 thread_extended_policy_t info;
316
317 info = (thread_extended_policy_t)policy_info;
318 info->timeshare = timeshare;
319 }
1c79356b 320
1c79356b 321 break;
0b4e3aa0 322 }
1c79356b
A
323
324 case THREAD_TIME_CONSTRAINT_POLICY:
325 {
326 thread_time_constraint_policy_t info;
327
328 if (*count < THREAD_TIME_CONSTRAINT_POLICY_COUNT) {
329 result = KERN_INVALID_ARGUMENT;
330 break;
331 }
332
333 info = (thread_time_constraint_policy_t)policy_info;
334
0b4e3aa0
A
335 if (!(*get_default)) {
336 s = splsched();
337 thread_lock(thread);
1c79356b 338
0b4e3aa0
A
339 if ( (thread->sched_mode & TH_MODE_REALTIME) ||
340 (thread->safe_mode & TH_MODE_REALTIME) ) {
341 info->period = thread->realtime.period;
342 info->computation = thread->realtime.computation;
343 info->constraint = thread->realtime.constraint;
344 info->preemptible = thread->realtime.preemptible;
345 }
346 else
347 *get_default = TRUE;
1c79356b 348
0b4e3aa0
A
349 thread_unlock(thread);
350 splx(s);
351 }
1c79356b 352
0b4e3aa0 353 if (*get_default) {
1c79356b 354 info->period = 0;
0b4e3aa0
A
355 info->computation = std_quantum / 2;
356 info->constraint = std_quantum;
1c79356b
A
357 info->preemptible = TRUE;
358 }
359
1c79356b
A
360 break;
361 }
362
363 case THREAD_PRECEDENCE_POLICY:
364 {
365 thread_precedence_policy_t info;
366
367 if (*count < THREAD_PRECEDENCE_POLICY_COUNT) {
368 result = KERN_INVALID_ARGUMENT;
369 break;
370 }
371
372 info = (thread_precedence_policy_t)policy_info;
373
0b4e3aa0 374 if (!(*get_default)) {
1c79356b
A
375 s = splsched();
376 thread_lock(thread);
377
378 info->importance = thread->importance;
379
380 thread_unlock(thread);
381 splx(s);
382 }
0b4e3aa0
A
383 else
384 info->importance = 0;
1c79356b
A
385
386 break;
387 }
388
389 default:
390 result = KERN_INVALID_ARGUMENT;
391 break;
392 }
393
91447636 394 thread_mtx_unlock(thread);
1c79356b
A
395
396 return (result);
397}