+ if (pmDispatch != NULL
+ && pmDispatch->pmCPUSafeMode != NULL) {
+ pmDispatch->pmCPUSafeMode(lcpu, flags);
+ } else {
+ /*
+ * Do something reasonable if the KEXT isn't present.
+ *
+ * We only look at the PAUSE and RESUME flags. The other flag(s)
+ * will not make any sense without the KEXT, so just ignore them.
+ *
+ * We set the CPU's state to indicate that it's halted. If this
+ * is the CPU we're currently running on, then spin until the
+ * state becomes non-halted.
+ */
+ if (flags & PM_SAFE_FL_PAUSE) {
+ lcpu->state = LCPU_PAUSE;
+ if (lcpu == x86_lcpu()) {
+ while (lcpu->state == LCPU_PAUSE) {
+ cpu_pause();
+ }
+ }
+ }
+
+ /*
+ * Clear the halted flag for the specified CPU, that will
+ * get it out of it's spin loop.
+ */
+ if (flags & PM_SAFE_FL_RESUME) {
+ lcpu->state = LCPU_RUN;
+ }
+ }
+}
+
+static uint32_t saved_run_count = 0;
+
+void
+machine_run_count(uint32_t count)
+{
+ if (pmDispatch != NULL
+ && pmDispatch->pmSetRunCount != NULL) {
+ pmDispatch->pmSetRunCount(count);
+ } else {
+ saved_run_count = count;
+ }
+}
+
+processor_t
+machine_choose_processor(processor_set_t pset,
+ processor_t preferred)
+{
+ int startCPU;
+ int endCPU;
+ int preferredCPU;
+ int chosenCPU;
+
+ if (!pmInitDone) {
+ return preferred;
+ }
+
+ if (pset == NULL) {
+ startCPU = -1;
+ endCPU = -1;
+ } else {
+ startCPU = pset->cpu_set_low;
+ endCPU = pset->cpu_set_hi;
+ }
+
+ if (preferred == NULL) {
+ preferredCPU = -1;
+ } else {
+ preferredCPU = preferred->cpu_id;
+ }
+
+ if (pmDispatch != NULL
+ && pmDispatch->pmChooseCPU != NULL) {
+ chosenCPU = pmDispatch->pmChooseCPU(startCPU, endCPU, preferredCPU);
+
+ if (chosenCPU == -1) {
+ return NULL;
+ }
+ return cpu_datap(chosenCPU)->cpu_processor;
+ }
+
+ return preferred;
+}
+
+static int
+pmThreadGetUrgency(uint64_t *rt_period, uint64_t *rt_deadline)
+{
+ thread_urgency_t urgency;
+ uint64_t arg1, arg2;
+
+ urgency = thread_get_urgency(THREAD_NULL, &arg1, &arg2);
+
+ if (urgency == THREAD_URGENCY_REAL_TIME) {
+ if (rt_period != NULL) {
+ *rt_period = arg1;
+ }
+
+ if (rt_deadline != NULL) {
+ *rt_deadline = arg2;
+ }
+ }
+
+ return (int)urgency;
+}
+
+#if DEBUG
+uint32_t urgency_stats[64][THREAD_URGENCY_MAX];
+#endif
+
+#define URGENCY_NOTIFICATION_ASSERT_NS (5 * 1000 * 1000)
+uint64_t urgency_notification_assert_abstime_threshold, urgency_notification_max_recorded;
+
+void
+thread_tell_urgency(thread_urgency_t urgency,
+ uint64_t rt_period,
+ uint64_t rt_deadline,
+ uint64_t sched_latency,
+ thread_t nthread)
+{
+ uint64_t urgency_notification_time_start = 0, delta;
+ boolean_t urgency_assert = (urgency_notification_assert_abstime_threshold != 0);
+ assert(get_preemption_level() > 0 || ml_get_interrupts_enabled() == FALSE);
+#if DEBUG
+ urgency_stats[cpu_number() % 64][urgency]++;
+#endif
+ if (!pmInitDone
+ || pmDispatch == NULL
+ || pmDispatch->pmThreadTellUrgency == NULL) {
+ return;
+ }
+
+ SCHED_DEBUG_PLATFORM_KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED, MACH_URGENCY) | DBG_FUNC_START, urgency, rt_period, rt_deadline, sched_latency, 0);
+
+ if (__improbable((urgency_assert == TRUE))) {
+ urgency_notification_time_start = mach_absolute_time();
+ }
+
+ current_cpu_datap()->cpu_nthread = nthread;
+ pmDispatch->pmThreadTellUrgency(urgency, rt_period, rt_deadline);
+
+ if (__improbable((urgency_assert == TRUE))) {
+ delta = mach_absolute_time() - urgency_notification_time_start;
+
+ if (__improbable(delta > urgency_notification_max_recorded)) {
+ /* This is not synchronized, but it doesn't matter
+ * if we (rarely) miss an event, as it is statistically
+ * unlikely that it will never recur.
+ */
+ urgency_notification_max_recorded = delta;
+
+ if (__improbable((delta > urgency_notification_assert_abstime_threshold) && !machine_timeout_suspended())) {
+ panic("Urgency notification callout %p exceeded threshold, 0x%llx abstime units", pmDispatch->pmThreadTellUrgency, delta);
+ }
+ }
+ }
+
+ SCHED_DEBUG_PLATFORM_KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED, MACH_URGENCY) | DBG_FUNC_END, urgency, rt_period, rt_deadline, 0, 0);
+}
+
+void
+machine_thread_going_on_core(__unused thread_t new_thread,
+ __unused thread_urgency_t urgency,
+ __unused uint64_t sched_latency,
+ __unused uint64_t same_pri_latency,
+ __unused uint64_t dispatch_time)
+{
+}
+
+void
+machine_thread_going_off_core(thread_t old_thread, boolean_t thread_terminating,
+ uint64_t last_dispatch, boolean_t thread_runnable)
+{
+ if (!pmInitDone
+ || pmDispatch == NULL
+ || pmDispatch->pmThreadGoingOffCore == NULL) {
+ return;
+ }
+
+ pmDispatch->pmThreadGoingOffCore(old_thread, thread_terminating,
+ last_dispatch, thread_runnable);
+}
+
+void
+machine_max_runnable_latency(__unused uint64_t bg_max_latency,
+ __unused uint64_t default_max_latency,
+ __unused uint64_t realtime_max_latency)
+{
+}
+
+void
+machine_work_interval_notify(__unused thread_t thread,
+ __unused struct kern_work_interval_args* kwi_args)
+{
+}
+
+
+void
+machine_switch_perfcontrol_context(__unused perfcontrol_event event,
+ __unused uint64_t timestamp,
+ __unused uint32_t flags,
+ __unused uint64_t new_thread_same_pri_latency,
+ __unused thread_t old,
+ __unused thread_t new)
+{
+}
+
+void
+machine_switch_perfcontrol_state_update(__unused perfcontrol_event event,
+ __unused uint64_t timestamp,
+ __unused uint32_t flags,
+ __unused thread_t thread)
+{
+}
+
+void
+active_rt_threads(boolean_t active)
+{
+ if (!pmInitDone
+ || pmDispatch == NULL
+ || pmDispatch->pmActiveRTThreads == NULL) {
+ return;