|
|
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,1987 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: * File: kern/machine.c ! 54: * Author: Avadis Tevanian, Jr. ! 55: * Date: 1987 ! 56: * ! 57: * Support for machine independent machine abstraction. ! 58: */ ! 59: ! 60: #include <cpus.h> ! 61: #include <mach_host.h> ! 62: ! 63: #include <string.h> ! 64: #include <mach/boolean.h> ! 65: #include <mach/kern_return.h> ! 66: #include <mach/mach_types.h> ! 67: #include <mach/machine.h> ! 68: #include <mach/host_info.h> ! 69: #include <mach/host_reboot.h> ! 70: #include <kern/counters.h> ! 71: #include <kern/cpu_data.h> ! 72: #include <kern/ipc_host.h> ! 73: #include <kern/host.h> ! 74: #include <kern/lock.h> ! 75: #include <kern/machine.h> ! 76: #include <kern/processor.h> ! 77: #include <kern/queue.h> ! 78: #include <kern/sched.h> ! 79: #include <kern/task.h> ! 80: #include <kern/thread.h> ! 81: #include <kern/thread_swap.h> ! 82: #include <kern/misc_protos.h> ! 83: ! 84: #include <mach/mach_host_server.h> ! 85: ! 86: ! 87: /* ! 88: * Exported variables: ! 89: */ ! 90: ! 91: struct machine_info machine_info; ! 92: struct machine_slot machine_slot[NCPUS]; ! 93: ! 94: queue_head_t action_queue; /* assign/shutdown queue */ ! 95: decl_simple_lock_data(,action_lock) ! 96: ! 97: static thread_call_t processor_action_call; ! 98: ! 99: /* Forwards */ ! 100: processor_set_t processor_request_action( ! 101: processor_t processor, ! 102: processor_set_t new_pset); ! 103: ! 104: void processor_doaction( ! 105: processor_t processor); ! 106: ! 107: void processor_doshutdown( ! 108: processor_t processor); ! 109: ! 110: int thread_stop_freeze( ! 111: thread_t thread, ! 112: processor_set_t pset); ! 113: ! 114: /* ! 115: * cpu_up: ! 116: * ! 117: * Flag specified cpu as up and running. Called when a processor comes ! 118: * online. ! 119: */ ! 120: void ! 121: cpu_up( ! 122: int cpu) ! 123: { ! 124: processor_t processor; ! 125: struct machine_slot *ms; ! 126: spl_t s; ! 127: ! 128: processor = cpu_to_processor(cpu); ! 129: /* ! 130: * Can't risk blocking with no current thread established. ! 131: * Just twiddle our thumbs; we've got nothing better to do ! 132: * yet, anyway. ! 133: */ ! 134: while (!pset_lock_try(&default_pset)) ! 135: continue; ! 136: ! 137: s = splsched(); ! 138: processor_lock(processor); ! 139: #if NCPUS > 1 ! 140: init_ast_check(processor); ! 141: #endif /* NCPUS > 1 */ ! 142: ms = &machine_slot[cpu]; ! 143: ms->running = TRUE; ! 144: machine_info.avail_cpus++; ! 145: pset_add_processor(&default_pset, processor); ! 146: processor->state = PROCESSOR_RUNNING; ! 147: processor_unlock(processor); ! 148: splx(s); ! 149: pset_unlock(&default_pset); ! 150: } ! 151: ! 152: /* ! 153: * cpu_down: ! 154: * ! 155: * Flag specified cpu as down. Called when a processor is about to ! 156: * go offline. ! 157: */ ! 158: ! 159: void ! 160: cpu_down( ! 161: int cpu) ! 162: { ! 163: processor_t processor; ! 164: struct machine_slot *ms; ! 165: spl_t s; ! 166: ! 167: processor = cpu_to_processor(cpu); ! 168: ! 169: s = splsched(); ! 170: processor_lock(processor); ! 171: ms = &machine_slot[cpu]; ! 172: ms->running = FALSE; ! 173: machine_info.avail_cpus--; ! 174: /* ! 175: * processor has already been removed from pset. ! 176: */ ! 177: processor->processor_set_next = PROCESSOR_SET_NULL; ! 178: processor->state = PROCESSOR_OFF_LINE; ! 179: processor_unlock(processor); ! 180: splx(s); ! 181: } ! 182: ! 183: kern_return_t ! 184: host_reboot( ! 185: host_t host, ! 186: int options) ! 187: { ! 188: if (host == HOST_NULL) ! 189: return (KERN_INVALID_HOST); ! 190: ! 191: if (options & HOST_REBOOT_DEBUGGER) { ! 192: Debugger("Debugger"); ! 193: } ! 194: else ! 195: halt_all_cpus(!(options & HOST_REBOOT_HALT)); ! 196: ! 197: return (KERN_SUCCESS); ! 198: } ! 199: ! 200: #if NCPUS > 1 ! 201: /* ! 202: * processor_request_action - common internals of processor_assign ! 203: * and processor_shutdown. If new_pset is null, this is ! 204: * a shutdown, else it's an assign and caller must donate ! 205: * a reference. For assign operations, it returns ! 206: * an old pset that must be deallocated if it's not NULL. For ! 207: * shutdown operations, it always returns PROCESSOR_SET_NULL. ! 208: */ ! 209: processor_set_t ! 210: processor_request_action( ! 211: processor_t processor, ! 212: processor_set_t new_pset) ! 213: { ! 214: register processor_set_t pset, old_next_pset; ! 215: ! 216: /* ! 217: * Processor must be in a processor set. Must lock its idle lock to ! 218: * get at processor state. ! 219: */ ! 220: pset = processor->processor_set; ! 221: simple_lock(&pset->idle_lock); ! 222: ! 223: /* ! 224: * If the processor is dispatching, let it finish - it will set its ! 225: * state to running very soon. ! 226: */ ! 227: while (*(volatile int *)&processor->state == PROCESSOR_DISPATCHING) ! 228: continue; ! 229: ! 230: /* ! 231: * Now lock the action queue and do the dirty work. ! 232: */ ! 233: simple_lock(&action_lock); ! 234: ! 235: switch (processor->state) { ! 236: ! 237: case PROCESSOR_IDLE: ! 238: /* ! 239: * Remove from idle queue. ! 240: */ ! 241: queue_remove(&pset->idle_queue, ! 242: processor, processor_t, processor_queue); ! 243: pset->idle_count--; ! 244: ! 245: /* fall through ... */ ! 246: case PROCESSOR_RUNNING: ! 247: /* ! 248: * Put it on the action queue. ! 249: */ ! 250: queue_enter(&action_queue, ! 251: processor, processor_t,processor_queue); ! 252: ! 253: /* fall through ... */ ! 254: case PROCESSOR_ASSIGN: ! 255: /* ! 256: * And ask the action_thread to do the work. ! 257: */ ! 258: ! 259: if (new_pset == PROCESSOR_SET_NULL) { ! 260: processor->state = PROCESSOR_SHUTDOWN; ! 261: old_next_pset = PROCESSOR_SET_NULL; ! 262: } ! 263: else { ! 264: processor->state = PROCESSOR_ASSIGN; ! 265: old_next_pset = processor->processor_set_next; ! 266: processor->processor_set_next = new_pset; ! 267: } ! 268: break; ! 269: ! 270: default: ! 271: printf("state: %d\n", processor->state); ! 272: panic("processor_request_action: bad state"); ! 273: } ! 274: ! 275: simple_unlock(&action_lock); ! 276: simple_unlock(&pset->idle_lock); ! 277: ! 278: thread_call_enter(processor_action_call); ! 279: ! 280: return (old_next_pset); ! 281: } ! 282: ! 283: #if MACH_HOST ! 284: /* ! 285: * processor_assign() changes the processor set that a processor is ! 286: * assigned to. Any previous assignment in progress is overriden. ! 287: * Synchronizes with assignment completion if wait is TRUE. ! 288: */ ! 289: kern_return_t ! 290: processor_assign( ! 291: processor_t processor, ! 292: processor_set_t new_pset, ! 293: boolean_t wait) ! 294: { ! 295: register processor_set_t old_next_pset; ! 296: spl_t s; ! 297: ! 298: /* ! 299: * Check for null arguments. ! 300: * XXX Can't assign master processor. ! 301: */ ! 302: if ( processor == PROCESSOR_NULL || ! 303: new_pset == PROCESSOR_SET_NULL || ! 304: processor == master_processor) ! 305: return (KERN_FAILURE); ! 306: ! 307: /* ! 308: * Get pset reference to donate to processor_request_action. ! 309: */ ! 310: pset_reference(new_pset); ! 311: ! 312: s = splsched(); ! 313: processor_lock(processor); ! 314: if ( processor->state == PROCESSOR_OFF_LINE || ! 315: processor->state == PROCESSOR_SHUTDOWN) { ! 316: /* ! 317: * Already shutdown or being shutdown -- Can't reassign. ! 318: */ ! 319: processor_unlock(processor); ! 320: splx(s); ! 321: pset_deallocate(new_pset); ! 322: ! 323: return (KERN_FAILURE); ! 324: } ! 325: ! 326: old_next_pset = processor_request_action(processor, new_pset); ! 327: ! 328: ! 329: /* ! 330: * Synchronization with completion. ! 331: */ ! 332: while ( wait && (processor->state == PROCESSOR_ASSIGN || ! 333: processor->state == PROCESSOR_SHUTDOWN)) { ! 334: assert_wait((event_t)processor, THREAD_ABORTSAFE); ! 335: processor_unlock(processor); ! 336: splx(s); ! 337: ! 338: thread_block((void (*)(void)) 0); ! 339: ! 340: s = splsched(); ! 341: processor_lock(processor); ! 342: } ! 343: ! 344: processor_unlock(processor); ! 345: splx(s); ! 346: ! 347: if (old_next_pset != PROCESSOR_SET_NULL) ! 348: pset_deallocate(old_next_pset); ! 349: ! 350: return (KERN_SUCCESS); ! 351: } ! 352: ! 353: #else /* MACH_HOST */ ! 354: ! 355: kern_return_t ! 356: processor_assign( ! 357: processor_t processor, ! 358: processor_set_t new_pset, ! 359: boolean_t wait) ! 360: { ! 361: #ifdef lint ! 362: processor++; new_pset++; wait++; ! 363: #endif /* lint */ ! 364: return (KERN_FAILURE); ! 365: } ! 366: ! 367: #endif /* MACH_HOST */ ! 368: ! 369: /* ! 370: * processor_shutdown() queues a processor up for shutdown. ! 371: * Any assignment in progress is overriden. It does not synchronize ! 372: * with the shutdown (can be called from interrupt level). ! 373: */ ! 374: kern_return_t ! 375: processor_shutdown( ! 376: processor_t processor) ! 377: { ! 378: spl_t s; ! 379: ! 380: s = splsched(); ! 381: processor_lock(processor); ! 382: if ( processor->state == PROCESSOR_OFF_LINE || ! 383: processor->state == PROCESSOR_SHUTDOWN) { ! 384: /* ! 385: * Already shutdown or being shutdown -- nothing to do. ! 386: */ ! 387: processor_unlock(processor); ! 388: splx(s); ! 389: ! 390: return (KERN_SUCCESS); ! 391: } ! 392: ! 393: (void) processor_request_action(processor, PROCESSOR_SET_NULL); ! 394: processor_unlock(processor); ! 395: splx(s); ! 396: ! 397: return (KERN_SUCCESS); ! 398: } ! 399: ! 400: /* ! 401: * processor_action() shuts down processors or changes their assignment. ! 402: */ ! 403: ! 404: static thread_call_data_t processor_action_call_data; ! 405: ! 406: void ! 407: processor_action(void) ! 408: { ! 409: register processor_t processor; ! 410: spl_t s; ! 411: ! 412: s = splsched(); ! 413: simple_lock(&action_lock); ! 414: ! 415: if (processor_action_call == NULL) { ! 416: thread_call_setup(&processor_action_call_data, ! 417: processor_action, NULL); ! 418: processor_action_call = &processor_action_call_data; ! 419: } ! 420: ! 421: while (!queue_empty(&action_queue)) { ! 422: processor = (processor_t) queue_first(&action_queue); ! 423: queue_remove(&action_queue, processor, processor_t, processor_queue); ! 424: simple_unlock(&action_lock); ! 425: splx(s); ! 426: ! 427: processor_doaction(processor); ! 428: ! 429: s = splsched(); ! 430: simple_lock(&action_lock); ! 431: } ! 432: ! 433: simple_unlock(&action_lock); ! 434: splx(s); ! 435: } ! 436: ! 437: /* ! 438: * thread_stop_freeze ! 439: * Block the thread in the kernel and freeze the processor set. ! 440: * return value: ! 441: * TRUE - the thread has blocked interruptibly, is stopped, and ! 442: * the processor set assignment is frozen ! 443: * FALSE - the thread is no longer in the processor set, so it ! 444: * isn't stopped, and the processor set assignment ! 445: * is released. ! 446: */ ! 447: int ! 448: thread_stop_freeze( ! 449: thread_t thread, ! 450: processor_set_t pset) ! 451: { ! 452: #if 0 /* HACK ALERT!!!! (TEST/DEBUG) */ ! 453: thread_act_t thr_act; ! 454: spl_t s; ! 455: ! 456: /* ! 457: * hold it, and wait for it to stop. ! 458: */ ! 459: thr_act = thread_lock_act(thread); ! 460: thread_hold(thr_act); ! 461: act_unlock_thread(thr_act); ! 462: ! 463: thread_stop(thread); ! 464: ! 465: s = splsched(); ! 466: wake_lock(thread); ! 467: while( thread->state & (TH_RUN|TH_UNINT) ) { ! 468: thread->wake_active = TRUE; ! 469: assert_wait((event_t)&thread->wake_active, THREAD_UNINT); ! 470: wake_unlock(thread); ! 471: splx(s); ! 472: thread_block( (void (*)(void)) 0 ); ! 473: (void) splsched(); ! 474: wake_lock(thread); ! 475: } ! 476: ! 477: /* ! 478: * Now, the thread has blocked uninterruptibly; freeze the ! 479: * assignment and make sure it's still part of the processor set. ! 480: */ ! 481: wake_unlock(thread); ! 482: thread_freeze(thread); ! 483: thread_lock(thread); ! 484: ! 485: /* ! 486: * if the processor set has changed, release the freeze and ! 487: * then unstop it. ! 488: */ ! 489: if( thread->processor_set != pset ) { ! 490: thread_unlock(thread); ! 491: splx(s); ! 492: thread_unfreeze(thread); ! 493: thread_unstop(thread); ! 494: return FALSE; ! 495: } ! 496: thread_unlock(thread); ! 497: splx(s); ! 498: #endif /* HACK ALERT!!!! */ ! 499: ! 500: return TRUE; ! 501: } ! 502: ! 503: /* ! 504: * processor_doaction actually does the shutdown. The trick here ! 505: * is to schedule ourselves onto a cpu and then save our ! 506: * context back into the runqs before taking out the cpu. ! 507: */ ! 508: ! 509: void ! 510: processor_doaction( ! 511: processor_t processor) ! 512: { ! 513: thread_t this_thread; ! 514: spl_t s; ! 515: register processor_set_t pset; ! 516: #if MACH_HOST ! 517: register processor_set_t new_pset; ! 518: register thread_t thread; ! 519: register thread_t prev_thread = THREAD_NULL; ! 520: thread_act_t thr_act; ! 521: boolean_t have_pset_ref = FALSE; ! 522: #endif /* MACH_HOST */ ! 523: ! 524: /* ! 525: * Get onto the processor to shutdown ! 526: */ ! 527: this_thread = current_thread(); ! 528: thread_bind(this_thread, processor); ! 529: thread_block((void (*)(void)) 0); ! 530: ! 531: pset = processor->processor_set; ! 532: #if MACH_HOST ! 533: /* ! 534: * If this is the last processor in the processor_set, ! 535: * stop all the threads first. ! 536: */ ! 537: pset_lock(pset); ! 538: if (pset->processor_count == 1) { ! 539: thread = (thread_t) queue_first(&pset->threads); ! 540: prev_thread = THREAD_NULL; ! 541: pset->ref_count++; ! 542: have_pset_ref = TRUE; ! 543: pset->empty = TRUE; ! 544: ! 545: /* ! 546: * loop through freezing the processor set assignment ! 547: * and reference counting the threads; ! 548: */ ! 549: while (!queue_end(&pset->threads, (queue_entry_t) thread)) { ! 550: thread_reference(thread); ! 551: pset_unlock(pset); ! 552: ! 553: /* ! 554: * Freeze the thread on the processor set. ! 555: * If it's moved, just release the reference. ! 556: * Get the next thread in the processor set list ! 557: * from the last one which was frozen. ! 558: */ ! 559: if (thread_stop_freeze(thread, pset)) ! 560: prev_thread = thread; ! 561: else ! 562: thread_deallocate(thread); ! 563: ! 564: pset_lock(pset); ! 565: if (prev_thread != THREAD_NULL) ! 566: thread = (thread_t)queue_next(&prev_thread->pset_threads); ! 567: else ! 568: thread = (thread_t) queue_first(&pset->threads); ! 569: } ! 570: ! 571: /* ! 572: * Remove the processor from the set so that when the threads ! 573: * are unstopped below the ones blocked in the kernel don't ! 574: * start running again. ! 575: */ ! 576: s = splsched(); ! 577: processor_lock(processor); ! 578: pset_remove_processor(pset, processor); ! 579: ! 580: /* ! 581: * Prevent race with another processor being added to the set ! 582: * See code after Restart_pset: ! 583: * while(new_pset->empty && new_pset->processor_count > 0) ! 584: * ! 585: * ... it tests for the condition where a new processor is ! 586: * added to the set while the last one is still being removed. ! 587: */ ! 588: pset->processor_count++; /* block new processors being added */ ! 589: assert(pset->processor_count == 1); ! 590: ! 591: /* ! 592: * Release the thread assignment locks, unstop the threads and ! 593: * release the thread references which were taken above. ! 594: */ ! 595: thread = (thread_t) queue_first(&pset->threads); ! 596: while(!queue_empty(&pset->threads) && (thread != THREAD_NULL)) { ! 597: prev_thread = thread; ! 598: if (queue_end(&pset->threads, (queue_entry_t) thread)) ! 599: thread = THREAD_NULL; ! 600: else ! 601: thread = (thread_t) queue_next(&prev_thread->pset_threads); ! 602: ! 603: pset_unlock(pset); ! 604: thread_unfreeze(prev_thread); ! 605: thread_unstop(prev_thread); ! 606: thread_deallocate(prev_thread); ! 607: pset_lock(pset); ! 608: } ! 609: /* ! 610: * allow a processor to be added to the empty pset ! 611: */ ! 612: pset->processor_count--; ! 613: } ! 614: else { ! 615: /* not last processor in set */ ! 616: #endif /* MACH_HOST */ ! 617: /* ! 618: * At this point, it is ok to rm the processor from the pset. ! 619: */ ! 620: s = splsched(); ! 621: processor_lock(processor); ! 622: pset_remove_processor(pset, processor); ! 623: #if MACH_HOST ! 624: } ! 625: pset_unlock(pset); ! 626: ! 627: /* ! 628: * Copy the next pset pointer into a local variable and clear ! 629: * it because we are taking over its reference. ! 630: */ ! 631: new_pset = processor->processor_set_next; ! 632: processor->processor_set_next = PROCESSOR_SET_NULL; ! 633: ! 634: if (processor->state == PROCESSOR_ASSIGN) { ! 635: ! 636: Restart_pset: ! 637: /* ! 638: * Nasty problem: we want to lock the target pset, but ! 639: * we have to enable interrupts to do that which requires ! 640: * dropping the processor lock. While the processor ! 641: * is unlocked, it could be reassigned or shutdown. ! 642: */ ! 643: processor_unlock(processor); ! 644: splx(s); ! 645: ! 646: /* ! 647: * Lock target pset and handle remove last / assign first race. ! 648: * Only happens if there is more than one action thread. ! 649: */ ! 650: pset_lock(new_pset); ! 651: while (new_pset->empty && new_pset->processor_count > 0) { ! 652: pset_unlock(new_pset); ! 653: while ( *(volatile boolean_t *)&new_pset->empty && ! 654: *(volatile int *)&new_pset->processor_count > 0) ! 655: continue; ! 656: pset_lock(new_pset); ! 657: } ! 658: ! 659: /* ! 660: * Finally relock the processor and see if something changed. ! 661: * The only possibilities are assignment to a different pset ! 662: * and shutdown. ! 663: */ ! 664: s = splsched(); ! 665: processor_lock(processor); ! 666: ! 667: if (processor->state == PROCESSOR_SHUTDOWN) { ! 668: pset_unlock(new_pset); ! 669: goto shutdown; /* will release pset reference */ ! 670: } ! 671: ! 672: if (processor->processor_set_next != PROCESSOR_SET_NULL) { ! 673: /* ! 674: * Processor was reassigned. Drop the reference ! 675: * we have on the wrong new_pset, and get the ! 676: * right one. Involves lots of lock juggling. ! 677: */ ! 678: processor_unlock(processor); ! 679: splx(s); ! 680: pset_unlock(new_pset); ! 681: pset_deallocate(new_pset); ! 682: ! 683: s = splsched(); ! 684: processor_lock(processor); ! 685: new_pset = processor->processor_set_next; ! 686: processor->processor_set_next = PROCESSOR_SET_NULL; ! 687: goto Restart_pset; ! 688: } ! 689: ! 690: /* ! 691: * If the pset has been deactivated since the operation ! 692: * was requested, redirect to the default pset. ! 693: */ ! 694: if (!new_pset->active) { ! 695: pset_unlock(new_pset); ! 696: pset_deallocate(new_pset); ! 697: new_pset = &default_pset; ! 698: apset_lock(new_pset); ! 699: new_pset->ref_count++; ! 700: } ! 701: ! 702: /* ! 703: * Do assignment, then wakeup anyone waiting for it. ! 704: * Finally context switch to have it take effect. ! 705: */ ! 706: pset_add_processor(new_pset, processor); ! 707: if (new_pset->empty) { ! 708: /* ! 709: * Set all the threads loose ! 710: */ ! 711: thread = (thread_t) queue_first(&new_pset->threads); ! 712: while (!queue_end(&new_pset->threads,(queue_entry_t)thread)) { ! 713: thr_act = thread_lock_act(thread); ! 714: thread_release(thread->top_act); ! 715: act_unlock_thread(thr_act); ! 716: thread = (thread_t) queue_next(&thread->pset_threads); ! 717: } ! 718: ! 719: new_pset->empty = FALSE; ! 720: } ! 721: processor->processor_set_next = PROCESSOR_SET_NULL; ! 722: processor->state = PROCESSOR_RUNNING; ! 723: thread_wakeup((event_t)processor); ! 724: processor_unlock(processor); ! 725: splx(s); ! 726: pset_unlock(new_pset); ! 727: ! 728: /* ! 729: * Clean up dangling references, and release our binding. ! 730: */ ! 731: pset_deallocate(new_pset); ! 732: if (have_pset_ref) ! 733: pset_deallocate(pset); ! 734: ! 735: if (prev_thread != THREAD_NULL) ! 736: thread_deallocate(prev_thread); ! 737: ! 738: thread_bind(this_thread, PROCESSOR_NULL); ! 739: ! 740: thread_block((void (*)(void)) 0); ! 741: return; ! 742: } ! 743: ! 744: shutdown: ! 745: #endif /* MACH_HOST */ ! 746: ! 747: /* ! 748: * Do shutdown, make sure we live when processor dies. ! 749: */ ! 750: if (processor->state != PROCESSOR_SHUTDOWN) { ! 751: printf("state: %d\n", processor->state); ! 752: panic("action_thread -- bad processor state"); ! 753: } ! 754: processor_unlock(processor); ! 755: /* ! 756: * Clean up dangling references, and release our binding. ! 757: */ ! 758: #if MACH_HOST ! 759: if (new_pset != PROCESSOR_SET_NULL) ! 760: pset_deallocate(new_pset); ! 761: if (have_pset_ref) ! 762: pset_deallocate(pset); ! 763: if (prev_thread != THREAD_NULL) ! 764: thread_deallocate(prev_thread); ! 765: #endif /* MACH_HOST */ ! 766: ! 767: thread_bind(this_thread, PROCESSOR_NULL); ! 768: switch_to_shutdown_context(this_thread, processor_doshutdown, processor); ! 769: splx(s); ! 770: } ! 771: ! 772: /* ! 773: * Actually do the processor shutdown. This is called at splsched, ! 774: * running on the processor's shutdown stack. ! 775: */ ! 776: ! 777: void ! 778: processor_doshutdown( ! 779: processor_t processor) ! 780: { ! 781: register int cpu = processor->slot_num; ! 782: ! 783: timer_switch(&kernel_timer[cpu]); ! 784: ! 785: /* ! 786: * OK, now exit this cpu. ! 787: */ ! 788: PMAP_DEACTIVATE_KERNEL(cpu); ! 789: cpu_data[cpu].active_thread = THREAD_NULL; ! 790: active_kloaded[cpu] = THR_ACT_NULL; ! 791: cpu_down(cpu); ! 792: thread_wakeup((event_t)processor); ! 793: halt_cpu(); ! 794: panic("zombie processor"); ! 795: ! 796: /* ! 797: * The action thread returns to life after the call to ! 798: * switch_to_shutdown_context above, on some other cpu. ! 799: */ ! 800: ! 801: /*NOTREACHED*/ ! 802: } ! 803: #else /* NCPUS > 1 */ ! 804: ! 805: kern_return_t ! 806: processor_assign( ! 807: processor_t processor, ! 808: processor_set_t new_pset, ! 809: boolean_t wait) ! 810: { ! 811: #ifdef lint ! 812: processor++; new_pset++; wait++; ! 813: #endif /* lint */ ! 814: return (KERN_FAILURE); ! 815: } ! 816: ! 817: #endif /* NCPUS > 1 */ ! 818: ! 819: kern_return_t ! 820: host_get_boot_info( ! 821: host_t priv_host, ! 822: kernel_boot_info_t boot_info) ! 823: { ! 824: char *src = ""; ! 825: extern char *machine_boot_info( ! 826: kernel_boot_info_t boot_info, ! 827: vm_size_t buf_len); ! 828: ! 829: if (priv_host == HOST_NULL) ! 830: return (KERN_INVALID_HOST); ! 831: ! 832: /* ! 833: * Copy first operator string terminated by '\0' followed by ! 834: * standardized strings generated from boot string. ! 835: */ ! 836: src = machine_boot_info(boot_info, KERNEL_BOOT_INFO_MAX); ! 837: if (src != boot_info) ! 838: (void) strncpy(boot_info, src, KERNEL_BOOT_INFO_MAX); ! 839: ! 840: return (KERN_SUCCESS); ! 841: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.