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