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);
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);
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);
}
/*
/*
* processor has already been removed from pset.
*/
- processor->processor_set_next = PROCESSOR_SET_NULL;
processor->state = PROCESSOR_OFF_LINE;
processor_unlock(processor);
splx(s);
kern_return_t
host_reboot(
- host_priv_t host_priv,
+ host_priv_t host_priv,
int options)
{
if (host_priv == HOST_PRIV_NULL)
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
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);
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);
}
/*
*/
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");