|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1993-1988 Carnegie Mellon University ! 4: * All Rights Reserved. ! 5: * ! 6: * Permission to use, copy, modify and distribute this software and its ! 7: * documentation is hereby granted, provided that both the copyright ! 8: * notice and this permission notice appear in all copies of the ! 9: * software, derivative works or modified versions, and any portions ! 10: * thereof, and that both notices appear in supporting documentation. ! 11: * ! 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 15: * ! 16: * Carnegie Mellon requests users of this software to return to ! 17: * ! 18: * Software Distribution Coordinator or [email protected] ! 19: * School of Computer Science ! 20: * Carnegie Mellon University ! 21: * Pittsburgh PA 15213-3890 ! 22: * ! 23: * any improvements or extensions that they make and grant Carnegie Mellon ! 24: * the rights to redistribute these changes. ! 25: */ ! 26: /* ! 27: * processor.c: processor and processor_set manipulation routines. ! 28: */ ! 29: ! 30: #include <cpus.h> ! 31: #include <mach_fixpri.h> ! 32: #include <mach_host.h> ! 33: ! 34: #include <mach/boolean.h> ! 35: #include <mach/policy.h> ! 36: #include <mach/processor_info.h> ! 37: #include <mach/vm_param.h> ! 38: #include <kern/cpu_number.h> ! 39: #include <kern/lock.h> ! 40: #include <kern/host.h> ! 41: #include <kern/processor.h> ! 42: #include <kern/sched.h> ! 43: #include <kern/task.h> ! 44: #include <kern/thread.h> ! 45: #include <kern/ipc_host.h> ! 46: #include <ipc/ipc_port.h> ! 47: ! 48: #if MACH_HOST ! 49: #include <kern/zalloc.h> ! 50: zone_t pset_zone; ! 51: #endif /* MACH_HOST */ ! 52: ! 53: ! 54: /* ! 55: * Exported variables. ! 56: */ ! 57: struct processor_set default_pset; ! 58: struct processor processor_array[NCPUS]; ! 59: ! 60: queue_head_t all_psets; ! 61: int all_psets_count; ! 62: decl_simple_lock_data(, all_psets_lock); ! 63: ! 64: processor_t master_processor; ! 65: processor_t processor_ptr[NCPUS]; ! 66: ! 67: /* ! 68: * Forward declarations. ! 69: */ ! 70: void quantum_set(processor_set_t); ! 71: void pset_init(processor_set_t); ! 72: void processor_init(processor_t, int); ! 73: ! 74: /* ! 75: * Bootstrap the processor/pset system so the scheduler can run. ! 76: */ ! 77: void pset_sys_bootstrap(void) ! 78: { ! 79: register int i; ! 80: ! 81: pset_init(&default_pset); ! 82: default_pset.empty = FALSE; ! 83: for (i = 0; i < NCPUS; i++) { ! 84: /* ! 85: * Initialize processor data structures. ! 86: * Note that cpu_to_processor(i) is processor_ptr[i]. ! 87: */ ! 88: processor_ptr[i] = &processor_array[i]; ! 89: processor_init(processor_ptr[i], i); ! 90: } ! 91: master_processor = cpu_to_processor(master_cpu); ! 92: queue_init(&all_psets); ! 93: simple_lock_init(&all_psets_lock); ! 94: queue_enter(&all_psets, &default_pset, processor_set_t, all_psets); ! 95: all_psets_count = 1; ! 96: default_pset.active = TRUE; ! 97: default_pset.empty = FALSE; ! 98: ! 99: /* ! 100: * Note: the default_pset has a max_priority of BASEPRI_USER. ! 101: * Internal kernel threads override this in kernel_thread. ! 102: */ ! 103: } ! 104: ! 105: #if MACH_HOST ! 106: /* ! 107: * Rest of pset system initializations. ! 108: */ ! 109: void pset_sys_init(void) ! 110: { ! 111: register int i; ! 112: register processor_t processor; ! 113: ! 114: /* ! 115: * Allocate the zone for processor sets. ! 116: */ ! 117: pset_zone = zinit(sizeof(struct processor_set), 128*PAGE_SIZE, ! 118: PAGE_SIZE, 0, "processor sets"); ! 119: ! 120: /* ! 121: * Give each processor a control port. ! 122: * The master processor already has one. ! 123: */ ! 124: for (i = 0; i < NCPUS; i++) { ! 125: processor = cpu_to_processor(i); ! 126: if (processor != master_processor && ! 127: machine_slot[i].is_cpu) ! 128: { ! 129: ipc_processor_init(processor); ! 130: } ! 131: } ! 132: } ! 133: #endif /* MACH_HOST */ ! 134: ! 135: /* ! 136: * Initialize the given processor_set structure. ! 137: */ ! 138: ! 139: void pset_init( ! 140: register processor_set_t pset) ! 141: { ! 142: int i; ! 143: ! 144: simple_lock_init(&pset->runq.lock); ! 145: pset->runq.low = 0; ! 146: pset->runq.count = 0; ! 147: for (i = 0; i < NRQS; i++) { ! 148: queue_init(&(pset->runq.runq[i])); ! 149: } ! 150: queue_init(&pset->idle_queue); ! 151: pset->idle_count = 0; ! 152: simple_lock_init(&pset->idle_lock); ! 153: queue_init(&pset->processors); ! 154: pset->processor_count = 0; ! 155: pset->empty = TRUE; ! 156: queue_init(&pset->tasks); ! 157: pset->task_count = 0; ! 158: queue_init(&pset->threads); ! 159: pset->thread_count = 0; ! 160: pset->ref_count = 1; ! 161: simple_lock_init(&pset->ref_lock); ! 162: queue_init(&pset->all_psets); ! 163: pset->active = FALSE; ! 164: simple_lock_init(&pset->lock); ! 165: pset->pset_self = IP_NULL; ! 166: pset->pset_name_self = IP_NULL; ! 167: pset->max_priority = BASEPRI_USER; ! 168: #if MACH_FIXPRI ! 169: pset->policies = POLICY_TIMESHARE; ! 170: #endif /* MACH_FIXPRI */ ! 171: pset->set_quantum = min_quantum; ! 172: #if NCPUS > 1 ! 173: pset->quantum_adj_index = 0; ! 174: simple_lock_init(&pset->quantum_adj_lock); ! 175: ! 176: for (i = 0; i <= NCPUS; i++) { ! 177: pset->machine_quantum[i] = min_quantum; ! 178: } ! 179: #endif /* NCPUS > 1 */ ! 180: pset->mach_factor = 0; ! 181: pset->load_average = 0; ! 182: pset->sched_load = SCHED_SCALE; /* i.e. 1 */ ! 183: } ! 184: ! 185: /* ! 186: * Initialize the given processor structure for the processor in ! 187: * the slot specified by slot_num. ! 188: */ ! 189: ! 190: void processor_init( ! 191: register processor_t pr, ! 192: int slot_num) ! 193: { ! 194: int i; ! 195: ! 196: simple_lock_init(&pr->runq.lock); ! 197: pr->runq.low = 0; ! 198: pr->runq.count = 0; ! 199: for (i = 0; i < NRQS; i++) { ! 200: queue_init(&(pr->runq.runq[i])); ! 201: } ! 202: queue_init(&pr->processor_queue); ! 203: pr->state = PROCESSOR_OFF_LINE; ! 204: pr->next_thread = THREAD_NULL; ! 205: pr->idle_thread = THREAD_NULL; ! 206: pr->quantum = 0; ! 207: pr->first_quantum = FALSE; ! 208: pr->last_quantum = 0; ! 209: pr->processor_set = PROCESSOR_SET_NULL; ! 210: pr->processor_set_next = PROCESSOR_SET_NULL; ! 211: queue_init(&pr->processors); ! 212: simple_lock_init(&pr->lock); ! 213: pr->processor_self = IP_NULL; ! 214: pr->slot_num = slot_num; ! 215: } ! 216: ! 217: /* ! 218: * pset_remove_processor() removes a processor from a processor_set. ! 219: * It can only be called on the current processor. Caller must ! 220: * hold lock on current processor and processor set. ! 221: */ ! 222: ! 223: void pset_remove_processor( ! 224: processor_set_t pset, ! 225: processor_t processor) ! 226: { ! 227: if (pset != processor->processor_set) ! 228: panic("pset_remove_processor: wrong pset"); ! 229: ! 230: queue_remove(&pset->processors, processor, processor_t, processors); ! 231: processor->processor_set = PROCESSOR_SET_NULL; ! 232: pset->processor_count--; ! 233: quantum_set(pset); ! 234: } ! 235: ! 236: /* ! 237: * pset_add_processor() adds a processor to a processor_set. ! 238: * It can only be called on the current processor. Caller must ! 239: * hold lock on curent processor and on pset. No reference counting on ! 240: * processors. Processor reference to pset is implicit. ! 241: */ ! 242: ! 243: void pset_add_processor( ! 244: processor_set_t pset, ! 245: processor_t processor) ! 246: { ! 247: queue_enter(&pset->processors, processor, processor_t, processors); ! 248: processor->processor_set = pset; ! 249: pset->processor_count++; ! 250: quantum_set(pset); ! 251: } ! 252: ! 253: /* ! 254: * pset_remove_task() removes a task from a processor_set. ! 255: * Caller must hold locks on pset and task. Pset reference count ! 256: * is not decremented; caller must explicitly pset_deallocate. ! 257: */ ! 258: ! 259: void pset_remove_task( ! 260: processor_set_t pset, ! 261: task_t task) ! 262: { ! 263: if (pset != task->processor_set) ! 264: return; ! 265: ! 266: queue_remove(&pset->tasks, task, task_t, pset_tasks); ! 267: task->processor_set = PROCESSOR_SET_NULL; ! 268: pset->task_count--; ! 269: } ! 270: ! 271: /* ! 272: * pset_add_task() adds a task to a processor_set. ! 273: * Caller must hold locks on pset and task. Pset references to ! 274: * tasks are implicit. ! 275: */ ! 276: ! 277: void pset_add_task( ! 278: processor_set_t pset, ! 279: task_t task) ! 280: { ! 281: queue_enter(&pset->tasks, task, task_t, pset_tasks); ! 282: task->processor_set = pset; ! 283: pset->task_count++; ! 284: } ! 285: ! 286: /* ! 287: * pset_remove_thread() removes a thread from a processor_set. ! 288: * Caller must hold locks on pset and thread. Pset reference count ! 289: * is not decremented; caller must explicitly pset_deallocate. ! 290: */ ! 291: ! 292: void pset_remove_thread( ! 293: processor_set_t pset, ! 294: thread_t thread) ! 295: { ! 296: queue_remove(&pset->threads, thread, thread_t, pset_threads); ! 297: thread->processor_set = PROCESSOR_SET_NULL; ! 298: pset->thread_count--; ! 299: } ! 300: ! 301: /* ! 302: * pset_add_thread() adds a thread to a processor_set. ! 303: * Caller must hold locks on pset and thread. Pset references to ! 304: * threads are implicit. ! 305: */ ! 306: ! 307: void pset_add_thread( ! 308: processor_set_t pset, ! 309: thread_t thread) ! 310: { ! 311: queue_enter(&pset->threads, thread, thread_t, pset_threads); ! 312: thread->processor_set = pset; ! 313: pset->thread_count++; ! 314: } ! 315: ! 316: /* ! 317: * thread_change_psets() changes the pset of a thread. Caller must ! 318: * hold locks on both psets and thread. The old pset must be ! 319: * explicitly pset_deallocat()'ed by caller. ! 320: */ ! 321: ! 322: void thread_change_psets( ! 323: thread_t thread, ! 324: processor_set_t old_pset, ! 325: processor_set_t new_pset) ! 326: { ! 327: queue_remove(&old_pset->threads, thread, thread_t, pset_threads); ! 328: old_pset->thread_count--; ! 329: queue_enter(&new_pset->threads, thread, thread_t, pset_threads); ! 330: thread->processor_set = new_pset; ! 331: new_pset->thread_count++; ! 332: } ! 333: ! 334: /* ! 335: * pset_deallocate: ! 336: * ! 337: * Remove one reference to the processor set. Destroy processor_set ! 338: * if this was the last reference. ! 339: */ ! 340: void pset_deallocate( ! 341: processor_set_t pset) ! 342: { ! 343: if (pset == PROCESSOR_SET_NULL) ! 344: return; ! 345: ! 346: pset_ref_lock(pset); ! 347: if (--pset->ref_count > 0) { ! 348: pset_ref_unlock(pset); ! 349: return; ! 350: } ! 351: #if !MACH_HOST ! 352: panic("pset_deallocate: default_pset destroyed"); ! 353: #endif /* !MACH_HOST */ ! 354: ! 355: #if MACH_HOST ! 356: /* ! 357: * Reference count is zero, however the all_psets list ! 358: * holds an implicit reference and may make new ones. ! 359: * Its lock also dominates the pset lock. To check for this, ! 360: * temporarily restore one reference, and then lock the ! 361: * other structures in the right order. ! 362: */ ! 363: pset->ref_count = 1; ! 364: pset_ref_unlock(pset); ! 365: ! 366: simple_lock(&all_psets_lock); ! 367: pset_ref_lock(pset); ! 368: if (--pset->ref_count > 0) { ! 369: /* ! 370: * Made an extra reference. ! 371: */ ! 372: pset_ref_unlock(pset); ! 373: simple_unlock(&all_psets_lock); ! 374: return; ! 375: } ! 376: ! 377: /* ! 378: * Ok to destroy pset. Make a few paranoia checks. ! 379: */ ! 380: ! 381: if ((pset == &default_pset) || (pset->thread_count > 0) || ! 382: (pset->task_count > 0) || pset->processor_count > 0) { ! 383: panic("pset_deallocate: destroy default or active pset"); ! 384: } ! 385: /* ! 386: * Remove from all_psets queue. ! 387: */ ! 388: queue_remove(&all_psets, pset, processor_set_t, all_psets); ! 389: all_psets_count--; ! 390: ! 391: pset_ref_unlock(pset); ! 392: simple_unlock(&all_psets_lock); ! 393: ! 394: /* ! 395: * That's it, free data structure. ! 396: */ ! 397: zfree(pset_zone, (vm_offset_t)pset); ! 398: #endif /* MACH_HOST */ ! 399: } ! 400: ! 401: /* ! 402: * pset_reference: ! 403: * ! 404: * Add one reference to the processor set. ! 405: */ ! 406: void pset_reference( ! 407: processor_set_t pset) ! 408: { ! 409: pset_ref_lock(pset); ! 410: pset->ref_count++; ! 411: pset_ref_unlock(pset); ! 412: } ! 413: ! 414: kern_return_t ! 415: processor_info( ! 416: register processor_t processor, ! 417: int flavor, ! 418: host_t *host, ! 419: processor_info_t info, ! 420: natural_t *count) ! 421: { ! 422: register int slot_num, state; ! 423: register processor_basic_info_t basic_info; ! 424: ! 425: if (processor == PROCESSOR_NULL) ! 426: return KERN_INVALID_ARGUMENT; ! 427: ! 428: if (flavor != PROCESSOR_BASIC_INFO || ! 429: *count < PROCESSOR_BASIC_INFO_COUNT) ! 430: return KERN_FAILURE; ! 431: ! 432: basic_info = (processor_basic_info_t) info; ! 433: ! 434: slot_num = processor->slot_num; ! 435: basic_info->cpu_type = machine_slot[slot_num].cpu_type; ! 436: basic_info->cpu_subtype = machine_slot[slot_num].cpu_subtype; ! 437: state = processor->state; ! 438: if (state == PROCESSOR_SHUTDOWN || state == PROCESSOR_OFF_LINE) ! 439: basic_info->running = FALSE; ! 440: else ! 441: basic_info->running = TRUE; ! 442: basic_info->slot_num = slot_num; ! 443: if (processor == master_processor) ! 444: basic_info->is_master = TRUE; ! 445: else ! 446: basic_info->is_master = FALSE; ! 447: ! 448: *count = PROCESSOR_BASIC_INFO_COUNT; ! 449: *host = &realhost; ! 450: return KERN_SUCCESS; ! 451: } ! 452: ! 453: kern_return_t processor_start( ! 454: processor_t processor) ! 455: { ! 456: if (processor == PROCESSOR_NULL) ! 457: return KERN_INVALID_ARGUMENT; ! 458: #if NCPUS > 1 ! 459: return cpu_start(processor->slot_num); ! 460: #else /* NCPUS > 1 */ ! 461: return KERN_FAILURE; ! 462: #endif /* NCPUS > 1 */ ! 463: } ! 464: ! 465: kern_return_t processor_exit( ! 466: processor_t processor) ! 467: { ! 468: if (processor == PROCESSOR_NULL) ! 469: return KERN_INVALID_ARGUMENT; ! 470: ! 471: #if NCPUS > 1 ! 472: return processor_shutdown(processor); ! 473: #else /* NCPUS > 1 */ ! 474: return KERN_FAILURE; ! 475: #endif /* NCPUS > 1 */ ! 476: } ! 477: ! 478: kern_return_t ! 479: processor_control( ! 480: processor_t processor, ! 481: processor_info_t info, ! 482: natural_t count) ! 483: { ! 484: if (processor == PROCESSOR_NULL) ! 485: return KERN_INVALID_ARGUMENT; ! 486: ! 487: #if NCPUS > 1 ! 488: return cpu_control(processor->slot_num, (int *)info, count); ! 489: #else /* NCPUS > 1 */ ! 490: return KERN_FAILURE; ! 491: #endif /* NCPUS > 1 */ ! 492: } ! 493: ! 494: /* ! 495: * Precalculate the appropriate system quanta based on load. The ! 496: * index into machine_quantum is the number of threads on the ! 497: * processor set queue. It is limited to the number of processors in ! 498: * the set. ! 499: */ ! 500: ! 501: void quantum_set( ! 502: processor_set_t pset) ! 503: { ! 504: #if NCPUS > 1 ! 505: register int i,ncpus; ! 506: ! 507: ncpus = pset->processor_count; ! 508: ! 509: for ( i=1 ; i <= ncpus ; i++) { ! 510: pset->machine_quantum[i] = ! 511: ((min_quantum * ncpus) + (i/2)) / i ; ! 512: } ! 513: pset->machine_quantum[0] = 2 * pset->machine_quantum[1]; ! 514: ! 515: i = ((pset->runq.count > pset->processor_count) ? ! 516: pset->processor_count : pset->runq.count); ! 517: pset->set_quantum = pset->machine_quantum[i]; ! 518: #else /* NCPUS > 1 */ ! 519: default_pset.set_quantum = min_quantum; ! 520: #endif /* NCPUS > 1 */ ! 521: } ! 522: ! 523: #if MACH_HOST ! 524: /* ! 525: * processor_set_create: ! 526: * ! 527: * Create and return a new processor set. ! 528: */ ! 529: ! 530: kern_return_t ! 531: processor_set_create( ! 532: host_t host, ! 533: processor_set_t *new_set, ! 534: processor_set_t *new_name) ! 535: { ! 536: processor_set_t pset; ! 537: ! 538: if (host == HOST_NULL) ! 539: return KERN_INVALID_ARGUMENT; ! 540: ! 541: pset = (processor_set_t) zalloc(pset_zone); ! 542: pset_init(pset); ! 543: pset_reference(pset); /* for new_set out argument */ ! 544: pset_reference(pset); /* for new_name out argument */ ! 545: ipc_pset_init(pset); ! 546: pset->active = TRUE; ! 547: ! 548: simple_lock(&all_psets_lock); ! 549: queue_enter(&all_psets, pset, processor_set_t, all_psets); ! 550: all_psets_count++; ! 551: simple_unlock(&all_psets_lock); ! 552: ! 553: ipc_pset_enable(pset); ! 554: ! 555: *new_set = pset; ! 556: *new_name = pset; ! 557: return KERN_SUCCESS; ! 558: } ! 559: ! 560: /* ! 561: * processor_set_destroy: ! 562: * ! 563: * destroy a processor set. Any tasks, threads or processors ! 564: * currently assigned to it are reassigned to the default pset. ! 565: */ ! 566: kern_return_t processor_set_destroy( ! 567: processor_set_t pset) ! 568: { ! 569: register queue_entry_t elem; ! 570: register queue_head_t *list; ! 571: ! 572: if (pset == PROCESSOR_SET_NULL || pset == &default_pset) ! 573: return KERN_INVALID_ARGUMENT; ! 574: ! 575: /* ! 576: * Handle multiple termination race. First one through sets ! 577: * active to FALSE and disables ipc access. ! 578: */ ! 579: pset_lock(pset); ! 580: if (!(pset->active)) { ! 581: pset_unlock(pset); ! 582: return KERN_FAILURE; ! 583: } ! 584: ! 585: pset->active = FALSE; ! 586: ipc_pset_disable(pset); ! 587: ! 588: ! 589: /* ! 590: * Now reassign everything in this set to the default set. ! 591: */ ! 592: ! 593: if (pset->task_count > 0) { ! 594: list = &pset->tasks; ! 595: while (!queue_empty(list)) { ! 596: elem = queue_first(list); ! 597: task_reference((task_t) elem); ! 598: pset_unlock(pset); ! 599: task_assign((task_t) elem, &default_pset, FALSE); ! 600: task_deallocate((task_t) elem); ! 601: pset_lock(pset); ! 602: } ! 603: } ! 604: ! 605: if (pset->thread_count > 0) { ! 606: list = &pset->threads; ! 607: while (!queue_empty(list)) { ! 608: elem = queue_first(list); ! 609: thread_reference((thread_t) elem); ! 610: pset_unlock(pset); ! 611: thread_assign((thread_t) elem, &default_pset); ! 612: thread_deallocate((thread_t) elem); ! 613: pset_lock(pset); ! 614: } ! 615: } ! 616: ! 617: if (pset->processor_count > 0) { ! 618: list = &pset->processors; ! 619: while(!queue_empty(list)) { ! 620: elem = queue_first(list); ! 621: pset_unlock(pset); ! 622: processor_assign((processor_t) elem, &default_pset, TRUE); ! 623: pset_lock(pset); ! 624: } ! 625: } ! 626: ! 627: pset_unlock(pset); ! 628: ! 629: /* ! 630: * Destroy ipc state. ! 631: */ ! 632: ipc_pset_terminate(pset); ! 633: ! 634: /* ! 635: * Deallocate pset's reference to itself. ! 636: */ ! 637: pset_deallocate(pset); ! 638: return KERN_SUCCESS; ! 639: } ! 640: ! 641: #else /* MACH_HOST */ ! 642: ! 643: kern_return_t ! 644: processor_set_create( ! 645: host_t host, ! 646: processor_set_t *new_set, ! 647: processor_set_t *new_name) ! 648: { ! 649: #ifdef lint ! 650: host++; new_set++; new_name++; ! 651: #endif /* lint */ ! 652: return KERN_FAILURE; ! 653: } ! 654: ! 655: kern_return_t processor_set_destroy( ! 656: processor_set_t pset) ! 657: { ! 658: #ifdef lint ! 659: pset++; ! 660: #endif /* lint */ ! 661: return KERN_FAILURE; ! 662: } ! 663: ! 664: #endif /* MACH_HOST */ ! 665: ! 666: kern_return_t ! 667: processor_get_assignment( ! 668: processor_t processor, ! 669: processor_set_t *pset) ! 670: { ! 671: int state; ! 672: ! 673: state = processor->state; ! 674: if (state == PROCESSOR_SHUTDOWN || state == PROCESSOR_OFF_LINE) ! 675: return KERN_FAILURE; ! 676: ! 677: *pset = processor->processor_set; ! 678: pset_reference(*pset); ! 679: return KERN_SUCCESS; ! 680: } ! 681: ! 682: kern_return_t ! 683: processor_set_info( ! 684: processor_set_t pset, ! 685: int flavor, ! 686: host_t *host, ! 687: processor_set_info_t info, ! 688: natural_t *count) ! 689: { ! 690: if (pset == PROCESSOR_SET_NULL) ! 691: return KERN_INVALID_ARGUMENT; ! 692: ! 693: if (flavor == PROCESSOR_SET_BASIC_INFO) { ! 694: register processor_set_basic_info_t basic_info; ! 695: ! 696: if (*count < PROCESSOR_SET_BASIC_INFO_COUNT) ! 697: return KERN_FAILURE; ! 698: ! 699: basic_info = (processor_set_basic_info_t) info; ! 700: ! 701: pset_lock(pset); ! 702: basic_info->processor_count = pset->processor_count; ! 703: basic_info->task_count = pset->task_count; ! 704: basic_info->thread_count = pset->thread_count; ! 705: basic_info->mach_factor = pset->mach_factor; ! 706: basic_info->load_average = pset->load_average; ! 707: pset_unlock(pset); ! 708: ! 709: *count = PROCESSOR_SET_BASIC_INFO_COUNT; ! 710: *host = &realhost; ! 711: return KERN_SUCCESS; ! 712: } ! 713: else if (flavor == PROCESSOR_SET_SCHED_INFO) { ! 714: register processor_set_sched_info_t sched_info; ! 715: ! 716: if (*count < PROCESSOR_SET_SCHED_INFO_COUNT) ! 717: return KERN_FAILURE; ! 718: ! 719: sched_info = (processor_set_sched_info_t) info; ! 720: ! 721: pset_lock(pset); ! 722: #if MACH_FIXPRI ! 723: sched_info->policies = pset->policies; ! 724: #else /* MACH_FIXPRI */ ! 725: sched_info->policies = POLICY_TIMESHARE; ! 726: #endif /* MACH_FIXPRI */ ! 727: sched_info->max_priority = pset->max_priority; ! 728: pset_unlock(pset); ! 729: ! 730: *count = PROCESSOR_SET_SCHED_INFO_COUNT; ! 731: *host = &realhost; ! 732: return KERN_SUCCESS; ! 733: } ! 734: ! 735: *host = HOST_NULL; ! 736: return KERN_INVALID_ARGUMENT; ! 737: } ! 738: ! 739: /* ! 740: * processor_set_max_priority: ! 741: * ! 742: * Specify max priority permitted on processor set. This affects ! 743: * newly created and assigned threads. Optionally change existing ! 744: * ones. ! 745: */ ! 746: kern_return_t ! 747: processor_set_max_priority( ! 748: processor_set_t pset, ! 749: int max_priority, ! 750: boolean_t change_threads) ! 751: { ! 752: if (pset == PROCESSOR_SET_NULL || invalid_pri(max_priority)) ! 753: return KERN_INVALID_ARGUMENT; ! 754: ! 755: pset_lock(pset); ! 756: pset->max_priority = max_priority; ! 757: ! 758: if (change_threads) { ! 759: register queue_head_t *list; ! 760: register thread_t thread; ! 761: ! 762: list = &pset->threads; ! 763: queue_iterate(list, thread, thread_t, pset_threads) { ! 764: if (thread->max_priority < max_priority) ! 765: thread_max_priority(thread, pset, max_priority); ! 766: } ! 767: } ! 768: ! 769: pset_unlock(pset); ! 770: ! 771: return KERN_SUCCESS; ! 772: } ! 773: ! 774: /* ! 775: * processor_set_policy_enable: ! 776: * ! 777: * Allow indicated policy on processor set. ! 778: */ ! 779: ! 780: kern_return_t ! 781: processor_set_policy_enable( ! 782: processor_set_t pset, ! 783: int policy) ! 784: { ! 785: if ((pset == PROCESSOR_SET_NULL) || invalid_policy(policy)) ! 786: return KERN_INVALID_ARGUMENT; ! 787: ! 788: #if MACH_FIXPRI ! 789: pset_lock(pset); ! 790: pset->policies |= policy; ! 791: pset_unlock(pset); ! 792: ! 793: return KERN_SUCCESS; ! 794: #else /* MACH_FIXPRI */ ! 795: if (policy == POLICY_TIMESHARE) ! 796: return KERN_SUCCESS; ! 797: else ! 798: return KERN_FAILURE; ! 799: #endif /* MACH_FIXPRI */ ! 800: } ! 801: ! 802: /* ! 803: * processor_set_policy_disable: ! 804: * ! 805: * Forbid indicated policy on processor set. Time sharing cannot ! 806: * be forbidden. ! 807: */ ! 808: ! 809: kern_return_t ! 810: processor_set_policy_disable( ! 811: processor_set_t pset, ! 812: int policy, ! 813: boolean_t change_threads) ! 814: { ! 815: if ((pset == PROCESSOR_SET_NULL) || policy == POLICY_TIMESHARE || ! 816: invalid_policy(policy)) ! 817: return KERN_INVALID_ARGUMENT; ! 818: ! 819: #if MACH_FIXPRI ! 820: pset_lock(pset); ! 821: ! 822: /* ! 823: * Check if policy enabled. Disable if so, then handle ! 824: * change_threads. ! 825: */ ! 826: if (pset->policies & policy) { ! 827: pset->policies &= ~policy; ! 828: ! 829: if (change_threads) { ! 830: register queue_head_t *list; ! 831: register thread_t thread; ! 832: ! 833: list = &pset->threads; ! 834: queue_iterate(list, thread, thread_t, pset_threads) { ! 835: if (thread->policy == policy) ! 836: thread_policy(thread, POLICY_TIMESHARE, 0); ! 837: } ! 838: } ! 839: } ! 840: pset_unlock(pset); ! 841: #endif /* MACH_FIXPRI */ ! 842: ! 843: return KERN_SUCCESS; ! 844: } ! 845: ! 846: #define THING_TASK 0 ! 847: #define THING_THREAD 1 ! 848: ! 849: /* ! 850: * processor_set_things: ! 851: * ! 852: * Common internals for processor_set_{threads,tasks} ! 853: */ ! 854: kern_return_t ! 855: processor_set_things( ! 856: processor_set_t pset, ! 857: mach_port_t **thing_list, ! 858: natural_t *count, ! 859: int type) ! 860: { ! 861: unsigned int actual; /* this many things */ ! 862: int i; ! 863: ! 864: vm_size_t size, size_needed; ! 865: vm_offset_t addr; ! 866: ! 867: if (pset == PROCESSOR_SET_NULL) ! 868: return KERN_INVALID_ARGUMENT; ! 869: ! 870: size = 0; addr = 0; ! 871: ! 872: for (;;) { ! 873: pset_lock(pset); ! 874: if (!pset->active) { ! 875: pset_unlock(pset); ! 876: return KERN_FAILURE; ! 877: } ! 878: ! 879: if (type == THING_TASK) ! 880: actual = pset->task_count; ! 881: else ! 882: actual = pset->thread_count; ! 883: ! 884: /* do we have the memory we need? */ ! 885: ! 886: size_needed = actual * sizeof(mach_port_t); ! 887: if (size_needed <= size) ! 888: break; ! 889: ! 890: /* unlock the pset and allocate more memory */ ! 891: pset_unlock(pset); ! 892: ! 893: if (size != 0) ! 894: kfree(addr, size); ! 895: ! 896: assert(size_needed > 0); ! 897: size = size_needed; ! 898: ! 899: addr = kalloc(size); ! 900: if (addr == 0) ! 901: return KERN_RESOURCE_SHORTAGE; ! 902: } ! 903: ! 904: /* OK, have memory and the processor_set is locked & active */ ! 905: ! 906: switch (type) { ! 907: case THING_TASK: { ! 908: task_t *tasks = (task_t *) addr; ! 909: task_t task; ! 910: ! 911: for (i = 0, task = (task_t) queue_first(&pset->tasks); ! 912: i < actual; ! 913: i++, task = (task_t) queue_next(&task->pset_tasks)) { ! 914: /* take ref for convert_task_to_port */ ! 915: task_reference(task); ! 916: tasks[i] = task; ! 917: } ! 918: assert(queue_end(&pset->tasks, (queue_entry_t) task)); ! 919: break; ! 920: } ! 921: ! 922: case THING_THREAD: { ! 923: thread_t *threads = (thread_t *) addr; ! 924: thread_t thread; ! 925: ! 926: for (i = 0, thread = (thread_t) queue_first(&pset->threads); ! 927: i < actual; ! 928: i++, ! 929: thread = (thread_t) queue_next(&thread->pset_threads)) { ! 930: /* take ref for convert_thread_to_port */ ! 931: thread_reference(thread); ! 932: threads[i] = thread; ! 933: } ! 934: assert(queue_end(&pset->threads, (queue_entry_t) thread)); ! 935: break; ! 936: } ! 937: } ! 938: ! 939: /* can unlock processor set now that we have the task/thread refs */ ! 940: pset_unlock(pset); ! 941: ! 942: if (actual == 0) { ! 943: /* no things, so return null pointer and deallocate memory */ ! 944: *thing_list = 0; ! 945: *count = 0; ! 946: ! 947: if (size != 0) ! 948: kfree(addr, size); ! 949: } else { ! 950: /* if we allocated too much, must copy */ ! 951: ! 952: if (size_needed < size) { ! 953: vm_offset_t newaddr; ! 954: ! 955: newaddr = kalloc(size_needed); ! 956: if (newaddr == 0) { ! 957: switch (type) { ! 958: case THING_TASK: { ! 959: task_t *tasks = (task_t *) addr; ! 960: ! 961: for (i = 0; i < actual; i++) ! 962: task_deallocate(tasks[i]); ! 963: break; ! 964: } ! 965: ! 966: case THING_THREAD: { ! 967: thread_t *threads = (thread_t *) addr; ! 968: ! 969: for (i = 0; i < actual; i++) ! 970: thread_deallocate(threads[i]); ! 971: break; ! 972: } ! 973: } ! 974: kfree(addr, size); ! 975: return KERN_RESOURCE_SHORTAGE; ! 976: } ! 977: ! 978: bcopy((char *) addr, (char *) newaddr, size_needed); ! 979: kfree(addr, size); ! 980: addr = newaddr; ! 981: } ! 982: ! 983: *thing_list = (mach_port_t *) addr; ! 984: *count = actual; ! 985: ! 986: /* do the conversion that Mig should handle */ ! 987: ! 988: switch (type) { ! 989: case THING_TASK: { ! 990: task_t *tasks = (task_t *) addr; ! 991: ! 992: for (i = 0; i < actual; i++) ! 993: ((mach_port_t *) tasks)[i] = ! 994: (mach_port_t)convert_task_to_port(tasks[i]); ! 995: break; ! 996: } ! 997: ! 998: case THING_THREAD: { ! 999: thread_t *threads = (thread_t *) addr; ! 1000: ! 1001: for (i = 0; i < actual; i++) ! 1002: ((mach_port_t *) threads)[i] = ! 1003: (mach_port_t)convert_thread_to_port(threads[i]); ! 1004: break; ! 1005: } ! 1006: } ! 1007: } ! 1008: ! 1009: return KERN_SUCCESS; ! 1010: } ! 1011: ! 1012: ! 1013: /* ! 1014: * processor_set_tasks: ! 1015: * ! 1016: * List all tasks in the processor set. ! 1017: */ ! 1018: kern_return_t ! 1019: processor_set_tasks( ! 1020: processor_set_t pset, ! 1021: task_array_t *task_list, ! 1022: natural_t *count) ! 1023: { ! 1024: return processor_set_things(pset, task_list, count, THING_TASK); ! 1025: } ! 1026: ! 1027: /* ! 1028: * processor_set_threads: ! 1029: * ! 1030: * List all threads in the processor set. ! 1031: */ ! 1032: kern_return_t ! 1033: processor_set_threads( ! 1034: processor_set_t pset, ! 1035: thread_array_t *thread_list, ! 1036: natural_t *count) ! 1037: { ! 1038: return processor_set_things(pset, thread_list, count, THING_THREAD); ! 1039: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.