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