|
|
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: * Mach Operating System ! 27: * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University ! 28: * All Rights Reserved. ! 29: * ! 30: * Permission to use, copy, modify and distribute this software and its ! 31: * documentation is hereby granted, provided that both the copyright ! 32: * notice and this permission notice appear in all copies of the ! 33: * software, derivative works or modified versions, and any portions ! 34: * thereof, and that both notices appear in supporting documentation. ! 35: * ! 36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 39: * ! 40: * Carnegie Mellon requests users of this software to return to ! 41: * ! 42: * Software Distribution Coordinator or [email protected] ! 43: * School of Computer Science ! 44: * Carnegie Mellon University ! 45: * Pittsburgh PA 15213-3890 ! 46: * ! 47: * any improvements or extensions that they make and grant Carnegie Mellon ! 48: * the rights to redistribute these changes. ! 49: */ ! 50: /* ! 51: */ ! 52: ! 53: /* ! 54: * processor.c: processor and processor_set manipulation routines. ! 55: */ ! 56: ! 57: #include <cpus.h> ! 58: #include <mach_host.h> ! 59: ! 60: #include <mach/boolean.h> ! 61: #include <mach/policy.h> ! 62: #include <mach/processor_info.h> ! 63: #include <mach/vm_param.h> ! 64: #include <kern/cpu_number.h> ! 65: #include <kern/host.h> ! 66: #include <kern/machine.h> ! 67: #include <kern/misc_protos.h> ! 68: #include <kern/processor.h> ! 69: #include <kern/sched.h> ! 70: #include <kern/task.h> ! 71: #include <kern/thread.h> ! 72: #include <kern/ipc_host.h> ! 73: #include <kern/ipc_tt.h> ! 74: #include <ipc/ipc_port.h> ! 75: #include <kern/kalloc.h> ! 76: #include <kern/rtmalloc.h> ! 77: ! 78: #if MACH_HOST ! 79: #include <kern/zalloc.h> ! 80: zone_t pset_zone; ! 81: #endif /* MACH_HOST */ ! 82: ! 83: #include <kern/sf.h> ! 84: #include <kern/mk_sp.h> /*** ??? fix so this can be removed ***/ ! 85: ! 86: /* ! 87: * Exported interface ! 88: */ ! 89: #include <mach/mach_host_server.h> ! 90: ! 91: /* ! 92: * Exported variables. ! 93: */ ! 94: struct processor_set default_pset; ! 95: struct processor processor_array[NCPUS]; ! 96: ! 97: queue_head_t all_psets; ! 98: int all_psets_count; ! 99: decl_mutex_data(, all_psets_lock) ! 100: ! 101: processor_t master_processor; ! 102: processor_t processor_ptr[NCPUS]; ! 103: ! 104: /* Forwards */ ! 105: void pset_init( ! 106: processor_set_t pset); ! 107: ! 108: void processor_init( ! 109: register processor_t pr, ! 110: int slot_num); ! 111: ! 112: void quantum_set( ! 113: processor_set_t pset); ! 114: ! 115: kern_return_t processor_set_base( ! 116: processor_set_t pset, ! 117: policy_t policy, ! 118: policy_base_t base, ! 119: boolean_t change); ! 120: ! 121: kern_return_t processor_set_limit( ! 122: processor_set_t pset, ! 123: policy_t policy, ! 124: policy_limit_t limit, ! 125: boolean_t change); ! 126: ! 127: kern_return_t processor_set_things( ! 128: processor_set_t pset, ! 129: mach_port_t **thing_list, ! 130: mach_msg_type_number_t *count, ! 131: int type); ! 132: ! 133: ! 134: /* ! 135: * Bootstrap the processor/pset system so the scheduler can run. ! 136: */ ! 137: void ! 138: pset_sys_bootstrap(void) ! 139: { ! 140: register int i; ! 141: ! 142: pset_init(&default_pset); ! 143: default_pset.empty = FALSE; ! 144: for (i = 0; i < NCPUS; i++) { ! 145: /* ! 146: * Initialize processor data structures. ! 147: * Note that cpu_to_processor(i) is processor_ptr[i]. ! 148: */ ! 149: processor_ptr[i] = &processor_array[i]; ! 150: processor_init(processor_ptr[i], i); ! 151: } ! 152: master_processor = cpu_to_processor(master_cpu); ! 153: queue_init(&all_psets); ! 154: mutex_init(&all_psets_lock, ETAP_THREAD_PSET_ALL); ! 155: queue_enter(&all_psets, &default_pset, processor_set_t, all_psets); ! 156: all_psets_count = 1; ! 157: default_pset.active = TRUE; ! 158: default_pset.empty = FALSE; ! 159: ! 160: /* ! 161: * Note: the default_pset has a max_priority of BASEPRI_USER. ! 162: * Internal kernel threads override this in kernel_thread. ! 163: */ ! 164: } ! 165: ! 166: #if MACH_HOST ! 167: /* ! 168: * Rest of pset system initializations. ! 169: */ ! 170: void ! 171: pset_sys_init(void) ! 172: { ! 173: register int i; ! 174: register processor_t processor; ! 175: ! 176: /* ! 177: * Allocate the zone for processor sets. ! 178: */ ! 179: pset_zone = zinit(sizeof(struct processor_set), 128*PAGE_SIZE, ! 180: PAGE_SIZE, "processor sets"); ! 181: ! 182: /* ! 183: * Give each processor a control port. ! 184: * The master processor already has one. ! 185: */ ! 186: for (i = 0; i < NCPUS; i++) { ! 187: processor = cpu_to_processor(i); ! 188: if (processor != master_processor && ! 189: machine_slot[i].is_cpu) ! 190: { ! 191: ipc_processor_init(processor); ! 192: ipc_processor_enable(processor); ! 193: } ! 194: } ! 195: } ! 196: #endif /* MACH_HOST */ ! 197: ! 198: /* ! 199: * Initialize the given processor_set structure. ! 200: */ ! 201: ! 202: void pset_init( ! 203: register processor_set_t pset) ! 204: { ! 205: int i; ! 206: ! 207: /* setup run-queues */ ! 208: simple_lock_init(&pset->runq.lock, ETAP_THREAD_PSET_RUNQ); ! 209: pset->runq.count = 0; ! 210: pset->runq.depress_count = 0; ! 211: for (i = 0; i < NRQBM; i++) { ! 212: pset->runq.bitmap[i] = 0; ! 213: } ! 214: setbit(MAXPRI - IDLEPRI, pset->runq.bitmap); ! 215: pset->runq.highq = IDLEPRI; ! 216: for (i = 0; i < NRQS; i++) { ! 217: queue_init(&(pset->runq.runq[i])); ! 218: } ! 219: ! 220: queue_init(&pset->idle_queue); ! 221: pset->idle_count = 0; ! 222: simple_lock_init(&pset->idle_lock, ETAP_THREAD_PSET_IDLE); ! 223: queue_init(&pset->processors); ! 224: pset->processor_count = 0; ! 225: pset->empty = TRUE; ! 226: queue_init(&pset->tasks); ! 227: pset->task_count = 0; ! 228: queue_init(&pset->threads); ! 229: pset->thread_count = 0; ! 230: pset->ref_count = 1; ! 231: queue_init(&pset->all_psets); ! 232: pset->active = FALSE; ! 233: mutex_init(&pset->lock, ETAP_THREAD_PSET); ! 234: pset->pset_self = IP_NULL; ! 235: pset->pset_name_self = IP_NULL; ! 236: pset->max_priority = BASEPRI_USER; ! 237: pset->policies = POLICY_TIMESHARE | POLICY_FIFO | POLICY_RR; ! 238: pset->set_quantum = min_quantum; ! 239: ! 240: pset->quantum_adj_index = 0; ! 241: simple_lock_init(&pset->quantum_adj_lock, ETAP_THREAD_PSET_QUANT); ! 242: ! 243: for (i = 0; i <= NCPUS; i++) { ! 244: pset->machine_quantum[i] = min_quantum; ! 245: } ! 246: ! 247: pset->mach_factor = 0; ! 248: pset->load_average = 0; ! 249: pset->sched_load = SCHED_SCALE; /* i.e. 1 */ ! 250: ! 251: pset->policy_default = POLICY_TIMESHARE; ! 252: pset->policy_limit.ts.max_priority = BASEPRI_USER; ! 253: pset->policy_limit.rr.max_priority = BASEPRI_USER; ! 254: pset->policy_limit.fifo.max_priority = BASEPRI_USER; ! 255: pset->policy_base.ts.base_priority = BASEPRI_USER; ! 256: pset->policy_base.rr.base_priority = BASEPRI_USER; ! 257: pset->policy_base.rr.quantum = min_quantum; ! 258: pset->policy_base.fifo.base_priority = BASEPRI_USER; ! 259: } ! 260: ! 261: ! 262: /* ! 263: * Find the pset's maximum priority (limit) for the given policy. ! 264: * This is for internal use only. ! 265: */ ! 266: ! 267: int ! 268: pset_max_priority( ! 269: processor_set_t pset, ! 270: policy_t policy) ! 271: { ! 272: int max = BASEPRI_USER; ! 273: ! 274: if (invalid_policy(policy) || pset == PROCESSOR_SET_NULL) ! 275: return max; ! 276: ! 277: switch (policy) { ! 278: case POLICY_TIMESHARE: ! 279: max = pset->policy_limit.ts.max_priority; ! 280: break; ! 281: ! 282: case POLICY_RR: ! 283: max = pset->policy_limit.rr.max_priority; ! 284: break; ! 285: ! 286: case POLICY_FIFO: ! 287: max = pset->policy_limit.fifo.max_priority; ! 288: break; ! 289: } ! 290: ! 291: return max; ! 292: } ! 293: ! 294: /* ! 295: * Find the pset's base priority for the given policy. This is ! 296: * for internal use only. ! 297: */ ! 298: ! 299: int ! 300: pset_base_priority( ! 301: processor_set_t pset, ! 302: policy_t policy) ! 303: { ! 304: int base = BASEPRI_USER; ! 305: ! 306: if (invalid_policy(policy) || pset == PROCESSOR_SET_NULL) ! 307: return base; ! 308: ! 309: switch (policy) { ! 310: case POLICY_TIMESHARE: ! 311: base = pset->policy_base.ts.base_priority; ! 312: break; ! 313: ! 314: case POLICY_RR: ! 315: base = pset->policy_base.rr.base_priority; ! 316: break; ! 317: ! 318: case POLICY_FIFO: ! 319: base = pset->policy_base.fifo.base_priority; ! 320: break; ! 321: } ! 322: ! 323: return base; ! 324: } ! 325: ! 326: /* ! 327: * Find the pset's sched data for the given policy. This is ! 328: * for internal use only. ! 329: */ ! 330: ! 331: int ! 332: pset_sched_data( ! 333: processor_set_t pset, ! 334: policy_t policy) ! 335: { ! 336: int temp, data = 0; ! 337: ! 338: if (invalid_policy(policy) || pset == PROCESSOR_SET_NULL) ! 339: return data; ! 340: ! 341: switch (policy) { ! 342: case POLICY_TIMESHARE: ! 343: data = 0; ! 344: break; ! 345: ! 346: case POLICY_RR: ! 347: temp = pset->policy_base.rr.quantum * 1000; ! 348: if (temp % tick) ! 349: temp += tick; ! 350: data = temp/tick; ! 351: break; ! 352: ! 353: case POLICY_FIFO: ! 354: data = 0; ! 355: break; ! 356: } ! 357: ! 358: return data; ! 359: } ! 360: ! 361: /* ! 362: * Initialize the given processor structure for the processor in ! 363: * the slot specified by slot_num. ! 364: */ ! 365: ! 366: void ! 367: processor_init( ! 368: register processor_t pr, ! 369: int slot_num) ! 370: { ! 371: int i; ! 372: ! 373: /* setup run-queues */ ! 374: simple_lock_init(&pr->runq.lock, ETAP_THREAD_PROC_RUNQ); ! 375: pr->runq.count = 0; ! 376: pr->runq.depress_count = 0; ! 377: for (i = 0; i < NRQBM; i++) { ! 378: pr->runq.bitmap[i] = 0; ! 379: } ! 380: setbit(MAXPRI - IDLEPRI, pr->runq.bitmap); ! 381: pr->runq.highq = IDLEPRI; ! 382: for (i = 0; i < NRQS; i++) { ! 383: queue_init(&(pr->runq.runq[i])); ! 384: } ! 385: ! 386: queue_init(&pr->processor_queue); ! 387: pr->state = PROCESSOR_OFF_LINE; ! 388: pr->next_thread = THREAD_NULL; ! 389: pr->idle_thread = THREAD_NULL; ! 390: pr->quantum = 0; ! 391: pr->first_quantum = FALSE; ! 392: pr->last_quantum = 0; ! 393: pr->processor_set = PROCESSOR_SET_NULL; ! 394: pr->processor_set_next = PROCESSOR_SET_NULL; ! 395: queue_init(&pr->processors); ! 396: simple_lock_init(&pr->lock, ETAP_THREAD_PROC); ! 397: pr->processor_self = IP_NULL; ! 398: pr->slot_num = slot_num; ! 399: } ! 400: ! 401: /* ! 402: * pset_remove_processor() removes a processor from a processor_set. ! 403: * It can only be called on the current processor. Caller must ! 404: * hold lock on current processor and processor set. ! 405: */ ! 406: ! 407: void ! 408: pset_remove_processor( ! 409: processor_set_t pset, ! 410: processor_t processor) ! 411: { ! 412: if (pset != processor->processor_set) ! 413: panic("pset_remove_processor: wrong pset"); ! 414: ! 415: queue_remove(&pset->processors, processor, processor_t, processors); ! 416: processor->processor_set = PROCESSOR_SET_NULL; ! 417: pset->processor_count--; ! 418: quantum_set(pset); ! 419: } ! 420: ! 421: /* ! 422: * pset_add_processor() adds a processor to a processor_set. ! 423: * It can only be called on the current processor. Caller must ! 424: * hold lock on curent processor and on pset. No reference counting on ! 425: * processors. Processor reference to pset is implicit. ! 426: */ ! 427: ! 428: void ! 429: pset_add_processor( ! 430: processor_set_t pset, ! 431: processor_t processor) ! 432: { ! 433: queue_enter(&pset->processors, processor, processor_t, processors); ! 434: processor->processor_set = pset; ! 435: pset->processor_count++; ! 436: quantum_set(pset); ! 437: } ! 438: ! 439: /* ! 440: * pset_remove_task() removes a task from a processor_set. ! 441: * Caller must hold locks on pset and task. Pset reference count ! 442: * is not decremented; caller must explicitly pset_deallocate. ! 443: */ ! 444: ! 445: void ! 446: pset_remove_task( ! 447: processor_set_t pset, ! 448: task_t task) ! 449: { ! 450: if (pset != task->processor_set) ! 451: return; ! 452: ! 453: queue_remove(&pset->tasks, task, task_t, pset_tasks); ! 454: task->processor_set = PROCESSOR_SET_NULL; ! 455: pset->task_count--; ! 456: } ! 457: ! 458: /* ! 459: * pset_add_task() adds a task to a processor_set. ! 460: * Caller must hold locks on pset and task. Pset references to ! 461: * tasks are implicit. ! 462: */ ! 463: ! 464: void ! 465: pset_add_task( ! 466: processor_set_t pset, ! 467: task_t task) ! 468: { ! 469: queue_enter(&pset->tasks, task, task_t, pset_tasks); ! 470: task->processor_set = pset; ! 471: pset->task_count++; ! 472: pset->ref_count++; ! 473: } ! 474: ! 475: /* ! 476: * pset_remove_thread() removes a thread from a processor_set. ! 477: * Caller must hold locks on pset and thread. Pset reference count ! 478: * is not decremented; caller must explicitly pset_deallocate. ! 479: */ ! 480: ! 481: void ! 482: pset_remove_thread( ! 483: processor_set_t pset, ! 484: thread_t thread) ! 485: { ! 486: queue_remove(&pset->threads, thread, thread_t, pset_threads); ! 487: thread->processor_set = PROCESSOR_SET_NULL; ! 488: pset->thread_count--; ! 489: } ! 490: ! 491: /* ! 492: * pset_add_thread() adds a thread to a processor_set. ! 493: * Caller must hold locks on pset and thread. Pset references to ! 494: * threads are implicit. ! 495: */ ! 496: ! 497: void ! 498: pset_add_thread( ! 499: processor_set_t pset, ! 500: thread_t thread) ! 501: { ! 502: queue_enter(&pset->threads, thread, thread_t, pset_threads); ! 503: thread->processor_set = pset; ! 504: pset->thread_count++; ! 505: pset->ref_count++; ! 506: } ! 507: ! 508: /* ! 509: * thread_change_psets() changes the pset of a thread. Caller must ! 510: * hold locks on both psets and thread. The old pset must be ! 511: * explicitly pset_deallocat()'ed by caller. ! 512: */ ! 513: ! 514: void ! 515: thread_change_psets( ! 516: thread_t thread, ! 517: processor_set_t old_pset, ! 518: processor_set_t new_pset) ! 519: { ! 520: queue_remove(&old_pset->threads, thread, thread_t, pset_threads); ! 521: old_pset->thread_count--; ! 522: queue_enter(&new_pset->threads, thread, thread_t, pset_threads); ! 523: thread->processor_set = new_pset; ! 524: new_pset->thread_count++; ! 525: new_pset->ref_count++; ! 526: } ! 527: ! 528: /* ! 529: * pset_deallocate: ! 530: * ! 531: * Remove one reference to the processor set. Destroy processor_set ! 532: * if this was the last reference. ! 533: */ ! 534: ! 535: void ! 536: pset_deallocate( ! 537: processor_set_t pset) ! 538: { ! 539: if (pset == PROCESSOR_SET_NULL) ! 540: return; ! 541: ! 542: pset_lock(pset); ! 543: if (--pset->ref_count > 0) { ! 544: pset_unlock(pset); ! 545: return; ! 546: } ! 547: #if !MACH_HOST ! 548: panic("pset_deallocate: default_pset destroyed"); ! 549: #endif /* !MACH_HOST */ ! 550: #if MACH_HOST ! 551: /* ! 552: * Reference count is zero, however the all_psets list ! 553: * holds an implicit reference and may make new ones. ! 554: * Its lock also dominates the pset lock. To check for this, ! 555: * temporarily restore one reference, and then lock the ! 556: * other structures in the right order. ! 557: */ ! 558: pset->ref_count = 1; ! 559: pset_unlock(pset); ! 560: ! 561: mutex_lock(&all_psets_lock); ! 562: pset_lock(pset); ! 563: if (--pset->ref_count > 0) { ! 564: /* ! 565: * Made an extra reference. ! 566: */ ! 567: pset_unlock(pset); ! 568: mutex_unlock(&all_psets_lock); ! 569: return; ! 570: } ! 571: ! 572: /* ! 573: * Ok to destroy pset. Make a few paranoia checks. ! 574: */ ! 575: ! 576: if ((pset == &default_pset) || (pset->thread_count > 0) || ! 577: (pset->task_count > 0) || pset->processor_count > 0) { ! 578: panic("pset_deallocate: destroy default or active pset"); ! 579: } ! 580: /* ! 581: * Remove from all_psets queue. ! 582: */ ! 583: queue_remove(&all_psets, pset, processor_set_t, all_psets); ! 584: all_psets_count--; ! 585: ! 586: pset_unlock(pset); ! 587: mutex_unlock(&all_psets_lock); ! 588: ! 589: /* ! 590: * That's it, free data structure. ! 591: */ ! 592: zfree(pset_zone, (vm_offset_t)pset); ! 593: #endif /* MACH_HOST */ ! 594: } ! 595: ! 596: /* ! 597: * pset_reference: ! 598: * ! 599: * Add one reference to the processor set. ! 600: */ ! 601: ! 602: void ! 603: pset_reference( ! 604: processor_set_t pset) ! 605: { ! 606: pset_lock(pset); ! 607: pset->ref_count++; ! 608: pset_unlock(pset); ! 609: } ! 610: ! 611: kern_return_t ! 612: processor_info( ! 613: register processor_t processor, ! 614: processor_flavor_t flavor, ! 615: host_t *host, ! 616: processor_info_t info, ! 617: mach_msg_type_number_t *count) ! 618: { ! 619: register int i, slot_num, state; ! 620: register processor_basic_info_t basic_info; ! 621: register processor_cpu_load_info_t cpu_load_info; ! 622: kern_return_t kr; ! 623: ! 624: if (processor == PROCESSOR_NULL) ! 625: return(KERN_INVALID_ARGUMENT); ! 626: ! 627: slot_num = processor->slot_num; ! 628: ! 629: switch (flavor) { ! 630: ! 631: case PROCESSOR_BASIC_INFO: ! 632: { ! 633: if (*count < PROCESSOR_BASIC_INFO_COUNT) ! 634: return(KERN_FAILURE); ! 635: ! 636: basic_info = (processor_basic_info_t) info; ! 637: basic_info->cpu_type = machine_slot[slot_num].cpu_type; ! 638: basic_info->cpu_subtype = machine_slot[slot_num].cpu_subtype; ! 639: state = processor->state; ! 640: if (state == PROCESSOR_SHUTDOWN || state == PROCESSOR_OFF_LINE) ! 641: basic_info->running = FALSE; ! 642: else ! 643: basic_info->running = TRUE; ! 644: basic_info->slot_num = slot_num; ! 645: if (processor == master_processor) ! 646: basic_info->is_master = TRUE; ! 647: else ! 648: basic_info->is_master = FALSE; ! 649: ! 650: *count = PROCESSOR_BASIC_INFO_COUNT; ! 651: *host = &realhost; ! 652: return(KERN_SUCCESS); ! 653: } ! 654: case PROCESSOR_CPU_LOAD_INFO: ! 655: { ! 656: if (*count < PROCESSOR_CPU_LOAD_INFO_COUNT) ! 657: return(KERN_FAILURE); ! 658: ! 659: cpu_load_info = (processor_cpu_load_info_t) info; ! 660: for (i=0;i<CPU_STATE_MAX;i++) ! 661: cpu_load_info->cpu_ticks[i] = machine_slot[slot_num].cpu_ticks[i]; ! 662: ! 663: *count = PROCESSOR_CPU_LOAD_INFO_COUNT; ! 664: *host = &realhost; ! 665: return(KERN_SUCCESS); ! 666: } ! 667: default: ! 668: { ! 669: kr=cpu_info(flavor, slot_num, info, count); ! 670: if (kr == KERN_SUCCESS) ! 671: *host = &realhost; ! 672: return(kr); ! 673: } ! 674: } ! 675: } ! 676: ! 677: kern_return_t ! 678: processor_start( ! 679: processor_t processor) ! 680: { ! 681: if (processor == PROCESSOR_NULL) ! 682: return(KERN_INVALID_ARGUMENT); ! 683: ! 684: /* TODO: Test if the target processor has already been started */ ! 685: /* TODO: boot_processor : for now, assume cpu 0 */ ! 686: if (processor->slot_num != 0) ! 687: { ! 688: thread_t thread; ! 689: sched_policy_t *policy; ! 690: sf_return_t sfr; ! 691: spl_t s; ! 692: extern void start_cpu_thread(void); ! 693: ! 694: thread = kernel_thread_with_attributes( kernel_task, SP_ATTRIBUTES_NULL, start_cpu_thread, FALSE); ! 695: s = splsched(); ! 696: thread_lock(thread); ! 697: thread_bind_locked(thread, processor); ! 698: processor->next_thread = thread; ! 699: thread->state |= TH_RUN; ! 700: /*(void) thread_resume(thread->top_act);*/ ! 701: ! 702: /* get pointer to scheduling policy "object" */ ! 703: policy = &sched_policy[thread->policy]; ! 704: ! 705: sfr = policy->sp_ops.sp_thread_unblock(policy, thread); ! 706: assert(sfr == SF_SUCCESS); ! 707: thread_unlock(thread); ! 708: splx(s); ! 709: } ! 710: ! 711: return(cpu_start(processor->slot_num)); ! 712: } ! 713: ! 714: kern_return_t ! 715: processor_exit( ! 716: processor_t processor) ! 717: { ! 718: if (processor == PROCESSOR_NULL) ! 719: return(KERN_INVALID_ARGUMENT); ! 720: ! 721: return(processor_shutdown(processor)); ! 722: } ! 723: ! 724: kern_return_t ! 725: processor_control( ! 726: processor_t processor, ! 727: processor_info_t info, ! 728: mach_msg_type_number_t count) ! 729: { ! 730: if (processor == PROCESSOR_NULL) ! 731: return(KERN_INVALID_ARGUMENT); ! 732: ! 733: return(cpu_control(processor->slot_num, info, count)); ! 734: } ! 735: ! 736: /* ! 737: * Precalculate the appropriate system quanta based on load. The ! 738: * index into machine_quantum is the number of threads on the ! 739: * processor set queue. It is limited to the number of processors in ! 740: * the set. ! 741: */ ! 742: ! 743: void ! 744: quantum_set( ! 745: processor_set_t pset) ! 746: { ! 747: #if NCPUS > 1 ! 748: register int i, ncpus; ! 749: ! 750: ncpus = pset->processor_count; ! 751: ! 752: for (i=1; i <= ncpus; i++) ! 753: pset->machine_quantum[i] = ((min_quantum * ncpus) + (i / 2)) / i ; ! 754: ! 755: pset->machine_quantum[0] = pset->machine_quantum[1]; ! 756: ! 757: i = (pset->runq.count > ncpus) ? ncpus : pset->runq.count; ! 758: pset->set_quantum = pset->machine_quantum[i]; ! 759: #else /* NCPUS > 1 */ ! 760: default_pset.set_quantum = min_quantum; ! 761: #endif /* NCPUS > 1 */ ! 762: } ! 763: ! 764: #if MACH_HOST ! 765: /* ! 766: * processor_set_create: ! 767: * ! 768: * Create and return a new processor set. ! 769: */ ! 770: ! 771: kern_return_t ! 772: processor_set_create( ! 773: host_t host, ! 774: processor_set_t *new_set, ! 775: processor_set_t *new_name) ! 776: { ! 777: processor_set_t pset; ! 778: ! 779: if (host == HOST_NULL) ! 780: return(KERN_INVALID_ARGUMENT); ! 781: pset = (processor_set_t) zalloc(pset_zone); ! 782: pset_init(pset); ! 783: pset_reference(pset); /* for new_set out argument */ ! 784: pset_reference(pset); /* for new_name out argument */ ! 785: ipc_pset_init(pset); ! 786: pset->active = TRUE; ! 787: ! 788: mutex_lock(&all_psets_lock); ! 789: queue_enter(&all_psets, pset, processor_set_t, all_psets); ! 790: all_psets_count++; ! 791: mutex_unlock(&all_psets_lock); ! 792: ! 793: ipc_pset_enable(pset); ! 794: ! 795: *new_set = pset; ! 796: *new_name = pset; ! 797: return(KERN_SUCCESS); ! 798: } ! 799: ! 800: /* ! 801: * processor_set_destroy: ! 802: * ! 803: * destroy a processor set. Any tasks, threads or processors ! 804: * currently assigned to it are reassigned to the default pset. ! 805: */ ! 806: kern_return_t ! 807: processor_set_destroy( ! 808: processor_set_t pset) ! 809: { ! 810: register queue_entry_t elem; ! 811: register queue_head_t *list; ! 812: ! 813: if (pset == PROCESSOR_SET_NULL || pset == &default_pset) ! 814: return(KERN_INVALID_ARGUMENT); ! 815: ! 816: /* ! 817: * Handle multiple termination race. First one through sets ! 818: * active to FALSE and disables ipc access. ! 819: */ ! 820: pset_lock(pset); ! 821: if (!(pset->active)) { ! 822: pset_unlock(pset); ! 823: return(KERN_FAILURE); ! 824: } ! 825: ! 826: pset->active = FALSE; ! 827: ipc_pset_disable(pset); ! 828: ! 829: ! 830: /* ! 831: * Now reassign everything in this set to the default set. ! 832: */ ! 833: ! 834: if (pset->task_count > 0) { ! 835: list = &pset->tasks; ! 836: while (!queue_empty(list)) { ! 837: elem = queue_first(list); ! 838: task_reference((task_t) elem); ! 839: pset_unlock(pset); ! 840: task_assign((task_t) elem, &default_pset, FALSE); ! 841: task_deallocate((task_t) elem); ! 842: pset_lock(pset); ! 843: } ! 844: } ! 845: ! 846: if (pset->thread_count > 0) { ! 847: list = &pset->threads; ! 848: while (!queue_empty(list)) { ! 849: thread_t thread; ! 850: thread_act_t thr_act; ! 851: ! 852: elem = queue_first(list); ! 853: thread = (thread_t)elem; ! 854: /* ! 855: * Get top activation of thread safely. ! 856: */ ! 857: thr_act = thread_lock_act(thread); ! 858: /* ! 859: * Inline thread_assign() here to avoid silly double ! 860: * locking. ! 861: */ ! 862: thread_freeze(thread); ! 863: thread_doassign(thread, &default_pset, TRUE); ! 864: /* ! 865: * All thread-related locks released at this point. ! 866: */ ! 867: pset_lock(pset); ! 868: } ! 869: } ! 870: ! 871: if (pset->processor_count > 0) { ! 872: list = &pset->processors; ! 873: while(!queue_empty(list)) { ! 874: elem = queue_first(list); ! 875: pset_unlock(pset); ! 876: processor_assign((processor_t) elem, &default_pset, TRUE); ! 877: pset_lock(pset); ! 878: } ! 879: } ! 880: ! 881: pset_unlock(pset); ! 882: ! 883: /* ! 884: * Destroy ipc state. ! 885: */ ! 886: ipc_pset_terminate(pset); ! 887: ! 888: /* ! 889: * Deallocate pset's reference to itself. ! 890: */ ! 891: pset_deallocate(pset); ! 892: return(KERN_SUCCESS); ! 893: } ! 894: ! 895: #else /* MACH_HOST */ ! 896: ! 897: kern_return_t ! 898: processor_set_create( ! 899: host_t host, ! 900: processor_set_t *new_set, ! 901: processor_set_t *new_name) ! 902: { ! 903: #ifdef lint ! 904: host++; new_set++; new_name++; ! 905: #endif /* lint */ ! 906: return(KERN_FAILURE); ! 907: } ! 908: ! 909: kern_return_t ! 910: processor_set_destroy( ! 911: processor_set_t pset) ! 912: { ! 913: #ifdef lint ! 914: pset++; ! 915: #endif /* lint */ ! 916: return(KERN_FAILURE); ! 917: } ! 918: ! 919: #endif /* MACH_HOST */ ! 920: ! 921: kern_return_t ! 922: processor_get_assignment( ! 923: processor_t processor, ! 924: processor_set_t *pset) ! 925: { ! 926: int state; ! 927: ! 928: state = processor->state; ! 929: if (state == PROCESSOR_SHUTDOWN || state == PROCESSOR_OFF_LINE) ! 930: return(KERN_FAILURE); ! 931: ! 932: *pset = processor->processor_set; ! 933: pset_reference(*pset); ! 934: return(KERN_SUCCESS); ! 935: } ! 936: ! 937: kern_return_t ! 938: processor_set_info( ! 939: processor_set_t pset, ! 940: int flavor, ! 941: host_t *host, ! 942: processor_set_info_t info, ! 943: mach_msg_type_number_t *count) ! 944: { ! 945: if (pset == PROCESSOR_SET_NULL) ! 946: return(KERN_INVALID_ARGUMENT); ! 947: ! 948: if (flavor == PROCESSOR_SET_BASIC_INFO) { ! 949: register processor_set_basic_info_t basic_info; ! 950: ! 951: if (*count < PROCESSOR_SET_BASIC_INFO_COUNT) ! 952: return(KERN_FAILURE); ! 953: ! 954: basic_info = (processor_set_basic_info_t) info; ! 955: ! 956: pset_lock(pset); ! 957: basic_info->processor_count = pset->processor_count; ! 958: basic_info->default_policy = pset->policy_default; ! 959: pset_unlock(pset); ! 960: ! 961: *count = PROCESSOR_SET_BASIC_INFO_COUNT; ! 962: *host = &realhost; ! 963: return(KERN_SUCCESS); ! 964: } ! 965: else if (flavor == PROCESSOR_SET_TIMESHARE_DEFAULT) { ! 966: register policy_timeshare_base_t ts_base; ! 967: ! 968: if (*count < POLICY_TIMESHARE_BASE_COUNT) ! 969: return(KERN_FAILURE); ! 970: ! 971: ts_base = (policy_timeshare_base_t) info; ! 972: ! 973: pset_lock(pset); ! 974: *ts_base = pset->policy_base.ts; ! 975: pset_unlock(pset); ! 976: ! 977: *count = POLICY_TIMESHARE_BASE_COUNT; ! 978: *host = &realhost; ! 979: return(KERN_SUCCESS); ! 980: } ! 981: else if (flavor == PROCESSOR_SET_FIFO_DEFAULT) { ! 982: register policy_fifo_base_t fifo_base; ! 983: ! 984: if (*count < POLICY_FIFO_BASE_COUNT) ! 985: return(KERN_FAILURE); ! 986: ! 987: fifo_base = (policy_fifo_base_t) info; ! 988: ! 989: pset_lock(pset); ! 990: *fifo_base = pset->policy_base.fifo; ! 991: pset_unlock(pset); ! 992: ! 993: *count = POLICY_FIFO_BASE_COUNT; ! 994: *host = &realhost; ! 995: return(KERN_SUCCESS); ! 996: } ! 997: else if (flavor == PROCESSOR_SET_RR_DEFAULT) { ! 998: register policy_rr_base_t rr_base; ! 999: ! 1000: if (*count < POLICY_RR_BASE_COUNT) ! 1001: return(KERN_FAILURE); ! 1002: ! 1003: rr_base = (policy_rr_base_t) info; ! 1004: ! 1005: pset_lock(pset); ! 1006: *rr_base = pset->policy_base.rr; ! 1007: pset_unlock(pset); ! 1008: ! 1009: *count = POLICY_RR_BASE_COUNT; ! 1010: *host = &realhost; ! 1011: return(KERN_SUCCESS); ! 1012: } ! 1013: else if (flavor == PROCESSOR_SET_TIMESHARE_LIMITS) { ! 1014: register policy_timeshare_limit_t ts_limit; ! 1015: ! 1016: if (*count < POLICY_TIMESHARE_LIMIT_COUNT) ! 1017: return(KERN_FAILURE); ! 1018: ! 1019: ts_limit = (policy_timeshare_limit_t) info; ! 1020: ! 1021: pset_lock(pset); ! 1022: *ts_limit = pset->policy_limit.ts; ! 1023: pset_unlock(pset); ! 1024: ! 1025: *count = POLICY_TIMESHARE_LIMIT_COUNT; ! 1026: *host = &realhost; ! 1027: return(KERN_SUCCESS); ! 1028: } ! 1029: else if (flavor == PROCESSOR_SET_FIFO_LIMITS) { ! 1030: register policy_fifo_limit_t fifo_limit; ! 1031: ! 1032: if (*count < POLICY_FIFO_LIMIT_COUNT) ! 1033: return(KERN_FAILURE); ! 1034: ! 1035: fifo_limit = (policy_fifo_limit_t) info; ! 1036: ! 1037: pset_lock(pset); ! 1038: *fifo_limit = pset->policy_limit.fifo; ! 1039: pset_unlock(pset); ! 1040: ! 1041: *count = POLICY_FIFO_LIMIT_COUNT; ! 1042: *host = &realhost; ! 1043: return(KERN_SUCCESS); ! 1044: } ! 1045: else if (flavor == PROCESSOR_SET_RR_LIMITS) { ! 1046: register policy_rr_limit_t rr_limit; ! 1047: ! 1048: if (*count < POLICY_RR_LIMIT_COUNT) ! 1049: return(KERN_FAILURE); ! 1050: ! 1051: rr_limit = (policy_rr_limit_t) info; ! 1052: ! 1053: pset_lock(pset); ! 1054: *rr_limit = pset->policy_limit.rr; ! 1055: pset_unlock(pset); ! 1056: ! 1057: *count = POLICY_RR_LIMIT_COUNT; ! 1058: *host = &realhost; ! 1059: return(KERN_SUCCESS); ! 1060: } ! 1061: else if (flavor == PROCESSOR_SET_ENABLED_POLICIES) { ! 1062: register int *enabled; ! 1063: ! 1064: if (*count < (sizeof(*enabled)/sizeof(int))) ! 1065: return(KERN_FAILURE); ! 1066: ! 1067: enabled = (int *) info; ! 1068: ! 1069: pset_lock(pset); ! 1070: *enabled = pset->policies; ! 1071: pset_unlock(pset); ! 1072: ! 1073: *count = sizeof(*enabled)/sizeof(int); ! 1074: *host = &realhost; ! 1075: return(KERN_SUCCESS); ! 1076: } ! 1077: ! 1078: ! 1079: *host = HOST_NULL; ! 1080: return(KERN_INVALID_ARGUMENT); ! 1081: } ! 1082: ! 1083: /* ! 1084: * processor_set_statistics ! 1085: * ! 1086: * Returns scheduling statistics for a processor set. ! 1087: */ ! 1088: kern_return_t ! 1089: processor_set_statistics( ! 1090: processor_set_t pset, ! 1091: int flavor, ! 1092: processor_set_info_t info, ! 1093: mach_msg_type_number_t *count) ! 1094: { ! 1095: if (pset == PROCESSOR_SET_NULL) ! 1096: return (KERN_INVALID_PROCESSOR_SET); ! 1097: ! 1098: if (flavor == PROCESSOR_SET_LOAD_INFO) { ! 1099: register processor_set_load_info_t load_info; ! 1100: ! 1101: if (*count < PROCESSOR_SET_LOAD_INFO_COUNT) ! 1102: return(KERN_FAILURE); ! 1103: ! 1104: load_info = (processor_set_load_info_t) info; ! 1105: ! 1106: pset_lock(pset); ! 1107: load_info->task_count = pset->task_count; ! 1108: load_info->thread_count = pset->thread_count; ! 1109: load_info->mach_factor = pset->mach_factor; ! 1110: load_info->load_average = pset->load_average; ! 1111: pset_unlock(pset); ! 1112: ! 1113: *count = PROCESSOR_SET_LOAD_INFO_COUNT; ! 1114: return(KERN_SUCCESS); ! 1115: } ! 1116: ! 1117: return(KERN_INVALID_ARGUMENT); ! 1118: } ! 1119: ! 1120: /* ! 1121: * processor_set_max_priority: ! 1122: * ! 1123: * Specify max priority permitted on processor set. This affects ! 1124: * newly created and assigned threads. Optionally change existing ! 1125: * ones. ! 1126: */ ! 1127: kern_return_t ! 1128: processor_set_max_priority( ! 1129: processor_set_t pset, ! 1130: int max_priority, ! 1131: boolean_t change_threads) ! 1132: { ! 1133: thread_act_t thr_act; ! 1134: ! 1135: if (pset == PROCESSOR_SET_NULL || invalid_pri(max_priority)) ! 1136: return(KERN_INVALID_ARGUMENT); ! 1137: ! 1138: pset_lock(pset); ! 1139: pset->max_priority = max_priority; ! 1140: ! 1141: if (change_threads) { ! 1142: register queue_head_t *list; ! 1143: register thread_t thread; ! 1144: ! 1145: list = &pset->threads; ! 1146: thread = (thread_t) queue_first(list); ! 1147: while (!queue_end(list, (queue_entry_t) thread)) { ! 1148: thr_act = thread_lock_act(thread); ! 1149: /*** ??? fix me ***/ ! 1150: assert(thread->sp_info != SP_INFO_NULL); ! 1151: if (((thread->policy == POLICY_TIMESHARE) || ! 1152: (thread->policy == POLICY_RR) || ! 1153: (thread->policy == POLICY_FIFO)) && ! 1154: (((mk_sp_info_t)thread->sp_info)->max_priority < max_priority)) ! 1155: { ! 1156: thread_max_priority_locked(thread, pset, max_priority); ! 1157: } ! 1158: thread_unlock_act(thread); ! 1159: thread = (thread_t) queue_next(&thread->pset_threads); ! 1160: } ! 1161: } ! 1162: ! 1163: pset_unlock(pset); ! 1164: ! 1165: return(KERN_SUCCESS); ! 1166: } ! 1167: ! 1168: /* ! 1169: * processor_set_policy_enable: ! 1170: * ! 1171: * Allow indicated policy on processor set. ! 1172: */ ! 1173: ! 1174: kern_return_t ! 1175: processor_set_policy_enable( ! 1176: processor_set_t pset, ! 1177: int policy) ! 1178: { ! 1179: if ((pset == PROCESSOR_SET_NULL) || invalid_policy(policy)) ! 1180: return(KERN_INVALID_ARGUMENT); ! 1181: ! 1182: pset_lock(pset); ! 1183: pset->policies |= policy; ! 1184: pset_unlock(pset); ! 1185: ! 1186: return(KERN_SUCCESS); ! 1187: } ! 1188: ! 1189: /* ! 1190: * processor_set_policy_disable: ! 1191: * ! 1192: * Forbid indicated policy on processor set. Time sharing cannot ! 1193: * be forbidden. ! 1194: */ ! 1195: ! 1196: kern_return_t ! 1197: processor_set_policy_disable( ! 1198: processor_set_t pset, ! 1199: int policy, ! 1200: boolean_t change_threads) ! 1201: { ! 1202: thread_act_t thr_act; ! 1203: ! 1204: if ((pset == PROCESSOR_SET_NULL) || policy == POLICY_TIMESHARE || ! 1205: invalid_policy(policy)) ! 1206: return(KERN_INVALID_ARGUMENT); ! 1207: ! 1208: pset_lock(pset); ! 1209: ! 1210: /* ! 1211: * Check if policy enabled. Disable if so, then handle ! 1212: * change_threads. ! 1213: */ ! 1214: if (pset->policies & policy) { ! 1215: pset->policies &= ~policy; ! 1216: ! 1217: if (change_threads) { ! 1218: register queue_head_t *list; ! 1219: register thread_t thread; ! 1220: policy_base_t base; ! 1221: policy_timeshare_base_data_t ts_data; ! 1222: ! 1223: base = (policy_base_t) &ts_data; ! 1224: ts_data.base_priority = 0; ! 1225: list = &pset->threads; ! 1226: thread = (thread_t) queue_first(list); ! 1227: while (!queue_end(list, (queue_entry_t) thread)) { ! 1228: thr_act = thread_lock_act(thread); ! 1229: if (thr_act && thread->policy == policy) ! 1230: thread_policy(thr_act, POLICY_TIMESHARE, base, ! 1231: POLICY_TIMESHARE_BASE_COUNT, FALSE); ! 1232: thread_unlock_act(thread); ! 1233: thread = (thread_t) queue_next(&thread->pset_threads); ! 1234: } ! 1235: } ! 1236: } ! 1237: pset_unlock(pset); ! 1238: ! 1239: return(KERN_SUCCESS); ! 1240: } ! 1241: ! 1242: #define THING_TASK 0 ! 1243: #define THING_THREAD 1 ! 1244: ! 1245: /* ! 1246: * processor_set_things: ! 1247: * ! 1248: * Common internals for processor_set_{threads,tasks} ! 1249: */ ! 1250: kern_return_t ! 1251: processor_set_things( ! 1252: processor_set_t pset, ! 1253: mach_port_t **thing_list, ! 1254: mach_msg_type_number_t *count, ! 1255: int type) ! 1256: { ! 1257: unsigned int actual; /* this many things */ ! 1258: int i; ! 1259: boolean_t rt = FALSE; /* ### This boolean is FALSE, because there ! 1260: * currently exists no mechanism to determine ! 1261: * whether or not the reply port is an RT port ! 1262: */ ! 1263: ! 1264: vm_size_t size, size_needed; ! 1265: vm_offset_t addr; ! 1266: ! 1267: if (pset == PROCESSOR_SET_NULL) ! 1268: return KERN_INVALID_ARGUMENT; ! 1269: ! 1270: size = 0; addr = 0; ! 1271: ! 1272: for (;;) { ! 1273: pset_lock(pset); ! 1274: if (!pset->active) { ! 1275: pset_unlock(pset); ! 1276: return KERN_FAILURE; ! 1277: } ! 1278: ! 1279: if (type == THING_TASK) ! 1280: actual = pset->task_count; ! 1281: else ! 1282: actual = pset->thread_count; ! 1283: ! 1284: /* do we have the memory we need? */ ! 1285: ! 1286: size_needed = actual * sizeof(mach_port_t); ! 1287: if (size_needed <= size) ! 1288: break; ! 1289: ! 1290: /* unlock the pset and allocate more memory */ ! 1291: pset_unlock(pset); ! 1292: ! 1293: if (size != 0) ! 1294: KFREE(addr, size, rt); ! 1295: ! 1296: assert(size_needed > 0); ! 1297: size = size_needed; ! 1298: ! 1299: addr = KALLOC(size, rt); ! 1300: if (addr == 0) ! 1301: return KERN_RESOURCE_SHORTAGE; ! 1302: } ! 1303: ! 1304: /* OK, have memory and the processor_set is locked & active */ ! 1305: ! 1306: switch (type) { ! 1307: case THING_TASK: { ! 1308: task_t *tasks = (task_t *) addr; ! 1309: task_t task; ! 1310: ! 1311: for (i = 0, task = (task_t) queue_first(&pset->tasks); ! 1312: i < actual; ! 1313: i++, task = (task_t) queue_next(&task->pset_tasks)) { ! 1314: /* take ref for convert_task_to_port */ ! 1315: task_reference(task); ! 1316: tasks[i] = task; ! 1317: } ! 1318: assert(queue_end(&pset->tasks, (queue_entry_t) task)); ! 1319: break; ! 1320: } ! 1321: ! 1322: case THING_THREAD: { ! 1323: thread_act_t *thr_acts = (thread_act_t *) addr; ! 1324: thread_t thread; ! 1325: thread_act_t thr_act; ! 1326: queue_head_t *list; ! 1327: ! 1328: list = &pset->threads; ! 1329: thread = (thread_t) queue_first(list); ! 1330: i = 0; ! 1331: while (i < actual && !queue_end(list, (queue_entry_t)thread)) { ! 1332: thr_act = thread_lock_act(thread); ! 1333: if (thr_act && thr_act->ref_count > 0) { ! 1334: /* take ref for convert_act_to_port */ ! 1335: act_locked_act_reference(thr_act); ! 1336: thr_acts[i] = thr_act; ! 1337: i++; ! 1338: } ! 1339: thread_unlock_act(thread); ! 1340: thread = (thread_t) queue_next(&thread->pset_threads); ! 1341: } ! 1342: if (i < actual) { ! 1343: actual = i; ! 1344: size_needed = actual * sizeof(mach_port_t); ! 1345: } ! 1346: break; ! 1347: } ! 1348: } ! 1349: ! 1350: /* can unlock processor set now that we have the task/thread refs */ ! 1351: pset_unlock(pset); ! 1352: ! 1353: if (actual == 0) { ! 1354: /* no things, so return null pointer and deallocate memory */ ! 1355: *thing_list = 0; ! 1356: *count = 0; ! 1357: ! 1358: if (size != 0) ! 1359: KFREE(addr, size, rt); ! 1360: } else { ! 1361: /* if we allocated too much, must copy */ ! 1362: ! 1363: if (size_needed < size) { ! 1364: vm_offset_t newaddr; ! 1365: ! 1366: newaddr = KALLOC(size_needed, rt); ! 1367: if (newaddr == 0) { ! 1368: switch (type) { ! 1369: case THING_TASK: { ! 1370: task_t *tasks = (task_t *) addr; ! 1371: ! 1372: for (i = 0; i < actual; i++) ! 1373: task_deallocate(tasks[i]); ! 1374: break; ! 1375: } ! 1376: ! 1377: case THING_THREAD: { ! 1378: thread_t *threads = (thread_t *) addr; ! 1379: ! 1380: for (i = 0; i < actual; i++) ! 1381: thread_deallocate(threads[i]); ! 1382: break; ! 1383: } ! 1384: } ! 1385: KFREE(addr, size, rt); ! 1386: return KERN_RESOURCE_SHORTAGE; ! 1387: } ! 1388: ! 1389: bcopy((char *) addr, (char *) newaddr, size_needed); ! 1390: KFREE(addr, size, rt); ! 1391: addr = newaddr; ! 1392: } ! 1393: ! 1394: *thing_list = (mach_port_t *) addr; ! 1395: *count = actual; ! 1396: ! 1397: /* do the conversion that Mig should handle */ ! 1398: ! 1399: switch (type) { ! 1400: case THING_TASK: { ! 1401: task_t *tasks = (task_t *) addr; ! 1402: ! 1403: for (i = 0; i < actual; i++) ! 1404: (*thing_list)[i] = convert_task_to_port(tasks[i]); ! 1405: break; ! 1406: } ! 1407: ! 1408: case THING_THREAD: { ! 1409: thread_act_t *thr_acts = (thread_act_t *) addr; ! 1410: ! 1411: for (i = 0; i < actual; i++) ! 1412: (*thing_list)[i] = convert_act_to_port(thr_acts[i]); ! 1413: break; ! 1414: } ! 1415: } ! 1416: } ! 1417: ! 1418: return(KERN_SUCCESS); ! 1419: } ! 1420: ! 1421: ! 1422: /* ! 1423: * processor_set_tasks: ! 1424: * ! 1425: * List all tasks in the processor set. ! 1426: */ ! 1427: kern_return_t ! 1428: processor_set_tasks( ! 1429: processor_set_t pset, ! 1430: task_array_t *task_list, ! 1431: mach_msg_type_number_t *count) ! 1432: { ! 1433: return(processor_set_things(pset, (mach_port_t **)task_list, count, THING_TASK)); ! 1434: } ! 1435: ! 1436: /* ! 1437: * processor_set_threads: ! 1438: * ! 1439: * List all threads in the processor set. ! 1440: */ ! 1441: kern_return_t ! 1442: processor_set_threads( ! 1443: processor_set_t pset, ! 1444: thread_array_t *thread_list, ! 1445: mach_msg_type_number_t *count) ! 1446: { ! 1447: return(processor_set_things(pset, (mach_port_t **)thread_list, count, THING_THREAD)); ! 1448: } ! 1449: ! 1450: /* ! 1451: * processor_set_base: ! 1452: * ! 1453: * Specify per-policy base priority for a processor set. Set processor ! 1454: * set default policy to the given policy. This affects newly created ! 1455: * and assigned threads. Optionally change existing ones. ! 1456: */ ! 1457: kern_return_t ! 1458: processor_set_base( ! 1459: processor_set_t pset, ! 1460: policy_t policy, ! 1461: policy_base_t base, ! 1462: boolean_t change) ! 1463: { ! 1464: int bc, lc; ! 1465: policy_limit_t limit; ! 1466: policy_rr_limit_data_t rr_limit; ! 1467: policy_fifo_limit_data_t fifo_limit; ! 1468: policy_timeshare_limit_data_t ts_limit; ! 1469: kern_return_t ret = KERN_SUCCESS; ! 1470: ! 1471: if (pset == PROCESSOR_SET_NULL) ! 1472: return(KERN_INVALID_PROCESSOR_SET); ! 1473: ! 1474: pset_lock(pset); ! 1475: ! 1476: switch (policy) { ! 1477: case POLICY_RR: ! 1478: { ! 1479: policy_rr_base_t rr_base = (policy_rr_base_t) base; ! 1480: ! 1481: if (invalid_pri(rr_base->base_priority)) { ! 1482: ret = KERN_INVALID_ARGUMENT; ! 1483: break; ! 1484: } ! 1485: bc = POLICY_RR_BASE_COUNT; ! 1486: lc = POLICY_RR_LIMIT_COUNT; ! 1487: pset->policy_base.rr = *rr_base; ! 1488: rr_limit.max_priority = rr_base->base_priority; ! 1489: limit = (policy_limit_t) &rr_limit; ! 1490: break; ! 1491: } ! 1492: ! 1493: case POLICY_FIFO: ! 1494: { ! 1495: policy_fifo_base_t fifo_base = (policy_fifo_base_t) base; ! 1496: ! 1497: if (invalid_pri(fifo_base->base_priority)) { ! 1498: ret = KERN_INVALID_ARGUMENT; ! 1499: break; ! 1500: } ! 1501: bc = POLICY_FIFO_BASE_COUNT; ! 1502: lc = POLICY_FIFO_LIMIT_COUNT; ! 1503: pset->policy_base.fifo = *fifo_base; ! 1504: fifo_limit.max_priority = fifo_base->base_priority; ! 1505: limit = (policy_limit_t) &fifo_limit; ! 1506: break; ! 1507: } ! 1508: ! 1509: case POLICY_TIMESHARE: ! 1510: { ! 1511: policy_timeshare_base_t ts_base = ! 1512: (policy_timeshare_base_t) base; ! 1513: if (invalid_pri(ts_base->base_priority)) { ! 1514: ret = KERN_INVALID_ARGUMENT; ! 1515: break; ! 1516: } ! 1517: bc = POLICY_TIMESHARE_BASE_COUNT; ! 1518: lc = POLICY_TIMESHARE_LIMIT_COUNT; ! 1519: pset->policy_base.ts = *ts_base; ! 1520: ts_limit.max_priority = ts_base->base_priority; ! 1521: limit = (policy_limit_t) &ts_limit; ! 1522: break; ! 1523: } ! 1524: ! 1525: default: ! 1526: ret = KERN_INVALID_POLICY; ! 1527: } ! 1528: ! 1529: if (ret != KERN_SUCCESS) { ! 1530: pset_unlock(pset); ! 1531: return (ret); ! 1532: } ! 1533: ! 1534: pset->policy_default = policy; ! 1535: ! 1536: ! 1537: /* ! 1538: * When changing the default policy and base priority, set the ! 1539: * limit priority equal to the base priority. ! 1540: */ ! 1541: if (change) { ! 1542: register queue_head_t *list; ! 1543: register task_t task; ! 1544: ! 1545: list = &pset->tasks; ! 1546: task = (task_t) queue_first(list); ! 1547: while (!queue_end(list, (queue_entry_t) task)) { ! 1548: task_set_policy(task, pset, policy, base, bc, ! 1549: limit, lc, TRUE); ! 1550: task = (task_t) queue_next(&task->pset_tasks); ! 1551: } ! 1552: } ! 1553: ! 1554: pset_unlock(pset); ! 1555: ! 1556: return(ret); ! 1557: } ! 1558: ! 1559: /* ! 1560: * processor_set_limit: ! 1561: * ! 1562: * Specify per-policy limits for a processor set. This affects ! 1563: * newly created and assigned threads. Optionally change existing ! 1564: * ones. ! 1565: */ ! 1566: kern_return_t ! 1567: processor_set_limit( ! 1568: processor_set_t pset, ! 1569: policy_t policy, ! 1570: policy_limit_t limit, ! 1571: boolean_t change) ! 1572: { ! 1573: int max; ! 1574: kern_return_t ret = KERN_SUCCESS; ! 1575: thread_act_t thr_act; ! 1576: ! 1577: if (pset == PROCESSOR_SET_NULL) ! 1578: return(KERN_INVALID_PROCESSOR_SET); ! 1579: ! 1580: pset_lock(pset); ! 1581: ! 1582: switch (policy) { ! 1583: case POLICY_RR: ! 1584: { ! 1585: policy_rr_limit_t rr_limit = (policy_rr_limit_t) limit; ! 1586: ! 1587: max = rr_limit->max_priority; ! 1588: if (invalid_pri(max)) { ! 1589: ret = KERN_POLICY_LIMIT; ! 1590: break; ! 1591: } ! 1592: pset->policy_limit.rr = *rr_limit; ! 1593: break; ! 1594: } ! 1595: ! 1596: case POLICY_FIFO: ! 1597: { ! 1598: policy_fifo_limit_t fifo_limit = (policy_fifo_limit_t) limit; ! 1599: ! 1600: max = fifo_limit->max_priority; ! 1601: if (invalid_pri(max)) { ! 1602: ret = KERN_POLICY_LIMIT; ! 1603: break; ! 1604: } ! 1605: pset->policy_limit.fifo = *fifo_limit; ! 1606: break; ! 1607: } ! 1608: ! 1609: case POLICY_TIMESHARE: ! 1610: { ! 1611: policy_timeshare_limit_t ts_limit = ! 1612: (policy_timeshare_limit_t) limit; ! 1613: ! 1614: max = ts_limit->max_priority; ! 1615: if (invalid_pri(max)) { ! 1616: ret = KERN_POLICY_LIMIT; ! 1617: break; ! 1618: } ! 1619: pset->policy_limit.ts = *ts_limit; ! 1620: break; ! 1621: } ! 1622: ! 1623: default: ! 1624: ret = KERN_INVALID_POLICY; ! 1625: } ! 1626: ! 1627: if (ret != KERN_SUCCESS) { ! 1628: pset_unlock(pset); ! 1629: return(ret); ! 1630: } ! 1631: ! 1632: if (change) { ! 1633: register queue_head_t *list; ! 1634: register task_t task; ! 1635: register thread_t thread; ! 1636: ! 1637: /* ! 1638: * Only change the policy limits for those tasks and ! 1639: * threads whose policy matches our 'policy' variable. ! 1640: */ ! 1641: list = &pset->tasks; ! 1642: task = (task_t) queue_first(list); ! 1643: while (!queue_end(list, (queue_entry_t) task)) { ! 1644: if (task->policy == policy) ! 1645: task_max_priority(task, pset, max); ! 1646: task = (task_t) queue_next(&task->pset_tasks); ! 1647: } ! 1648: ! 1649: list = &pset->threads; ! 1650: thread = (thread_t) queue_first(list); ! 1651: while (!queue_end(list, (queue_entry_t) thread)) { ! 1652: thr_act = thread_lock_act(thread); ! 1653: if (thr_act && thread->policy == policy) ! 1654: thread_max_priority(thr_act, pset, max); ! 1655: thread_unlock_act(thread); ! 1656: thread = (thread_t) queue_next(&thread->pset_threads); ! 1657: } ! 1658: } ! 1659: ! 1660: pset_unlock(pset); ! 1661: ! 1662: return(KERN_SUCCESS); ! 1663: } ! 1664: ! 1665: ! 1666: /* ! 1667: * New scheduling control interface ! 1668: */ ! 1669: ! 1670: /* ! 1671: * processor_set_policy_control ! 1672: * ! 1673: * Controls the scheduling attributes governing the processor set. ! 1674: * Allows control of enabled policies, and per-policy base and limit ! 1675: * priorities. ! 1676: */ ! 1677: kern_return_t ! 1678: processor_set_policy_control( ! 1679: processor_set_t pset, ! 1680: int flavor, ! 1681: processor_set_info_t policy_info, ! 1682: mach_msg_type_number_t count, ! 1683: boolean_t change) ! 1684: { ! 1685: policy_t policy, i; ! 1686: policy_base_t base; ! 1687: policy_limit_t limit; ! 1688: kern_return_t ret = KERN_SUCCESS; ! 1689: ! 1690: if (pset == PROCESSOR_SET_NULL) ! 1691: return (KERN_INVALID_PROCESSOR_SET); ! 1692: ! 1693: switch (flavor) { ! 1694: case PROCESSOR_SET_ENABLED_POLICIES: ! 1695: if (count != sizeof(policy_t)) ! 1696: return(KERN_INVALID_ARGUMENT); ! 1697: policy = (policy_t) *policy_info; ! 1698: for (i = POLICY_TIMESHARE ; i <= POLICY_FIFO ; i = i << 1) { ! 1699: if (policy & i) { ! 1700: ret = processor_set_policy_enable(pset, i); ! 1701: if (ret != KERN_SUCCESS) return ret; ! 1702: } else { ! 1703: ret = processor_set_policy_disable(pset, i, change); ! 1704: if (ret != KERN_SUCCESS) return ret; ! 1705: } ! 1706: } ! 1707: return ret; ! 1708: ! 1709: case PROCESSOR_SET_RR_LIMITS: ! 1710: if (count != POLICY_RR_LIMIT_COUNT) ! 1711: return(KERN_INVALID_ARGUMENT); ! 1712: limit = (policy_limit_t) policy_info; ! 1713: ret = processor_set_limit(pset, POLICY_RR, limit, change); ! 1714: return ret; ! 1715: ! 1716: case PROCESSOR_SET_FIFO_LIMITS: ! 1717: if (count != POLICY_FIFO_LIMIT_COUNT) ! 1718: return(KERN_INVALID_ARGUMENT); ! 1719: limit = (policy_limit_t) policy_info; ! 1720: ret = processor_set_limit(pset, POLICY_FIFO, limit, change); ! 1721: return ret; ! 1722: ! 1723: case PROCESSOR_SET_TIMESHARE_LIMITS: ! 1724: if (count != POLICY_TIMESHARE_LIMIT_COUNT) ! 1725: return(KERN_INVALID_ARGUMENT); ! 1726: limit = (policy_limit_t) policy_info; ! 1727: ret = processor_set_limit(pset, POLICY_TIMESHARE, limit, ! 1728: change); ! 1729: return ret; ! 1730: ! 1731: case PROCESSOR_SET_RR_DEFAULT: ! 1732: if (count != POLICY_RR_BASE_COUNT) ! 1733: return(KERN_INVALID_ARGUMENT); ! 1734: base = (policy_base_t) policy_info; ! 1735: ret = processor_set_base(pset, POLICY_RR, base, change); ! 1736: return ret; ! 1737: ! 1738: case PROCESSOR_SET_FIFO_DEFAULT: ! 1739: if (count != POLICY_FIFO_BASE_COUNT) ! 1740: return(KERN_INVALID_ARGUMENT); ! 1741: base = (policy_base_t) policy_info; ! 1742: ret = processor_set_base(pset, POLICY_FIFO, base, change); ! 1743: return ret; ! 1744: ! 1745: case PROCESSOR_SET_TIMESHARE_DEFAULT: ! 1746: if (count != POLICY_TIMESHARE_BASE_COUNT) ! 1747: return(KERN_INVALID_ARGUMENT); ! 1748: base = (policy_base_t) policy_info; ! 1749: ret = processor_set_base(pset, POLICY_TIMESHARE, ! 1750: base, change); ! 1751: return ret; ! 1752: ! 1753: default: ! 1754: return (KERN_INVALID_ARGUMENT); ! 1755: ! 1756: } ! 1757: ! 1758: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.