]>
Commit | Line | Data |
---|---|---|
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 |
34 | static void |
35 | thread_recompute_priority( | |
36 | thread_t thread); | |
37 | ||
1c79356b A |
38 | kern_return_t |
39 | thread_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 |
193 | static void |
194 | thread_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 | ||
222 | void | |
223 | thread_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 |
244 | kern_return_t |
245 | thread_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 | } |