|
|
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: #ifndef _KERN_SF_H_
28: #define _KERN_SF_H_
29:
30: /*
31: * The calls most likely to change are: policy_thread_done and
32: * policy_thread_begin. They're the policy calls related to
33: * context switching. I'm not satisfied with what I have now and
34: * these are the forms I'm trying next.
35: *
36: * I still have to merge the data type names from my different sandboxes
37: * and I don't really talk about locking except for the run queue locking.
38: *
39: * A good example of the data type problem is sched_thread_t and thread_t.
40: * Right now, they're equivalent BUT eventually, i expect that policies
41: * will only use sched_thread_t which will only contain the scheduling
42: * attributes and the framework will know how to convert sched_thread_t
43: * to thread_t (policy-mechanism seperation).
44: *
45: * There is a big change for run queues: there is a single lock for an
46: * entire run queue array structure (instead of a lock per queue header).
47: * It's OK for a policy to reorganize a particular queue BUT it has to
48: * disable the queue header (sched_queue_disable). Since a queue header
49: * isn't shared by multiple policies and the framework won't touch the
50: * queue header if it's disabled, the policy can do anything it wants
51: * without taking out a global lock.
52: *
53: * The only run queue primitives provided are the really fast ones:
54: * insert at the head (sched_queue_preempt), insert at the tail
55: * and if the queue was empty check for preemption
56: * (sched_queue_add_preempt), just insert at the tail
57: * (sched_queue_add_only), and remove (sched_queue_remove). Everything
58: * else needs to be done by first disabling the queue header (and then
59: * you can do whatever you want to the queue).
60: *
61: * BTW, the convention here is:
62: *
63: * policy_xxx - calls from the framework into policies (via the
64: * pointers in the policy object)
65: *
66: * sched_xxx - scheduling mechanisms provided by the framework
67: * which can be called by policies.
68: *
69: * ----------
70: *
71: * Initializes an instance of a scheduling policy assigning it the
72: * corresponding policy_id and run queue headers.
73: *
74: * policy_init(
75: * sched_policy_object *policy,
76: * int policy_id, / * policy number * /
77: * int priority_mask_length, / * length of a priority mask * /
78: * sched_priority_mask *priority_mask ); / * mask for this policy * /
79: *
80: * Enable/disable a scheduling policy on a processor [set]
81: *
82: * policy_enable_processor_set(
83: * sched_policy_object *policy, / * policy * /
84: * processor_set_t processor_set ); / * processor set * /
85: *
86: * policy_disable_processor_set(
87: * sched_policy_object *policy,
88: * processor_set_t processor_set);
89: *
90: * policy_enable_processor(
91: * sched_policy_object *policy, / * policy * /
92: * processor_t processor ); / * processor set * /
93: *
94: * policy_disable_processor(
95: * sched_policy_object *policy,
96: * processor_t processor);
97: *
98: * Notifies the policy that the thread has become runnable
99: *
100: * policy_thread_unblock(
101: * sched_policy_object *policy,
102: * sched_thread_t thread )
103: *
104: * Notifies the policy that the current thread is done or
105: * a new thread has been selected to run
106: *
107: * policy_thread_done(
108: * sched_policy_object *policy,
109: * sched_thread_t *old_thread );
110: *
111: * policy_thread_begin(
112: * sched_policy_object *policy,
113: * sched_thread_t *new_thread );
114: *
115: * Attach/detach a thread from the scheduling policy
116: *
117: * policy_thread_attach(
118: * sched_policy_object *policy,
119: * sched_thread_t *thread );
120: *
121: * policy_thread_detach(
122: * sched_policy_object *policy,
123: * sched_thread_t *thread );
124: *
125: * Set the thread's processor [set]
126: *
127: * policy_thread_processor(
128: * sched_policy_object *policy,
129: * sched_thread_t *thread,
130: * processor_t processor );
131: *
132: * policy_thread_processor_set(
133: * sched_policy_object *policy,
134: * sched_thread_t *thread,
135: * processor_set_t processor_set);
136: *
137: * Set/get a thread's scheduling attributes
138: *
139: * policy_thread_set(
140: * sched_policy_object *policy,
141: * sched_thread_t thread,
142: * sched_policy_attributes policy_attributes);
143: *
144: * policy_thread_get(
145: * sched_policy_object *policy,
146: * sched_thread_t thread,
147: * sched_policy_attributes *policy_attributes);
148: *
149: * Scheduling Framework Interfaces
150: *
151: * [en/dis]able particular run queue headers on a processor [set],
152: *
153: * Lock the run queues, update the mask, unlock the run queues. If
154: * enabling, check preemption.
155: *
156: * sched_queue_enable(
157: * run_queue_t runq,
158: * sched_priority_mask *mask );
159: *
160: * sched_queue_disable(
161: * run_queue_t runq,
162: * sched_priority_mask *mask );
163: *
164: * Lock the run queues, insert the thread at the head, unlock the
165: * run queues and preempt (if possible).
166: *
167: * sched_queue_preempt(
168: * meta_priority_t priority,
169: * thread_t thread,
170: * run_queue_t run_queues );
171: *
172: * Lock the run queues, add the thread to the tail, unlock the run queues
173: * and preempt if appropriate.
174: *
175: * sched_queue_add_preempt(
176: * meta_priority_t priority,
177: * thread_t thread,
178: * run_queue_t run_queues );
179: *
180: * Lock the run queues, add the thread to the tail, unlock the queues
181: * but don't check for preemption.
182: *
183: * sched_queue_add_only(
184: * meta_priority_t priority,
185: * thread_t thread,
186: * run_queue_t run_queues );
187: *
188: * Lock the run queues, remove the entry the thread, unlock the run queues.
189: *
190: * sched_queue_remove(
191: * thread_t thread );
192: */
193:
194: #include <kern/kern_types.h>
195: #include <kern/sched.h>
196: #include <mach/thread_switch.h>
197: #include <mach/mach_types.h>
198:
199: /*
200: * Type definitions and constants for MK Scheduling Framework
201: */
202: typedef int sf_return_t;
203:
204: /* successful completion */
205: #define SF_SUCCESS 0
206:
207: /* error codes */
208: #define SF_FAILURE 1
209: #define SF_KERN_RESOURCE_SHORTAGE 2
210:
211: /* Scheduler Framework Object -- i.e., a scheduling policy */
212: typedef struct sf_policy *sf_object_t;
213:
214: /* Scheduler Framework thread definition is just a thread (for now) */
215: typedef thread_t sched_thread_t;
216:
217: /* Scheduler Framework priority mask definition */
218: typedef struct {
219: int bitmap[NRQBM];
220: } sf_priority_mask, *sf_priority_mask_t;
221:
222: /* Scheduler Framework meta-priority definition is just an int (for now) */
223: typedef int meta_priority_t;
224:
225: /**********
226: *
227: * Scheduling Attributes
228: *
229: **********/
230:
231: struct sp_attributes {
232: int policy_id; /* index of SP for kernel */
233: };
234:
235: typedef int sp_attributes_size_t;
236:
237: #define SP_ATTRIBUTES_NULL ((sp_attributes_t) 0)
238:
239: /**********
240: *
241: * Scheduling Information
242: *
243: **********/
244:
245: /*** ??? typedef void *sp_info_t; ***/
246: typedef int sp_info_size_t;
247:
248: #define SP_INFO_NULL ((sp_info_t) 0)
249:
250: /*
251: * maximum number of scheduling policies that the Scheduling Framework
252: * will host (picked arbitrarily)
253: */
254: #define MAX_SCHED_POLS ( 10 )
255:
256: /**********
257: *
258: * Scheduling Framework Interfaces
259: *
260: **********/
261:
262: /* Initialize Framework and selected policies */
263: void sf_init(void);
264:
265: /* [En/Dis]able particular run queue headers on a processor [set] */
266:
267: /* Lock run queues, update mask, unlock run queues. If enabling, check preemption */
268: sf_return_t (*sf_queue_enable)(
269: run_queue_t runq,
270: sf_priority_mask *mask);
271:
272: sf_return_t (*sf_queue_disable)(
273: run_queue_t runq,
274: sf_priority_mask *mask);
275:
276: /* Lock run queues, insert thread at head, unlock run queues and preempt (if possible) */
277: sf_return_t (*sf_queue_preempt)(
278: meta_priority_t priority,
279: thread_t thread,
280: run_queue_t run_queues);
281:
282: /* Lock run queues, add thread to tail, unlock run queues and preempt if appropriate */
283: sf_return_t (*sf_queue_add_preempt)(
284: meta_priority_t priority,
285: thread_t thread,
286: run_queue_t run_queues);
287:
288: /* Lock run queues, add thread to tail, unlock queues but don't check for preemption */
289: sf_return_t (*sf_queue_add_only)(
290: meta_priority_t priority,
291: thread_t thread,
292: run_queue_t run_queues);
293:
294: /* Lock run queues, remove thread entry, unlock run queues */
295: sf_return_t (*sf_queue_remove)(
296: thread_t thread);
297:
298: /**********
299: *
300: * Scheduling Policy Interfaces
301: *
302: **********/
303:
304: /*
305: * Operation list for scheduling policies. (Modeled after the
306: * device operations `.../mach_kernel/device/conf.h.')
307: *
308: * Key to some abbreviations:
309: * sp = scheduling policy
310: * sf = scheduling framework
311: */
312: typedef struct sched_policy_ops {
313: /* Initialize an instance of a scheduling policy */
314: sf_return_t (*sp_init)(
315: sf_object_t policy,
316: int policy_id,
317: int priority_mask_length,
318: sf_priority_mask *priority_mask);
319:
320: /* Enable/disable a scheduling policy on a processor [set] */
321: sf_return_t (*sp_enable_processor_set)(
322: sf_object_t policy,
323: processor_set_t processor_set);
324:
325: sf_return_t (*sp_disable_processor_set)(
326: sf_object_t policy,
327: processor_set_t processor_set);
328:
329: sf_return_t (*sp_enable_processor)(
330: sf_object_t policy,
331: processor_t processor);
332:
333: sf_return_t (*sp_disable_processor)(
334: sf_object_t policy,
335: processor_t processor);
336:
337: /* Allow the policy to update the meta-priority of a running thread */
338: sf_return_t (*sp_thread_update_mpri)(
339: sf_object_t policy,
340: sched_thread_t thread);
341:
342: /* Notify the policy that a thread has become runnable */
343: sf_return_t (*sp_thread_unblock)(
344: sf_object_t policy,
345: sched_thread_t thread);
346:
347: /* Notify the policy that the current thread is done */
348: /*** ??? Should this call take a `reason' argument? ***/
349: sf_return_t (*sp_thread_done)(
350: sf_object_t policy,
351: sched_thread_t old_thread);
352:
353: /* Notify the policy that a new thread has been selected to run */
354: sf_return_t (*sp_thread_begin)(
355: sf_object_t policy,
356: sched_thread_t new_thread);
357:
358: /* Notify the policy that an old thread is ready to be requeued */
359: sf_return_t (*sp_thread_dispatch)(
360: sf_object_t policy,
361: sched_thread_t old_thread);
362:
363: /* Attach/detach a thread from the scheduling policy */
364: sf_return_t (*sp_thread_attach)(
365: sf_object_t policy,
366: sched_thread_t thread);
367:
368: sf_return_t (*sp_thread_detach)(
369: sf_object_t policy,
370: sched_thread_t thread);
371:
372: /* Set the thread's processor [set] */
373: sf_return_t (*sp_thread_processor)(
374: sf_object_t policy,
375: sched_thread_t *thread,
376: processor_t processor);
377:
378: sf_return_t (*sp_thread_processor_set)(
379: sf_object_t policy,
380: sched_thread_t thread,
381: processor_set_t processor_set);
382:
383: /* Set/get a thread's scheduling attributes */
384: sf_return_t (*sp_thread_set)(
385: sf_object_t policy,
386: sched_thread_t thread,
387: sp_attributes_t policy_attributes);
388:
389: sf_return_t (*sp_thread_get)(
390: sf_object_t policy,
391: sched_thread_t thread,
392: sp_attributes_t policy_attributes,
393: sp_attributes_size_t size);
394:
395: /* Print scheduling info for a given thread */
396: int (*sp_db_print_sched_stats)(
397: sf_object_t policy,
398: sched_thread_t thread);
399:
400: /***
401: *** ??? Hopefully, many of the following operations are only
402: *** temporary. Consequently, they haven't been forced to take
403: *** the same form as the others just yet. That should happen
404: *** for all of those that end up being permanent additions to the
405: *** list of standard operations.
406: ***/
407:
408: /* `swtch_pri()' routine -- attempt to give up processor */
409: void (*sp_swtch_pri)(
410: sf_object_t policy,
411: int pri);
412:
413: /* `thread_switch()' routine -- context switch w/ optional hint */
414: kern_return_t (*sp_thread_switch)(
415: sf_object_t policy,
416: thread_act_t hint_act,
417: int option,
418: mach_msg_timeout_t option_time);
419:
420: /* `thread_depress_abort()' routine -- prematurely abort depression */
421: kern_return_t (*sp_thread_depress_abort)(
422: sf_object_t policy,
423: sched_thread_t thread);
424:
425: /* `thread_depress_timeout()' routine -- timeout on depression */
426: void (*sp_thread_depress_timeout)(
427: sf_object_t policy,
428: thread_t thread);
429:
430: /* `task_attach()' routine -- associate task with scheduling policy */
431: sf_return_t (*sp_task_attach)(
432: sf_object_t policy,
433: task_t task);
434:
435: /* `task_detach()' routine -- disassociate task from scheduling policy */
436: sf_return_t (*sp_task_detach)(
437: sf_object_t policy,
438: task_t task);
439:
440: /* `task_policy()' routine -- set scheduling policy and parameters */
441: kern_return_t (*sp_task_policy)(
442: sf_object_t policy,
443: task_t task,
444: policy_t policy_id,
445: policy_base_t base,
446: mach_msg_type_number_t count,
447: boolean_t set_limit,
448: boolean_t change,
449: policy_limit_t *limit_ptr,
450: int *lc_ptr);
451:
452: /* `task_set_policy()' routine -- set scheduling policy and parameters */
453: kern_return_t (*sp_task_set_policy)(
454: sf_object_t policy,
455: task_t task,
456: processor_set_t pset,
457: policy_t policy_id,
458: policy_base_t base,
459: mach_msg_type_number_t base_count,
460: policy_limit_t limit,
461: mach_msg_type_number_t limit_count,
462: boolean_t change);
463:
464: kern_return_t (*sp_task_set_sched)(
465: sf_object_t policy,
466: task_t task,
467: policy_t policy_id,
468: sched_attr_t sched_attr,
469: mach_msg_type_number_t sched_attrCnt,
470: boolean_t set_limit,
471: boolean_t change);
472:
473: kern_return_t (*sp_task_get_sched)(
474: sf_object_t policy,
475: task_t task,
476: policy_t policy_id,
477: sched_attr_t sched_attr,
478: mach_msg_type_number_t sched_attrCnt,
479: mach_msg_type_number_t sched_attr_size);
480:
481: boolean_t (*sp_thread_runnable)(
482: sf_object_t policy,
483: sched_thread_t thread);
484:
485: sf_return_t (*sp_alarm_expired)(
486: sf_object_t policy,
487: long alarm_seqno,
488: kern_return_t result,
489: int alarm_type,
490: mach_timespec_t wakeup_time,
491: void *alarm_data);
492:
493: } sp_ops_t;
494:
495: /**********
496: *
497: * Scheduling Policy
498: *
499: **********/
500:
501: typedef struct sf_policy {
502: int policy_id; /* policy number */
503: int priority_mask_length; /* length of a priority mask */
504: sf_priority_mask priority_mask; /* mask for this policy */
505:
506: /***
507: *** ??? does this have to be so general? why not just
508: *** have room in this struct for the priority mask? then
509: *** there is no need for an allocation and less indirection
510: *** is required for normal access.
511: ***/
512:
513: /*
514: * This is the size of the scheduling parameters
515: * data structure for this scheduling policy, in
516: * bytes.
517: *
518: * These are the parameters that are actually
519: * communicated -- and meaningful -- outside
520: * the policy. (This is as opposed to the
521: * internal state, which has some overlap with
522: * the scheduling parameters. The size of the
523: * internal state is given by `sched_info_size'
524: * in this structure.)
525: *
526: * By convention, the first field in the sched
527: * parameters structure is the scheduling policy
528: * ID. This makes the parameters more readily
529: * self-describing.
530: */
531: sp_attributes_size_t sched_attributes_size;
532:
533: /*
534: * This is the size of the scheduling policy's
535: * internal state that describes the state of a
536: * thread, in bytes.
537: */
538: sp_info_size_t sched_info_size;
539:
540: /*
541: * policy-specific versions
542: * of standard sched ops
543: */
544: sp_ops_t sp_ops;
545: } sched_policy_t;
546:
547: #define SCHED_POLICY_NULL ((sched_policy_t *) 0)
548:
549: #define policy_id_to_sched_policy(policy_id) \
550: (((policy_id) != POLICY_NULL)? \
551: &sched_policy[(policy_id)] : SCHED_POLICY_NULL)
552:
553: /*
554: * Declaration for array of scheduling policies known to kernel
555: */
556: extern sched_policy_t sched_policy[MAX_SCHED_POLS];
557:
558: /*
559: * Maximum sizes for scheduling-policy-specific information and
560: * attributes, calculated dynamically based on the scheduling
561: * policies that were initialized at system startup time.
562: */
563: extern sp_info_size_t max_sched_info_size;
564: extern sp_attributes_size_t max_sched_attributes_size;
565:
566: #endif /* _KERN_SF_H_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.