]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kern/thread_policy.c
xnu-344.49.tar.gz
[apple/xnu.git] / osfmk / kern / thread_policy.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
27 *
28 * HISTORY
29 *
30 * 15 October 2000 (debo)
31 * Created.
32 */
33
34 #include <kern/thread.h>
35
36 static void
37 thread_recompute_priority(
38 thread_t thread);
39
40 kern_return_t
41 thread_policy_set(
42 thread_act_t act,
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;
48 thread_t thread;
49 spl_t s;
50
51 if (act == THR_ACT_NULL)
52 return (KERN_INVALID_ARGUMENT);
53
54 thread = act_lock_thread(act);
55 if (!act->active) {
56 act_unlock_thread(act);
57
58 return (KERN_TERMINATED);
59 }
60
61 assert(thread != THREAD_NULL);
62
63 switch (flavor) {
64
65 case THREAD_EXTENDED_POLICY:
66 {
67 boolean_t timeshare = TRUE;
68
69 if (count >= THREAD_EXTENDED_POLICY_COUNT) {
70 thread_extended_policy_t info;
71
72 info = (thread_extended_policy_t)policy_info;
73 timeshare = info->timeshare;
74 }
75
76 s = splsched();
77 thread_lock(thread);
78
79 if (!(thread->sched_mode & TH_MODE_FAILSAFE)) {
80 thread->sched_mode &= ~TH_MODE_REALTIME;
81
82 if (timeshare)
83 thread->sched_mode |= TH_MODE_TIMESHARE;
84 else
85 thread->sched_mode &= ~TH_MODE_TIMESHARE;
86
87 thread_recompute_priority(thread);
88 }
89 else {
90 thread->safe_mode &= ~TH_MODE_REALTIME;
91
92 if (timeshare)
93 thread->safe_mode |= TH_MODE_TIMESHARE;
94 else
95 thread->safe_mode &= ~TH_MODE_TIMESHARE;
96 }
97
98 thread_unlock(thread);
99 splx(s);
100
101 break;
102 }
103
104 case THREAD_TIME_CONSTRAINT_POLICY:
105 {
106 thread_time_constraint_policy_t info;
107
108 if (count < THREAD_TIME_CONSTRAINT_POLICY_COUNT) {
109 result = KERN_INVALID_ARGUMENT;
110 break;
111 }
112
113 info = (thread_time_constraint_policy_t)policy_info;
114 if ( info->computation > max_rt_quantum ||
115 info->computation < min_rt_quantum ) {
116 result = KERN_INVALID_ARGUMENT;
117 break;
118 }
119
120 s = splsched();
121 thread_lock(thread);
122
123 thread->realtime.period = info->period;
124 thread->realtime.computation = info->computation;
125 thread->realtime.constraint = info->constraint;
126 thread->realtime.preemptible = info->preemptible;
127
128 if (!(thread->sched_mode & TH_MODE_FAILSAFE)) {
129 thread->sched_mode &= ~TH_MODE_TIMESHARE;
130 thread->sched_mode |= TH_MODE_REALTIME;
131 thread_recompute_priority(thread);
132 }
133 else {
134 thread->safe_mode &= ~TH_MODE_TIMESHARE;
135 thread->safe_mode |= TH_MODE_REALTIME;
136 }
137
138 thread_unlock(thread);
139 splx(s);
140
141 break;
142 }
143
144 case THREAD_PRECEDENCE_POLICY:
145 {
146 thread_precedence_policy_t info;
147
148 if (count < THREAD_PRECEDENCE_POLICY_COUNT) {
149 result = KERN_INVALID_ARGUMENT;
150 break;
151 }
152
153 info = (thread_precedence_policy_t)policy_info;
154
155 s = splsched();
156 thread_lock(thread);
157
158 thread->importance = info->importance;
159
160 thread_recompute_priority(thread);
161
162 thread_unlock(thread);
163 splx(s);
164
165 break;
166 }
167
168 default:
169 result = KERN_INVALID_ARGUMENT;
170 break;
171 }
172
173 act_unlock_thread(act);
174
175 return (result);
176 }
177
178 static void
179 thread_recompute_priority(
180 thread_t thread)
181 {
182 integer_t priority;
183
184 if (thread->sched_mode & TH_MODE_REALTIME)
185 priority = BASEPRI_REALTIME;
186 else {
187 if (thread->importance > MAXPRI)
188 priority = MAXPRI;
189 else
190 if (thread->importance < -MAXPRI)
191 priority = -MAXPRI;
192 else
193 priority = thread->importance;
194
195 priority += thread->task_priority;
196
197 if (priority > thread->max_priority)
198 priority = thread->max_priority;
199 else
200 if (priority < MINPRI)
201 priority = MINPRI;
202 }
203
204 set_priority(thread, priority);
205 }
206
207 void
208 thread_task_priority(
209 thread_t thread,
210 integer_t priority,
211 integer_t max_priority)
212 {
213 spl_t s;
214
215 assert(thread != THREAD_NULL);
216
217 s = splsched();
218 thread_lock(thread);
219
220 thread->task_priority = priority;
221 thread->max_priority = max_priority;
222
223 thread_recompute_priority(thread);
224
225 thread_unlock(thread);
226 splx(s);
227 }
228
229 kern_return_t
230 thread_policy_get(
231 thread_act_t act,
232 thread_policy_flavor_t flavor,
233 thread_policy_t policy_info,
234 mach_msg_type_number_t *count,
235 boolean_t *get_default)
236 {
237 kern_return_t result = KERN_SUCCESS;
238 thread_t thread;
239 spl_t s;
240
241 if (act == THR_ACT_NULL)
242 return (KERN_INVALID_ARGUMENT);
243
244 thread = act_lock_thread(act);
245 if (!act->active) {
246 act_unlock_thread(act);
247
248 return (KERN_TERMINATED);
249 }
250
251 assert(thread != THREAD_NULL);
252
253 switch (flavor) {
254
255 case THREAD_EXTENDED_POLICY:
256 {
257 boolean_t timeshare = TRUE;
258
259 if (!(*get_default)) {
260 s = splsched();
261 thread_lock(thread);
262
263 if ( !(thread->sched_mode & TH_MODE_REALTIME) &&
264 !(thread->safe_mode & TH_MODE_REALTIME) ) {
265 if (!(thread->sched_mode & TH_MODE_FAILSAFE))
266 timeshare = (thread->sched_mode & TH_MODE_TIMESHARE) != 0;
267 else
268 timeshare = (thread->safe_mode & TH_MODE_TIMESHARE) != 0;
269 }
270 else
271 *get_default = TRUE;
272
273 thread_unlock(thread);
274 splx(s);
275 }
276
277 if (*count >= THREAD_EXTENDED_POLICY_COUNT) {
278 thread_extended_policy_t info;
279
280 info = (thread_extended_policy_t)policy_info;
281 info->timeshare = timeshare;
282 }
283
284 break;
285 }
286
287 case THREAD_TIME_CONSTRAINT_POLICY:
288 {
289 thread_time_constraint_policy_t info;
290
291 if (*count < THREAD_TIME_CONSTRAINT_POLICY_COUNT) {
292 result = KERN_INVALID_ARGUMENT;
293 break;
294 }
295
296 info = (thread_time_constraint_policy_t)policy_info;
297
298 if (!(*get_default)) {
299 s = splsched();
300 thread_lock(thread);
301
302 if ( (thread->sched_mode & TH_MODE_REALTIME) ||
303 (thread->safe_mode & TH_MODE_REALTIME) ) {
304 info->period = thread->realtime.period;
305 info->computation = thread->realtime.computation;
306 info->constraint = thread->realtime.constraint;
307 info->preemptible = thread->realtime.preemptible;
308 }
309 else
310 *get_default = TRUE;
311
312 thread_unlock(thread);
313 splx(s);
314 }
315
316 if (*get_default) {
317 info->period = 0;
318 info->computation = std_quantum / 2;
319 info->constraint = std_quantum;
320 info->preemptible = TRUE;
321 }
322
323 break;
324 }
325
326 case THREAD_PRECEDENCE_POLICY:
327 {
328 thread_precedence_policy_t info;
329
330 if (*count < THREAD_PRECEDENCE_POLICY_COUNT) {
331 result = KERN_INVALID_ARGUMENT;
332 break;
333 }
334
335 info = (thread_precedence_policy_t)policy_info;
336
337 if (!(*get_default)) {
338 s = splsched();
339 thread_lock(thread);
340
341 info->importance = thread->importance;
342
343 thread_unlock(thread);
344 splx(s);
345 }
346 else
347 info->importance = 0;
348
349 break;
350 }
351
352 default:
353 result = KERN_INVALID_ARGUMENT;
354 break;
355 }
356
357 act_unlock_thread(act);
358
359 return (result);
360 }