]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kern/thread_policy.c
b04cf8f01d8d806ab87135cc0d5a54c760929059
[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 * 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
33 kern_return_t
34 thread_policy_set(
35 thread_act_t act,
36 thread_policy_flavor_t flavor,
37 thread_policy_t policy_info,
38 mach_msg_type_number_t count)
39 {
40 kern_return_t result = KERN_SUCCESS;
41 thread_t thread;
42 task_t task;
43 spl_t s;
44
45 if (act == THR_ACT_NULL)
46 return (KERN_INVALID_ARGUMENT);
47
48 act_lock(act);
49 task = act->task;
50 act_unlock(act);
51
52 task_lock(task);
53
54 thread = act_lock_thread(act);
55 if (!act->active) {
56 act_unlock_thread(act);
57 task_unlock(task);
58
59 return (KERN_TERMINATED);
60 }
61
62 if (thread == THREAD_NULL) {
63 act_unlock_thread(act);
64 task_unlock(task);
65
66 return (KERN_NOT_SUPPORTED);
67 }
68
69 #define thread_priority_set(thread, pri) \
70 MACRO_BEGIN \
71 if ((thread)->depress_priority >= 0) \
72 (thread)->depress_priority = (pri); \
73 else { \
74 (thread)->priority = (pri); \
75 compute_priority((thread), TRUE); \
76 \
77 if ((thread) == current_thread()) \
78 ast_on(AST_BLOCK); \
79 } \
80 MACRO_END
81
82 switch (flavor) {
83
84 case THREAD_STANDARD_POLICY:
85 {
86 integer_t priority;
87
88 s = splsched();
89 thread_lock(thread);
90
91 thread->sched_mode &=~ TH_MODE_REALTIME;
92
93 thread->policy = POLICY_TIMESHARE;
94
95 if (thread->importance > MAXPRI)
96 priority = MAXPRI;
97 else
98 if (thread->importance < -MAXPRI)
99 priority = -MAXPRI;
100 else
101 priority = thread->importance;
102
103 priority += task->priority;
104
105 if (priority > thread->max_priority)
106 priority = thread->max_priority;
107 else
108 if (priority < MINPRI)
109 priority = MINPRI;
110
111 thread_priority_set(thread, priority);
112
113 thread_unlock(thread);
114 splx(s);
115
116 break;
117 }
118
119 case THREAD_TIME_CONSTRAINT_POLICY:
120 {
121 thread_time_constraint_policy_t info;
122
123 if (count < THREAD_TIME_CONSTRAINT_POLICY_COUNT) {
124 result = KERN_INVALID_ARGUMENT;
125 break;
126 }
127
128 info = (thread_time_constraint_policy_t)policy_info;
129
130 s = splsched();
131 thread_lock(thread);
132
133 thread->sched_mode |= TH_MODE_REALTIME;
134
135 thread->realtime.period = info->period;
136 thread->realtime.computation = info->computation;
137 thread->realtime.constraint = info->constraint;
138 thread->realtime.preemptible = info->preemptible;
139
140 thread->policy = POLICY_RR;
141
142 thread_priority_set(thread, BASEPRI_REALTIME);
143
144 thread_unlock(thread);
145 splx(s);
146
147 break;
148 }
149
150 case THREAD_PRECEDENCE_POLICY:
151 {
152 thread_precedence_policy_t info;
153
154 if (count < THREAD_PRECEDENCE_POLICY_COUNT) {
155 result = KERN_INVALID_ARGUMENT;
156 break;
157 }
158
159 info = (thread_precedence_policy_t)policy_info;
160
161 s = splsched();
162 thread_lock(thread);
163
164 thread->importance = info->importance;
165
166 if (!(thread->sched_mode & TH_MODE_REALTIME)) {
167 integer_t priority;
168
169 if (thread->importance > MAXPRI)
170 priority = MAXPRI;
171 else
172 if (thread->importance < -MAXPRI)
173 priority = -MAXPRI;
174 else
175 priority = thread->importance;
176
177 priority += task->priority;
178
179 if (priority > thread->max_priority)
180 priority = thread->max_priority;
181 else
182 if (priority < MINPRI)
183 priority = MINPRI;
184
185 thread_priority_set(thread, priority);
186 }
187
188 thread_unlock(thread);
189 splx(s);
190
191 break;
192 }
193
194 default:
195 result = KERN_INVALID_ARGUMENT;
196 break;
197 }
198
199 act_unlock_thread(act);
200
201 task_unlock(task);
202
203 return (result);
204 }
205
206 kern_return_t
207 thread_policy_get(
208 thread_act_t act,
209 thread_policy_flavor_t flavor,
210 thread_policy_t policy_info,
211 mach_msg_type_number_t *count,
212 boolean_t *get_default)
213 {
214 kern_return_t result = KERN_SUCCESS;
215 thread_t thread;
216 spl_t s;
217
218 if (act == THR_ACT_NULL)
219 return (KERN_INVALID_ARGUMENT);
220
221 thread = act_lock_thread(act);
222 if (!act->active) {
223 act_unlock_thread(act);
224
225 return (KERN_TERMINATED);
226 }
227
228 if (thread == THREAD_NULL) {
229 act_unlock_thread(act);
230
231 return (KERN_NOT_SUPPORTED);
232 }
233
234 switch (flavor) {
235
236 case THREAD_STANDARD_POLICY:
237 s = splsched();
238 thread_lock(thread);
239
240 if (thread->sched_mode & TH_MODE_REALTIME)
241 *get_default = TRUE;
242
243 thread_unlock(thread);
244 splx(s);
245 break;
246
247 case THREAD_TIME_CONSTRAINT_POLICY:
248 {
249 thread_time_constraint_policy_t info;
250
251 if (*count < THREAD_TIME_CONSTRAINT_POLICY_COUNT) {
252 result = KERN_INVALID_ARGUMENT;
253 break;
254 }
255
256 info = (thread_time_constraint_policy_t)policy_info;
257
258 s = splsched();
259 thread_lock(thread);
260
261 if ((thread->sched_mode & TH_MODE_REALTIME) && !(*get_default)) {
262 info->period = thread->realtime.period;
263 info->computation = thread->realtime.computation;
264 info->constraint = thread->realtime.constraint;
265 info->preemptible = thread->realtime.preemptible;
266 }
267 else {
268 extern natural_t min_quantum_abstime;
269
270 *get_default = TRUE;
271
272 info->period = 0;
273 info->computation = min_quantum_abstime / 2;
274 info->constraint = min_quantum_abstime;
275 info->preemptible = TRUE;
276 }
277
278 thread_unlock(thread);
279 splx(s);
280
281 break;
282 }
283
284 case THREAD_PRECEDENCE_POLICY:
285 {
286 thread_precedence_policy_t info;
287
288 if (*count < THREAD_PRECEDENCE_POLICY_COUNT) {
289 result = KERN_INVALID_ARGUMENT;
290 break;
291 }
292
293 info = (thread_precedence_policy_t)policy_info;
294
295 if (*get_default)
296 info->importance = 0;
297 else {
298 s = splsched();
299 thread_lock(thread);
300
301 info->importance = thread->importance;
302
303 thread_unlock(thread);
304 splx(s);
305 }
306
307 break;
308 }
309
310 default:
311 result = KERN_INVALID_ARGUMENT;
312 break;
313 }
314
315 act_unlock_thread(act);
316
317 return (result);
318 }