+ }
+ else
+ if ( processor->state == PROCESSOR_SHUTDOWN &&
+ thread->sched_pri >= processor->current_pri ) {
+ cause_ast_check(processor);
+ }
+ else
+ if ( processor->state == PROCESSOR_IDLE &&
+ processor != current_processor() ) {
+ machine_signal_idle(processor);
+ }
+
+ pset_unlock(pset);
+}
+
+#if defined(CONFIG_SCHED_TRADITIONAL)
+
+static boolean_t
+processor_queue_empty(processor_t processor)
+{
+ return runq_for_processor(processor)->count == 0;
+
+}
+
+static boolean_t
+sched_traditional_with_pset_runqueue_processor_queue_empty(processor_t processor)
+{
+ processor_set_t pset = processor->processor_set;
+ int count = runq_for_processor(processor)->count;
+
+ /*
+ * The pset runq contains the count of all runnable threads
+ * for all processors in the pset. However, for threads that
+ * are bound to another processor, the current "processor"
+ * is not eligible to execute the thread. So we only
+ * include bound threads that our bound to the current
+ * "processor". This allows the processor to idle when the
+ * count of eligible threads drops to 0, even if there's
+ * a runnable thread bound to a different processor in the
+ * shared runq.
+ */
+
+ count -= pset->pset_runq_bound_count;
+ count += processor->runq_bound_count;
+
+ return count == 0;
+}
+
+static ast_t
+processor_csw_check(processor_t processor)
+{
+ run_queue_t runq;
+
+ assert(processor->active_thread != NULL);
+
+ runq = runq_for_processor(processor);
+ if (runq->highq > processor->current_pri) {
+ if (runq->urgency > 0)
+ return (AST_PREEMPT | AST_URGENT);
+
+ if (processor->active_thread && thread_eager_preemption(processor->active_thread))
+ return (AST_PREEMPT | AST_URGENT);
+
+ return AST_PREEMPT;
+ }
+
+ return AST_NONE;
+}
+
+static boolean_t
+processor_queue_has_priority(processor_t processor,
+ int priority,
+ boolean_t gte)
+{
+ if (gte)
+ return runq_for_processor(processor)->highq >= priority;
+ else
+ return runq_for_processor(processor)->highq > priority;
+}
+
+static boolean_t
+should_current_thread_rechoose_processor(processor_t processor)
+{
+ return (processor->current_pri < BASEPRI_RTQUEUES
+ && processor->processor_meta != PROCESSOR_META_NULL
+ && processor->processor_meta->primary != processor);
+}
+
+static int
+sched_traditional_processor_runq_count(processor_t processor)
+{
+ return runq_for_processor(processor)->count;
+}
+
+
+static uint64_t
+sched_traditional_processor_runq_stats_count_sum(processor_t processor)
+{
+ return runq_for_processor(processor)->runq_stats.count_sum;
+}
+
+static uint64_t
+sched_traditional_with_pset_runqueue_processor_runq_stats_count_sum(processor_t processor)
+{
+ if (processor->cpu_id == processor->processor_set->cpu_set_low)
+ return runq_for_processor(processor)->runq_stats.count_sum;
+ else
+ return 0ULL;
+}
+
+#endif /* CONFIG_SCHED_TRADITIONAL */
+
+#define next_pset(p) (((p)->pset_list != PROCESSOR_SET_NULL)? (p)->pset_list: (p)->node->psets)
+
+/*
+ * choose_next_pset:
+ *
+ * Return the next sibling pset containing
+ * available processors.
+ *
+ * Returns the original pset if none other is
+ * suitable.
+ */
+static processor_set_t
+choose_next_pset(
+ processor_set_t pset)
+{
+ processor_set_t nset = pset;
+
+ do {
+ nset = next_pset(nset);
+ } while (nset->online_processor_count < 1 && nset != pset);
+
+ return (nset);
+}
+
+/*
+ * choose_processor:
+ *
+ * Choose a processor for the thread, beginning at
+ * the pset. Accepts an optional processor hint in
+ * the pset.
+ *
+ * Returns a processor, possibly from a different pset.
+ *
+ * The thread must be locked. The pset must be locked,
+ * and the resulting pset is locked on return.
+ */
+processor_t
+choose_processor(
+ processor_set_t pset,
+ processor_t processor,
+ thread_t thread)
+{
+ processor_set_t nset, cset = pset;
+ processor_meta_t pmeta = PROCESSOR_META_NULL;
+ processor_t mprocessor;
+
+ /*
+ * Prefer the hinted processor, when appropriate.
+ */
+
+ if (processor != PROCESSOR_NULL) {
+ if (processor->processor_meta != PROCESSOR_META_NULL)
+ processor = processor->processor_meta->primary;
+ }
+
+ mprocessor = machine_choose_processor(pset, processor);
+ if (mprocessor != PROCESSOR_NULL)
+ processor = mprocessor;
+
+ if (processor != PROCESSOR_NULL) {
+ if (processor->processor_set != pset ||
+ processor->state == PROCESSOR_INACTIVE ||
+ processor->state == PROCESSOR_SHUTDOWN ||
+ processor->state == PROCESSOR_OFF_LINE)
+ processor = PROCESSOR_NULL;
+ else
+ if (processor->state == PROCESSOR_IDLE ||
+ ((thread->sched_pri >= BASEPRI_RTQUEUES) &&
+ (processor->current_pri < BASEPRI_RTQUEUES)))
+ return (processor);
+ }
+
+ /*
+ * Iterate through the processor sets to locate
+ * an appropriate processor.
+ */
+ do {
+ /*
+ * Choose an idle processor.
+ */
+ if (!queue_empty(&cset->idle_queue))
+ return ((processor_t)queue_first(&cset->idle_queue));
+
+ if (thread->sched_pri >= BASEPRI_RTQUEUES) {
+ integer_t lowest_priority = MAXPRI + 1;
+ integer_t lowest_unpaired = MAXPRI + 1;
+ uint64_t furthest_deadline = 1;
+ processor_t lp_processor = PROCESSOR_NULL;
+ processor_t lp_unpaired = PROCESSOR_NULL;
+ processor_t fd_processor = PROCESSOR_NULL;
+
+ lp_processor = cset->low_pri;
+ /* Consider hinted processor */
+ if (lp_processor != PROCESSOR_NULL &&
+ ((lp_processor->processor_meta == PROCESSOR_META_NULL) ||
+ ((lp_processor == lp_processor->processor_meta->primary) &&
+ !queue_empty(&lp_processor->processor_meta->idle_queue))) &&
+ lp_processor->state != PROCESSOR_INACTIVE &&
+ lp_processor->state != PROCESSOR_SHUTDOWN &&
+ lp_processor->state != PROCESSOR_OFF_LINE &&
+ (lp_processor->current_pri < thread->sched_pri))
+ return lp_processor;
+
+ processor = (processor_t)queue_first(&cset->active_queue);
+ while (!queue_end(&cset->active_queue, (queue_entry_t)processor)) {
+ /* Discover the processor executing the
+ * thread with the lowest priority within
+ * this pset, or the one with the furthest
+ * deadline
+ */
+ integer_t cpri = processor->current_pri;
+ if (cpri < lowest_priority) {
+ lowest_priority = cpri;
+ lp_processor = processor;
+ }
+
+ if ((cpri >= BASEPRI_RTQUEUES) && (processor->deadline > furthest_deadline)) {
+ furthest_deadline = processor->deadline;
+ fd_processor = processor;
+ }