+ pset_unlock(pset);
+
+ /*
+ * Choose idle thread if fast idle is not possible.
+ */
+ if ((thread->state & (TH_IDLE|TH_TERMINATE|TH_SUSP)) || !(thread->state & TH_WAIT) || thread->wake_active)
+ return (processor->idle_thread);
+
+ /*
+ * Perform idling activities directly without a
+ * context switch. Return dispatched thread,
+ * else check again for a runnable thread.
+ */
+ new_thread = thread_select_idle(thread, processor);
+
+ } while (new_thread == THREAD_NULL);
+
+ return (new_thread);
+}
+
+/*
+ * thread_select_idle:
+ *
+ * Idle the processor using the current thread context.
+ *
+ * Called with thread locked, then dropped and relocked.
+ */
+static thread_t
+thread_select_idle(
+ thread_t thread,
+ processor_t processor)
+{
+ thread_t new_thread;
+
+ if (thread->sched_mode & TH_MODE_TIMESHARE)
+ sched_share_decr();
+ sched_run_decr();
+
+ thread->state |= TH_IDLE;
+ processor->current_pri = IDLEPRI;
+
+ thread_unlock(thread);
+
+ /*
+ * Switch execution timing to processor idle thread.
+ */
+ processor->last_dispatch = mach_absolute_time();
+ thread_timer_event(processor->last_dispatch, &processor->idle_thread->system_timer);
+ PROCESSOR_DATA(processor, kernel_timer) = &processor->idle_thread->system_timer;
+
+ /*
+ * Cancel the quantum timer while idling.
+ */
+ timer_call_cancel(&processor->quantum_timer);
+ processor->timeslice = 0;
+
+ (*thread->sched_call)(SCHED_CALL_BLOCK, thread);
+
+ /*
+ * Enable interrupts and perform idling activities. No
+ * preemption due to TH_IDLE being set.
+ */
+ spllo(); new_thread = processor_idle(thread, processor);
+
+ /*
+ * Return at splsched.
+ */
+ (*thread->sched_call)(SCHED_CALL_UNBLOCK, thread);
+
+ thread_lock(thread);
+
+ /*
+ * If awakened, switch to thread timer and start a new quantum.
+ * Otherwise skip; we will context switch to another thread or return here.
+ */
+ if (!(thread->state & TH_WAIT)) {
+ processor->last_dispatch = mach_absolute_time();
+ thread_timer_event(processor->last_dispatch, &thread->system_timer);
+ PROCESSOR_DATA(processor, kernel_timer) = &thread->system_timer;
+
+ thread_quantum_init(thread);
+
+ processor->quantum_end = processor->last_dispatch + thread->current_quantum;
+ timer_call_enter1(&processor->quantum_timer, thread, processor->quantum_end);
+ processor->timeslice = 1;