2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <mach/mach_types.h>
30 #include <mach/thread_act_server.h>
32 #include <kern/kern_types.h>
33 #include <kern/processor.h>
34 #include <kern/thread.h>
35 #include <kern/affinity.h>
38 thread_recompute_priority(
44 thread_policy_flavor_t flavor
,
45 thread_policy_t policy_info
,
46 mach_msg_type_number_t count
)
48 kern_return_t result
= KERN_SUCCESS
;
51 if (thread
== THREAD_NULL
)
52 return (KERN_INVALID_ARGUMENT
);
54 thread_mtx_lock(thread
);
55 if (!thread
->active
) {
56 thread_mtx_unlock(thread
);
58 return (KERN_TERMINATED
);
61 if (thread
->static_param
) {
62 thread_mtx_unlock(thread
);
64 return (KERN_SUCCESS
);
69 case THREAD_EXTENDED_POLICY
:
71 boolean_t timeshare
= TRUE
;
73 if (count
>= THREAD_EXTENDED_POLICY_COUNT
) {
74 thread_extended_policy_t info
;
76 info
= (thread_extended_policy_t
)policy_info
;
77 timeshare
= info
->timeshare
;
83 if (!(thread
->sched_mode
& TH_MODE_FAILSAFE
)) {
84 integer_t oldmode
= (thread
->sched_mode
& TH_MODE_TIMESHARE
);
86 thread
->sched_mode
&= ~TH_MODE_REALTIME
;
88 if (timeshare
&& !oldmode
) {
89 thread
->sched_mode
|= TH_MODE_TIMESHARE
;
91 if ((thread
->state
& (TH_RUN
|TH_IDLE
)) == TH_RUN
)
95 if (!timeshare
&& oldmode
) {
96 thread
->sched_mode
&= ~TH_MODE_TIMESHARE
;
98 if ((thread
->state
& (TH_RUN
|TH_IDLE
)) == TH_RUN
)
102 thread_recompute_priority(thread
);
105 thread
->safe_mode
&= ~TH_MODE_REALTIME
;
108 thread
->safe_mode
|= TH_MODE_TIMESHARE
;
110 thread
->safe_mode
&= ~TH_MODE_TIMESHARE
;
113 thread_unlock(thread
);
119 case THREAD_TIME_CONSTRAINT_POLICY
:
121 thread_time_constraint_policy_t info
;
123 if (count
< THREAD_TIME_CONSTRAINT_POLICY_COUNT
) {
124 result
= KERN_INVALID_ARGUMENT
;
128 info
= (thread_time_constraint_policy_t
)policy_info
;
129 if ( info
->constraint
< info
->computation
||
130 info
->computation
> max_rt_quantum
||
131 info
->computation
< min_rt_quantum
) {
132 result
= KERN_INVALID_ARGUMENT
;
139 thread
->realtime
.period
= info
->period
;
140 thread
->realtime
.computation
= info
->computation
;
141 thread
->realtime
.constraint
= info
->constraint
;
142 thread
->realtime
.preemptible
= info
->preemptible
;
144 if (!(thread
->sched_mode
& TH_MODE_FAILSAFE
)) {
145 if (thread
->sched_mode
& TH_MODE_TIMESHARE
) {
146 thread
->sched_mode
&= ~TH_MODE_TIMESHARE
;
148 if ((thread
->state
& (TH_RUN
|TH_IDLE
)) == TH_RUN
)
151 thread
->sched_mode
|= TH_MODE_REALTIME
;
152 thread_recompute_priority(thread
);
155 thread
->safe_mode
&= ~TH_MODE_TIMESHARE
;
156 thread
->safe_mode
|= TH_MODE_REALTIME
;
159 thread_unlock(thread
);
165 case THREAD_PRECEDENCE_POLICY
:
167 thread_precedence_policy_t info
;
169 if (count
< THREAD_PRECEDENCE_POLICY_COUNT
) {
170 result
= KERN_INVALID_ARGUMENT
;
174 info
= (thread_precedence_policy_t
)policy_info
;
179 thread
->importance
= info
->importance
;
181 thread_recompute_priority(thread
);
183 thread_unlock(thread
);
189 case THREAD_AFFINITY_POLICY
:
191 thread_affinity_policy_t info
;
193 if (!thread_affinity_is_supported()) {
194 result
= KERN_NOT_SUPPORTED
;
197 if (count
< THREAD_AFFINITY_POLICY_COUNT
) {
198 result
= KERN_INVALID_ARGUMENT
;
202 info
= (thread_affinity_policy_t
) policy_info
;
204 * Unlock the thread mutex here and
205 * return directly after calling thread_affinity_set().
206 * This is necessary for correct lock ordering because
207 * thread_affinity_set() takes the task lock.
209 thread_mtx_unlock(thread
);
210 return thread_affinity_set(thread
, info
->affinity_tag
);
213 result
= KERN_INVALID_ARGUMENT
;
217 thread_mtx_unlock(thread
);
223 thread_recompute_priority(
228 if (thread
->sched_mode
& TH_MODE_REALTIME
)
229 priority
= BASEPRI_RTQUEUES
;
231 if (thread
->importance
> MAXPRI
)
234 if (thread
->importance
< -MAXPRI
)
237 priority
= thread
->importance
;
239 priority
+= thread
->task_priority
;
241 if (priority
> thread
->max_priority
)
242 priority
= thread
->max_priority
;
244 if (priority
< MINPRI
)
248 set_priority(thread
, priority
);
252 thread_task_priority(
255 integer_t max_priority
)
259 assert(thread
!= THREAD_NULL
);
264 thread
->task_priority
= priority
;
265 thread
->max_priority
= max_priority
;
267 thread_recompute_priority(thread
);
269 thread_unlock(thread
);
282 if (!(thread
->sched_mode
& TH_MODE_FAILSAFE
)) {
283 thread
->sched_mode
&= ~TH_MODE_REALTIME
;
285 if (!(thread
->sched_mode
& TH_MODE_TIMESHARE
)) {
286 thread
->sched_mode
|= TH_MODE_TIMESHARE
;
288 if ((thread
->state
& (TH_RUN
|TH_IDLE
)) == TH_RUN
)
293 thread
->safe_mode
= 0;
294 thread
->sched_mode
&= ~TH_MODE_FAILSAFE
;
297 thread
->importance
= 0;
299 thread_recompute_priority(thread
);
301 thread_unlock(thread
);
308 thread_policy_flavor_t flavor
,
309 thread_policy_t policy_info
,
310 mach_msg_type_number_t
*count
,
311 boolean_t
*get_default
)
313 kern_return_t result
= KERN_SUCCESS
;
316 if (thread
== THREAD_NULL
)
317 return (KERN_INVALID_ARGUMENT
);
319 thread_mtx_lock(thread
);
320 if (!thread
->active
) {
321 thread_mtx_unlock(thread
);
323 return (KERN_TERMINATED
);
328 case THREAD_EXTENDED_POLICY
:
330 boolean_t timeshare
= TRUE
;
332 if (!(*get_default
)) {
336 if ( !(thread
->sched_mode
& TH_MODE_REALTIME
) &&
337 !(thread
->safe_mode
& TH_MODE_REALTIME
) ) {
338 if (!(thread
->sched_mode
& TH_MODE_FAILSAFE
))
339 timeshare
= (thread
->sched_mode
& TH_MODE_TIMESHARE
) != 0;
341 timeshare
= (thread
->safe_mode
& TH_MODE_TIMESHARE
) != 0;
346 thread_unlock(thread
);
350 if (*count
>= THREAD_EXTENDED_POLICY_COUNT
) {
351 thread_extended_policy_t info
;
353 info
= (thread_extended_policy_t
)policy_info
;
354 info
->timeshare
= timeshare
;
360 case THREAD_TIME_CONSTRAINT_POLICY
:
362 thread_time_constraint_policy_t info
;
364 if (*count
< THREAD_TIME_CONSTRAINT_POLICY_COUNT
) {
365 result
= KERN_INVALID_ARGUMENT
;
369 info
= (thread_time_constraint_policy_t
)policy_info
;
371 if (!(*get_default
)) {
375 if ( (thread
->sched_mode
& TH_MODE_REALTIME
) ||
376 (thread
->safe_mode
& TH_MODE_REALTIME
) ) {
377 info
->period
= thread
->realtime
.period
;
378 info
->computation
= thread
->realtime
.computation
;
379 info
->constraint
= thread
->realtime
.constraint
;
380 info
->preemptible
= thread
->realtime
.preemptible
;
385 thread_unlock(thread
);
391 info
->computation
= std_quantum
/ 2;
392 info
->constraint
= std_quantum
;
393 info
->preemptible
= TRUE
;
399 case THREAD_PRECEDENCE_POLICY
:
401 thread_precedence_policy_t info
;
403 if (*count
< THREAD_PRECEDENCE_POLICY_COUNT
) {
404 result
= KERN_INVALID_ARGUMENT
;
408 info
= (thread_precedence_policy_t
)policy_info
;
410 if (!(*get_default
)) {
414 info
->importance
= thread
->importance
;
416 thread_unlock(thread
);
420 info
->importance
= 0;
425 case THREAD_AFFINITY_POLICY
:
427 thread_affinity_policy_t info
;
429 if (!thread_affinity_is_supported()) {
430 result
= KERN_NOT_SUPPORTED
;
433 if (*count
< THREAD_AFFINITY_POLICY_COUNT
) {
434 result
= KERN_INVALID_ARGUMENT
;
438 info
= (thread_affinity_policy_t
)policy_info
;
441 info
->affinity_tag
= thread_affinity_get(thread
);
443 info
->affinity_tag
= THREAD_AFFINITY_TAG_NULL
;
449 result
= KERN_INVALID_ARGUMENT
;
453 thread_mtx_unlock(thread
);