]> git.saurik.com Git - apple/xnu.git/blame_incremental - osfmk/kern/thread_policy.c
xnu-517.tar.gz
[apple/xnu.git] / osfmk / kern / thread_policy.c
... / ...
CommitLineData
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/processor.h>
35#include <kern/thread.h>
36
37static void
38thread_recompute_priority(
39 thread_t thread);
40
41kern_return_t
42thread_policy_set(
43 thread_act_t act,
44 thread_policy_flavor_t flavor,
45 thread_policy_t policy_info,
46 mach_msg_type_number_t count)
47{
48 kern_return_t result = KERN_SUCCESS;
49 thread_t thread;
50 spl_t s;
51
52 if (act == THR_ACT_NULL)
53 return (KERN_INVALID_ARGUMENT);
54
55 thread = act_lock_thread(act);
56 if (!act->active) {
57 act_unlock_thread(act);
58
59 return (KERN_TERMINATED);
60 }
61
62 assert(thread != THREAD_NULL);
63
64 switch (flavor) {
65
66 case THREAD_EXTENDED_POLICY:
67 {
68 boolean_t timeshare = TRUE;
69
70 if (count >= THREAD_EXTENDED_POLICY_COUNT) {
71 thread_extended_policy_t info;
72
73 info = (thread_extended_policy_t)policy_info;
74 timeshare = info->timeshare;
75 }
76
77 s = splsched();
78 thread_lock(thread);
79
80 if (!(thread->sched_mode & TH_MODE_FAILSAFE)) {
81 integer_t oldmode = (thread->sched_mode & TH_MODE_TIMESHARE);
82
83 thread->sched_mode &= ~TH_MODE_REALTIME;
84
85 if (timeshare && !oldmode) {
86 thread->sched_mode |= TH_MODE_TIMESHARE;
87
88 if (thread->state & TH_RUN)
89 pset_share_incr(thread->processor_set);
90 }
91 else
92 if (!timeshare && oldmode) {
93 thread->sched_mode &= ~TH_MODE_TIMESHARE;
94
95 if (thread->state & TH_RUN)
96 pset_share_decr(thread->processor_set);
97 }
98
99 thread_recompute_priority(thread);
100 }
101 else {
102 thread->safe_mode &= ~TH_MODE_REALTIME;
103
104 if (timeshare)
105 thread->safe_mode |= TH_MODE_TIMESHARE;
106 else
107 thread->safe_mode &= ~TH_MODE_TIMESHARE;
108 }
109
110 thread_unlock(thread);
111 splx(s);
112
113 break;
114 }
115
116 case THREAD_TIME_CONSTRAINT_POLICY:
117 {
118 thread_time_constraint_policy_t info;
119
120 if (count < THREAD_TIME_CONSTRAINT_POLICY_COUNT) {
121 result = KERN_INVALID_ARGUMENT;
122 break;
123 }
124
125 info = (thread_time_constraint_policy_t)policy_info;
126 if ( info->constraint < info->computation ||
127 info->computation > max_rt_quantum ||
128 info->computation < min_rt_quantum ) {
129 result = KERN_INVALID_ARGUMENT;
130 break;
131 }
132
133 s = splsched();
134 thread_lock(thread);
135
136 thread->realtime.period = info->period;
137 thread->realtime.computation = info->computation;
138 thread->realtime.constraint = info->constraint;
139 thread->realtime.preemptible = info->preemptible;
140
141 if (!(thread->sched_mode & TH_MODE_FAILSAFE)) {
142 if (thread->sched_mode & TH_MODE_TIMESHARE) {
143 thread->sched_mode &= ~TH_MODE_TIMESHARE;
144
145 if (thread->state & TH_RUN)
146 pset_share_decr(thread->processor_set);
147 }
148 thread->sched_mode |= TH_MODE_REALTIME;
149 thread_recompute_priority(thread);
150 }
151 else {
152 thread->safe_mode &= ~TH_MODE_TIMESHARE;
153 thread->safe_mode |= TH_MODE_REALTIME;
154 }
155
156 thread_unlock(thread);
157 splx(s);
158
159 break;
160 }
161
162 case THREAD_PRECEDENCE_POLICY:
163 {
164 thread_precedence_policy_t info;
165
166 if (count < THREAD_PRECEDENCE_POLICY_COUNT) {
167 result = KERN_INVALID_ARGUMENT;
168 break;
169 }
170
171 info = (thread_precedence_policy_t)policy_info;
172
173 s = splsched();
174 thread_lock(thread);
175
176 thread->importance = info->importance;
177
178 thread_recompute_priority(thread);
179
180 thread_unlock(thread);
181 splx(s);
182
183 break;
184 }
185
186 default:
187 result = KERN_INVALID_ARGUMENT;
188 break;
189 }
190
191 act_unlock_thread(act);
192
193 return (result);
194}
195
196static void
197thread_recompute_priority(
198 thread_t thread)
199{
200 integer_t priority;
201
202 if (thread->sched_mode & TH_MODE_REALTIME)
203 priority = BASEPRI_RTQUEUES;
204 else {
205 if (thread->importance > MAXPRI)
206 priority = MAXPRI;
207 else
208 if (thread->importance < -MAXPRI)
209 priority = -MAXPRI;
210 else
211 priority = thread->importance;
212
213 priority += thread->task_priority;
214
215 if (priority > thread->max_priority)
216 priority = thread->max_priority;
217 else
218 if (priority < MINPRI)
219 priority = MINPRI;
220 }
221
222 set_priority(thread, priority);
223}
224
225void
226thread_task_priority(
227 thread_t thread,
228 integer_t priority,
229 integer_t max_priority)
230{
231 spl_t s;
232
233 assert(thread != THREAD_NULL);
234
235 s = splsched();
236 thread_lock(thread);
237
238 thread->task_priority = priority;
239 thread->max_priority = max_priority;
240
241 thread_recompute_priority(thread);
242
243 thread_unlock(thread);
244 splx(s);
245}
246
247kern_return_t
248thread_policy_get(
249 thread_act_t act,
250 thread_policy_flavor_t flavor,
251 thread_policy_t policy_info,
252 mach_msg_type_number_t *count,
253 boolean_t *get_default)
254{
255 kern_return_t result = KERN_SUCCESS;
256 thread_t thread;
257 spl_t s;
258
259 if (act == THR_ACT_NULL)
260 return (KERN_INVALID_ARGUMENT);
261
262 thread = act_lock_thread(act);
263 if (!act->active) {
264 act_unlock_thread(act);
265
266 return (KERN_TERMINATED);
267 }
268
269 assert(thread != THREAD_NULL);
270
271 switch (flavor) {
272
273 case THREAD_EXTENDED_POLICY:
274 {
275 boolean_t timeshare = TRUE;
276
277 if (!(*get_default)) {
278 s = splsched();
279 thread_lock(thread);
280
281 if ( !(thread->sched_mode & TH_MODE_REALTIME) &&
282 !(thread->safe_mode & TH_MODE_REALTIME) ) {
283 if (!(thread->sched_mode & TH_MODE_FAILSAFE))
284 timeshare = (thread->sched_mode & TH_MODE_TIMESHARE) != 0;
285 else
286 timeshare = (thread->safe_mode & TH_MODE_TIMESHARE) != 0;
287 }
288 else
289 *get_default = TRUE;
290
291 thread_unlock(thread);
292 splx(s);
293 }
294
295 if (*count >= THREAD_EXTENDED_POLICY_COUNT) {
296 thread_extended_policy_t info;
297
298 info = (thread_extended_policy_t)policy_info;
299 info->timeshare = timeshare;
300 }
301
302 break;
303 }
304
305 case THREAD_TIME_CONSTRAINT_POLICY:
306 {
307 thread_time_constraint_policy_t info;
308
309 if (*count < THREAD_TIME_CONSTRAINT_POLICY_COUNT) {
310 result = KERN_INVALID_ARGUMENT;
311 break;
312 }
313
314 info = (thread_time_constraint_policy_t)policy_info;
315
316 if (!(*get_default)) {
317 s = splsched();
318 thread_lock(thread);
319
320 if ( (thread->sched_mode & TH_MODE_REALTIME) ||
321 (thread->safe_mode & TH_MODE_REALTIME) ) {
322 info->period = thread->realtime.period;
323 info->computation = thread->realtime.computation;
324 info->constraint = thread->realtime.constraint;
325 info->preemptible = thread->realtime.preemptible;
326 }
327 else
328 *get_default = TRUE;
329
330 thread_unlock(thread);
331 splx(s);
332 }
333
334 if (*get_default) {
335 info->period = 0;
336 info->computation = std_quantum / 2;
337 info->constraint = std_quantum;
338 info->preemptible = TRUE;
339 }
340
341 break;
342 }
343
344 case THREAD_PRECEDENCE_POLICY:
345 {
346 thread_precedence_policy_t info;
347
348 if (*count < THREAD_PRECEDENCE_POLICY_COUNT) {
349 result = KERN_INVALID_ARGUMENT;
350 break;
351 }
352
353 info = (thread_precedence_policy_t)policy_info;
354
355 if (!(*get_default)) {
356 s = splsched();
357 thread_lock(thread);
358
359 info->importance = thread->importance;
360
361 thread_unlock(thread);
362 splx(s);
363 }
364 else
365 info->importance = 0;
366
367 break;
368 }
369
370 default:
371 result = KERN_INVALID_ARGUMENT;
372 break;
373 }
374
375 act_unlock_thread(act);
376
377 return (result);
378}