+ if (thread->sched_mode == TH_MODE_REALTIME)
+ priority = BASEPRI_RTQUEUES;
+ else {
+ if (thread->importance > MAXPRI)
+ priority = MAXPRI;
+ else
+ if (thread->importance < -MAXPRI)
+ priority = -MAXPRI;
+ else
+ priority = thread->importance;
+
+ priority += thread->task_priority;
+
+ if (priority > thread->max_priority)
+ priority = thread->max_priority;
+ else
+ if (priority < MINPRI)
+ priority = MINPRI;
+#if CONFIG_EMBEDDED
+ /* No one can have a base priority less than MAXPRI_THROTTLE */
+ if (priority < MAXPRI_THROTTLE)
+ priority = MAXPRI_THROTTLE;
+#endif /* CONFIG_EMBEDDED */
+ }
+
+ set_priority(thread, priority);
+}
+
+#if CONFIG_EMBEDDED
+static void
+thread_throttle(
+ thread_t thread,
+ integer_t task_priority)
+{
+ if (!(thread->sched_flags & TH_SFLAG_THROTTLED) &&
+ (task_priority <= MAXPRI_THROTTLE)) {
+
+ if (!((thread->sched_mode == TH_MODE_REALTIME) ||
+ (thread->saved_mode == TH_MODE_REALTIME))) {
+ return;
+ }
+
+ /* Demote to timeshare if throttling */
+ if (thread->sched_mode == TH_MODE_REALTIME)
+ {
+ thread->saved_mode = TH_MODE_REALTIME;
+
+ if (thread->sched_mode == TH_MODE_TIMESHARE) {
+ if ((thread->state & (TH_RUN|TH_IDLE)) == TH_RUN)
+ sched_share_incr();
+ }
+ }
+
+ /* TH_SFLAG_FAILSAFE and TH_SFLAG_THROTTLED are mutually exclusive,
+ * since a throttled thread is not realtime during the throttle
+ * and doesn't need the failsafe repromotion. We therefore clear
+ * the former and set the latter flags here.
+ */
+ thread->sched_flags &= ~TH_SFLAG_FAILSAFE;
+ thread->sched_flags |= TH_SFLAG_THROTTLED;
+
+ if (SCHED(supports_timeshare_mode)())
+ thread->sched_mode = TH_MODE_TIMESHARE;
+ else
+ thread->sched_mode = TH_MODE_FIXED;
+ }
+ else if ((thread->sched_flags & TH_SFLAG_THROTTLED) &&
+ (task_priority > MAXPRI_THROTTLE)) {
+
+ /* Promote back to real time if unthrottling */
+ if (!(thread->saved_mode == TH_MODE_TIMESHARE)) {
+
+ thread->sched_mode = thread->saved_mode;
+
+ if (thread->sched_mode == TH_MODE_TIMESHARE) {
+ if ((thread->state & (TH_RUN|TH_IDLE)) == TH_RUN)
+ sched_share_decr();
+ }
+
+ thread->saved_mode = TH_MODE_NONE;
+ }
+
+ thread->sched_flags &= ~TH_SFLAG_THROTTLED;
+ }
+}
+#endif
+
+void
+thread_task_priority(
+ thread_t thread,
+ integer_t priority,
+ integer_t max_priority)
+{
+ spl_t s;
+
+ assert(thread != THREAD_NULL);
+
+ s = splsched();
+ thread_lock(thread);
+
+#if CONFIG_EMBEDDED
+ thread_throttle(thread, priority);
+#endif
+
+ thread->task_priority = priority;
+ thread->max_priority = max_priority;
+
+ thread_recompute_priority(thread);
+
+ thread_unlock(thread);
+ splx(s);
+}
+
+void
+thread_policy_reset(
+ thread_t thread)
+{
+ spl_t s;
+
+ s = splsched();
+ thread_lock(thread);
+
+ if (!(thread->sched_flags & TH_SFLAG_DEMOTED_MASK)) {
+ sched_mode_t oldmode = thread->sched_mode;
+
+ thread->sched_mode = SCHED(initial_thread_sched_mode)(thread->task);
+
+ if ((oldmode != TH_MODE_TIMESHARE) && (thread->sched_mode == TH_MODE_TIMESHARE)) {
+
+ if ((thread->state & (TH_RUN|TH_IDLE)) == TH_RUN)
+ sched_share_incr();
+ }
+ }
+ else {
+ thread->saved_mode = TH_MODE_NONE;
+ thread->sched_flags &= ~TH_SFLAG_DEMOTED_MASK;
+ }
+
+ thread->importance = 0;
+
+ thread_recompute_priority(thread);
+
+ thread_unlock(thread);
+ splx(s);