]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kern/mk_sp.c
xnu-792.22.5.tar.gz
[apple/xnu.git] / osfmk / kern / mk_sp.c
1 /*
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * @OSF_COPYRIGHT@
30 *
31 */
32
33 /* The routines in this module are all obsolete */
34
35 #include <mach/boolean.h>
36 #include <mach/thread_switch.h>
37 #include <ipc/ipc_port.h>
38 #include <ipc/ipc_space.h>
39 #include <kern/ipc_kobject.h>
40 #include <kern/processor.h>
41 #include <kern/sched.h>
42 #include <kern/sched_prim.h>
43 #include <kern/spl.h>
44 #include <kern/task.h>
45 #include <kern/thread.h>
46 #include <mach/policy.h>
47
48 #include <kern/syscall_subr.h>
49 #include <mach/mach_host_server.h>
50 #include <mach/mach_syscalls.h>
51
52 #include <kern/misc_protos.h>
53 #include <kern/spl.h>
54 #include <kern/sched.h>
55 #include <kern/sched_prim.h>
56 #include <kern/assert.h>
57 #include <kern/thread.h>
58 #include <mach/mach_host_server.h>
59 #include <mach/thread_act_server.h>
60 #include <mach/host_priv_server.h>
61
62 /*
63 * thread_policy_common:
64 *
65 * Set scheduling policy & priority for thread.
66 */
67 static kern_return_t
68 thread_policy_common(
69 thread_t thread,
70 integer_t policy,
71 integer_t priority)
72 {
73 spl_t s;
74
75 if ( thread == THREAD_NULL ||
76 invalid_policy(policy) )
77 return(KERN_INVALID_ARGUMENT);
78
79 s = splsched();
80 thread_lock(thread);
81
82 if ( !(thread->sched_mode & TH_MODE_REALTIME) &&
83 !(thread->safe_mode & TH_MODE_REALTIME) ) {
84 if (!(thread->sched_mode & TH_MODE_FAILSAFE)) {
85 integer_t oldmode = (thread->sched_mode & TH_MODE_TIMESHARE);
86
87 if (policy == POLICY_TIMESHARE && !oldmode) {
88 thread->sched_mode |= TH_MODE_TIMESHARE;
89
90 if (thread->state & TH_RUN)
91 pset_share_incr(thread->processor_set);
92 }
93 else
94 if (policy != POLICY_TIMESHARE && oldmode) {
95 thread->sched_mode &= ~TH_MODE_TIMESHARE;
96
97 if (thread->state & TH_RUN)
98 pset_share_decr(thread->processor_set);
99 }
100 }
101 else {
102 if (policy == POLICY_TIMESHARE)
103 thread->safe_mode |= TH_MODE_TIMESHARE;
104 else
105 thread->safe_mode &= ~TH_MODE_TIMESHARE;
106 }
107
108 if (priority >= thread->max_priority)
109 priority = thread->max_priority - thread->task_priority;
110 else
111 if (priority >= MINPRI_KERNEL)
112 priority -= MINPRI_KERNEL;
113 else
114 if (priority >= MINPRI_RESERVED)
115 priority -= MINPRI_RESERVED;
116 else
117 priority -= BASEPRI_DEFAULT;
118
119 priority += thread->task_priority;
120
121 if (priority > thread->max_priority)
122 priority = thread->max_priority;
123 else
124 if (priority < MINPRI)
125 priority = MINPRI;
126
127 thread->importance = priority - thread->task_priority;
128
129 set_priority(thread, priority);
130 }
131
132 thread_unlock(thread);
133 splx(s);
134
135 return (KERN_SUCCESS);
136 }
137
138 /*
139 * thread_set_policy
140 *
141 * Set scheduling policy and parameters, both base and limit, for
142 * the given thread. Policy can be any policy implemented by the
143 * processor set, whether enabled or not.
144 */
145 kern_return_t
146 thread_set_policy(
147 thread_t thread,
148 processor_set_t pset,
149 policy_t policy,
150 policy_base_t base,
151 mach_msg_type_number_t base_count,
152 policy_limit_t limit,
153 mach_msg_type_number_t limit_count)
154 {
155 int max, bas;
156 kern_return_t result = KERN_SUCCESS;
157
158 if ( thread == THREAD_NULL ||
159 pset == PROCESSOR_SET_NULL )
160 return (KERN_INVALID_ARGUMENT);
161
162 thread_mtx_lock(thread);
163
164 if (pset != thread->processor_set) {
165 thread_mtx_unlock(thread);
166
167 return (KERN_FAILURE);
168 }
169
170 switch (policy) {
171
172 case POLICY_RR:
173 {
174 policy_rr_base_t rr_base = (policy_rr_base_t) base;
175 policy_rr_limit_t rr_limit = (policy_rr_limit_t) limit;
176
177 if ( base_count != POLICY_RR_BASE_COUNT ||
178 limit_count != POLICY_RR_LIMIT_COUNT ) {
179 result = KERN_INVALID_ARGUMENT;
180 break;
181 }
182
183 bas = rr_base->base_priority;
184 max = rr_limit->max_priority;
185 if (invalid_pri(bas) || invalid_pri(max)) {
186 result = KERN_INVALID_ARGUMENT;
187 break;
188 }
189
190 break;
191 }
192
193 case POLICY_FIFO:
194 {
195 policy_fifo_base_t fifo_base = (policy_fifo_base_t) base;
196 policy_fifo_limit_t fifo_limit = (policy_fifo_limit_t) limit;
197
198 if ( base_count != POLICY_FIFO_BASE_COUNT ||
199 limit_count != POLICY_FIFO_LIMIT_COUNT) {
200 result = KERN_INVALID_ARGUMENT;
201 break;
202 }
203
204 bas = fifo_base->base_priority;
205 max = fifo_limit->max_priority;
206 if (invalid_pri(bas) || invalid_pri(max)) {
207 result = KERN_INVALID_ARGUMENT;
208 break;
209 }
210
211 break;
212 }
213
214 case POLICY_TIMESHARE:
215 {
216 policy_timeshare_base_t ts_base = (policy_timeshare_base_t) base;
217 policy_timeshare_limit_t ts_limit =
218 (policy_timeshare_limit_t) limit;
219
220 if ( base_count != POLICY_TIMESHARE_BASE_COUNT ||
221 limit_count != POLICY_TIMESHARE_LIMIT_COUNT ) {
222 result = KERN_INVALID_ARGUMENT;
223 break;
224 }
225
226 bas = ts_base->base_priority;
227 max = ts_limit->max_priority;
228 if (invalid_pri(bas) || invalid_pri(max)) {
229 result = KERN_INVALID_ARGUMENT;
230 break;
231 }
232
233 break;
234 }
235
236 default:
237 result = KERN_INVALID_POLICY;
238 }
239
240 if (result != KERN_SUCCESS) {
241 thread_mtx_unlock(thread);
242
243 return (result);
244 }
245
246 result = thread_policy_common(thread, policy, bas);
247
248 thread_mtx_unlock(thread);
249
250 return (result);
251 }
252
253
254 /*
255 * thread_policy
256 *
257 * Set scheduling policy and parameters, both base and limit, for
258 * the given thread. Policy must be a policy which is enabled for the
259 * processor set. Change contained threads if requested.
260 */
261 kern_return_t
262 thread_policy(
263 thread_t thread,
264 policy_t policy,
265 policy_base_t base,
266 mach_msg_type_number_t count,
267 boolean_t set_limit)
268 {
269 kern_return_t result = KERN_SUCCESS;
270 processor_set_t pset;
271 policy_limit_t limit;
272 int limcount;
273 policy_rr_limit_data_t rr_limit;
274 policy_fifo_limit_data_t fifo_limit;
275 policy_timeshare_limit_data_t ts_limit;
276
277 if (thread == THREAD_NULL)
278 return (KERN_INVALID_ARGUMENT);
279
280 thread_mtx_lock(thread);
281
282 pset = thread->processor_set;
283 if (pset == PROCESSOR_SET_NULL) {
284 thread_mtx_unlock(thread);
285
286 return (KERN_INVALID_ARGUMENT);
287 }
288
289 if ( invalid_policy(policy) ||
290 ((POLICY_TIMESHARE | POLICY_RR | POLICY_FIFO) & policy) == 0 ) {
291 thread_mtx_unlock(thread);
292
293 return (KERN_INVALID_POLICY);
294 }
295
296 if (set_limit) {
297 /*
298 * Set scheduling limits to base priority.
299 */
300 switch (policy) {
301
302 case POLICY_RR:
303 {
304 policy_rr_base_t rr_base;
305
306 if (count != POLICY_RR_BASE_COUNT) {
307 result = KERN_INVALID_ARGUMENT;
308 break;
309 }
310
311 limcount = POLICY_RR_LIMIT_COUNT;
312 rr_base = (policy_rr_base_t) base;
313 rr_limit.max_priority = rr_base->base_priority;
314 limit = (policy_limit_t) &rr_limit;
315
316 break;
317 }
318
319 case POLICY_FIFO:
320 {
321 policy_fifo_base_t fifo_base;
322
323 if (count != POLICY_FIFO_BASE_COUNT) {
324 result = KERN_INVALID_ARGUMENT;
325 break;
326 }
327
328 limcount = POLICY_FIFO_LIMIT_COUNT;
329 fifo_base = (policy_fifo_base_t) base;
330 fifo_limit.max_priority = fifo_base->base_priority;
331 limit = (policy_limit_t) &fifo_limit;
332
333 break;
334 }
335
336 case POLICY_TIMESHARE:
337 {
338 policy_timeshare_base_t ts_base;
339
340 if (count != POLICY_TIMESHARE_BASE_COUNT) {
341 result = KERN_INVALID_ARGUMENT;
342 break;
343 }
344
345 limcount = POLICY_TIMESHARE_LIMIT_COUNT;
346 ts_base = (policy_timeshare_base_t) base;
347 ts_limit.max_priority = ts_base->base_priority;
348 limit = (policy_limit_t) &ts_limit;
349
350 break;
351 }
352
353 default:
354 result = KERN_INVALID_POLICY;
355 break;
356 }
357
358 }
359 else {
360 /*
361 * Use current scheduling limits. Ensure that the
362 * new base priority will not exceed current limits.
363 */
364 switch (policy) {
365
366 case POLICY_RR:
367 {
368 policy_rr_base_t rr_base;
369
370 if (count != POLICY_RR_BASE_COUNT) {
371 result = KERN_INVALID_ARGUMENT;
372 break;
373 }
374
375 limcount = POLICY_RR_LIMIT_COUNT;
376 rr_base = (policy_rr_base_t) base;
377 if (rr_base->base_priority > thread->max_priority) {
378 result = KERN_POLICY_LIMIT;
379 break;
380 }
381
382 rr_limit.max_priority = thread->max_priority;
383 limit = (policy_limit_t) &rr_limit;
384
385 break;
386 }
387
388 case POLICY_FIFO:
389 {
390 policy_fifo_base_t fifo_base;
391
392 if (count != POLICY_FIFO_BASE_COUNT) {
393 result = KERN_INVALID_ARGUMENT;
394 break;
395 }
396
397 limcount = POLICY_FIFO_LIMIT_COUNT;
398 fifo_base = (policy_fifo_base_t) base;
399 if (fifo_base->base_priority > thread->max_priority) {
400 result = KERN_POLICY_LIMIT;
401 break;
402 }
403
404 fifo_limit.max_priority = thread->max_priority;
405 limit = (policy_limit_t) &fifo_limit;
406
407 break;
408 }
409
410 case POLICY_TIMESHARE:
411 {
412 policy_timeshare_base_t ts_base;
413
414 if (count != POLICY_TIMESHARE_BASE_COUNT) {
415 result = KERN_INVALID_ARGUMENT;
416 break;
417 }
418
419 limcount = POLICY_TIMESHARE_LIMIT_COUNT;
420 ts_base = (policy_timeshare_base_t) base;
421 if (ts_base->base_priority > thread->max_priority) {
422 result = KERN_POLICY_LIMIT;
423 break;
424 }
425
426 ts_limit.max_priority = thread->max_priority;
427 limit = (policy_limit_t) &ts_limit;
428
429 break;
430 }
431
432 default:
433 result = KERN_INVALID_POLICY;
434 break;
435 }
436
437 }
438
439 thread_mtx_unlock(thread);
440
441 if (result == KERN_SUCCESS)
442 result = thread_set_policy(thread, pset,
443 policy, base, count, limit, limcount);
444
445 return(result);
446 }