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