|
|
1.1.1.2 ! root 1: /* 1.1 root 2: * Mach Operating System 3: * Copyright (c) 1993-1988 Carnegie Mellon University 4: * All Rights Reserved. 1.1.1.2 ! root 5: * 1.1 root 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. 1.1.1.2 ! root 11: * 1.1 root 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. 1.1.1.2 ! root 15: * 1.1 root 16: * Carnegie Mellon requests users of this software to return to 1.1.1.2 ! root 17: * 1.1 root 18: * Software Distribution Coordinator or [email protected] 19: * School of Computer Science 20: * Carnegie Mellon University 21: * Pittsburgh PA 15213-3890 1.1.1.2 ! root 22: * 1.1 root 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++; 1.1.1.2 ! root 332: } 1.1 root 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); 1.1.1.2 ! root 365: 1.1 root 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; 1.1.1.2 ! root 443: if (processor == master_processor) 1.1 root 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: } 1.1.1.2 ! root 616: 1.1 root 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 */ 1.1.1.2 ! root 642: 1.1 root 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: 1.1.1.2 ! root 664: #endif /* MACH_HOST */ 1.1 root 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.