|
|
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 lines were picked up when code was incorporated ! 29: *** into this file from `kern/syscall_subr.c.' These should be moved ! 30: *** with the code if it moves again. Otherwise, they should be trimmed, ! 31: *** based on the files included above. ! 32: ***/ ! 33: ! 34: #include <mach/boolean.h> ! 35: #include <mach/thread_switch.h> ! 36: #include <ipc/ipc_port.h> ! 37: #include <ipc/ipc_space.h> ! 38: #include <kern/counters.h> ! 39: #include <kern/ipc_kobject.h> ! 40: #include <kern/processor.h> ! 41: #include <kern/sched.h> ! 42: #include <kern/sched_prim.h> ! 43: #include <kern/spl.h> ! 44: #include <kern/task.h> ! 45: #include <kern/thread.h> ! 46: #include <kern/ast.h> ! 47: #include <mach/policy.h> ! 48: ! 49: #include <kern/syscall_subr.h> ! 50: #include <mach/mach_host_server.h> ! 51: #include <mach/mach_syscalls.h> ! 52: ! 53: /*** ! 54: *** ??? End of lines picked up when code was incorporated ! 55: *** into this file from `kern/syscall_subr.c.' ! 56: ***/ ! 57: ! 58: #include <kern/sf.h> ! 59: #include <kern/mk_sp.h> ! 60: #include <kern/misc_protos.h> ! 61: #include <kern/spl.h> ! 62: #include <kern/sched.h> ! 63: #include <kern/sched_prim.h> ! 64: #include <kern/assert.h> ! 65: #include <kern/thread.h> ! 66: #include <mach/mach_host_server.h> ! 67: ! 68: /* Forwards */ ! 69: void _mk_sp_thread_depress_priority( ! 70: sf_object_t policy, ! 71: mach_msg_timeout_t depress_time); ! 72: ! 73: /*** ! 74: *** ??? The next two files supply the prototypes for `thread_set_policy()' ! 75: *** and `thread_policy.' These routines cannot stay here if they are ! 76: *** exported Mach system calls. ! 77: ***/ ! 78: #include <mach/thread_act_server.h> ! 79: #include <mach/host_priv_server.h> ! 80: ! 81: /* ! 82: * Vector containing standard scheduling policy operations ! 83: */ ! 84: sp_ops_t mk_sp_ops = { ! 85: _mk_sp_init, ! 86: _mk_sp_enable_processor_set, ! 87: _mk_sp_disable_processor_set, ! 88: _mk_sp_enable_processor, ! 89: _mk_sp_disable_processor, ! 90: _mk_sp_thread_update_mpri, ! 91: _mk_sp_thread_unblock, ! 92: _mk_sp_thread_done, ! 93: _mk_sp_thread_begin, ! 94: _mk_sp_thread_dispatch, ! 95: _mk_sp_thread_attach, ! 96: _mk_sp_thread_detach, ! 97: _mk_sp_thread_processor, ! 98: _mk_sp_thread_processor_set, ! 99: _mk_sp_thread_set, ! 100: _mk_sp_thread_get, ! 101: _mk_sp_db_print_sched_stats, ! 102: _mk_sp_swtch_pri, ! 103: _mk_sp_thread_switch, ! 104: _mk_sp_thread_depress_abort, ! 105: _mk_sp_thread_depress_timeout, ! 106: _mk_sp_task_attach, ! 107: _mk_sp_task_detach, ! 108: _mk_sp_task_policy, ! 109: _mk_sp_task_set_policy, ! 110: _mk_sp_task_set_sched, ! 111: _mk_sp_task_get_sched, ! 112: _mk_sp_thread_runnable, ! 113: _mk_sp_alarm_expired ! 114: }; ! 115: ! 116: /* Forwards */ ! 117: kern_return_t thread_policy_common( ! 118: thread_t thread, ! 119: int policy, ! 120: int data, ! 121: processor_set_t pset); ! 122: ! 123: void _mk_sp_thread_dump( ! 124: sched_thread_t thread); ! 125: ! 126: /* ! 127: * Local variables ! 128: */ ! 129: #ifdef MACH_ASSERT ! 130: boolean_t mk_sp_first_thread = TRUE; ! 131: #endif /* MACH_ASSERT */ ! 132: ! 133: /* ! 134: * Counters to monitor policy-related events ! 135: */ ! 136: mach_counter_t c_mk_sp_init = 0, ! 137: c_mk_sp_enable_processor_set = 0, ! 138: c_mk_sp_disable_processor_set = 0, ! 139: c_mk_sp_enable_processor = 0, ! 140: c_mk_sp_disable_processor = 0, ! 141: c_mk_sp_thread_update_mpri = 0, ! 142: c_mk_sp_thread_unblock = 0, ! 143: c_mk_sp_thread_done = 0, ! 144: c_mk_sp_thread_begin = 0, ! 145: c_mk_sp_thread_dispatch = 0, ! 146: c_mk_sp_thread_attach = 0, ! 147: c_mk_sp_thread_detach = 0, ! 148: c_mk_sp_thread_processor = 0, ! 149: c_mk_sp_thread_processor_set = 0, ! 150: c_mk_sp_thread_set = 0, ! 151: c_mk_sp_thread_get = 0, ! 152: c_mk_sp_db_print_sched_stats = 0, ! 153: c_mk_sp_swtch_pri = 0, ! 154: c_mk_sp_thread_switch = 0, ! 155: c_mk_sp_thread_depress_abort = 0, ! 156: c_mk_sp_thread_depress_timeout = 0, ! 157: c_mk_sp_task_attach = 0, ! 158: c_mk_sp_task_detach = 0, ! 159: c_mk_sp_task_policy = 0, ! 160: c_mk_sp_task_set_policy = 0, ! 161: c_mk_sp_task_set_sched = 0, ! 162: c_mk_sp_task_get_sched = 0, ! 163: c_mk_sp_thread_runnable = 0, ! 164: c_mk_sp_alarm_expired = 0; ! 165: ! 166: /* ! 167: * Table to convert computed priorities into allocated priority range. ! 168: */ ! 169: int convert_pri[NRQS]; ! 170: ! 171: /* ! 172: * Lowest (normal -- i.e., not idle and not depressed) priority ! 173: */ ! 174: int lpri = -1; ! 175: ! 176: natural_t min_quantum_ms; ! 177: ! 178: /* ! 179: * Standard operations for MK Scheduling Policy ! 180: */ ! 181: ! 182: sf_return_t ! 183: _mk_sp_init( ! 184: sf_object_t policy, ! 185: int policy_id, ! 186: int priority_mask_length, ! 187: sf_priority_mask_t priority_mask) ! 188: { ! 189: int i; ! 190: int first_metapri; ! 191: int last_metapri; ! 192: ! 193: counter(c_mk_sp_init++); ! 194: ! 195: /* ! 196: * Initialize fields in the structure ! 197: */ ! 198: policy->policy_id = policy_id; ! 199: policy->priority_mask_length = priority_mask_length; ! 200: policy->priority_mask = *priority_mask; ! 201: /*** ??? should something more dynamic be done here for mask? ***/ ! 202: policy->sched_attributes_size = sizeof (mk_sp_attribute_struct_t); ! 203: policy->sched_info_size = sizeof (mk_sp_info_struct_t); ! 204: ! 205: /* ! 206: * Initialize table that maps computed priority values into ! 207: * allocated metapriority values. ! 208: */ ! 209: ! 210: /* Find first metapriority value allocated to this policy */ ! 211: first_metapri = MAXPRI - ffsbit(priority_mask->bitmap); ! 212: /*** ??? how to test for no set bits? ***/ ! 213: ! 214: /* Map computed priorities higher than this to first metapriority */ ! 215: for (i = MAXPRI; i > first_metapri; i--) ! 216: convert_pri[i] = first_metapri; ! 217: ! 218: /* For each remaining computed priority value... */ ! 219: for (i = first_metapri; i >= 0; i--) { ! 220: /* ... is it a metapriority value assigned to this policy ?*/ ! 221: if (testbit(MAXPRI - i, priority_mask->bitmap)) { ! 222: /* Yes; just use it */ ! 223: convert_pri[i] = i; ! 224: last_metapri = i; ! 225: } ! 226: else { ! 227: /* No, bump it up to the last value assigned */ ! 228: convert_pri[i] = last_metapri; ! 229: } ! 230: } ! 231: ! 232: /* Remember lowest "normal" priority available to this policy */ ! 233: lpri = convert_pri[LPRI]; ! 234: ! 235: min_quantum_ms = (1000 / hz) * min_quantum; ! 236: ! 237: #if 0 ! 238: /* Initialize operation entries in "jump table" */ ! 239: /*** ! 240: *** ??? These must be done elsewhere. Otherwise, there is a ! 241: *** circularity: How does the framework find this init operation? ! 242: ***/ ! 243: policy->sp_ops = mk_sp_ops; ! 244: ! 245: policy->sp_ops.sp_enable_processor_set = sp_mk_enable_processor_set; ! 246: policy->sp_ops.sp_disable_processor_set = sp_mk_disable_processor_set; ! 247: policy->sp_ops.sp_enable_processor = sp_mk_enable_processor; ! 248: policy->sp_ops.sp_disable_processor = sp_mk_disable_processor; ! 249: policy->sp_ops.sp_thread_unblock = sp_mk_thread_unblock; ! 250: policy->sp_ops.sp_thread_done = sp_mk_thread_done; ! 251: policy->sp_ops.sp_thread_begin = sp_mk_thread_begin; ! 252: policy->sp_ops.sp_thread_attach = sp_mk_thread_attach; ! 253: policy->sp_ops.sp_thread_detach = sp_mk_thread_detach; ! 254: policy->sp_ops.sp_thread_processor = sp_mk_thread_processor; ! 255: policy->sp_ops.sp_thread_processor_set = sp_mk_thread_processor_set; ! 256: policy->sp_ops.sp_thread_set = sp_mk_thread_set; ! 257: policy->sp_ops.sp_thread_get = sp_mk_thread_get; ! 258: policy->sp_ops.sp_db_print_sched_stats = sp_mk_db_print_sched_stats; ! 259: #endif ! 260: ! 261: return(SF_SUCCESS); ! 262: } ! 263: ! 264: sf_return_t ! 265: _mk_sp_enable_processor_set( ! 266: sf_object_t policy, ! 267: processor_set_t processor_set) ! 268: { ! 269: kern_return_t result; ! 270: ! 271: counter(c_mk_sp_enable_processor_set++); ! 272: ! 273: result = processor_set_policy_enable(processor_set, policy->policy_id); ! 274: assert(result == KERN_SUCCESS); ! 275: ! 276: return(SF_SUCCESS); ! 277: } ! 278: ! 279: sf_return_t ! 280: _mk_sp_disable_processor_set( ! 281: sf_object_t policy, ! 282: processor_set_t processor_set) ! 283: { ! 284: kern_return_t result; ! 285: ! 286: counter(c_mk_sp_disable_processor_set++); ! 287: ! 288: result = processor_set_policy_disable( ! 289: processor_set, policy->policy_id, TRUE); ! 290: assert(result == KERN_SUCCESS); ! 291: ! 292: return(SF_SUCCESS); ! 293: } ! 294: ! 295: sf_return_t ! 296: _mk_sp_enable_processor( ! 297: sf_object_t policy, ! 298: processor_t processor) ! 299: { ! 300: counter(c_mk_sp_enable_processor++); ! 301: ! 302: panic("not yet implemented???"); ! 303: ! 304: return(SF_FAILURE); ! 305: } ! 306: ! 307: sf_return_t ! 308: _mk_sp_disable_processor( ! 309: sf_object_t policy, ! 310: processor_t processor) ! 311: { ! 312: counter(c_mk_sp_disable_processor++); ! 313: ! 314: panic("not yet implemented???"); ! 315: ! 316: return(SF_FAILURE); ! 317: } ! 318: ! 319: sf_return_t ! 320: _mk_sp_thread_update_mpri( ! 321: sf_object_t policy, ! 322: sched_thread_t thread) ! 323: { ! 324: mk_sp_info_t sp_info; ! 325: ! 326: counter(c_mk_sp_thread_update_mpri++); ! 327: ! 328: /* get pointer to scheduling policy-specific data */ ! 329: assert(thread->sp_info != SP_INFO_NULL); ! 330: sp_info = (mk_sp_info_t)thread->sp_info; ! 331: ! 332: if (sp_info->sched_stamp != sched_tick) ! 333: update_priority(thread); ! 334: ! 335: return(SF_SUCCESS); ! 336: } ! 337: ! 338: sf_return_t ! 339: _mk_sp_thread_unblock( ! 340: sf_object_t policy, ! 341: sched_thread_t thread) ! 342: { ! 343: mk_sp_info_t sp_info; ! 344: ! 345: counter(c_mk_sp_thread_unblock++); ! 346: ! 347: /* get pointer to scheduling policy-specific data */ ! 348: assert(thread->sp_info != SP_INFO_NULL); ! 349: sp_info = (mk_sp_info_t)thread->sp_info; ! 350: ! 351: counter(sp_info->c_mk_sp_thread_unblock++); ! 352: ! 353: /* ! 354: * The following assert is removed because we're hacking the ! 355: * MK_SP_BLOCKED bit and removing it early to get SMP to work ! 356: * with this gosh darned scheduler. The whole danged thing is lousy and ! 357: * needs to be removed. Hopefully for now, no one tries to ! 358: * unblock a really runnable guy - HACKALERT!!! ! 359: */ ! 360: ! 361: /* check for legal thread states */ ! 362: #if 0 ! 363: assert(sp_info->th_state == MK_SP_BLOCKED || ! 364: sp_info->th_state == MK_SP_ATTACHED); /* ??? work to remove*/ ! 365: #endif ! 366: /* indicate thread is now runnable */ ! 367: sp_info->th_state = MK_SP_RUNNABLE; ! 368: ! 369: /* place thread at end of appropriate run queue */ ! 370: thread_setrun(thread, TRUE, TAIL_Q); ! 371: ! 372: return(SF_SUCCESS); ! 373: } ! 374: ! 375: sf_return_t ! 376: _mk_sp_thread_done( ! 377: sf_object_t policy, ! 378: sched_thread_t old_thread) ! 379: { ! 380: processor_t myprocessor = cpu_to_processor(cpu_number()); ! 381: mk_sp_info_t sp_info; ! 382: ! 383: counter(c_mk_sp_thread_done++); ! 384: ! 385: /* ! 386: * A running thread is being taken off a processor: ! 387: * ! 388: * - update the thread's `unconsumed_quantum' field ! 389: * - update the thread's state field ! 390: */ ! 391: ! 392: /* get pointer to scheduling policy-specific data */ ! 393: assert(old_thread->sp_info != SP_INFO_NULL); ! 394: sp_info = (mk_sp_info_t)old_thread->sp_info; ! 395: ! 396: counter(sp_info->c_mk_sp_thread_done++); ! 397: assert((sp_info->c_mk_sp_thread_done ! 398: == sp_info->c_mk_sp_thread_begin + 1) || ! 399: (sp_info->c_mk_sp_thread_done ! 400: == sp_info->c_mk_sp_thread_begin)); ! 401: ! 402: sp_info->unconsumed_quantum = myprocessor->quantum; ! 403: ! 404: /* check thread's current state */ ! 405: assert(mk_sp_first_thread || (sp_info->th_state & MK_SP_RUNNABLE)); ! 406: #ifdef MACH_ASSERT ! 407: mk_sp_first_thread = FALSE; ! 408: #endif /* MACH_ASSERT */ ! 409: ! 410: /* update thread's state field based on reason for stopping now */ ! 411: /*** ??? is this condition correct? should it be more selective? ***/ ! 412: /*** ??? if ((old_thread->reason != AST_NONE) || ! 413: (old_thread->wait_event != NO_EVENT)) { ***/ ! 414: if (old_thread->state & TH_WAIT) { ! 415: sp_info->th_state = MK_SP_BLOCKED; ! 416: } ! 417: ! 418: return(SF_SUCCESS); ! 419: } ! 420: ! 421: sf_return_t ! 422: _mk_sp_thread_begin( ! 423: sf_object_t policy, ! 424: sched_thread_t thread) ! 425: { ! 426: ! 427: processor_t myprocessor = cpu_to_processor(cpu_number()); ! 428: processor_set_t pset; ! 429: mk_sp_info_t sp_info; ! 430: ! 431: counter(c_mk_sp_thread_begin++); ! 432: ! 433: pset = myprocessor->processor_set; ! 434: /* ! 435: * The designated thread is about to begin execution: ! 436: * ! 437: * - update the processor's `quantum' field ! 438: */ ! 439: ! 440: /* get pointer to scheduling policy-specific data */ ! 441: assert(thread->sp_info != SP_INFO_NULL); ! 442: sp_info = (mk_sp_info_t)thread->sp_info; ! 443: ! 444: counter(sp_info->c_mk_sp_thread_begin++); ! 445: assert((sp_info->c_mk_sp_thread_done ! 446: == sp_info->c_mk_sp_thread_begin) || ! 447: (sp_info->c_mk_sp_thread_done + 1 ! 448: == sp_info->c_mk_sp_thread_begin)); ! 449: ! 450: /* check for legal thread state */ ! 451: assert(sp_info->th_state == MK_SP_RUNNABLE); ! 452: ! 453: if (thread->policy & (POLICY_RR|POLICY_FIFO)) ! 454: myprocessor->quantum = sp_info->unconsumed_quantum; ! 455: else ! 456: myprocessor->quantum = (thread->bound_processor ? ! 457: min_quantum : pset->set_quantum); ! 458: ! 459: return(SF_SUCCESS); ! 460: } ! 461: ! 462: sf_return_t ! 463: _mk_sp_thread_dispatch( ! 464: sf_object_t policy, ! 465: sched_thread_t old_thread) ! 466: { ! 467: mk_sp_info_t sp_info; ! 468: ! 469: counter(c_mk_sp_thread_dispatch++); ! 470: ! 471: /* get pointer to scheduling policy-specific data */ ! 472: assert(old_thread->sp_info != SP_INFO_NULL); ! 473: sp_info = (mk_sp_info_t)old_thread->sp_info; ! 474: ! 475: counter(sp_info->c_mk_sp_thread_dispatch++); ! 476: ! 477: if (sp_info->th_state & MK_SP_RUNNABLE) { ! 478: if (old_thread->reason & AST_QUANTUM) { ! 479: thread_setrun(old_thread, FALSE, TAIL_Q); ! 480: sp_info->unconsumed_quantum = sp_info->sched_data; ! 481: } ! 482: else ! 483: thread_setrun(old_thread, FALSE, HEAD_Q); ! 484: } ! 485: ! 486: if (sp_info->th_state & MK_SP_ATTACHED) { ! 487: /* indicate thread is now runnable */ ! 488: sp_info->th_state = MK_SP_RUNNABLE; ! 489: ! 490: /* place thread at end of appropriate run queue */ ! 491: thread_setrun(old_thread, FALSE, TAIL_Q); ! 492: } ! 493: ! 494: return(SF_SUCCESS); ! 495: } ! 496: ! 497: /* ! 498: * Thread must already be locked. ! 499: */ ! 500: sf_return_t ! 501: _mk_sp_thread_attach( ! 502: sf_object_t policy, ! 503: sched_thread_t thread) ! 504: { ! 505: mk_sp_info_t sp_info; ! 506: ! 507: counter(c_mk_sp_thread_attach++); ! 508: ! 509: /* Make sure there is a place for policy-specific state */ ! 510: assert(thread->sp_info != SP_INFO_NULL); ! 511: ! 512: sp_info = (mk_sp_info_t)thread->sp_info; ! 513: sp_info->th_state = MK_SP_ATTACHED; ! 514: /*** ??? Do these need to be done here? ***/ ! 515: /*** ??? If so, could fill from template for speed -- maybe ***/ ! 516: sp_info->priority = MINPRI; /*** ??? ***/ ! 517: sp_info->max_priority = BASEPRI_USER; ! 518: /*** ??? sp_info->sched_pri = ! 519: (later - compute_priority); (for now, at least) ***/ ! 520: sp_info->sched_data = 0; ! 521: sp_info->policy = policy->policy_id; /*** ??? ***/ ! 522: sp_info->depress_priority = -1; ! 523: sp_info->cpu_usage = 0; ! 524: sp_info->sched_usage = 0; ! 525: sp_info->sched_stamp = 0; /*** ??? ***/ ! 526: sp_info->unconsumed_quantum = 0; /*** ??? ***/ ! 527: ! 528: #ifdef MACH_ASSERT ! 529: sp_info->c_mk_sp_thread_attach = 1; ! 530: sp_info->c_mk_sp_thread_detach = 0; ! 531: sp_info->c_mk_sp_thread_begin = 0; ! 532: sp_info->c_mk_sp_thread_done = 0; ! 533: sp_info->c_mk_sp_thread_dispatch = 0; ! 534: sp_info->c_mk_sp_thread_unblock = 0; ! 535: sp_info->c_mk_sp_thread_set = 0; ! 536: sp_info->c_mk_sp_thread_get = 0; ! 537: #endif /* MACH_ASSERT */ ! 538: ! 539: /* Reflect this policy in thread data structure */ ! 540: thread->policy = policy->policy_id; ! 541: ! 542: return(SF_SUCCESS); ! 543: } ! 544: ! 545: /* ! 546: * Check to make sure that thread is removed from run ! 547: * queues and active execution; and clean up the ! 548: * policy-specific data structure for thread. ! 549: * ! 550: * Thread must already be locked. ! 551: */ ! 552: sf_return_t ! 553: _mk_sp_thread_detach( ! 554: sf_object_t policy, ! 555: sched_thread_t thread) ! 556: { ! 557: mk_sp_info_t sp_info; ! 558: struct run_queue *rq; ! 559: ! 560: assert(thread->policy == policy->policy_id); ! 561: ! 562: counter(c_mk_sp_thread_detach++); ! 563: /* get pointer to scheduling policy-specific data */ ! 564: assert(thread->sp_info != SP_INFO_NULL); ! 565: sp_info = (mk_sp_info_t)thread->sp_info; ! 566: ! 567: counter(sp_info->c_mk_sp_thread_detach++); ! 568: ! 569: /* make sure that the thread has stopped executing */ ! 570: /*** ??? look at machine's version of RUN bit, too? ***/ ! 571: /*** ! 572: *** Fix for SMP case. ! 573: ***/ ! 574: ! 575: /* make sure that the thread is no longer on any run queue */ ! 576: if (thread->runq != RUN_QUEUE_NULL) { ! 577: rq = rem_runq(thread); ! 578: if (rq == RUN_QUEUE_NULL) { ! 579: panic("mk_sp_thread_detach: missed thread"); ! 580: } ! 581: } ! 582: ! 583: /* (optionally) clear policy-specific data structure for the thread */ ! 584: ! 585: if (sp_info->depress_priority >= 0) { ! 586: sp_info->priority = sp_info->depress_priority; ! 587: sp_info->depress_priority = -1; ! 588: if (thread_call_cancel(&thread->depress_timer)) ! 589: thread_call_enter(&thread->depress_timer); ! 590: } ! 591: ! 592: /* clear the thread's policy field */ ! 593: thread->policy = POLICY_NULL; ! 594: ! 595: return(SF_SUCCESS); ! 596: } ! 597: ! 598: sf_return_t ! 599: _mk_sp_thread_processor( ! 600: sf_object_t policy, ! 601: sched_thread_t *thread, ! 602: processor_t processor) ! 603: { ! 604: counter(c_mk_sp_thread_processor++); ! 605: ! 606: panic("not yet implemented???"); ! 607: ! 608: return(SF_FAILURE); ! 609: } ! 610: ! 611: sf_return_t ! 612: _mk_sp_thread_processor_set( ! 613: sf_object_t policy, ! 614: sched_thread_t thread, ! 615: processor_set_t processor_set) ! 616: { ! 617: counter(c_mk_sp_thread_processor_set++); ! 618: ! 619: pset_add_thread(processor_set, thread); ! 620: ! 621: return(SF_SUCCESS); ! 622: } ! 623: ! 624: sf_return_t ! 625: _mk_sp_thread_set( ! 626: sf_object_t policy, ! 627: sched_thread_t thread, ! 628: sp_attributes_t policy_attributes) ! 629: { ! 630: mk_sp_info_t sp_info; ! 631: mk_sp_attributes_t attributes; ! 632: ! 633: counter(c_mk_sp_thread_set++); ! 634: ! 635: /* check that attributes are for this policy */ ! 636: assert(policy_attributes->policy_id == policy->policy_id); ! 637: ! 638: attributes = (mk_sp_attributes_t)policy_attributes; ! 639: ! 640: /* get pointer to scheduling policy-specific data */ ! 641: assert(thread->sp_info != SP_INFO_NULL); ! 642: sp_info = (mk_sp_info_t)thread->sp_info; ! 643: ! 644: counter(sp_info->c_mk_sp_thread_set++); ! 645: ! 646: /* update scheduling parameters */ ! 647: sp_info->priority = attributes->priority; ! 648: sp_info->max_priority = attributes->max_priority; ! 649: sp_info->sched_data = attributes->sched_data; ! 650: sp_info->unconsumed_quantum = attributes->unconsumed_quantum; ! 651: ! 652: /* ! 653: * No check is needed against the pset limit. If the task could raise ! 654: * its priority above the limit, then it must have had permisssion. ! 655: */ ! 656: ! 657: /* ! 658: * Determine thread's state. (It may be an "older" thread ! 659: * that has just been associated with this policy.) ! 660: */ ! 661: if (thread->state & TH_WAIT) { ! 662: sp_info->th_state = MK_SP_BLOCKED; ! 663: } ! 664: ! 665: /* recompute priority */ ! 666: sp_info->sched_stamp = sched_tick; ! 667: compute_priority(thread, TRUE); ! 668: ! 669: return(SF_SUCCESS); ! 670: } ! 671: ! 672: sf_return_t ! 673: _mk_sp_thread_get( ! 674: sf_object_t policy, ! 675: sched_thread_t thread, ! 676: sp_attributes_t policy_attributes, ! 677: sp_attributes_size_t size) ! 678: /* ! 679: * Assumes that thread is locked. ! 680: */ ! 681: /*** ! 682: *** ??? Does it assume `splsched()'? ! 683: ***/ ! 684: { ! 685: mk_sp_info_t sp_info; ! 686: mk_sp_attributes_t attributes; ! 687: ! 688: counter(c_mk_sp_thread_get++); ! 689: ! 690: /* check size of attribute structure provided by caller */ ! 691: if (policy->sched_attributes_size > size) ! 692: return(SF_FAILURE); ! 693: ! 694: attributes = (mk_sp_attributes_t)policy_attributes; ! 695: ! 696: ! 697: /* get pointer to scheduling policy-specific data */ ! 698: assert(thread->sp_info != SP_INFO_NULL); ! 699: sp_info = (mk_sp_info_t)thread->sp_info; ! 700: ! 701: counter(sp_info->c_mk_sp_thread_get++); ! 702: ! 703: /* copy scheduling attributes */ ! 704: attributes->policy_id = policy->policy_id; ! 705: attributes->priority = sp_info->priority; ! 706: attributes->max_priority = sp_info->max_priority; ! 707: attributes->sched_data = sp_info->sched_data; ! 708: attributes->unconsumed_quantum = sp_info->unconsumed_quantum; ! 709: ! 710: return(SF_SUCCESS); ! 711: } ! 712: ! 713: int ! 714: _mk_sp_db_print_sched_stats( ! 715: sf_object_t policy, ! 716: sched_thread_t thread) ! 717: { ! 718: mk_sp_info_t sp_info; ! 719: ! 720: counter(c_mk_sp_db_print_sched_stats++); ! 721: ! 722: /* get pointer to scheduling policy-specific data */ ! 723: assert(thread->sp_info != SP_INFO_NULL); ! 724: sp_info = (mk_sp_info_t)thread->sp_info; ! 725: ! 726: /* print one field -- `sched_pri' */ ! 727: return (thread->sched_pri); ! 728: } ! 729: ! 730: /* ! 731: * thread_priority: ! 732: * ! 733: * Set priority (and possibly max priority) for thread. ! 734: */ ! 735: kern_return_t ! 736: thread_priority( ! 737: thread_act_t thr_act, ! 738: int priority, ! 739: boolean_t set_max) ! 740: { ! 741: kern_return_t result; ! 742: thread_t thread; ! 743: ! 744: if (thr_act == THR_ACT_NULL) ! 745: return (KERN_INVALID_ARGUMENT); ! 746: ! 747: thread = act_lock_thread(thr_act); ! 748: if (thread == THREAD_NULL || invalid_pri(priority)) { ! 749: act_unlock_thread(thr_act); ! 750: return (KERN_INVALID_ARGUMENT); ! 751: } ! 752: ! 753: result = thread_priority_locked(thread, priority, set_max); ! 754: act_unlock_thread(thr_act); ! 755: ! 756: return (result); ! 757: } ! 758: ! 759: /* ! 760: * thread_priority_locked: ! 761: * ! 762: * Kernel-internal work function for thread_priority(). Called ! 763: * with thread "properly locked" to ensure synchrony with RPC ! 764: * (see act_lock_thread()). ! 765: */ ! 766: kern_return_t ! 767: thread_priority_locked( ! 768: thread_t thread, ! 769: int priority, ! 770: boolean_t set_max) ! 771: { ! 772: kern_return_t result = KERN_SUCCESS; ! 773: mk_sp_info_t sched_info; ! 774: spl_t s; ! 775: ! 776: s = splsched(); ! 777: thread_lock(thread); ! 778: ! 779: /* get pointer to scheduling policy-specific data */ ! 780: assert(thread->sp_info != SP_INFO_NULL); ! 781: sched_info = (mk_sp_info_t)thread->sp_info; ! 782: ! 783: /* ! 784: * Check for violation of max priority ! 785: */ ! 786: if (priority > sched_info->max_priority) ! 787: result = KERN_FAILURE; ! 788: else { ! 789: /* ! 790: * Set priorities. If a depression is in progress, ! 791: * change the priority to restore. ! 792: */ ! 793: if (sched_info->depress_priority >= 0) { ! 794: sched_info->depress_priority = priority; ! 795: } ! 796: else { ! 797: sched_info->priority = priority; ! 798: compute_priority(thread, TRUE); ! 799: ! 800: /* ! 801: * If the current thread has changed its ! 802: * priority let the ast code decide whether ! 803: * a different thread should run. ! 804: */ ! 805: if (thread == current_thread()) ! 806: ast_on(AST_BLOCK); ! 807: } ! 808: ! 809: if (set_max) ! 810: sched_info->max_priority = priority; ! 811: } ! 812: ! 813: thread_unlock(thread); ! 814: splx(s); ! 815: ! 816: return(result); ! 817: } ! 818: ! 819: /* ! 820: * thread_set_own_priority: ! 821: * ! 822: * Internal use only; sets the priority of the calling thread. ! 823: * Will adjust max_priority if necessary. ! 824: */ ! 825: void ! 826: thread_set_own_priority( ! 827: int priority) ! 828: { ! 829: thread_t thread = current_thread(); ! 830: mk_sp_info_t sched_info; ! 831: spl_t s; ! 832: ! 833: s = splsched(); ! 834: thread_lock(thread); ! 835: ! 836: /* get pointer to scheduling policy-specific data */ ! 837: assert(thread->sp_info != SP_INFO_NULL); ! 838: sched_info = (mk_sp_info_t)thread->sp_info; ! 839: ! 840: if (priority > sched_info->max_priority) ! 841: sched_info->max_priority = priority; ! 842: sched_info->priority = priority; ! 843: compute_priority(thread, TRUE); ! 844: ! 845: thread_unlock(thread); ! 846: splx(s); ! 847: } ! 848: ! 849: /* ! 850: * thread_max_priority: ! 851: * ! 852: * Reset the max priority for a thread. ! 853: */ ! 854: kern_return_t ! 855: thread_max_priority( ! 856: thread_act_t thr_act, ! 857: processor_set_t pset, ! 858: int max_priority) ! 859: { ! 860: thread_t thread; ! 861: kern_return_t result = KERN_SUCCESS; ! 862: ! 863: if (thr_act == THR_ACT_NULL) ! 864: return(KERN_INVALID_ARGUMENT); ! 865: ! 866: thread = act_lock_thread(thr_act); ! 867: if (thread == THREAD_NULL || pset == PROCESSOR_SET_NULL || ! 868: invalid_pri(max_priority)) { ! 869: act_unlock_thread(thr_act); ! 870: return(KERN_INVALID_ARGUMENT); ! 871: } ! 872: ! 873: result = thread_max_priority_locked(thread, pset, max_priority); ! 874: act_unlock_thread(thr_act); ! 875: ! 876: return (result); ! 877: } ! 878: ! 879: /* ! 880: * thread_max_priority_locked: ! 881: * ! 882: * Work function for thread_max_priority. ! 883: * ! 884: * Called with all RPC-related locks held for thread (see ! 885: * act_lock_thread()). ! 886: */ ! 887: kern_return_t ! 888: thread_max_priority_locked( ! 889: thread_t thread, ! 890: processor_set_t pset, ! 891: int max_priority) ! 892: { ! 893: kern_return_t result = KERN_SUCCESS; ! 894: mk_sp_info_t sched_info; ! 895: spl_t s; ! 896: ! 897: s = splsched(); ! 898: thread_lock(thread); ! 899: ! 900: /* get pointer to scheduling policy-specific data */ ! 901: assert(thread->sp_info != SP_INFO_NULL); ! 902: sched_info = (mk_sp_info_t)thread->sp_info; ! 903: ! 904: #if MACH_HOST ! 905: /* ! 906: * Check for wrong processor set. ! 907: */ ! 908: if (pset != thread->processor_set) ! 909: result = KERN_FAILURE; ! 910: else { ! 911: #endif /* MACH_HOST */ ! 912: sched_info->max_priority = max_priority; ! 913: ! 914: /* ! 915: * Reset priority if it violates new max priority ! 916: */ ! 917: if (max_priority < sched_info->priority) { ! 918: sched_info->priority = max_priority; ! 919: ! 920: compute_priority(thread, TRUE); ! 921: } ! 922: else if (sched_info->depress_priority >= 0 && ! 923: max_priority < sched_info->depress_priority) ! 924: sched_info->depress_priority = max_priority; ! 925: #if MACH_HOST ! 926: } ! 927: #endif /* MACH_HOST */ ! 928: ! 929: thread_unlock(thread); ! 930: splx(s); ! 931: ! 932: return(result); ! 933: } ! 934: ! 935: /* ! 936: * thread_policy_common: ! 937: * ! 938: * Set scheduling policy for thread. If pset == PROCESSOR_SET_NULL, ! 939: * policy will be checked to make sure it is enabled. ! 940: */ ! 941: kern_return_t ! 942: thread_policy_common( ! 943: thread_t thread, ! 944: int policy, ! 945: int data, ! 946: processor_set_t pset) ! 947: { ! 948: kern_return_t result = KERN_SUCCESS; ! 949: mk_sp_info_t sched_info; ! 950: register int temp; ! 951: spl_t s; ! 952: ! 953: if (thread == THREAD_NULL || invalid_policy(policy)) ! 954: return(KERN_INVALID_ARGUMENT); ! 955: ! 956: s = splsched(); ! 957: thread_lock(thread); ! 958: ! 959: /* get pointer to scheduling policy-specific data */ ! 960: assert(thread->sp_info != SP_INFO_NULL); ! 961: sched_info = (mk_sp_info_t)thread->sp_info; ! 962: ! 963: /* ! 964: * Check if changing policy. ! 965: */ ! 966: if (policy == thread->policy) { ! 967: /* ! 968: * Just changing data. This is meaningless for ! 969: * timeshareing, quantum for fixed priority (but ! 970: * has no effect until current quantum runs out). ! 971: */ ! 972: if (policy == POLICY_FIFO || policy == POLICY_RR) { ! 973: temp = data * 1000; ! 974: if (temp % tick) ! 975: temp += tick; ! 976: sched_info->sched_data = temp/tick; ! 977: sched_info->unconsumed_quantum = temp/tick; ! 978: } ! 979: } ! 980: else { ! 981: /* ! 982: * Changing policy. Check if new policy is allowed. ! 983: */ ! 984: if (pset == PROCESSOR_SET_NULL && ! 985: (thread->processor_set->policies & policy) == 0) { ! 986: result = KERN_FAILURE; ! 987: } ! 988: else { ! 989: if (pset != thread->processor_set) { ! 990: result = KERN_FAILURE; ! 991: } ! 992: else { ! 993: /* ! 994: * Changing policy. Save data and calculate new ! 995: * priority. ! 996: */ ! 997: thread->policy = policy; ! 998: sched_info->policy = policy; ! 999: if (policy == POLICY_FIFO || policy == POLICY_RR) { ! 1000: temp = data * 1000; ! 1001: if (temp % tick) ! 1002: temp += tick; ! 1003: sched_info->sched_data = temp/tick; ! 1004: sched_info->unconsumed_quantum = temp/tick; ! 1005: } ! 1006: compute_priority(thread, TRUE); ! 1007: } ! 1008: } ! 1009: } ! 1010: ! 1011: thread_unlock(thread); ! 1012: splx(s); ! 1013: ! 1014: return(result); ! 1015: } ! 1016: ! 1017: /* ! 1018: * thread_set_policy ! 1019: * ! 1020: * Set scheduling policy and parameters, both base and limit, for ! 1021: * the given thread. Policy can be any policy implemented by the ! 1022: * processor set, whether enabled or not. ! 1023: */ ! 1024: kern_return_t ! 1025: thread_set_policy( ! 1026: thread_act_t thr_act, ! 1027: processor_set_t pset, ! 1028: policy_t policy, ! 1029: policy_base_t base, ! 1030: mach_msg_type_number_t base_count, ! 1031: policy_limit_t limit, ! 1032: mach_msg_type_number_t limit_count) ! 1033: { ! 1034: thread_t thread; ! 1035: int max, bas, dat; ! 1036: kern_return_t result = KERN_SUCCESS; ! 1037: ! 1038: if (thr_act == THR_ACT_NULL || pset == PROCESSOR_SET_NULL) ! 1039: return (KERN_INVALID_ARGUMENT); ! 1040: ! 1041: thread = act_lock_thread(thr_act); ! 1042: if (thread == THREAD_NULL) { ! 1043: act_unlock_thread(thr_act); ! 1044: return(KERN_INVALID_ARGUMENT); ! 1045: } ! 1046: ! 1047: if (pset != thread->processor_set) { ! 1048: act_unlock_thread(thr_act); ! 1049: return(KERN_FAILURE); ! 1050: } ! 1051: ! 1052: switch (policy) { ! 1053: case POLICY_RR: ! 1054: { ! 1055: policy_rr_base_t rr_base = (policy_rr_base_t) base; ! 1056: policy_rr_limit_t rr_limit = (policy_rr_limit_t) limit; ! 1057: ! 1058: if (base_count != POLICY_RR_BASE_COUNT || ! 1059: limit_count != POLICY_RR_LIMIT_COUNT) { ! 1060: result = KERN_INVALID_ARGUMENT; ! 1061: break; ! 1062: } ! 1063: dat = rr_base->quantum; ! 1064: bas = rr_base->base_priority; ! 1065: max = rr_limit->max_priority; ! 1066: if (invalid_pri(bas) || invalid_pri(max)) { ! 1067: result = KERN_INVALID_ARGUMENT; ! 1068: break; ! 1069: } ! 1070: break; ! 1071: } ! 1072: ! 1073: case POLICY_FIFO: ! 1074: { ! 1075: policy_fifo_base_t fifo_base = (policy_fifo_base_t) base; ! 1076: policy_fifo_limit_t fifo_limit = (policy_fifo_limit_t) limit; ! 1077: ! 1078: if (base_count != POLICY_FIFO_BASE_COUNT || ! 1079: limit_count != POLICY_FIFO_LIMIT_COUNT) { ! 1080: result = KERN_INVALID_ARGUMENT; ! 1081: break; ! 1082: } ! 1083: dat = 0; ! 1084: bas = fifo_base->base_priority; ! 1085: max = fifo_limit->max_priority; ! 1086: if (invalid_pri(bas) || invalid_pri(max)) { ! 1087: result = KERN_INVALID_ARGUMENT; ! 1088: break; ! 1089: } ! 1090: break; ! 1091: } ! 1092: ! 1093: case POLICY_TIMESHARE: ! 1094: { ! 1095: policy_timeshare_base_t ts_base = ! 1096: (policy_timeshare_base_t) base; ! 1097: policy_timeshare_limit_t ts_limit = ! 1098: (policy_timeshare_limit_t) limit; ! 1099: ! 1100: if (base_count != POLICY_TIMESHARE_BASE_COUNT || ! 1101: limit_count != POLICY_TIMESHARE_LIMIT_COUNT) { ! 1102: result = KERN_INVALID_ARGUMENT; ! 1103: break; ! 1104: } ! 1105: dat = 0; ! 1106: bas = ts_base->base_priority; ! 1107: max = ts_limit->max_priority; ! 1108: if (invalid_pri(bas) || invalid_pri(max)) { ! 1109: result = KERN_INVALID_ARGUMENT; ! 1110: break; ! 1111: } ! 1112: break; ! 1113: } ! 1114: ! 1115: default: ! 1116: result = KERN_INVALID_POLICY; ! 1117: } ! 1118: ! 1119: if (result != KERN_SUCCESS) { ! 1120: act_unlock_thread(thr_act); ! 1121: return(result); ! 1122: } ! 1123: ! 1124: /* ! 1125: * We've already checked the inputs for thread_max_priority, ! 1126: * so it's safe to ignore the return value. ! 1127: */ ! 1128: (void) thread_max_priority_locked(thread, pset, max); ! 1129: result = thread_priority_locked(thread, bas, FALSE); ! 1130: if (result == KERN_SUCCESS) ! 1131: result = thread_policy_common(thread, policy, dat, pset); ! 1132: act_unlock_thread(thr_act); ! 1133: return(result); ! 1134: } ! 1135: ! 1136: ! 1137: /* ! 1138: * thread_policy ! 1139: * ! 1140: * Set scheduling policy and parameters, both base and limit, for ! 1141: * the given thread. Policy must be a policy which is enabled for the ! 1142: * processor set. Change contained threads if requested. ! 1143: */ ! 1144: kern_return_t ! 1145: thread_policy( ! 1146: thread_act_t thr_act, ! 1147: policy_t policy, ! 1148: policy_base_t base, ! 1149: mach_msg_type_number_t count, ! 1150: boolean_t set_limit) ! 1151: { ! 1152: thread_t thread; ! 1153: processor_set_t pset; ! 1154: mk_sp_info_t sched_info; ! 1155: kern_return_t result = KERN_SUCCESS; ! 1156: policy_limit_t limit; ! 1157: policy_rr_limit_data_t rr_limit; ! 1158: policy_fifo_limit_data_t fifo_limit; ! 1159: policy_timeshare_limit_data_t ts_limit; ! 1160: int limcount; ! 1161: ! 1162: if (thr_act == THR_ACT_NULL) ! 1163: return (KERN_INVALID_ARGUMENT); ! 1164: ! 1165: thread = act_lock_thread(thr_act); ! 1166: pset = thread->processor_set; ! 1167: if (thread == THREAD_NULL || pset == PROCESSOR_SET_NULL) { ! 1168: act_unlock_thread(thr_act); ! 1169: return(KERN_INVALID_ARGUMENT); ! 1170: } ! 1171: ! 1172: if (invalid_policy(policy) || (pset->policies & policy) == 0) { ! 1173: act_unlock_thread(thr_act); ! 1174: return(KERN_INVALID_POLICY); ! 1175: } ! 1176: ! 1177: /* get pointer to scheduling policy-specific data */ ! 1178: assert(thread->sp_info != SP_INFO_NULL); ! 1179: sched_info = (mk_sp_info_t)thread->sp_info; ! 1180: ! 1181: if (set_limit) { ! 1182: /* ! 1183: * Set scheduling limits to base priority. ! 1184: */ ! 1185: switch (policy) { ! 1186: case POLICY_RR: ! 1187: { ! 1188: policy_rr_base_t rr_base; ! 1189: ! 1190: if (count != POLICY_RR_BASE_COUNT) { ! 1191: result = KERN_INVALID_ARGUMENT; ! 1192: break; ! 1193: } ! 1194: limcount = POLICY_RR_LIMIT_COUNT; ! 1195: rr_base = (policy_rr_base_t) base; ! 1196: rr_limit.max_priority = rr_base->base_priority; ! 1197: limit = (policy_limit_t) &rr_limit; ! 1198: break; ! 1199: } ! 1200: ! 1201: case POLICY_FIFO: ! 1202: { ! 1203: policy_fifo_base_t fifo_base; ! 1204: ! 1205: if (count != POLICY_FIFO_BASE_COUNT) { ! 1206: result = KERN_INVALID_ARGUMENT; ! 1207: break; ! 1208: } ! 1209: limcount = POLICY_FIFO_LIMIT_COUNT; ! 1210: fifo_base = (policy_fifo_base_t) base; ! 1211: fifo_limit.max_priority = fifo_base->base_priority; ! 1212: limit = (policy_limit_t) &fifo_limit; ! 1213: break; ! 1214: } ! 1215: ! 1216: case POLICY_TIMESHARE: ! 1217: { ! 1218: policy_timeshare_base_t ts_base; ! 1219: ! 1220: if (count != POLICY_TIMESHARE_BASE_COUNT) { ! 1221: result = KERN_INVALID_ARGUMENT; ! 1222: break; ! 1223: } ! 1224: limcount = POLICY_TIMESHARE_LIMIT_COUNT; ! 1225: ts_base = (policy_timeshare_base_t) base; ! 1226: ts_limit.max_priority = ts_base->base_priority; ! 1227: limit = (policy_limit_t) &ts_limit; ! 1228: break; ! 1229: } ! 1230: ! 1231: default: ! 1232: result = KERN_INVALID_POLICY; ! 1233: break; ! 1234: } ! 1235: ! 1236: } else { ! 1237: /* ! 1238: * Use current scheduling limits. Ensure that the ! 1239: * new base priority will not exceed current limits. ! 1240: */ ! 1241: switch (policy) { ! 1242: case POLICY_RR: ! 1243: { ! 1244: policy_rr_base_t rr_base; ! 1245: ! 1246: if (count != POLICY_RR_BASE_COUNT) { ! 1247: result = KERN_INVALID_ARGUMENT; ! 1248: break; ! 1249: } ! 1250: limcount = POLICY_RR_LIMIT_COUNT; ! 1251: rr_base = (policy_rr_base_t) base; ! 1252: if (rr_base->base_priority > ! 1253: sched_info->max_priority) { ! 1254: result = KERN_POLICY_LIMIT; ! 1255: break; ! 1256: } ! 1257: rr_limit.max_priority = sched_info->max_priority; ! 1258: limit = (policy_limit_t) &rr_limit; ! 1259: break; ! 1260: } ! 1261: ! 1262: case POLICY_FIFO: ! 1263: { ! 1264: policy_fifo_base_t fifo_base; ! 1265: ! 1266: if (count != POLICY_FIFO_BASE_COUNT) { ! 1267: result = KERN_INVALID_ARGUMENT; ! 1268: break; ! 1269: } ! 1270: limcount = POLICY_FIFO_LIMIT_COUNT; ! 1271: fifo_base = (policy_fifo_base_t) base; ! 1272: if (fifo_base->base_priority > ! 1273: sched_info->max_priority) { ! 1274: result = KERN_POLICY_LIMIT; ! 1275: break; ! 1276: } ! 1277: fifo_limit.max_priority = sched_info->max_priority; ! 1278: limit = (policy_limit_t) &fifo_limit; ! 1279: break; ! 1280: } ! 1281: ! 1282: case POLICY_TIMESHARE: ! 1283: { ! 1284: policy_timeshare_base_t ts_base; ! 1285: ! 1286: if (count != POLICY_TIMESHARE_BASE_COUNT) { ! 1287: result = KERN_INVALID_ARGUMENT; ! 1288: break; ! 1289: } ! 1290: limcount = POLICY_TIMESHARE_LIMIT_COUNT; ! 1291: ts_base = (policy_timeshare_base_t) base; ! 1292: if (ts_base->base_priority > ! 1293: sched_info->max_priority) { ! 1294: result = KERN_POLICY_LIMIT; ! 1295: break; ! 1296: } ! 1297: ts_limit.max_priority = sched_info->max_priority; ! 1298: limit = (policy_limit_t) &ts_limit; ! 1299: break; ! 1300: } ! 1301: ! 1302: default: ! 1303: result = KERN_INVALID_POLICY; ! 1304: break; ! 1305: } ! 1306: ! 1307: } ! 1308: ! 1309: act_unlock_thread(thr_act); ! 1310: ! 1311: if (result == KERN_SUCCESS) ! 1312: result = thread_set_policy(thr_act, pset, ! 1313: policy, base, count, limit, limcount); ! 1314: ! 1315: return(result); ! 1316: } ! 1317: ! 1318: ! 1319: /* ! 1320: * Define shifts for simulating (5/8)**n ! 1321: */ ! 1322: ! 1323: shift_data_t wait_shift[32] = { ! 1324: {1,1},{1,3},{1,-3},{2,-7},{3,5},{3,-5},{4,-8},{5,7}, ! 1325: {5,-7},{6,-10},{7,10},{7,-9},{8,-11},{9,12},{9,-11},{10,-13}, ! 1326: {11,14},{11,-13},{12,-15},{13,17},{13,-15},{14,-17},{15,19},{16,18}, ! 1327: {16,-19},{17,22},{18,20},{18,-20},{19,26},{20,22},{20,-22},{21,-27}}; ! 1328: ! 1329: /* ! 1330: * do_priority_computation: ! 1331: * ! 1332: * Calculate new priority for thread based on its base priority plus ! 1333: * accumulated usage. PRI_SHIFT and PRI_SHIFT_2 convert from ! 1334: * usage to priorities. SCHED_SHIFT converts for the scaling ! 1335: * of the sched_usage field by SCHED_SCALE. This scaling comes ! 1336: * from the multiplication by sched_load (thread_timer_delta) ! 1337: * in sched.h. sched_load is calculated as a scaled overload ! 1338: * factor in compute_mach_factor (mach_factor.c). ! 1339: */ ! 1340: #ifdef PRI_SHIFT_2 ! 1341: #if PRI_SHIFT_2 > 0 ! 1342: #define do_priority_computation(sp_info, pri) \ ! 1343: MACRO_BEGIN \ ! 1344: (pri) = (sp_info)->priority /* start with base priority */ \ ! 1345: - ((sp_info)->sched_usage >> (PRI_SHIFT + SCHED_SHIFT)) \ ! 1346: - ((sp_info)->sched_usage >> (PRI_SHIFT_2 + SCHED_SHIFT)); \ ! 1347: if ((pri) < lpri) (pri) = lpri; \ ! 1348: (pri) = convert_pri[(pri)]; \ ! 1349: MACRO_END ! 1350: #else /* PRI_SHIFT_2 */ ! 1351: #define do_priority_computation(sp_info, pri) \ ! 1352: MACRO_BEGIN \ ! 1353: (pri) = (sp_info)->priority /* start with base priority */ \ ! 1354: - ((sp_info)->sched_usage >> (PRI_SHIFT + SCHED_SHIFT)) \ ! 1355: + ((sp_info)->sched_usage >> (SCHED_SHIFT - PRI_SHIFT_2)); \ ! 1356: if ((pri) < lpri) (pri) = lpri; \ ! 1357: (pri) = convert_pri[(pri)]; \ ! 1358: MACRO_END ! 1359: #endif /* PRI_SHIFT_2 */ ! 1360: #else /* defined(PRI_SHIFT_2) */ ! 1361: #define do_priority_computation(sp_info, pri) \ ! 1362: MACRO_BEGIN \ ! 1363: (pri) = (sp_info)->priority /* start with base priority */ \ ! 1364: - ((sp_info)->sched_usage >> (PRI_SHIFT + SCHED_SHIFT)); \ ! 1365: if ((pri) < lpri) (pri) = lpri; \ ! 1366: (pri) = convert_pri[(pri)]; \ ! 1367: MACRO_END ! 1368: #endif /* defined(PRI_SHIFT_2) */ ! 1369: ! 1370: /* ! 1371: * compute_priority: ! 1372: * ! 1373: * Compute the effective priority of the specified thread. ! 1374: * The effective priority computation is as follows: ! 1375: * ! 1376: * Take the base priority for this thread and add ! 1377: * to it an increment derived from its cpu_usage. ! 1378: * ! 1379: * The thread *must* be locked by the caller. ! 1380: */ ! 1381: ! 1382: void ! 1383: compute_priority( ! 1384: register thread_t thread, ! 1385: boolean_t resched) ! 1386: { ! 1387: mk_sp_info_t sp_info = (mk_sp_info_t)thread->sp_info; ! 1388: register int pri; ! 1389: ! 1390: /* make sure policy-specific data are present */ ! 1391: assert(sp_info != SP_INFO_NULL); ! 1392: ! 1393: if (thread->policy == POLICY_TIMESHARE) { ! 1394: do_priority_computation(sp_info, pri); ! 1395: if (sp_info->depress_priority < 0) ! 1396: set_pri(thread, pri, resched); ! 1397: else ! 1398: sp_info->depress_priority = pri; ! 1399: } ! 1400: else ! 1401: set_pri(thread, sp_info->priority, resched); ! 1402: } ! 1403: ! 1404: /* ! 1405: * compute_my_priority: ! 1406: * ! 1407: * Version of compute priority for current thread or thread ! 1408: * being manipulated by scheduler (going on or off a runq). ! 1409: * Only used for priority updates. Policy or priority changes ! 1410: * must call compute_priority above. Caller must have thread ! 1411: * locked and know it is timesharing and not depressed. ! 1412: */ ! 1413: ! 1414: void ! 1415: compute_my_priority( ! 1416: register thread_t thread) ! 1417: { ! 1418: mk_sp_info_t sp_info = (mk_sp_info_t)thread->sp_info; ! 1419: register int temp_pri; ! 1420: ! 1421: /* make sure policy-specific data are present */ ! 1422: assert(thread->sp_info != SP_INFO_NULL); ! 1423: ! 1424: do_priority_computation(sp_info,temp_pri); ! 1425: assert(thread->runq == RUN_QUEUE_NULL); ! 1426: thread->sched_pri = temp_pri; ! 1427: } ! 1428: ! 1429: struct mk_sp_usage { ! 1430: natural_t cpu_delta, sched_delta; ! 1431: natural_t sched_tick, ticks; ! 1432: natural_t cpu_usage, sched_usage, ! 1433: aged_cpu, aged_sched; ! 1434: thread_t thread; ! 1435: } idled_info, loaded_info; ! 1436: ! 1437: /* ! 1438: * update_priority ! 1439: * ! 1440: * Cause the priority computation of a thread that has been ! 1441: * sleeping or suspended to "catch up" with the system. Thread ! 1442: * *MUST* be locked by caller. If thread is running, then this ! 1443: * can only be called by the thread on itself. ! 1444: */ ! 1445: void ! 1446: update_priority( ! 1447: register thread_t thread) ! 1448: { ! 1449: mk_sp_info_t sp_info = (mk_sp_info_t)thread->sp_info; ! 1450: register unsigned int ticks; ! 1451: register shift_t shiftp; ! 1452: ! 1453: /* make sure policy-specific data are present */ ! 1454: assert(sp_info != SP_INFO_NULL); ! 1455: ! 1456: ticks = sched_tick - sp_info->sched_stamp; ! 1457: assert(ticks != 0); ! 1458: ! 1459: /* ! 1460: * If asleep for more than 30 seconds forget all ! 1461: * cpu_usage, else catch up on missed aging. ! 1462: * 5/8 ** n is approximated by the two shifts ! 1463: * in the wait_shift array. ! 1464: */ ! 1465: sp_info->sched_stamp += ticks; ! 1466: thread_timer_delta(thread); ! 1467: if (ticks > 30) { ! 1468: sp_info->cpu_usage = 0; ! 1469: sp_info->sched_usage = 0; ! 1470: } ! 1471: else { ! 1472: struct mk_sp_usage *sp_usage; ! 1473: ! 1474: sp_info->cpu_usage += thread->cpu_delta; ! 1475: sp_info->sched_usage += thread->sched_delta; ! 1476: ! 1477: if (thread->state & TH_IDLE) ! 1478: sp_usage = &idled_info; ! 1479: else ! 1480: if (thread == loaded_info.thread) ! 1481: sp_usage = &loaded_info; ! 1482: else ! 1483: sp_usage = NULL; ! 1484: ! 1485: if (sp_usage != NULL) { ! 1486: sp_usage->cpu_delta = thread->cpu_delta; ! 1487: sp_usage->sched_delta = thread->sched_delta; ! 1488: sp_usage->sched_tick = sp_info->sched_stamp; ! 1489: sp_usage->ticks = ticks; ! 1490: sp_usage->cpu_usage = sp_info->cpu_usage; ! 1491: sp_usage->sched_usage = sp_info->sched_usage; ! 1492: sp_usage->thread = thread; ! 1493: } ! 1494: ! 1495: shiftp = &wait_shift[ticks]; ! 1496: if (shiftp->shift2 > 0) { ! 1497: sp_info->cpu_usage = ! 1498: (sp_info->cpu_usage >> shiftp->shift1) + ! 1499: (sp_info->cpu_usage >> shiftp->shift2); ! 1500: sp_info->sched_usage = ! 1501: (sp_info->sched_usage >> shiftp->shift1) + ! 1502: (sp_info->sched_usage >> shiftp->shift2); ! 1503: } ! 1504: else { ! 1505: sp_info->cpu_usage = ! 1506: (sp_info->cpu_usage >> shiftp->shift1) - ! 1507: (sp_info->cpu_usage >> -(shiftp->shift2)); ! 1508: sp_info->sched_usage = ! 1509: (sp_info->sched_usage >> shiftp->shift1) - ! 1510: (sp_info->sched_usage >> -(shiftp->shift2)); ! 1511: } ! 1512: ! 1513: if (sp_usage != NULL) { ! 1514: sp_usage->aged_cpu = sp_info->cpu_usage; ! 1515: sp_usage->aged_sched = sp_info->sched_usage; ! 1516: } ! 1517: } ! 1518: thread->cpu_delta = 0; ! 1519: thread->sched_delta = 0; ! 1520: ! 1521: /* ! 1522: * Recompute priority if appropriate. ! 1523: */ ! 1524: if ( thread->policy == POLICY_TIMESHARE && ! 1525: sp_info->depress_priority < 0 ) { ! 1526: register int new_pri; ! 1527: run_queue_t runq; ! 1528: ! 1529: do_priority_computation(sp_info, new_pri); ! 1530: runq = rem_runq(thread); ! 1531: thread->sched_pri = new_pri; ! 1532: if (runq != RUN_QUEUE_NULL) ! 1533: thread_setrun(thread, TRUE, TAIL_Q); ! 1534: } ! 1535: } ! 1536: ! 1537: /* ! 1538: * `mk_sp_swtch_pri()' attempts to context switch (logic in ! 1539: * thread_block no-ops the context switch if nothing would happen). ! 1540: * A boolean is returned that indicates whether there is anything ! 1541: * else runnable. ! 1542: * ! 1543: * This boolean can be used by a thread waiting on a ! 1544: * lock or condition: If FALSE is returned, the thread is justified ! 1545: * in becoming a resource hog by continuing to spin because there's ! 1546: * nothing else useful that the processor could do. If TRUE is ! 1547: * returned, the thread should make one more check on the ! 1548: * lock and then be a good citizen and really suspend. ! 1549: */ ! 1550: ! 1551: void ! 1552: _mk_sp_swtch_pri( ! 1553: sf_object_t policy, ! 1554: int pri) ! 1555: { ! 1556: register thread_t self = current_thread(); ! 1557: ! 1558: #ifdef lint ! 1559: pri++; ! 1560: #endif /* lint */ ! 1561: ! 1562: counter(c_mk_sp_swtch_pri++); ! 1563: /* ! 1564: * XXX need to think about depression duration. ! 1565: * XXX currently using min quantum. ! 1566: */ ! 1567: _mk_sp_thread_depress_priority(policy, min_quantum_ms); ! 1568: ! 1569: counter(c_swtch_pri_block++); ! 1570: thread_block((void (*)(void)) 0); ! 1571: ! 1572: _mk_sp_thread_depress_abort(policy, self); ! 1573: } ! 1574: ! 1575: /* ! 1576: * thread_switch: ! 1577: * ! 1578: * Context switch. User may supply thread hint. ! 1579: * ! 1580: * Fixed priority threads that call this get what they asked for ! 1581: * even if that violates priority order. ! 1582: */ ! 1583: kern_return_t ! 1584: _mk_sp_thread_switch( ! 1585: sf_object_t policy, ! 1586: thread_act_t hint_act, ! 1587: int option, ! 1588: mach_msg_timeout_t option_time) ! 1589: { ! 1590: register thread_t self = current_thread(); ! 1591: register processor_t myprocessor; ! 1592: mk_sp_info_t sp_info; ! 1593: int s; ! 1594: ! 1595: counter(c_mk_sp_thread_switch++); ! 1596: ! 1597: /* ! 1598: * Process option. ! 1599: */ ! 1600: switch (option) { ! 1601: ! 1602: case SWITCH_OPTION_NONE: ! 1603: /* ! 1604: * Nothing to do. ! 1605: */ ! 1606: break; ! 1607: ! 1608: case SWITCH_OPTION_DEPRESS: ! 1609: /* ! 1610: * Depress priority for a given time. ! 1611: */ ! 1612: _mk_sp_thread_depress_priority(policy, option_time); ! 1613: break; ! 1614: ! 1615: case SWITCH_OPTION_WAIT: ! 1616: assert_wait_timeout(option_time, THREAD_ABORTSAFE); ! 1617: break; ! 1618: ! 1619: default: ! 1620: return (KERN_INVALID_ARGUMENT); ! 1621: } ! 1622: ! 1623: /* ! 1624: * Check and use thr_act hint if appropriate. It is not ! 1625: * appropriate to give a hint that shares the current shuttle. ! 1626: * ! 1627: * JMM - Is it really appropriate to give a hint that isn't ! 1628: * the top activation for a thread? ! 1629: */ ! 1630: if (hint_act->thread != self) { ! 1631: register thread_t thread = hint_act->thread; ! 1632: ! 1633: /* ! 1634: * Check if the thread is in the right pset. Then ! 1635: * pull it off its run queue. If it ! 1636: * doesn't come, then it's not eligible. ! 1637: */ ! 1638: if (thread) { ! 1639: s = splsched(); ! 1640: thread_lock(thread); ! 1641: ! 1642: if ( thread->processor_set == self->processor_set && ! 1643: rem_runq(thread) != RUN_QUEUE_NULL ) { ! 1644: /* ! 1645: * Hah, got it!! ! 1646: */ ! 1647: if (thread->policy & (POLICY_FIFO|POLICY_RR)) { ! 1648: myprocessor = current_processor(); ! 1649: ! 1650: assert(thread->sp_info != SP_INFO_NULL); ! 1651: sp_info = (mk_sp_info_t)thread->sp_info; ! 1652: ! 1653: myprocessor->quantum = sp_info->unconsumed_quantum; ! 1654: myprocessor->first_quantum = TRUE; ! 1655: } ! 1656: thread_unlock(thread); ! 1657: splx(s); ! 1658: act_unlock_thread(hint_act); ! 1659: ! 1660: counter(c_thread_switch_handoff++); ! 1661: thread_run((void(*)(void)) 0, thread); ! 1662: ! 1663: goto out; ! 1664: } ! 1665: ! 1666: thread_unlock(thread); ! 1667: splx(s); ! 1668: } ! 1669: ! 1670: act_unlock_thread(hint_act); ! 1671: } ! 1672: ! 1673: /* ! 1674: * No handoff hint supplied, or hint was wrong. Call thread_block() in ! 1675: * hopes of running something else. If nothing else is runnable, ! 1676: * thread_block will detect this. WARNING: thread_switch with no ! 1677: * option will not do anything useful if the thread calling it is the ! 1678: * highest priority thread (can easily happen with a collection ! 1679: * of timesharing threads). ! 1680: */ ! 1681: mp_disable_preemption(); ! 1682: myprocessor = current_processor(); ! 1683: if ( option != SWITCH_OPTION_NONE || ! 1684: myprocessor->processor_set->runq.count > 0 || ! 1685: myprocessor->runq.count > 0 ) { ! 1686: myprocessor->first_quantum = FALSE; ! 1687: mp_enable_preemption(); ! 1688: ! 1689: counter(c_thread_switch_block++); ! 1690: thread_block((void (*)(void)) 0); ! 1691: } ! 1692: else ! 1693: mp_enable_preemption(); ! 1694: ! 1695: out: ! 1696: if (option == SWITCH_OPTION_WAIT) ! 1697: thread_cancel_timer(); ! 1698: else if (option == SWITCH_OPTION_DEPRESS) ! 1699: _mk_sp_thread_depress_abort(policy, self); ! 1700: ! 1701: return (KERN_SUCCESS); ! 1702: } ! 1703: ! 1704: /* ! 1705: * mk_sp_thread_depress_priority ! 1706: * ! 1707: * Depress thread's priority to lowest possible for specified period. ! 1708: * Intended for use when thread wants a lock but doesn't know which ! 1709: * other thread is holding it. As with thread_switch, fixed ! 1710: * priority threads get exactly what they asked for. Users access ! 1711: * this by the SWITCH_OPTION_DEPRESS option to thread_switch. A Time ! 1712: * of zero will result in no timeout being scheduled. ! 1713: */ ! 1714: void ! 1715: _mk_sp_thread_depress_priority( ! 1716: sf_object_t policy, ! 1717: mach_msg_timeout_t interval) ! 1718: { ! 1719: register thread_t self = current_thread(); ! 1720: mk_sp_info_t sp_info; ! 1721: AbsoluteTime deadline; ! 1722: boolean_t release = FALSE; ! 1723: spl_t s; ! 1724: ! 1725: s = splsched(); ! 1726: thread_lock(self); ! 1727: ! 1728: if (self->policy == policy->policy_id) { ! 1729: /* get pointer to scheduling policy-specific data */ ! 1730: assert(self->sp_info != SP_INFO_NULL); ! 1731: sp_info = (mk_sp_info_t)self->sp_info; ! 1732: ! 1733: /* ! 1734: * If we haven't already saved the priority to be restored ! 1735: * (depress_priority), then save it. ! 1736: */ ! 1737: if (sp_info->depress_priority < 0) ! 1738: sp_info->depress_priority = sp_info->priority; ! 1739: else if (thread_call_cancel(&self->depress_timer)) ! 1740: release = TRUE; ! 1741: ! 1742: self->sched_pri = sp_info->priority = DEPRESSPRI; ! 1743: ! 1744: if (interval != 0) { ! 1745: clock_interval_to_deadline( ! 1746: interval, 1000*NSEC_PER_USEC, &deadline); ! 1747: thread_call_enter_delayed(&self->depress_timer, deadline); ! 1748: if (!release) ! 1749: self->ref_count++; ! 1750: else ! 1751: release = FALSE; ! 1752: } ! 1753: } ! 1754: ! 1755: thread_unlock(self); ! 1756: splx(s); ! 1757: ! 1758: if (release) ! 1759: thread_deallocate(self); ! 1760: } ! 1761: ! 1762: /* ! 1763: * mk_sp_thread_depress_timeout: ! 1764: * ! 1765: * Timeout routine for priority depression. ! 1766: */ ! 1767: void ! 1768: _mk_sp_thread_depress_timeout( ! 1769: sf_object_t policy, ! 1770: register thread_t thread) ! 1771: { ! 1772: mk_sp_info_t sp_info; ! 1773: spl_t s; ! 1774: ! 1775: counter(c_mk_sp_thread_depress_timeout++); ! 1776: ! 1777: s = splsched(); ! 1778: thread_lock(thread); ! 1779: if (thread->policy == policy->policy_id) { ! 1780: /* get pointer to scheduling policy-specific data */ ! 1781: assert(thread->sp_info != SP_INFO_NULL); ! 1782: sp_info = (mk_sp_info_t)thread->sp_info; ! 1783: ! 1784: /* ! 1785: * If we lose a race with mk_sp_thread_depress_abort, ! 1786: * then depress_priority might be -1. ! 1787: */ ! 1788: if ( sp_info->depress_priority >= 0 && ! 1789: !thread_call_is_delayed(&thread->depress_timer, NULL) ) { ! 1790: sp_info->priority = sp_info->depress_priority; ! 1791: sp_info->depress_priority = -1; ! 1792: compute_priority(thread, FALSE); ! 1793: } ! 1794: else ! 1795: if (sp_info->depress_priority == -2) { ! 1796: /* ! 1797: * Thread was temporarily undepressed by thread_suspend, to ! 1798: * be redepressed in special_handler as it blocks. We need to ! 1799: * prevent special_handler from redepressing it, since depression ! 1800: * has timed out: ! 1801: */ ! 1802: sp_info->depress_priority = -1; ! 1803: } ! 1804: } ! 1805: thread_unlock(thread); ! 1806: splx(s); ! 1807: } ! 1808: ! 1809: /* ! 1810: * mk_sp_thread_depress_abort: ! 1811: * ! 1812: * Prematurely abort priority depression if there is one. ! 1813: */ ! 1814: kern_return_t ! 1815: _mk_sp_thread_depress_abort( ! 1816: sf_object_t policy, ! 1817: register thread_t thread) ! 1818: { ! 1819: mk_sp_info_t sp_info; ! 1820: kern_return_t result = KERN_SUCCESS; ! 1821: boolean_t release = FALSE; ! 1822: spl_t s; ! 1823: ! 1824: s = splsched(); ! 1825: thread_lock(thread); ! 1826: ! 1827: if (thread->policy == policy->policy_id) { ! 1828: /* get pointer to scheduling policy-specific data */ ! 1829: assert(thread->sp_info != SP_INFO_NULL); ! 1830: sp_info = (mk_sp_info_t)thread->sp_info; ! 1831: ! 1832: if (sp_info->depress_priority >= 0) { ! 1833: if (thread_call_cancel(&thread->depress_timer)) ! 1834: release = TRUE; ! 1835: sp_info->priority = sp_info->depress_priority; ! 1836: sp_info->depress_priority = -1; ! 1837: compute_priority(thread, FALSE); ! 1838: } ! 1839: else ! 1840: result = KERN_NOT_DEPRESSED; ! 1841: } ! 1842: ! 1843: thread_unlock(thread); ! 1844: splx(s); ! 1845: ! 1846: if (release) ! 1847: thread_deallocate(thread); ! 1848: ! 1849: return (result); ! 1850: } ! 1851: ! 1852: /* ! 1853: * mk_sp_thread_runnable: ! 1854: * ! 1855: * Return TRUE iff policy believes thread is runnable ! 1856: */ ! 1857: boolean_t ! 1858: _mk_sp_thread_runnable( ! 1859: sf_object_t policy, ! 1860: sched_thread_t thread) ! 1861: { ! 1862: mk_sp_info_t sp_info; ! 1863: ! 1864: counter(c_mk_sp_thread_runnable++); ! 1865: ! 1866: /* get pointer to scheduling policy-specific data */ ! 1867: assert(thread->sp_info != SP_INFO_NULL); ! 1868: sp_info = (mk_sp_info_t)thread->sp_info; ! 1869: ! 1870: counter(sp_info->c_mk_sp_thread_runnable++); ! 1871: ! 1872: return (sp_info->th_state == MK_SP_RUNNABLE); ! 1873: } ! 1874: ! 1875: sf_return_t ! 1876: _mk_sp_alarm_expired( ! 1877: sf_object_t policy, ! 1878: long alarm_seqno, ! 1879: kern_return_t result, ! 1880: int alarm_type, ! 1881: mach_timespec_t wakeup_time, ! 1882: void *alarm_data) ! 1883: { ! 1884: counter(c_mk_sp_alarm_expired++); ! 1885: ! 1886: /* this should NEVER happen */ ! 1887: assert(0); ! 1888: ! 1889: return (SF_FAILURE); ! 1890: } ! 1891: ! 1892: ! 1893: void ! 1894: _mk_sp_thread_dump( ! 1895: sched_thread_t thread) /* thread */ ! 1896: { ! 1897: mk_sp_info_t sp_info; ! 1898: int count; ! 1899: ! 1900: /* get pointer to scheduling policy-specific data */ ! 1901: assert(thread->sp_info != SP_INFO_NULL); ! 1902: sp_info = (mk_sp_info_t)thread->sp_info; ! 1903: ! 1904: /* dump the data in a pretty format */ ! 1905: printf("\nthread shuttle(0x%x):\n", thread); ! 1906: ! 1907: printf("\tpolicy: "); ! 1908: switch(thread->policy) { ! 1909: case POLICY_TIMESHARE: ! 1910: printf("POLICY_TIMESHARE\n"); ! 1911: break; ! 1912: ! 1913: case POLICY_RR: ! 1914: printf("POLICY_RR\n"); ! 1915: break; ! 1916: ! 1917: case POLICY_FIFO: ! 1918: printf("POLICY_FIFO\n"); ! 1919: break; ! 1920: ! 1921: default: ! 1922: printf("NOT an MK Standard Policy\n"); ! 1923: return; ! 1924: } ! 1925: ! 1926: printf("\tth_state: "); ! 1927: if (sp_info->th_state == 0) { ! 1928: printf("NULL"); ! 1929: } ! 1930: else { ! 1931: count = 0; ! 1932: if (sp_info->th_state & MK_SP_ATTACHED) { ! 1933: printf("MK_SP_ATTACHED "); ! 1934: count++; ! 1935: } ! 1936: if (sp_info->th_state & MK_SP_RUNNABLE) { ! 1937: if (count > 0) printf(" | "); ! 1938: printf("MK_SP_RUNNABLE "); ! 1939: count++; ! 1940: } ! 1941: if (sp_info->th_state & MK_SP_BLOCKED) { ! 1942: if (count > 0) printf(" | "); ! 1943: printf("MK_SP_BLOCKED "); ! 1944: count++; ! 1945: } ! 1946: } ! 1947: printf("\n"); ! 1948: ! 1949: printf("\tpriority: %d\n", sp_info->priority); ! 1950: printf("\tmax_priority: %d\n", sp_info->max_priority); ! 1951: printf("\tsched_data: %d\n", sp_info->sched_data); ! 1952: printf("\tdepress_priority: %d\n", sp_info->depress_priority); ! 1953: printf("\tcpu_usage: %d\n", sp_info->cpu_usage); ! 1954: printf("\tsched_usage: %d\n", sp_info->sched_usage); ! 1955: printf("\tsched_stamp: %d\n", sp_info->sched_stamp); ! 1956: printf("\tunconsumed_quantum: %d\n", sp_info->unconsumed_quantum); ! 1957: printf("\tsched_pri: %d\n", thread->sched_pri); ! 1958: ! 1959: #ifdef MACH_ASSERT ! 1960: printf("\tc_mk_sp_thread_attach: %d\n", ! 1961: sp_info->c_mk_sp_thread_attach); ! 1962: printf("\tc_mk_sp_thread_detach: %d\n", ! 1963: sp_info->c_mk_sp_thread_detach); ! 1964: printf("\tc_mk_sp_thread_begin: %d\n", ! 1965: sp_info->c_mk_sp_thread_begin); ! 1966: printf("\tc_mk_sp_thread_done: %d\n", ! 1967: sp_info->c_mk_sp_thread_done); ! 1968: printf("\tc_mk_sp_thread_dispatch: %d\n", ! 1969: sp_info->c_mk_sp_thread_dispatch); ! 1970: printf("\tc_mk_sp_thread_unblock: %d\n", ! 1971: sp_info->c_mk_sp_thread_unblock); ! 1972: printf("\tc_mk_sp_thread_set: %d\n", ! 1973: sp_info->c_mk_sp_thread_set); ! 1974: printf("\tc_mk_sp_thread_get: %d\n", ! 1975: sp_info->c_mk_sp_thread_get); ! 1976: #endif /* MACH_ASSERT */ ! 1977: ! 1978: return; ! 1979: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.