2 * Copyright (c) 2000-2004 Apple Computer, 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>
37 thread_recompute_priority(
43 thread_policy_flavor_t flavor
,
44 thread_policy_t policy_info
,
45 mach_msg_type_number_t count
)
47 kern_return_t result
= KERN_SUCCESS
;
50 if (thread
== THREAD_NULL
)
51 return (KERN_INVALID_ARGUMENT
);
53 thread_mtx_lock(thread
);
54 if (!thread
->active
) {
55 thread_mtx_unlock(thread
);
57 return (KERN_TERMINATED
);
62 case THREAD_EXTENDED_POLICY
:
64 boolean_t timeshare
= TRUE
;
66 if (count
>= THREAD_EXTENDED_POLICY_COUNT
) {
67 thread_extended_policy_t info
;
69 info
= (thread_extended_policy_t
)policy_info
;
70 timeshare
= info
->timeshare
;
76 if (!(thread
->sched_mode
& TH_MODE_FAILSAFE
)) {
77 integer_t oldmode
= (thread
->sched_mode
& TH_MODE_TIMESHARE
);
79 thread
->sched_mode
&= ~TH_MODE_REALTIME
;
81 if (timeshare
&& !oldmode
) {
82 thread
->sched_mode
|= TH_MODE_TIMESHARE
;
84 if (thread
->state
& TH_RUN
)
85 pset_share_incr(thread
->processor_set
);
88 if (!timeshare
&& oldmode
) {
89 thread
->sched_mode
&= ~TH_MODE_TIMESHARE
;
91 if (thread
->state
& TH_RUN
)
92 pset_share_decr(thread
->processor_set
);
95 thread_recompute_priority(thread
);
98 thread
->safe_mode
&= ~TH_MODE_REALTIME
;
101 thread
->safe_mode
|= TH_MODE_TIMESHARE
;
103 thread
->safe_mode
&= ~TH_MODE_TIMESHARE
;
106 thread_unlock(thread
);
112 case THREAD_TIME_CONSTRAINT_POLICY
:
114 thread_time_constraint_policy_t info
;
116 if (count
< THREAD_TIME_CONSTRAINT_POLICY_COUNT
) {
117 result
= KERN_INVALID_ARGUMENT
;
121 info
= (thread_time_constraint_policy_t
)policy_info
;
122 if ( info
->constraint
< info
->computation
||
123 info
->computation
> max_rt_quantum
||
124 info
->computation
< min_rt_quantum
) {
125 result
= KERN_INVALID_ARGUMENT
;
132 thread
->realtime
.period
= info
->period
;
133 thread
->realtime
.computation
= info
->computation
;
134 thread
->realtime
.constraint
= info
->constraint
;
135 thread
->realtime
.preemptible
= info
->preemptible
;
137 if (!(thread
->sched_mode
& TH_MODE_FAILSAFE
)) {
138 if (thread
->sched_mode
& TH_MODE_TIMESHARE
) {
139 thread
->sched_mode
&= ~TH_MODE_TIMESHARE
;
141 if (thread
->state
& TH_RUN
)
142 pset_share_decr(thread
->processor_set
);
144 thread
->sched_mode
|= TH_MODE_REALTIME
;
145 thread_recompute_priority(thread
);
148 thread
->safe_mode
&= ~TH_MODE_TIMESHARE
;
149 thread
->safe_mode
|= TH_MODE_REALTIME
;
152 thread_unlock(thread
);
158 case THREAD_PRECEDENCE_POLICY
:
160 thread_precedence_policy_t info
;
162 if (count
< THREAD_PRECEDENCE_POLICY_COUNT
) {
163 result
= KERN_INVALID_ARGUMENT
;
167 info
= (thread_precedence_policy_t
)policy_info
;
172 thread
->importance
= info
->importance
;
174 thread_recompute_priority(thread
);
176 thread_unlock(thread
);
183 result
= KERN_INVALID_ARGUMENT
;
187 thread_mtx_unlock(thread
);
193 thread_recompute_priority(
198 if (thread
->sched_mode
& TH_MODE_REALTIME
)
199 priority
= BASEPRI_RTQUEUES
;
201 if (thread
->importance
> MAXPRI
)
204 if (thread
->importance
< -MAXPRI
)
207 priority
= thread
->importance
;
209 priority
+= thread
->task_priority
;
211 if (priority
> thread
->max_priority
)
212 priority
= thread
->max_priority
;
214 if (priority
< MINPRI
)
218 set_priority(thread
, priority
);
222 thread_task_priority(
225 integer_t max_priority
)
229 assert(thread
!= THREAD_NULL
);
234 thread
->task_priority
= priority
;
235 thread
->max_priority
= max_priority
;
237 thread_recompute_priority(thread
);
239 thread_unlock(thread
);
247 if (!(thread
->sched_mode
& TH_MODE_FAILSAFE
)) {
248 thread
->sched_mode
&= ~TH_MODE_REALTIME
;
250 if (!(thread
->sched_mode
& TH_MODE_TIMESHARE
)) {
251 thread
->sched_mode
|= TH_MODE_TIMESHARE
;
253 if (thread
->state
& TH_RUN
)
254 pset_share_incr(thread
->processor_set
);
258 thread
->safe_mode
= 0;
259 thread
->sched_mode
&= ~TH_MODE_FAILSAFE
;
262 thread
->importance
= 0;
264 thread_recompute_priority(thread
);
270 thread_policy_flavor_t flavor
,
271 thread_policy_t policy_info
,
272 mach_msg_type_number_t
*count
,
273 boolean_t
*get_default
)
275 kern_return_t result
= KERN_SUCCESS
;
278 if (thread
== THREAD_NULL
)
279 return (KERN_INVALID_ARGUMENT
);
281 thread_mtx_lock(thread
);
282 if (!thread
->active
) {
283 thread_mtx_unlock(thread
);
285 return (KERN_TERMINATED
);
290 case THREAD_EXTENDED_POLICY
:
292 boolean_t timeshare
= TRUE
;
294 if (!(*get_default
)) {
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;
303 timeshare
= (thread
->safe_mode
& TH_MODE_TIMESHARE
) != 0;
308 thread_unlock(thread
);
312 if (*count
>= THREAD_EXTENDED_POLICY_COUNT
) {
313 thread_extended_policy_t info
;
315 info
= (thread_extended_policy_t
)policy_info
;
316 info
->timeshare
= timeshare
;
322 case THREAD_TIME_CONSTRAINT_POLICY
:
324 thread_time_constraint_policy_t info
;
326 if (*count
< THREAD_TIME_CONSTRAINT_POLICY_COUNT
) {
327 result
= KERN_INVALID_ARGUMENT
;
331 info
= (thread_time_constraint_policy_t
)policy_info
;
333 if (!(*get_default
)) {
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
;
347 thread_unlock(thread
);
353 info
->computation
= std_quantum
/ 2;
354 info
->constraint
= std_quantum
;
355 info
->preemptible
= TRUE
;
361 case THREAD_PRECEDENCE_POLICY
:
363 thread_precedence_policy_t info
;
365 if (*count
< THREAD_PRECEDENCE_POLICY_COUNT
) {
366 result
= KERN_INVALID_ARGUMENT
;
370 info
= (thread_precedence_policy_t
)policy_info
;
372 if (!(*get_default
)) {
376 info
->importance
= thread
->importance
;
378 thread_unlock(thread
);
382 info
->importance
= 0;
388 result
= KERN_INVALID_ARGUMENT
;
392 thread_mtx_unlock(thread
);