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(
46 thread_policy_flavor_t flavor
,
47 thread_policy_t policy_info
,
48 mach_msg_type_number_t count
)
51 if (thread
== THREAD_NULL
)
52 return (KERN_INVALID_ARGUMENT
);
54 if (thread
->static_param
)
55 return (KERN_SUCCESS
);
57 return (thread_policy_set_internal(thread
, flavor
, policy_info
, count
));
61 thread_policy_set_internal(
63 thread_policy_flavor_t flavor
,
64 thread_policy_t policy_info
,
65 mach_msg_type_number_t count
)
67 kern_return_t result
= KERN_SUCCESS
;
70 thread_mtx_lock(thread
);
71 if (!thread
->active
) {
72 thread_mtx_unlock(thread
);
74 return (KERN_TERMINATED
);
78 case THREAD_EXTENDED_POLICY
:
80 boolean_t timeshare
= TRUE
;
82 if (count
>= THREAD_EXTENDED_POLICY_COUNT
) {
83 thread_extended_policy_t info
;
85 info
= (thread_extended_policy_t
)policy_info
;
86 timeshare
= info
->timeshare
;
92 if (!(thread
->sched_mode
& TH_MODE_FAILSAFE
)) {
93 integer_t oldmode
= (thread
->sched_mode
& TH_MODE_TIMESHARE
);
95 thread
->sched_mode
&= ~TH_MODE_REALTIME
;
97 if (timeshare
&& !oldmode
) {
98 thread
->sched_mode
|= TH_MODE_TIMESHARE
;
100 if ((thread
->state
& (TH_RUN
|TH_IDLE
)) == TH_RUN
)
104 if (!timeshare
&& oldmode
) {
105 thread
->sched_mode
&= ~TH_MODE_TIMESHARE
;
107 if ((thread
->state
& (TH_RUN
|TH_IDLE
)) == TH_RUN
)
111 thread_recompute_priority(thread
);
114 thread
->safe_mode
&= ~TH_MODE_REALTIME
;
117 thread
->safe_mode
|= TH_MODE_TIMESHARE
;
119 thread
->safe_mode
&= ~TH_MODE_TIMESHARE
;
122 thread_unlock(thread
);
128 case THREAD_TIME_CONSTRAINT_POLICY
:
130 thread_time_constraint_policy_t info
;
132 if (count
< THREAD_TIME_CONSTRAINT_POLICY_COUNT
) {
133 result
= KERN_INVALID_ARGUMENT
;
137 info
= (thread_time_constraint_policy_t
)policy_info
;
138 if ( info
->constraint
< info
->computation
||
139 info
->computation
> max_rt_quantum
||
140 info
->computation
< min_rt_quantum
) {
141 result
= KERN_INVALID_ARGUMENT
;
148 thread
->realtime
.period
= info
->period
;
149 thread
->realtime
.computation
= info
->computation
;
150 thread
->realtime
.constraint
= info
->constraint
;
151 thread
->realtime
.preemptible
= info
->preemptible
;
153 if (!(thread
->sched_mode
& TH_MODE_FAILSAFE
)) {
154 if (thread
->sched_mode
& TH_MODE_TIMESHARE
) {
155 thread
->sched_mode
&= ~TH_MODE_TIMESHARE
;
157 if ((thread
->state
& (TH_RUN
|TH_IDLE
)) == TH_RUN
)
160 thread
->sched_mode
|= TH_MODE_REALTIME
;
161 thread_recompute_priority(thread
);
164 thread
->safe_mode
&= ~TH_MODE_TIMESHARE
;
165 thread
->safe_mode
|= TH_MODE_REALTIME
;
168 thread_unlock(thread
);
174 case THREAD_PRECEDENCE_POLICY
:
176 thread_precedence_policy_t info
;
178 if (count
< THREAD_PRECEDENCE_POLICY_COUNT
) {
179 result
= KERN_INVALID_ARGUMENT
;
182 info
= (thread_precedence_policy_t
)policy_info
;
187 thread
->importance
= info
->importance
;
189 thread_recompute_priority(thread
);
191 thread_unlock(thread
);
197 case THREAD_AFFINITY_POLICY
:
199 thread_affinity_policy_t info
;
201 if (!thread_affinity_is_supported()) {
202 result
= KERN_NOT_SUPPORTED
;
205 if (count
< THREAD_AFFINITY_POLICY_COUNT
) {
206 result
= KERN_INVALID_ARGUMENT
;
210 info
= (thread_affinity_policy_t
) policy_info
;
212 * Unlock the thread mutex here and
213 * return directly after calling thread_affinity_set().
214 * This is necessary for correct lock ordering because
215 * thread_affinity_set() takes the task lock.
217 thread_mtx_unlock(thread
);
218 return thread_affinity_set(thread
, info
->affinity_tag
);
221 result
= KERN_INVALID_ARGUMENT
;
225 thread_mtx_unlock(thread
);
230 thread_recompute_priority(
235 if (thread
->sched_mode
& TH_MODE_REALTIME
)
236 priority
= BASEPRI_RTQUEUES
;
238 if (thread
->importance
> MAXPRI
)
241 if (thread
->importance
< -MAXPRI
)
244 priority
= thread
->importance
;
246 priority
+= thread
->task_priority
;
248 if (priority
> thread
->max_priority
)
249 priority
= thread
->max_priority
;
251 if (priority
< MINPRI
)
255 set_priority(thread
, priority
);
259 thread_task_priority(
262 integer_t max_priority
)
266 assert(thread
!= THREAD_NULL
);
271 thread
->task_priority
= priority
;
272 thread
->max_priority
= max_priority
;
274 thread_recompute_priority(thread
);
276 thread_unlock(thread
);
289 if (!(thread
->sched_mode
& TH_MODE_FAILSAFE
)) {
290 thread
->sched_mode
&= ~TH_MODE_REALTIME
;
292 if (!(thread
->sched_mode
& TH_MODE_TIMESHARE
)) {
293 thread
->sched_mode
|= TH_MODE_TIMESHARE
;
295 if ((thread
->state
& (TH_RUN
|TH_IDLE
)) == TH_RUN
)
300 thread
->safe_mode
= 0;
301 thread
->sched_mode
&= ~TH_MODE_FAILSAFE
;
304 thread
->importance
= 0;
306 thread_recompute_priority(thread
);
308 thread_unlock(thread
);
315 thread_policy_flavor_t flavor
,
316 thread_policy_t policy_info
,
317 mach_msg_type_number_t
*count
,
318 boolean_t
*get_default
)
320 kern_return_t result
= KERN_SUCCESS
;
323 if (thread
== THREAD_NULL
)
324 return (KERN_INVALID_ARGUMENT
);
326 thread_mtx_lock(thread
);
327 if (!thread
->active
) {
328 thread_mtx_unlock(thread
);
330 return (KERN_TERMINATED
);
335 case THREAD_EXTENDED_POLICY
:
337 boolean_t timeshare
= TRUE
;
339 if (!(*get_default
)) {
343 if ( !(thread
->sched_mode
& TH_MODE_REALTIME
) &&
344 !(thread
->safe_mode
& TH_MODE_REALTIME
) ) {
345 if (!(thread
->sched_mode
& TH_MODE_FAILSAFE
))
346 timeshare
= (thread
->sched_mode
& TH_MODE_TIMESHARE
) != 0;
348 timeshare
= (thread
->safe_mode
& TH_MODE_TIMESHARE
) != 0;
353 thread_unlock(thread
);
357 if (*count
>= THREAD_EXTENDED_POLICY_COUNT
) {
358 thread_extended_policy_t info
;
360 info
= (thread_extended_policy_t
)policy_info
;
361 info
->timeshare
= timeshare
;
367 case THREAD_TIME_CONSTRAINT_POLICY
:
369 thread_time_constraint_policy_t info
;
371 if (*count
< THREAD_TIME_CONSTRAINT_POLICY_COUNT
) {
372 result
= KERN_INVALID_ARGUMENT
;
376 info
= (thread_time_constraint_policy_t
)policy_info
;
378 if (!(*get_default
)) {
382 if ( (thread
->sched_mode
& TH_MODE_REALTIME
) ||
383 (thread
->safe_mode
& TH_MODE_REALTIME
) ) {
384 info
->period
= thread
->realtime
.period
;
385 info
->computation
= thread
->realtime
.computation
;
386 info
->constraint
= thread
->realtime
.constraint
;
387 info
->preemptible
= thread
->realtime
.preemptible
;
392 thread_unlock(thread
);
398 info
->computation
= std_quantum
/ 2;
399 info
->constraint
= std_quantum
;
400 info
->preemptible
= TRUE
;
406 case THREAD_PRECEDENCE_POLICY
:
408 thread_precedence_policy_t info
;
410 if (*count
< THREAD_PRECEDENCE_POLICY_COUNT
) {
411 result
= KERN_INVALID_ARGUMENT
;
415 info
= (thread_precedence_policy_t
)policy_info
;
417 if (!(*get_default
)) {
421 info
->importance
= thread
->importance
;
423 thread_unlock(thread
);
427 info
->importance
= 0;
432 case THREAD_AFFINITY_POLICY
:
434 thread_affinity_policy_t info
;
436 if (!thread_affinity_is_supported()) {
437 result
= KERN_NOT_SUPPORTED
;
440 if (*count
< THREAD_AFFINITY_POLICY_COUNT
) {
441 result
= KERN_INVALID_ARGUMENT
;
445 info
= (thread_affinity_policy_t
)policy_info
;
448 info
->affinity_tag
= thread_affinity_get(thread
);
450 info
->affinity_tag
= THREAD_AFFINITY_TAG_NULL
;
456 result
= KERN_INVALID_ARGUMENT
;
460 thread_mtx_unlock(thread
);