|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
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.
11: *
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
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * @OSF_COPYRIGHT@
24: *
25: */
26:
27: /***
28: *** ??? The following files were added when the task system call code
29: *** was moved into this file. They should be integrated with the above
30: *** files if these routine stay; or they should be moved elsewhere when
31: *** the routines are moved.
32: ***/
33: #include <mach/message.h>
34:
35: #include <kern/assert.h>
36: #include <kern/counters.h>
37: #include <kern/task.h>
38: #include <kern/sf.h>
39: #include <kern/mk_sp.h>
40:
41: /***
42: *** ??? The next file supplies the prototypes for `task_set_policy()'
43: *** and `task_policy.' These routines cannot stay here if they are
44: *** exported Mach system calls.
45: ***/
46: #include <mach/mach_host_server.h>
47:
48: sf_return_t
49: _mk_sp_task_attach(
50: sf_object_t pol, /* policy */
51: task_t task)
52: {
53: sp_attributes_t sp_attr;
54: sp_attributes_size_t sched_attributes_size;
55:
56: counter(c_mk_sp_task_attach++);
57:
58: /* get memory to hold scheduling parameters */
59: sched_attributes_size = pol->sched_attributes_size;
60: sp_attr = (sp_attributes_t)kalloc(sched_attributes_size);
61: if (sp_attr == 0) {
62: return(SF_KERN_RESOURCE_SHORTAGE);
63: }
64:
65: task->policy = pol->policy_id;
66: task->sp_attributes = sp_attr;
67:
68: return(SF_SUCCESS);
69: }
70:
71:
72: sf_return_t
73: _mk_sp_task_detach(
74: sf_object_t pol, /* policy */
75: task_t task)
76: {
77: sp_attributes_t sp_attr;
78: sp_attributes_size_t sched_attributes_size;
79:
80: counter(c_mk_sp_task_detach++);
81:
82: /* make sure task is associated with this policy */
83: if (task->policy != pol->policy_id) return(SF_SUCCESS);
84:
85: /* free memory holding scheduling parameters */
86: sched_attributes_size = pol->sched_attributes_size;
87: assert(task->sp_attributes != SP_ATTRIBUTES_NULL);
88: kfree((vm_offset_t) task->sp_attributes, sched_attributes_size);
89:
90: task->policy = POLICY_NULL;
91: task->sp_attributes = SP_ATTRIBUTES_NULL;
92:
93: return(SF_SUCCESS);
94: }
95:
96:
97: /*
98: * task_max_priority
99: *
100: * Set the maximum priority for a task. This does not affect threads
101: * within the task. Use thread_max_priority() to set their limits.
102: */
103: kern_return_t
104: task_max_priority(
105: task_t task,
106: processor_set_t pset,
107: int max_priority)
108: {
109: mk_sp_attributes_t sp_attr;
110: kern_return_t ret = KERN_SUCCESS;
111:
112: if (task == TASK_NULL || pset == PROCESSOR_SET_NULL ||
113: invalid_pri(max_priority))
114: return(KERN_INVALID_ARGUMENT);
115:
116: task_lock(task);
117:
118: /*
119: * Check for wrong processor set.
120: */
121: if (pset != task->processor_set) {
122: task_unlock(task);
123: return(KERN_FAILURE);
124: }
125:
126: /* get pointer to scheduling policy-specific data */
127: assert(task->sp_attributes != SP_ATTRIBUTES_NULL);
128: sp_attr = (mk_sp_attributes_t)task->sp_attributes;
129:
130: sp_attr->max_priority = max_priority;
131:
132: /*
133: * Reset priority if it violates new max priority
134: */
135: if (max_priority < sp_attr->priority) {
136: sp_attr->priority = max_priority;
137: }
138:
139: task_unlock(task);
140:
141: return(ret);
142: }
143:
144:
145: /*
146: * task_policy
147: *
148: * Set scheduling policy and parameters, both base and limit, for
149: * the given task. Policy must be a policy which is enabled for the
150: * processor set. Change contained threads if requested.
151: */
152: kern_return_t
153: _mk_sp_task_policy(
154: sf_object_t pol,
155: task_t task,
156: policy_t policy,
157: policy_base_t base,
158: mach_msg_type_number_t count,
159: boolean_t set_limit,
160: boolean_t change,
161: policy_limit_t *limit_ptr,
162: int *lc_ptr)
163: {
164: policy_rr_limit_data_t rr_limit;
165: policy_fifo_limit_data_t fifo_limit;
166: policy_timeshare_limit_data_t ts_limit;
167: kern_return_t ret = KERN_SUCCESS;
168: mk_sp_attributes_t sp_attr;
169:
170: counter(c_mk_sp_task_policy++);
171:
172: /* this routine currently only works with 3 standard MK policies */
173: assert((task->policy == POLICY_TIMESHARE)
174: || (task->policy == POLICY_RR)
175: || (task->policy == POLICY_FIFO));
176:
177: if (set_limit) {
178: /*
179: * Set scheduling limits to base priority.
180: */
181: switch (policy) {
182: case POLICY_RR:
183: {
184: policy_rr_base_t rr_base;
185:
186: if (count != POLICY_RR_BASE_COUNT)
187: return(KERN_INVALID_ARGUMENT);
188: *lc_ptr = POLICY_RR_LIMIT_COUNT;
189: rr_base = (policy_rr_base_t) base;
190: rr_limit.max_priority = rr_base->base_priority;
191: *limit_ptr = (policy_limit_t) &rr_limit;
192: break;
193: }
194:
195: case POLICY_FIFO:
196: {
197: policy_fifo_base_t fifo_base;
198:
199: if (count != POLICY_FIFO_BASE_COUNT)
200: return(KERN_INVALID_ARGUMENT);
201: *lc_ptr = POLICY_FIFO_LIMIT_COUNT;
202: fifo_base = (policy_fifo_base_t) base;
203: fifo_limit.max_priority = fifo_base->base_priority;
204: *limit_ptr = (policy_limit_t) &fifo_limit;
205: break;
206: }
207:
208: case POLICY_TIMESHARE:
209: {
210: policy_timeshare_base_t ts_base;
211:
212: if (count != POLICY_TIMESHARE_BASE_COUNT)
213: return(KERN_INVALID_ARGUMENT);
214: *lc_ptr = POLICY_TIMESHARE_LIMIT_COUNT;
215: ts_base = (policy_timeshare_base_t) base;
216: ts_limit.max_priority = ts_base->base_priority;
217: *limit_ptr = (policy_limit_t) &ts_limit;
218: break;
219: }
220:
221: default:
222: return(KERN_INVALID_POLICY);
223: }
224:
225: } else {
226: /*
227: * Use current scheduling limits. Ensure that the
228: * new base priority will not exceed current limits.
229: */
230:
231: /* get pointer to scheduling policy-specific data */
232: assert(task->sp_attributes != SP_ATTRIBUTES_NULL);
233: sp_attr = (mk_sp_attributes_t)task->sp_attributes;
234:
235: switch (policy) {
236: case POLICY_RR:
237: {
238: policy_rr_base_t rr_base;
239:
240: if (count != POLICY_RR_BASE_COUNT)
241: return(KERN_INVALID_ARGUMENT);
242: *lc_ptr = POLICY_RR_LIMIT_COUNT;
243: rr_base = (policy_rr_base_t) base;
244: if (rr_base->base_priority > sp_attr->max_priority) {
245: ret = KERN_POLICY_LIMIT;
246: break;
247: }
248: rr_limit.max_priority = sp_attr->max_priority;
249: *limit_ptr = (policy_limit_t) &rr_limit;
250: break;
251: }
252:
253: case POLICY_FIFO:
254: {
255: policy_fifo_base_t fifo_base;
256:
257: if (count != POLICY_FIFO_BASE_COUNT)
258: return(KERN_INVALID_ARGUMENT);
259: *lc_ptr = POLICY_FIFO_LIMIT_COUNT;
260: fifo_base = (policy_fifo_base_t) base;
261: if (fifo_base->base_priority > sp_attr->max_priority) {
262: ret = KERN_POLICY_LIMIT;
263: break;
264: }
265: fifo_limit.max_priority = sp_attr->max_priority;
266: *limit_ptr = (policy_limit_t) &fifo_limit;
267: break;
268: }
269:
270: case POLICY_TIMESHARE:
271: {
272: policy_timeshare_base_t ts_base;
273:
274: if (count != POLICY_TIMESHARE_BASE_COUNT)
275: return(KERN_INVALID_ARGUMENT);
276: *lc_ptr = POLICY_TIMESHARE_LIMIT_COUNT;
277: ts_base = (policy_timeshare_base_t) base;
278: if (ts_base->base_priority > sp_attr->max_priority) {
279: ret = KERN_POLICY_LIMIT;
280: break;
281: }
282: ts_limit.max_priority = sp_attr->max_priority;
283: *limit_ptr = (policy_limit_t) &ts_limit;
284: break;
285: }
286:
287: default:
288: return(KERN_INVALID_POLICY);
289: }
290:
291: }
292:
293: return(ret);
294: }
295:
296: /*
297: * task_set_policy
298: *
299: * Set scheduling policy and parameters, both base and limit, for
300: * the given task. Policy can be any policy implemented by the
301: * processor set, whether enabled or not. Change contained threads
302: * if requested.
303: */
304: kern_return_t
305: _mk_sp_task_set_policy(
306: sf_object_t pol,
307: task_t task,
308: processor_set_t pset,
309: policy_t policy,
310: policy_base_t base,
311: mach_msg_type_number_t base_count,
312: policy_limit_t limit,
313: mach_msg_type_number_t limit_count,
314: boolean_t change)
315: {
316: mk_sp_attributes_t sp_attr;
317: kern_return_t ret = KERN_SUCCESS;
318:
319: counter(c_mk_sp_task_set_policy++);
320:
321: /* check arguments */
322: switch (policy) {
323: case POLICY_RR:
324: {
325: policy_rr_base_t rr_base = (policy_rr_base_t) base;
326: policy_rr_limit_t rr_limit = (policy_rr_limit_t) limit;
327:
328: if (base_count != POLICY_RR_BASE_COUNT ||
329: limit_count != POLICY_RR_LIMIT_COUNT) {
330: ret = KERN_INVALID_ARGUMENT;
331: break;
332: }
333: if (invalid_pri(rr_base->base_priority) ||
334: invalid_pri(rr_limit->max_priority)) {
335: ret = KERN_INVALID_ARGUMENT;
336: break;
337: }
338: break;
339: }
340:
341: case POLICY_FIFO:
342: {
343: policy_fifo_base_t fifo_base = (policy_fifo_base_t) base;
344: policy_fifo_limit_t fifo_limit = (policy_fifo_limit_t) limit;
345:
346: if (base_count != POLICY_FIFO_BASE_COUNT ||
347: limit_count != POLICY_FIFO_LIMIT_COUNT) {
348: ret = KERN_INVALID_ARGUMENT;
349: break;
350: }
351: if (invalid_pri(fifo_base->base_priority) ||
352: invalid_pri(fifo_limit->max_priority)) {
353: ret = KERN_INVALID_ARGUMENT;
354: break;
355: }
356: break;
357: }
358:
359: case POLICY_TIMESHARE:
360: {
361: policy_timeshare_base_t ts_base =
362: (policy_timeshare_base_t) base;
363: policy_timeshare_limit_t ts_limit =
364: (policy_timeshare_limit_t) limit;
365:
366: if (base_count != POLICY_TIMESHARE_BASE_COUNT ||
367: limit_count != POLICY_TIMESHARE_LIMIT_COUNT) {
368: ret = KERN_INVALID_ARGUMENT;
369: break;
370: }
371: if (invalid_pri(ts_base->base_priority) ||
372: invalid_pri(ts_limit->max_priority)) {
373: ret = KERN_INVALID_ARGUMENT;
374: break;
375: }
376: break;
377: }
378:
379: default:
380: ret = KERN_INVALID_POLICY;
381: }
382:
383: /* stop if invalid arguments encountered */
384: if (ret != KERN_SUCCESS) {
385: return(ret);
386: }
387:
388: /* update task policy fields */
389: if ((task->policy == POLICY_TIMESHARE)
390: || (task->policy == POLICY_RR)
391: || (task->policy == POLICY_FIFO)) {
392: /* policies are close relatives; take advantage of that */
393:
394: /* get pointer to scheduling policy-specific data */
395: assert(task->sp_attributes != SP_ATTRIBUTES_NULL);
396: sp_attr = (mk_sp_attributes_t)task->sp_attributes;
397:
398: task->policy = policy;
399: sp_attr->policy_id = policy;
400: }
401: else {
402: /* old task policy is unrelated to standard MK policies */
403: /*** ??? fix me ***/
404: panic("mk_sp_task_set_policy");
405: }
406:
407: /* update scheduling parameters */
408: switch (policy) {
409: case POLICY_RR:
410: {
411: int temp;
412: policy_rr_base_t rr_base = (policy_rr_base_t) base;
413: policy_rr_limit_t rr_limit = (policy_rr_limit_t) limit;
414:
415: temp = rr_base->quantum * 1000;
416: if (temp % tick)
417: temp += tick;
418: sp_attr->sched_data = temp/tick;
419: sp_attr->priority = rr_base->base_priority;
420: sp_attr->max_priority = rr_limit->max_priority;
421: break;
422: }
423:
424: case POLICY_FIFO:
425: {
426: policy_fifo_base_t fifo_base = (policy_fifo_base_t) base;
427: policy_fifo_limit_t fifo_limit = (policy_fifo_limit_t) limit;
428:
429: sp_attr->sched_data = 0;
430: sp_attr->priority = fifo_base->base_priority;
431: sp_attr->max_priority = fifo_limit->max_priority;
432: break;
433: }
434:
435: case POLICY_TIMESHARE:
436: {
437: policy_timeshare_base_t ts_base =
438: (policy_timeshare_base_t) base;
439: policy_timeshare_limit_t ts_limit =
440: (policy_timeshare_limit_t) limit;
441:
442: sp_attr->sched_data = 0;
443: sp_attr->priority = ts_base->base_priority;
444: sp_attr->max_priority = ts_limit->max_priority;
445: break;
446: }
447:
448: default:
449: ret = KERN_INVALID_POLICY;
450: }
451:
452: return(ret);
453: }
454:
455:
456: kern_return_t
457: _mk_sp_task_set_sched(
458: sf_object_t pol, /* policy */
459: task_t task,
460: policy_t policy,
461: sched_attr_t sched_attr,
462: mach_msg_type_number_t sched_attrCnt,
463: boolean_t set_limit,
464: boolean_t change)
465: {
466: counter(c_mk_sp_task_set_sched++);
467:
468: panic("not yet implemented???");
469:
470: return(KERN_FAILURE);
471: }
472:
473:
474: kern_return_t
475: _mk_sp_task_get_sched(
476: sf_object_t pol, /* policy */
477: task_t task,
478: policy_t policy,
479: sched_attr_t sched_attr,
480: mach_msg_type_number_t sched_attrCnt,
481: mach_msg_type_number_t sched_attr_size)
482: {
483: counter(c_mk_sp_task_get_sched++);
484:
485: panic("not yet implemented???");
486:
487: return(KERN_FAILURE);
488: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.