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