|
|
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.