X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/43866e378188c25dd1e2208016ab3cbeb086ae6c..55e303ae13a4cf49d70f2294092726f2fffb9ef2:/osfmk/kern/machine.c?ds=inline diff --git a/osfmk/kern/machine.c b/osfmk/kern/machine.c index 20f13346e..33ff1338e 100644 --- a/osfmk/kern/machine.c +++ b/osfmk/kern/machine.c @@ -92,22 +92,9 @@ struct machine_info machine_info; struct machine_slot machine_slot[NCPUS]; -static queue_head_t processor_action_queue; -static boolean_t processor_action_active; -static thread_call_t processor_action_call; -static thread_call_data_t processor_action_call_data; -decl_simple_lock_data(static,processor_action_lock) - thread_t machine_wake_thread; /* Forwards */ -processor_set_t processor_request_action( - processor_t processor, - processor_set_t new_pset); - -void processor_doaction( - processor_t processor); - void processor_doshutdown( processor_t processor); @@ -125,13 +112,6 @@ cpu_up( processor_set_t pset = &default_pset; struct machine_slot *ms; spl_t s; - - /* - * Just twiddle our thumbs; we've got nothing better to do - * yet, anyway. - */ - while (!simple_lock_try(&pset->processors_lock)) - continue; s = splsched(); processor_lock(processor); @@ -139,15 +119,14 @@ cpu_up( ms = &machine_slot[cpu]; ms->running = TRUE; machine_info.avail_cpus++; - pset_add_processor(pset, processor); simple_lock(&pset->sched_lock); + pset_add_processor(pset, processor); enqueue_tail(&pset->active_queue, (queue_entry_t)processor); + processor->deadline = UINT64_MAX; processor->state = PROCESSOR_RUNNING; simple_unlock(&pset->sched_lock); processor_unlock(processor); splx(s); - - simple_unlock(&pset->processors_lock); } /* @@ -174,7 +153,6 @@ cpu_down( /* * processor has already been removed from pset. */ - processor->processor_set_next = PROCESSOR_SET_NULL; processor->state = PROCESSOR_OFF_LINE; processor_unlock(processor); splx(s); @@ -182,7 +160,7 @@ cpu_down( kern_return_t host_reboot( - host_priv_t host_priv, + host_priv_t host_priv, int options) { if (host_priv == HOST_PRIV_NULL) @@ -192,97 +170,12 @@ host_reboot( if (options & HOST_REBOOT_DEBUGGER) { Debugger("Debugger"); - } - else - halt_all_cpus(!(options & HOST_REBOOT_HALT)); - - return (KERN_SUCCESS); -} - -/* - * processor_request_action: - * - * Common internals of processor_assign and processor_shutdown. - * If new_pset is null, this is a shutdown, else it's an assign - * and caller must donate a reference. - * For assign operations, it returns an old pset that must be deallocated - * if it's not NULL. - * For shutdown operations, it always returns PROCESSOR_SET_NULL. - */ -processor_set_t -processor_request_action( - processor_t processor, - processor_set_t new_pset) -{ - processor_set_t pset, old_pset; - - /* - * Processor must be in a processor set. Must lock its idle lock to - * get at processor state. - */ - pset = processor->processor_set; - simple_lock(&pset->sched_lock); - - /* - * If the processor is dispatching, let it finish - it will set its - * state to running very soon. - */ - while (*(volatile int *)&processor->state == PROCESSOR_DISPATCHING) { - simple_unlock(&pset->sched_lock); - - simple_lock(&pset->sched_lock); - } - - assert( processor->state == PROCESSOR_IDLE || - processor->state == PROCESSOR_RUNNING || - processor->state == PROCESSOR_ASSIGN ); - - /* - * Now lock the action queue and do the dirty work. - */ - simple_lock(&processor_action_lock); - - if (processor->state == PROCESSOR_IDLE) { - remqueue(&pset->idle_queue, (queue_entry_t)processor); - pset->idle_count--; - } - else - if (processor->state == PROCESSOR_RUNNING) - remqueue(&pset->active_queue, (queue_entry_t)processor); - - if (processor->state != PROCESSOR_ASSIGN) - enqueue_tail(&processor_action_queue, (queue_entry_t)processor); - - /* - * And ask the action_thread to do the work. - */ - if (new_pset != PROCESSOR_SET_NULL) { - processor->state = PROCESSOR_ASSIGN; - old_pset = processor->processor_set_next; - processor->processor_set_next = new_pset; - } - else { - processor->state = PROCESSOR_SHUTDOWN; - old_pset = PROCESSOR_SET_NULL; - } - - simple_unlock(&pset->sched_lock); - - if (processor_action_active) { - simple_unlock(&processor_action_lock); - - return (old_pset); + return (KERN_SUCCESS); } - processor_action_active = TRUE; - simple_unlock(&processor_action_lock); + halt_all_cpus(!(options & HOST_REBOOT_HALT)); - processor_unlock(processor); - - thread_call_enter(processor_action_call); - processor_lock(processor); - - return (old_pset); + return (KERN_SUCCESS); } kern_return_t @@ -297,22 +190,19 @@ processor_assign( return (KERN_FAILURE); } -/* - * processor_shutdown() queues a processor up for shutdown. - * Any assignment in progress is overriden. - */ kern_return_t processor_shutdown( - processor_t processor) + processor_t processor) { - spl_t s; + processor_set_t pset; + spl_t s; s = splsched(); processor_lock(processor); if ( processor->state == PROCESSOR_OFF_LINE || processor->state == PROCESSOR_SHUTDOWN ) { /* - * Already shutdown or being shutdown -- nothing to do. + * Success if already shutdown or being shutdown. */ processor_unlock(processor); splx(s); @@ -320,135 +210,113 @@ processor_shutdown( return (KERN_SUCCESS); } - processor_request_action(processor, PROCESSOR_SET_NULL); - - assert_wait((event_t)processor, THREAD_UNINT); - - processor_unlock(processor); - splx(s); + if (processor->state == PROCESSOR_START) { + /* + * Failure if currently being started. + */ + processor_unlock(processor); + splx(s); - thread_block(THREAD_CONTINUE_NULL); + return (KERN_FAILURE); + } - return (KERN_SUCCESS); -} + /* + * Processor must be in a processor set. Must lock the scheduling + * lock to get at the processor state. + */ + pset = processor->processor_set; + simple_lock(&pset->sched_lock); -/* - * processor_action() shuts down processors or changes their assignment. - */ -static void -_processor_action( - thread_call_param_t p0, - thread_call_param_t p1) -{ - register processor_t processor; - spl_t s; + /* + * If the processor is dispatching, let it finish - it will set its + * state to running very soon. + */ + while (*(volatile int *)&processor->state == PROCESSOR_DISPATCHING) { + simple_unlock(&pset->sched_lock); + delay(1); + simple_lock(&pset->sched_lock); + } - s = splsched(); - simple_lock(&processor_action_lock); + if (processor->state == PROCESSOR_IDLE) { + remqueue(&pset->idle_queue, (queue_entry_t)processor); + pset->idle_count--; + } + else + if (processor->state == PROCESSOR_RUNNING) + remqueue(&pset->active_queue, (queue_entry_t)processor); + else + panic("processor_request_action"); - while (!queue_empty(&processor_action_queue)) { - processor = (processor_t)dequeue_head(&processor_action_queue); - simple_unlock(&processor_action_lock); - splx(s); + processor->state = PROCESSOR_SHUTDOWN; - processor_doaction(processor); + simple_unlock(&pset->sched_lock); - s = splsched(); - simple_lock(&processor_action_lock); - } + processor_unlock(processor); - processor_action_active = FALSE; - simple_unlock(&processor_action_lock); + processor_doshutdown(processor); splx(s); -} - -void -processor_action(void) -{ - queue_init(&processor_action_queue); - simple_lock_init(&processor_action_lock, ETAP_THREAD_ACTION); - processor_action_active = FALSE; - thread_call_setup(&processor_action_call_data, _processor_action, NULL); - processor_action_call = &processor_action_call_data; + return (KERN_SUCCESS); } /* - * processor_doaction actually does the shutdown. The trick here - * is to schedule ourselves onto a cpu and then save our - * context back into the runqs before taking out the cpu. + * Called at splsched. */ void -processor_doaction( - processor_t processor) +processor_doshutdown( + processor_t processor) { - thread_t self = current_thread(); + thread_t old_thread, self = current_thread(); processor_set_t pset; - thread_t old_thread; - spl_t s; + processor_t prev; /* * Get onto the processor to shutdown */ - thread_bind(self, processor); + prev = thread_bind(self, processor); thread_block(THREAD_CONTINUE_NULL); + processor_lock(processor); pset = processor->processor_set; - simple_lock(&pset->processors_lock); + simple_lock(&pset->sched_lock); if (pset->processor_count == 1) { thread_t thread; extern void start_cpu_thread(void); - simple_unlock(&pset->processors_lock); + simple_unlock(&pset->sched_lock); + processor_unlock(processor); /* * Create the thread, and point it at the routine. */ - thread = kernel_thread_with_priority( - kernel_task, MAXPRI_KERNEL, - start_cpu_thread, TRUE, FALSE); - - disable_preemption(); + thread = kernel_thread_create(start_cpu_thread, MAXPRI_KERNEL); - s = splsched(); thread_lock(thread); machine_wake_thread = thread; - thread_go_locked(thread, THREAD_AWAKENED); - (void)rem_runq(thread); + thread->state = TH_RUN; + pset_run_incr(thread->processor_set); thread_unlock(thread); - splx(s); - simple_lock(&pset->processors_lock); - enable_preemption(); + processor_lock(processor); + simple_lock(&pset->sched_lock); } - s = splsched(); - processor_lock(processor); - - /* - * Do shutdown, make sure we live when processor dies. - */ - if (processor->state != PROCESSOR_SHUTDOWN) { - panic("action_thread -- bad processor state"); - } + assert(processor->state == PROCESSOR_SHUTDOWN); pset_remove_processor(pset, processor); + simple_unlock(&pset->sched_lock); processor_unlock(processor); - simple_unlock(&pset->processors_lock); /* * Clean up. */ - thread_bind(self, PROCESSOR_NULL); - self->continuation = 0; + thread_bind(self, prev); old_thread = switch_to_shutdown_context(self, - processor_doshutdown, processor); + processor_offline, processor); if (processor != current_processor()) timer_call_shutdown(processor); thread_dispatch(old_thread); - thread_wakeup((event_t)processor); - splx(s); } /* @@ -457,20 +325,22 @@ processor_doaction( */ void -processor_doshutdown( +processor_offline( processor_t processor) { - register int cpu = processor->slot_num; + register thread_t old_thread = processor->active_thread; + register int cpu = processor->slot_num; timer_call_cancel(&processor->quantum_timer); - thread_dispatch(current_thread()); timer_switch(&kernel_timer[cpu]); + processor->active_thread = processor->idle_thread; + machine_thread_set_current(processor->active_thread); + thread_dispatch(old_thread); /* * OK, now exit this cpu. */ PMAP_DEACTIVATE_KERNEL(cpu); - thread_machine_set_current(processor->idle_thread); cpu_down(cpu); cpu_sleep(); panic("zombie processor");