]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/kern/machine.c
xnu-1699.22.73.tar.gz
[apple/xnu.git] / osfmk / kern / machine.c
index fe6ab43ce1a50dd69fe0ebbe1d173b7b8ecf296d..9b310f031cb6809ec9fcab9e74d06152bf8b5fc5 100644 (file)
@@ -1,31 +1,29 @@
 /*
- * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2009 Apple Inc. All rights reserved.
  *
- * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
- * This file contains Original Code and/or Modifications of Original Code 
- * as defined in and that are subject to the Apple Public Source License 
- * Version 2.0 (the 'License'). You may not use this file except in 
- * compliance with the License.  The rights granted to you under the 
- * License may not be used to create, or enable the creation or 
- * redistribution of, unlawful or unlicensed copies of an Apple operating 
- * system, or to circumvent, violate, or enable the circumvention or 
- * violation of, any terms of an Apple operating system software license 
- * agreement.
- *
- * Please obtain a copy of the License at 
- * http://www.opensource.apple.com/apsl/ and read it before using this 
- * file.
- *
- * The Original Code and all software distributed under the License are 
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
- * Please see the License for the specific language governing rights and 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ * 
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
  * limitations under the License.
- *
- * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
+ * 
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 /*
  * @OSF_COPYRIGHT@
 #include <kern/task.h>
 #include <kern/thread.h>
 
+#include <machine/commpage.h>
+
+#if HIBERNATION
 #include <IOKit/IOHibernatePrivate.h>
+#endif
+#include <IOKit/IOPlatformExpert.h>
 
 /*
  *     Exported variables:
@@ -110,22 +113,25 @@ void                      processor_doshutdown(
  */
 void
 processor_up(
-       processor_t             processor)
+       processor_t                     processor)
 {
-       processor_set_t         pset = &default_pset;
+       processor_set_t         pset;
        spl_t                           s;
 
        s = splsched();
-       processor_lock(processor);
        init_ast_check(processor);
-       simple_lock(&pset->sched_lock);
-       pset_add_processor(pset, processor);
+       pset = processor->processor_set;
+       pset_lock(pset);
+       if (++pset->online_processor_count == 1) {
+               pset_pri_init_hint(pset, processor);
+               pset_count_init_hint(pset, processor);
+       }
        enqueue_tail(&pset->active_queue, (queue_entry_t)processor);
        processor->state = PROCESSOR_RUNNING;
-       simple_unlock(&pset->sched_lock);
-       hw_atomic_add(&machine_info.avail_cpus, 1);
+       (void)hw_atomic_add(&processor_avail_count, 1);
+       commpage_update_active_cpus();
+       pset_unlock(pset);
        ml_cpu_up();
-       processor_unlock(processor);
        splx(s);
 }
 
@@ -144,7 +150,12 @@ host_reboot(
                return (KERN_SUCCESS);
        }
 
-       halt_all_cpus(!(options & HOST_REBOOT_HALT));
+    if (options & HOST_REBOOT_UPSDELAY) {
+        // UPS power cutoff path
+        PEHaltRestart( kPEUPSDelayHaltCPU );
+    } else {
+       halt_all_cpus(!(options & HOST_REBOOT_HALT));
+    }
 
        return (KERN_SUCCESS);
 }
@@ -166,12 +177,13 @@ processor_shutdown(
        spl_t                           s;
 
        s = splsched();
-       processor_lock(processor);
+       pset = processor->processor_set;
+       pset_lock(pset);
        if (processor->state == PROCESSOR_OFF_LINE) {
                /*
                 * Success if already shutdown.
                 */
-               processor_unlock(processor);
+               pset_unlock(pset);
                splx(s);
 
                return (KERN_SUCCESS);
@@ -181,70 +193,45 @@ processor_shutdown(
                /*
                 * Failure if currently being started.
                 */
-               processor_unlock(processor);
+               pset_unlock(pset);
                splx(s);
 
                return (KERN_FAILURE);
        }
 
        /*
-        * Must lock the scheduling lock
-        * to get at the processor state.
+        * If the processor is dispatching, let it finish.
         */
-       pset = processor->processor_set;
-       if (pset != PROCESSOR_SET_NULL) {
-               simple_lock(&pset->sched_lock);
-
-               /*
-                * If the processor is dispatching, let it finish.
-                */
-               while (processor->state == PROCESSOR_DISPATCHING) {
-                       simple_unlock(&pset->sched_lock);
-                       delay(1);
-                       simple_lock(&pset->sched_lock);
-               }
-
-               /*
-                * Success if already being shutdown.
-                */
-               if (processor->state == PROCESSOR_SHUTDOWN) {
-                       simple_unlock(&pset->sched_lock);
-                       processor_unlock(processor);
-                       splx(s);
-
-                       return (KERN_SUCCESS);
-               }
+       while (processor->state == PROCESSOR_DISPATCHING) {
+               pset_unlock(pset);
+               delay(1);
+               pset_lock(pset);
        }
-       else {
-               /*
-                * Success, already being shutdown.
-                */
-               processor_unlock(processor);
+
+       /*
+        * Success if already being shutdown.
+        */
+       if (processor->state == PROCESSOR_SHUTDOWN) {
+               pset_unlock(pset);
                splx(s);
 
                return (KERN_SUCCESS);
        }
 
-       if (processor->state == PROCESSOR_IDLE) {
-               remqueue(&pset->idle_queue, (queue_entry_t)processor);
-               pset->idle_count--;
-       }
+       if (processor->state == PROCESSOR_IDLE)
+               remqueue((queue_entry_t)processor);
        else
        if (processor->state == PROCESSOR_RUNNING)
-               remqueue(&pset->active_queue, (queue_entry_t)processor);
-       else
-               panic("processor_shutdown");
+               remqueue((queue_entry_t)processor);
 
        processor->state = PROCESSOR_SHUTDOWN;
 
-       simple_unlock(&pset->sched_lock);
-
-       processor_unlock(processor);
+       pset_unlock(pset);
 
        processor_doshutdown(processor);
        splx(s);
 
-       cpu_exit_wait(PROCESSOR_DATA(processor, slot_num));
+       cpu_exit_wait(processor->cpu_id);
 
        return (KERN_SUCCESS);
 }
@@ -257,60 +244,33 @@ processor_doshutdown(
        processor_t                     processor)
 {
        thread_t                        old_thread, self = current_thread();
-       processor_set_t         pset;
        processor_t                     prev;
-       int                                     pcount;
 
        /*
         *      Get onto the processor to shutdown
         */
-       prev = thread_bind(self, processor);
+       prev = thread_bind(processor);
        thread_block(THREAD_CONTINUE_NULL);
 
-       processor_lock(processor);
-       pset = processor->processor_set;
-       simple_lock(&pset->sched_lock);
-
-       if ((pcount = pset->processor_count) == 1) {
-               simple_unlock(&pset->sched_lock);
-               processor_unlock(processor);
-
+#if HIBERNATION
+       if (processor_avail_count < 2)
                hibernate_vm_lock();
-
-               processor_lock(processor);
-               simple_lock(&pset->sched_lock);
-       }
+#endif
 
        assert(processor->state == PROCESSOR_SHUTDOWN);
 
-       pset_remove_processor(pset, processor);
-       simple_unlock(&pset->sched_lock);
-       processor_unlock(processor);
-
-       if (pcount == 1)
+#if HIBERNATION
+       if (processor_avail_count < 2)
                hibernate_vm_unlock();
+#endif
 
        /*
         *      Continue processor shutdown in shutdown context.
         */
-       thread_bind(self, prev);
+       thread_bind(prev);
        old_thread = machine_processor_shutdown(self, processor_offline, processor);
 
-       thread_begin(self, self->last_processor);
-
-       thread_dispatch(old_thread);
-
-       /*
-        * If we just shutdown another processor, move the
-        * timer call outs to the current processor.
-        */
-       if (processor != current_processor()) {
-               processor_lock(processor);
-               if (    processor->state == PROCESSOR_OFF_LINE  ||
-                               processor->state == PROCESSOR_SHUTDOWN  )
-                       timer_call_shutdown(processor);
-               processor_unlock(processor);
-       }
+       thread_dispatch(old_thread, self);
 }
 
 /*
@@ -320,33 +280,40 @@ processor_doshutdown(
  */
 void
 processor_offline(
-       processor_t             processor)
+       processor_t                     processor)
 {
-       thread_t                thread, old_thread = processor->active_thread;
+       thread_t                        new_thread, old_thread = processor->active_thread;
+       processor_set_t         pset;
 
-       thread = processor->idle_thread;
-       processor->active_thread = 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_switch((uint32_t)processor->last_dispatch,
-                                                       &PROCESSOR_DATA(processor, offline_timer));
+       timer_stop(PROCESSOR_DATA(processor, thread_timer), processor->last_dispatch);
 
-       thread_done(old_thread, thread, processor);
+       machine_set_current_thread(new_thread);
 
-       machine_set_current_thread(thread);
+       thread_dispatch(old_thread, new_thread);
 
-       thread_begin(thread, processor);
+       PMAP_DEACTIVATE_KERNEL(processor->cpu_id);
 
-       thread_dispatch(old_thread);
-
-       PMAP_DEACTIVATE_KERNEL(PROCESSOR_DATA(processor, slot_num));
-
-       processor_lock(processor);
+       pset = processor->processor_set;
+       pset_lock(pset);
        processor->state = PROCESSOR_OFF_LINE;
-       hw_atomic_sub(&machine_info.avail_cpus, 1);
+       if (--pset->online_processor_count == 0) {
+               pset_pri_init_hint(pset, PROCESSOR_NULL);
+               pset_count_init_hint(pset, PROCESSOR_NULL);
+       }
+       (void)hw_atomic_sub(&processor_avail_count, 1);
+       commpage_update_active_cpus();
+       SCHED(processor_queue_shutdown)(processor);
+       /* pset lock dropped */
+
        ml_cpu_down();
-       processor_unlock(processor);
 
        cpu_sleep();
        panic("zombie processor");