/* *Complete the shutdown and place the processor offline. * * Called at splsched in the shutdown context. */ void processor_offline( processor_t processor) { thread_t new_thread, old_thread = processor->active_thread; new_thread = processor->idle_thread; processor->active_thread = new_thread; processor->current_pri = IDLEPRI; processor->current_thmode = TH_MODE_NONE; processor->deadline = UINT64_MAX; new_thread->last_processor = processor; processor->last_dispatch = mach_absolute_time(); timer_stop(PROCESSOR_DATA(processor, thread_timer), processor->last_dispatch); machine_set_current_thread(new_thread); thread_dispatch(old_thread, new_thread); PMAP_DEACTIVATE_KERNEL(processor->cpu_id); cpu_sleep(); panic("zombie processor"); /*NOTREACHED*/ }
/* * load_context: * * Start the first thread on a processor. */ static void load_context( thread_t thread) { processor_t processor = current_processor(); #define load_context_kprintf(x...) /* kprintf("load_context: " x) */ load_context_kprintf("calling machine_set_current_thread\n"); machine_set_current_thread(thread); load_context_kprintf("calling processor_up\n"); processor_up(processor); PMAP_ACTIVATE_KERNEL(processor->cpu_id); /* * Acquire a stack if none attached. The panic * should never occur since the thread is expected * to have reserved stack. */ load_context_kprintf("thread %p, stack %lx, stackptr %lx\n", thread, thread->kernel_stack, thread->machine.kstackptr); if (!thread->kernel_stack) { load_context_kprintf("calling stack_alloc_try\n"); if (!stack_alloc_try(thread)) panic("load_context"); } /* * The idle processor threads are not counted as * running for load calculations. */ if (!(thread->state & TH_IDLE)) sched_run_incr(); processor->active_thread = thread; processor->current_pri = thread->sched_pri; processor->current_thmode = thread->sched_mode; processor->deadline = UINT64_MAX; thread->last_processor = processor; processor->last_dispatch = mach_absolute_time(); timer_start(&thread->system_timer, processor->last_dispatch); PROCESSOR_DATA(processor, thread_timer) = PROCESSOR_DATA(processor, kernel_timer) = &thread->system_timer; timer_start(&PROCESSOR_DATA(processor, system_state), processor->last_dispatch); PROCESSOR_DATA(processor, current_state) = &PROCESSOR_DATA(processor, system_state); PMAP_ACTIVATE_USER(thread, processor->cpu_id); load_context_kprintf("calling machine_load_context\n"); machine_load_context(thread); /*NOTREACHED*/ }
/* * Complete the shutdown and place the processor offline. * * Called at splsched in the shutdown context. * This performs a minimal thread_invoke() to the idle thread, * so it needs to be kept in sync with what thread_invoke() does. * * The onlining half of this is done in load_context(). */ void processor_offline( processor_t processor) { assert(processor == current_processor()); assert(processor->active_thread == current_thread()); thread_t old_thread = processor->active_thread; thread_t new_thread = processor->idle_thread; processor->active_thread = new_thread; processor->current_pri = IDLEPRI; processor->current_thmode = TH_MODE_NONE; processor->starting_pri = IDLEPRI; processor->current_sfi_class = SFI_CLASS_KERNEL; processor->deadline = UINT64_MAX; new_thread->last_processor = processor; uint64_t ctime = mach_absolute_time(); processor->last_dispatch = ctime; old_thread->last_run_time = ctime; /* Update processor->thread_timer and ->kernel_timer to point to the new thread */ thread_timer_event(ctime, &new_thread->system_timer); PROCESSOR_DATA(processor, kernel_timer) = &new_thread->system_timer; timer_stop(PROCESSOR_DATA(processor, current_state), ctime); KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, MACHDBG_CODE(DBG_MACH_SCHED, MACH_SCHED) | DBG_FUNC_NONE, old_thread->reason, (uintptr_t)thread_tid(new_thread), old_thread->sched_pri, new_thread->sched_pri, 0); machine_set_current_thread(new_thread); thread_dispatch(old_thread, new_thread); PMAP_DEACTIVATE_KERNEL(processor->cpu_id); cpu_sleep(); panic("zombie processor"); /*NOTREACHED*/ }
void thread_bootstrap(void) { /* * Fill in a template thread for fast initialization. */ thread_template.runq = PROCESSOR_NULL; thread_template.ref_count = 2; thread_template.reason = AST_NONE; thread_template.at_safe_point = FALSE; thread_template.wait_event = NO_EVENT64; thread_template.wait_queue = WAIT_QUEUE_NULL; thread_template.wait_result = THREAD_WAITING; thread_template.options = THREAD_ABORTSAFE; thread_template.state = TH_WAIT | TH_UNINT; thread_template.wake_active = FALSE; thread_template.continuation = THREAD_CONTINUE_NULL; thread_template.parameter = NULL; thread_template.importance = 0; thread_template.sched_mode = TH_MODE_NONE; thread_template.sched_flags = 0; thread_template.saved_mode = TH_MODE_NONE; thread_template.safe_release = 0; thread_template.priority = 0; thread_template.sched_pri = 0; thread_template.max_priority = 0; thread_template.task_priority = 0; thread_template.promotions = 0; thread_template.pending_promoter_index = 0; thread_template.pending_promoter[0] = thread_template.pending_promoter[1] = NULL; thread_template.realtime.deadline = UINT64_MAX; thread_template.current_quantum = 0; thread_template.last_run_time = 0; thread_template.last_quantum_refill_time = 0; thread_template.computation_metered = 0; thread_template.computation_epoch = 0; #if defined(CONFIG_SCHED_TRADITIONAL) thread_template.sched_stamp = 0; thread_template.pri_shift = INT8_MAX; thread_template.sched_usage = 0; thread_template.cpu_usage = thread_template.cpu_delta = 0; #endif thread_template.c_switch = thread_template.p_switch = thread_template.ps_switch = 0; thread_template.bound_processor = PROCESSOR_NULL; thread_template.last_processor = PROCESSOR_NULL; thread_template.sched_call = sched_call_null; timer_init(&thread_template.user_timer); timer_init(&thread_template.system_timer); thread_template.user_timer_save = 0; thread_template.system_timer_save = 0; thread_template.vtimer_user_save = 0; thread_template.vtimer_prof_save = 0; thread_template.vtimer_rlim_save = 0; thread_template.wait_timer_is_set = FALSE; thread_template.wait_timer_active = 0; thread_template.depress_timer_active = 0; thread_template.special_handler.handler = special_handler; thread_template.special_handler.next = NULL; thread_template.funnel_lock = THR_FUNNEL_NULL; thread_template.funnel_state = 0; thread_template.recover = (vm_offset_t)NULL; thread_template.map = VM_MAP_NULL; #if CONFIG_DTRACE thread_template.t_dtrace_predcache = 0; thread_template.t_dtrace_vtime = 0; thread_template.t_dtrace_tracing = 0; #endif /* CONFIG_DTRACE */ thread_template.t_chud = 0; thread_template.t_page_creation_count = 0; thread_template.t_page_creation_time = 0; thread_template.affinity_set = NULL; thread_template.syscalls_unix = 0; thread_template.syscalls_mach = 0; thread_template.t_ledger = LEDGER_NULL; thread_template.t_threadledger = LEDGER_NULL; thread_template.appliedstate = default_task_null_policy; thread_template.ext_appliedstate = default_task_null_policy; thread_template.policystate = default_task_proc_policy; thread_template.ext_policystate = default_task_proc_policy; #if CONFIG_EMBEDDED thread_template.taskwatch = NULL; thread_template.saved_importance = 0; #endif /* CONFIG_EMBEDDED */ init_thread = thread_template; machine_set_current_thread(&init_thread); }