[PATCH] mm: __alloc_pages cleanup
[safe/jmp/linux-2.6] / kernel / sched.c
index c6827f9..b650667 100644 (file)
@@ -661,36 +661,59 @@ static int effective_prio(task_t *p)
 }
 
 #ifdef CONFIG_SMP
-static inline void inc_prio_bias(runqueue_t *rq, int static_prio)
+static inline void inc_prio_bias(runqueue_t *rq, int prio)
 {
-       rq->prio_bias += MAX_PRIO - static_prio;
+       rq->prio_bias += MAX_PRIO - prio;
 }
 
-static inline void dec_prio_bias(runqueue_t *rq, int static_prio)
+static inline void dec_prio_bias(runqueue_t *rq, int prio)
 {
-       rq->prio_bias -= MAX_PRIO - static_prio;
+       rq->prio_bias -= MAX_PRIO - prio;
+}
+
+static inline void inc_nr_running(task_t *p, runqueue_t *rq)
+{
+       rq->nr_running++;
+       if (rt_task(p)) {
+               if (p != rq->migration_thread)
+                       /*
+                        * The migration thread does the actual balancing. Do
+                        * not bias by its priority as the ultra high priority
+                        * will skew balancing adversely.
+                        */
+                       inc_prio_bias(rq, p->prio);
+       } else
+               inc_prio_bias(rq, p->static_prio);
+}
+
+static inline void dec_nr_running(task_t *p, runqueue_t *rq)
+{
+       rq->nr_running--;
+       if (rt_task(p)) {
+               if (p != rq->migration_thread)
+                       dec_prio_bias(rq, p->prio);
+       } else
+               dec_prio_bias(rq, p->static_prio);
 }
 #else
-static inline void inc_prio_bias(runqueue_t *rq, int static_prio)
+static inline void inc_prio_bias(runqueue_t *rq, int prio)
 {
 }
 
-static inline void dec_prio_bias(runqueue_t *rq, int static_prio)
+static inline void dec_prio_bias(runqueue_t *rq, int prio)
 {
 }
-#endif
 
 static inline void inc_nr_running(task_t *p, runqueue_t *rq)
 {
        rq->nr_running++;
-       inc_prio_bias(rq, p->static_prio);
 }
 
 static inline void dec_nr_running(task_t *p, runqueue_t *rq)
 {
        rq->nr_running--;
-       dec_prio_bias(rq, p->static_prio);
 }
+#endif
 
 /*
  * __activate_task - move a task to the runqueue.
@@ -792,7 +815,8 @@ static void activate_task(task_t *p, runqueue_t *rq, int local)
        }
 #endif
 
-       p->prio = recalc_task_prio(p, now);
+       if (!rt_task(p))
+               p->prio = recalc_task_prio(p, now);
 
        /*
         * This checks to make sure it's not an uninterruptible task
@@ -841,21 +865,28 @@ static void deactivate_task(struct task_struct *p, runqueue_t *rq)
 #ifdef CONFIG_SMP
 static void resched_task(task_t *p)
 {
-       int need_resched, nrpolling;
+       int cpu;
 
        assert_spin_locked(&task_rq(p)->lock);
 
-       /* minimise the chance of sending an interrupt to poll_idle() */
-       nrpolling = test_tsk_thread_flag(p,TIF_POLLING_NRFLAG);
-       need_resched = test_and_set_tsk_thread_flag(p,TIF_NEED_RESCHED);
-       nrpolling |= test_tsk_thread_flag(p,TIF_POLLING_NRFLAG);
+       if (unlikely(test_tsk_thread_flag(p, TIF_NEED_RESCHED)))
+               return;
+
+       set_tsk_thread_flag(p, TIF_NEED_RESCHED);
+
+       cpu = task_cpu(p);
+       if (cpu == smp_processor_id())
+               return;
 
-       if (!need_resched && !nrpolling && (task_cpu(p) != smp_processor_id()))
-               smp_send_reschedule(task_cpu(p));
+       /* NEED_RESCHED must be visible before we test POLLING_NRFLAG */
+       smp_mb();
+       if (!test_tsk_thread_flag(p, TIF_POLLING_NRFLAG))
+               smp_send_reschedule(cpu);
 }
 #else
 static inline void resched_task(task_t *p)
 {
+       assert_spin_locked(&task_rq(p)->lock);
        set_tsk_need_resched(p);
 }
 #endif
@@ -966,22 +997,27 @@ void kick_process(task_t *p)
 static inline unsigned long __source_load(int cpu, int type, enum idle_type idle)
 {
        runqueue_t *rq = cpu_rq(cpu);
-       unsigned long cpu_load = rq->cpu_load[type-1],
-               load_now = rq->nr_running * SCHED_LOAD_SCALE;
+       unsigned long running = rq->nr_running;
+       unsigned long source_load, cpu_load = rq->cpu_load[type-1],
+               load_now = running * SCHED_LOAD_SCALE;
 
-       if (idle == NOT_IDLE) {
+       if (type == 0)
+               source_load = load_now;
+       else
+               source_load = min(cpu_load, load_now);
+
+       if (running > 1 || (idle == NOT_IDLE && running))
                /*
-                * If we are balancing busy runqueues the load is biased by
-                * priority to create 'nice' support across cpus.
+                * If we are busy rebalancing the load is biased by
+                * priority to create 'nice' support across cpus. When
+                * idle rebalancing we should only bias the source_load if
+                * there is more than one task running on that queue to
+                * prevent idle rebalance from trying to pull tasks from a
+                * queue with only one running task.
                 */
-               cpu_load *= rq->prio_bias;
-               load_now *= rq->prio_bias;
-       }
-
-       if (type == 0)
-               return load_now;
+               source_load = source_load * rq->prio_bias / running;
 
-       return min(cpu_load, load_now);
+       return source_load;
 }
 
 static inline unsigned long source_load(int cpu, int type)
@@ -995,17 +1031,19 @@ static inline unsigned long source_load(int cpu, int type)
 static inline unsigned long __target_load(int cpu, int type, enum idle_type idle)
 {
        runqueue_t *rq = cpu_rq(cpu);
-       unsigned long cpu_load = rq->cpu_load[type-1],
-               load_now = rq->nr_running * SCHED_LOAD_SCALE;
+       unsigned long running = rq->nr_running;
+       unsigned long target_load, cpu_load = rq->cpu_load[type-1],
+               load_now = running * SCHED_LOAD_SCALE;
 
        if (type == 0)
-               return load_now;
+               target_load = load_now;
+       else
+               target_load = max(cpu_load, load_now);
 
-       if (idle == NOT_IDLE) {
-               cpu_load *= rq->prio_bias;
-               load_now *= rq->prio_bias;
-       }
-       return max(cpu_load, load_now);
+       if (running > 1 || (idle == NOT_IDLE && running))
+               target_load = target_load * rq->prio_bias / running;
+
+       return target_load;
 }
 
 static inline unsigned long target_load(int cpu, int type)
@@ -3508,25 +3546,24 @@ void set_user_nice(task_t *p, long nice)
         * not SCHED_NORMAL:
         */
        if (rt_task(p)) {
-               dec_prio_bias(rq, p->static_prio);
                p->static_prio = NICE_TO_PRIO(nice);
-               inc_prio_bias(rq, p->static_prio);
                goto out_unlock;
        }
        array = p->array;
-       if (array)
+       if (array) {
                dequeue_task(p, array);
+               dec_prio_bias(rq, p->static_prio);
+       }
 
        old_prio = p->prio;
        new_prio = NICE_TO_PRIO(nice);
        delta = new_prio - old_prio;
-       dec_prio_bias(rq, p->static_prio);
        p->static_prio = NICE_TO_PRIO(nice);
-       inc_prio_bias(rq, p->static_prio);
        p->prio += delta;
 
        if (array) {
                enqueue_task(p, array);
+               inc_prio_bias(rq, p->static_prio);
                /*
                 * If the task increased its priority or is running and
                 * lowered its priority, then reschedule its CPU: