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