]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
43866e37 | 6 | * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. |
1c79356b | 7 | * |
43866e37 A |
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 | |
1c79356b A |
17 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
18 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
43866e37 A |
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. | |
1c79356b A |
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 | ||
55e303ae | 34 | #include <kern/processor.h> |
1c79356b A |
35 | #include <kern/thread.h> |
36 | ||
0b4e3aa0 A |
37 | static void |
38 | thread_recompute_priority( | |
39 | thread_t thread); | |
40 | ||
1c79356b A |
41 | kern_return_t |
42 | thread_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; | |
1c79356b A |
50 | spl_t s; |
51 | ||
52 | if (act == THR_ACT_NULL) | |
53 | return (KERN_INVALID_ARGUMENT); | |
54 | ||
1c79356b A |
55 | thread = act_lock_thread(act); |
56 | if (!act->active) { | |
57 | act_unlock_thread(act); | |
1c79356b A |
58 | |
59 | return (KERN_TERMINATED); | |
60 | } | |
61 | ||
0b4e3aa0 | 62 | assert(thread != THREAD_NULL); |
1c79356b A |
63 | |
64 | switch (flavor) { | |
65 | ||
0b4e3aa0 | 66 | case THREAD_EXTENDED_POLICY: |
1c79356b | 67 | { |
0b4e3aa0 A |
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 | } | |
1c79356b A |
76 | |
77 | s = splsched(); | |
78 | thread_lock(thread); | |
79 | ||
0b4e3aa0 | 80 | if (!(thread->sched_mode & TH_MODE_FAILSAFE)) { |
55e303ae A |
81 | integer_t oldmode = (thread->sched_mode & TH_MODE_TIMESHARE); |
82 | ||
0b4e3aa0 | 83 | thread->sched_mode &= ~TH_MODE_REALTIME; |
1c79356b | 84 | |
55e303ae | 85 | if (timeshare && !oldmode) { |
0b4e3aa0 | 86 | thread->sched_mode |= TH_MODE_TIMESHARE; |
55e303ae A |
87 | |
88 | if (thread->state & TH_RUN) | |
89 | pset_share_incr(thread->processor_set); | |
90 | } | |
0b4e3aa0 | 91 | else |
55e303ae | 92 | if (!timeshare && oldmode) { |
0b4e3aa0 | 93 | thread->sched_mode &= ~TH_MODE_TIMESHARE; |
1c79356b | 94 | |
55e303ae A |
95 | if (thread->state & TH_RUN) |
96 | pset_share_decr(thread->processor_set); | |
97 | } | |
98 | ||
0b4e3aa0 A |
99 | thread_recompute_priority(thread); |
100 | } | |
101 | else { | |
102 | thread->safe_mode &= ~TH_MODE_REALTIME; | |
1c79356b | 103 | |
0b4e3aa0 A |
104 | if (timeshare) |
105 | thread->safe_mode |= TH_MODE_TIMESHARE; | |
106 | else | |
107 | thread->safe_mode &= ~TH_MODE_TIMESHARE; | |
108 | } | |
1c79356b A |
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; | |
55e303ae A |
126 | if ( info->constraint < info->computation || |
127 | info->computation > max_rt_quantum || | |
0b4e3aa0 A |
128 | info->computation < min_rt_quantum ) { |
129 | result = KERN_INVALID_ARGUMENT; | |
130 | break; | |
131 | } | |
1c79356b A |
132 | |
133 | s = splsched(); | |
134 | thread_lock(thread); | |
135 | ||
1c79356b A |
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 | ||
0b4e3aa0 | 141 | if (!(thread->sched_mode & TH_MODE_FAILSAFE)) { |
55e303ae A |
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 | } | |
0b4e3aa0 A |
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 | } | |
1c79356b A |
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 | ||
0b4e3aa0 | 178 | thread_recompute_priority(thread); |
1c79356b A |
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 | ||
1c79356b A |
193 | return (result); |
194 | } | |
195 | ||
0b4e3aa0 A |
196 | static void |
197 | thread_recompute_priority( | |
198 | thread_t thread) | |
199 | { | |
200 | integer_t priority; | |
201 | ||
202 | if (thread->sched_mode & TH_MODE_REALTIME) | |
55e303ae | 203 | priority = BASEPRI_RTQUEUES; |
0b4e3aa0 A |
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 | ||
9bccf70c | 222 | set_priority(thread, priority); |
0b4e3aa0 A |
223 | } |
224 | ||
225 | void | |
226 | thread_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 | ||
1c79356b A |
247 | kern_return_t |
248 | thread_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 | ||
0b4e3aa0 | 269 | assert(thread != THREAD_NULL); |
1c79356b A |
270 | |
271 | switch (flavor) { | |
272 | ||
0b4e3aa0 A |
273 | case THREAD_EXTENDED_POLICY: |
274 | { | |
275 | boolean_t timeshare = TRUE; | |
1c79356b | 276 | |
0b4e3aa0 A |
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 | } | |
1c79356b | 301 | |
1c79356b | 302 | break; |
0b4e3aa0 | 303 | } |
1c79356b A |
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 | ||
0b4e3aa0 A |
316 | if (!(*get_default)) { |
317 | s = splsched(); | |
318 | thread_lock(thread); | |
1c79356b | 319 | |
0b4e3aa0 A |
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; | |
1c79356b | 329 | |
0b4e3aa0 A |
330 | thread_unlock(thread); |
331 | splx(s); | |
332 | } | |
1c79356b | 333 | |
0b4e3aa0 | 334 | if (*get_default) { |
1c79356b | 335 | info->period = 0; |
0b4e3aa0 A |
336 | info->computation = std_quantum / 2; |
337 | info->constraint = std_quantum; | |
1c79356b A |
338 | info->preemptible = TRUE; |
339 | } | |
340 | ||
1c79356b A |
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 | ||
0b4e3aa0 | 355 | if (!(*get_default)) { |
1c79356b A |
356 | s = splsched(); |
357 | thread_lock(thread); | |
358 | ||
359 | info->importance = thread->importance; | |
360 | ||
361 | thread_unlock(thread); | |
362 | splx(s); | |
363 | } | |
0b4e3aa0 A |
364 | else |
365 | info->importance = 0; | |
1c79356b A |
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 | } |