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