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