]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/kern/thread_policy.c
xnu-2050.7.9.tar.gz
[apple/xnu.git] / osfmk / kern / thread_policy.c
index 45cd6ef24d3ab6d6de876879958a1e9e6ab49e58..8108514f547f3d0d3c530dfb82b96eef45208b30 100644 (file)
@@ -38,6 +38,16 @@ static void
 thread_recompute_priority(
        thread_t                thread);
 
+#if CONFIG_EMBEDDED
+static void
+thread_throttle(
+       thread_t                thread,
+       integer_t               task_priority);
+
+extern int mach_do_background_thread(thread_t thread, int prio);
+#endif
+
+
 kern_return_t
 thread_policy_set(
        thread_t                                thread,
@@ -45,25 +55,32 @@ thread_policy_set(
        thread_policy_t                 policy_info,
        mach_msg_type_number_t  count)
 {
-       kern_return_t                   result = KERN_SUCCESS;
-       spl_t                                   s;
 
        if (thread == THREAD_NULL)
                return (KERN_INVALID_ARGUMENT);
 
+       if (thread->static_param)
+               return (KERN_SUCCESS);
+
+       return (thread_policy_set_internal(thread, flavor, policy_info, count));
+}
+
+kern_return_t
+thread_policy_set_internal(
+       thread_t                                thread,
+       thread_policy_flavor_t  flavor,
+       thread_policy_t                 policy_info,
+       mach_msg_type_number_t  count)
+{
+       kern_return_t                   result = KERN_SUCCESS;
+       spl_t                                   s;
+
        thread_mtx_lock(thread);
        if (!thread->active) {
                thread_mtx_unlock(thread);
 
                return (KERN_TERMINATED);
        }
-
-       if (thread->static_param) {
-               thread_mtx_unlock(thread);
-
-               return (KERN_SUCCESS);
-       }
-
        switch (flavor) {
 
        case THREAD_EXTENDED_POLICY:
@@ -77,37 +94,40 @@ thread_policy_set(
                        timeshare = info->timeshare;
                }
 
+               if (!SCHED(supports_timeshare_mode)())
+                       timeshare = FALSE;
+               
                s = splsched();
                thread_lock(thread);
 
-               if (!(thread->sched_mode & TH_MODE_FAILSAFE)) {
-                       integer_t       oldmode = (thread->sched_mode & TH_MODE_TIMESHARE);
-
-                       thread->sched_mode &= ~TH_MODE_REALTIME;
+               if (!(thread->sched_flags & TH_SFLAG_DEMOTED_MASK)) {
+                       integer_t       oldmode = (thread->sched_mode == TH_MODE_TIMESHARE);
 
-                       if (timeshare && !oldmode) {
-                               thread->sched_mode |= TH_MODE_TIMESHARE;
+                       if (timeshare) {
+                               thread->sched_mode = TH_MODE_TIMESHARE;
 
-                               if ((thread->state & (TH_RUN|TH_IDLE)) == TH_RUN)
-                                       sched_share_incr();
+                               if (!oldmode) {
+                                       if ((thread->state & (TH_RUN|TH_IDLE)) == TH_RUN)
+                                               sched_share_incr();
+                               }
                        }
-                       else
-                       if (!timeshare && oldmode) {
-                               thread->sched_mode &= ~TH_MODE_TIMESHARE;
+                       else {
+                               thread->sched_mode = TH_MODE_FIXED;
 
-                               if ((thread->state & (TH_RUN|TH_IDLE)) == TH_RUN)
-                                       sched_share_decr();
+                               if (oldmode) {
+                                       if ((thread->state & (TH_RUN|TH_IDLE)) == TH_RUN)
+                                               sched_share_decr();
+                               }
                        }
 
                        thread_recompute_priority(thread);
                }
                else {
-                       thread->safe_mode &= ~TH_MODE_REALTIME;
 
                        if (timeshare)
-                               thread->safe_mode |= TH_MODE_TIMESHARE;
+                               thread->saved_mode = TH_MODE_TIMESHARE;
                        else
-                               thread->safe_mode &= ~TH_MODE_TIMESHARE;
+                               thread->saved_mode = TH_MODE_FIXED;
                }
 
                thread_unlock(thread);
@@ -141,20 +161,17 @@ thread_policy_set(
                thread->realtime.constraint = info->constraint;
                thread->realtime.preemptible = info->preemptible;
 
-               if (!(thread->sched_mode & TH_MODE_FAILSAFE)) {
-                       if (thread->sched_mode & TH_MODE_TIMESHARE) {
-                               thread->sched_mode &= ~TH_MODE_TIMESHARE;
-
+               if (thread->sched_flags & TH_SFLAG_DEMOTED_MASK) {
+                       thread->saved_mode = TH_MODE_REALTIME;
+               }
+               else {
+                       if (thread->sched_mode == TH_MODE_TIMESHARE) {
                                if ((thread->state & (TH_RUN|TH_IDLE)) == TH_RUN)
                                        sched_share_decr();
                        }
-                       thread->sched_mode |= TH_MODE_REALTIME;
+                       thread->sched_mode = TH_MODE_REALTIME;
                        thread_recompute_priority(thread);
                }
-               else {
-                       thread->safe_mode &= ~TH_MODE_TIMESHARE;
-                       thread->safe_mode |= TH_MODE_REALTIME;
-               }
 
                thread_unlock(thread);
                splx(s);
@@ -170,7 +187,6 @@ thread_policy_set(
                        result = KERN_INVALID_ARGUMENT;
                        break;
                }
-
                info = (thread_precedence_policy_t)policy_info;
 
                s = splsched();
@@ -209,13 +225,25 @@ thread_policy_set(
                thread_mtx_unlock(thread);
                return thread_affinity_set(thread, info->affinity_tag);
        }
+
+#if CONFIG_EMBEDDED
+       case THREAD_BACKGROUND_POLICY:
+       {
+               thread_background_policy_t      info;
+
+               info = (thread_background_policy_t) policy_info;
+
+               thread_mtx_unlock(thread);
+               return mach_do_background_thread(thread, info->priority);
+       }
+#endif /* CONFIG_EMBEDDED */
+
        default:
                result = KERN_INVALID_ARGUMENT;
                break;
        }
 
        thread_mtx_unlock(thread);
-
        return (result);
 }
 
@@ -225,7 +253,7 @@ thread_recompute_priority(
 {
        integer_t               priority;
 
-       if (thread->sched_mode & TH_MODE_REALTIME)
+       if (thread->sched_mode == TH_MODE_REALTIME)
                priority = BASEPRI_RTQUEUES;
        else {
                if (thread->importance > MAXPRI)
@@ -243,11 +271,51 @@ thread_recompute_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)
+                || (thread->sched_flags & TH_SFLAG_PENDING_THROTTLE_PROMOTION))
+                && (task_priority <= MAXPRI_THROTTLE)) {
+
+               /* Kill a promotion if it was in flight */
+               thread->sched_flags &= ~TH_SFLAG_PENDING_THROTTLE_PROMOTION;
+
+               if (!(thread->sched_flags & TH_SFLAG_THROTTLED)) {
+                       /*
+                        * Set the pending bit so that we can switch runqueues
+                        * (potentially) at a later time safely
+                        */
+                       thread->sched_flags |= TH_SFLAG_PENDING_THROTTLE_DEMOTION;
+               }
+       }
+       else if (((thread->sched_flags & TH_SFLAG_THROTTLED)
+                         || (thread->sched_flags & TH_SFLAG_PENDING_THROTTLE_DEMOTION))
+                         && (task_priority > MAXPRI_THROTTLE)) {
+
+               /* Kill a demotion if it was in flight */
+               thread->sched_flags &= ~TH_SFLAG_PENDING_THROTTLE_DEMOTION;
+
+               if (thread->sched_flags & TH_SFLAG_THROTTLED) {
+                       thread->sched_flags |= TH_SFLAG_PENDING_THROTTLE_PROMOTION;
+               }
+       }       
+}
+#endif
+
 void
 thread_task_priority(
        thread_t                thread,
@@ -261,6 +329,10 @@ thread_task_priority(
        s = splsched();
        thread_lock(thread);
 
+#if CONFIG_EMBEDDED
+       thread_throttle(thread, priority);
+#endif
+
        thread->task_priority = priority;
        thread->max_priority = max_priority;
 
@@ -279,19 +351,21 @@ thread_policy_reset(
        s = splsched();
        thread_lock(thread);
 
-       if (!(thread->sched_mode & TH_MODE_FAILSAFE)) {
-               thread->sched_mode &= ~TH_MODE_REALTIME;
+       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 (!(thread->sched_mode & TH_MODE_TIMESHARE)) {
-                       thread->sched_mode |= TH_MODE_TIMESHARE;
+               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->safe_mode = 0;
-               thread->sched_mode &= ~TH_MODE_FAILSAFE;
+               thread->sched_mode = thread->saved_mode;
+               thread->saved_mode = TH_MODE_NONE;
+               thread->sched_flags &= ~TH_SFLAG_DEMOTED_MASK;
        }
 
        thread->importance = 0;
@@ -333,12 +407,12 @@ thread_policy_get(
                        s = splsched();
                        thread_lock(thread);
 
-                       if (    !(thread->sched_mode & TH_MODE_REALTIME)        &&
-                                       !(thread->safe_mode & TH_MODE_REALTIME)                 ) {
-                               if (!(thread->sched_mode & TH_MODE_FAILSAFE))
-                                       timeshare = (thread->sched_mode & TH_MODE_TIMESHARE) != 0;
+                       if (     (thread->sched_mode != TH_MODE_REALTIME)       &&
+                                        (thread->saved_mode != TH_MODE_REALTIME)                       ) {
+                               if (!(thread->sched_flags & TH_SFLAG_DEMOTED_MASK))
+                                       timeshare = (thread->sched_mode == TH_MODE_TIMESHARE) != 0;
                                else
-                                       timeshare = (thread->safe_mode & TH_MODE_TIMESHARE) != 0;
+                                       timeshare = (thread->saved_mode == TH_MODE_TIMESHARE) != 0;
                        }
                        else
                                *get_default = TRUE;
@@ -372,8 +446,8 @@ thread_policy_get(
                        s = splsched();
                        thread_lock(thread);
 
-                       if (    (thread->sched_mode & TH_MODE_REALTIME) ||
-                                       (thread->safe_mode & TH_MODE_REALTIME)          ) {
+                       if (    (thread->sched_mode == TH_MODE_REALTIME)        ||
+                                       (thread->saved_mode == TH_MODE_REALTIME)                ) {
                                info->period = thread->realtime.period;
                                info->computation = thread->realtime.computation;
                                info->constraint = thread->realtime.constraint;
@@ -388,8 +462,8 @@ thread_policy_get(
 
                if (*get_default) {
                        info->period = 0;
-                       info->computation = std_quantum / 2;
-                       info->constraint = std_quantum;
+                       info->computation = default_timeshare_computation;
+                       info->constraint = default_timeshare_constraint;
                        info->preemptible = TRUE;
                }