]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/kern/machine.c
xnu-517.tar.gz
[apple/xnu.git] / osfmk / kern / machine.c
index 20f13346e149b3cf3aac1bd08ac7d25b612ff933..33ff1338e450f022deaa93937bcf04ab8fe453cc 100644 (file)
 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");