]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - kernel/sched.c
sched: fix SMP migration latencies
[linux-2.6-omap-h63xx.git] / kernel / sched.c
index 6c10fa796ca040ef8da1f1e65acd58e4d7644faa..4ad789d268fe4959d7a24789f06a0c711af516a1 100644 (file)
@@ -171,31 +171,22 @@ struct rt_prio_array {
        struct list_head queue[MAX_RT_PRIO];
 };
 
-struct load_stat {
-       struct load_weight load;
-       u64 load_update_start, load_update_last;
-       unsigned long delta_fair, delta_exec, delta_stat;
-};
-
 /* CFS-related fields in a runqueue */
 struct cfs_rq {
        struct load_weight load;
        unsigned long nr_running;
 
-       s64 fair_clock;
        u64 exec_clock;
-       s64 wait_runtime;
-       u64 sleeper_bonus;
-       unsigned long wait_runtime_overruns, wait_runtime_underruns;
+       u64 min_vruntime;
 
        struct rb_root tasks_timeline;
        struct rb_node *rb_leftmost;
        struct rb_node *rb_load_balance_curr;
-#ifdef CONFIG_FAIR_GROUP_SCHED
        /* 'curr' points to currently running entity on this cfs_rq.
         * It is set to NULL otherwise (i.e when none are currently running).
         */
        struct sched_entity *curr;
+#ifdef CONFIG_FAIR_GROUP_SCHED
        struct rq *rq;  /* cpu runqueue to which this cfs_rq is attached */
 
        /* leaf cfs_rqs are those that hold tasks (lowest schedulable entity in
@@ -237,7 +228,7 @@ struct rq {
 #ifdef CONFIG_NO_HZ
        unsigned char in_nohz_recently;
 #endif
-       struct load_stat ls;    /* capture load from *all* tasks on this cpu */
+       struct load_weight load;        /* capture load from *all* tasks on this cpu */
        unsigned long nr_load_updates;
        u64 nr_switches;
 
@@ -382,6 +373,33 @@ static void update_rq_clock(struct rq *rq)
 #define task_rq(p)             cpu_rq(task_cpu(p))
 #define cpu_curr(cpu)          (cpu_rq(cpu)->curr)
 
+/*
+ * Tunables that become constants when CONFIG_SCHED_DEBUG is off:
+ */
+#ifdef CONFIG_SCHED_DEBUG
+# define const_debug __read_mostly
+#else
+# define const_debug static const
+#endif
+
+/*
+ * Debugging: various feature bits
+ */
+enum {
+       SCHED_FEAT_NEW_FAIR_SLEEPERS    = 1,
+       SCHED_FEAT_START_DEBIT          = 2,
+       SCHED_FEAT_USE_TREE_AVG         = 4,
+       SCHED_FEAT_APPROX_AVG           = 8,
+};
+
+const_debug unsigned int sysctl_sched_features =
+               SCHED_FEAT_NEW_FAIR_SLEEPERS    *1 |
+               SCHED_FEAT_START_DEBIT          *1 |
+               SCHED_FEAT_USE_TREE_AVG         *0 |
+               SCHED_FEAT_APPROX_AVG           *0;
+
+#define sched_feat(x) (sysctl_sched_features & SCHED_FEAT_##x)
+
 /*
  * For kernel-internal use: high-speed (but slightly incorrect) per-cpu
  * clock constructed from sched_clock():
@@ -645,19 +663,6 @@ static inline void resched_task(struct task_struct *p)
 }
 #endif
 
-static u64 div64_likely32(u64 divident, unsigned long divisor)
-{
-#if BITS_PER_LONG == 32
-       if (likely(divident <= 0xffffffffULL))
-               return (u32)divident / divisor;
-       do_div(divident, divisor);
-
-       return divident;
-#else
-       return divident / divisor;
-#endif
-}
-
 #if BITS_PER_LONG == 32
 # define WMULT_CONST   (~0UL)
 #else
@@ -699,16 +704,14 @@ calc_delta_fair(unsigned long delta_exec, struct load_weight *lw)
        return calc_delta_mine(delta_exec, NICE_0_LOAD, lw);
 }
 
-static void update_load_add(struct load_weight *lw, unsigned long inc)
+static inline void update_load_add(struct load_weight *lw, unsigned long inc)
 {
        lw->weight += inc;
-       lw->inv_weight = 0;
 }
 
-static void update_load_sub(struct load_weight *lw, unsigned long dec)
+static inline void update_load_sub(struct load_weight *lw, unsigned long dec)
 {
        lw->weight -= dec;
-       lw->inv_weight = 0;
 }
 
 /*
@@ -793,20 +796,11 @@ static int balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
 
 #define sched_class_highest (&rt_sched_class)
 
-static void __update_curr_load(struct rq *rq, struct load_stat *ls)
-{
-       if (rq->curr != rq->idle && ls->load.weight) {
-               ls->delta_exec += ls->delta_stat;
-               ls->delta_fair += calc_delta_fair(ls->delta_stat, &ls->load);
-               ls->delta_stat = 0;
-       }
-}
-
 /*
  * Update delta_exec, delta_fair fields for rq.
  *
  * delta_fair clock advances at a rate inversely proportional to
- * total load (rq->ls.load.weight) on the runqueue, while
+ * total load (rq->load.weight) on the runqueue, while
  * delta_exec advances at the same rate as wall-clock (provided
  * cpu is not idle).
  *
@@ -814,35 +808,17 @@ static void __update_curr_load(struct rq *rq, struct load_stat *ls)
  * runqueue over any given interval. This (smoothened) load is used
  * during load balance.
  *
- * This function is called /before/ updating rq->ls.load
+ * This function is called /before/ updating rq->load
  * and when switching tasks.
  */
-static void update_curr_load(struct rq *rq)
-{
-       struct load_stat *ls = &rq->ls;
-       u64 start;
-
-       start = ls->load_update_start;
-       ls->load_update_start = rq->clock;
-       ls->delta_stat += rq->clock - start;
-       /*
-        * Stagger updates to ls->delta_fair. Very frequent updates
-        * can be expensive.
-        */
-       if (ls->delta_stat >= sysctl_sched_stat_granularity)
-               __update_curr_load(rq, ls);
-}
-
 static inline void inc_load(struct rq *rq, const struct task_struct *p)
 {
-       update_curr_load(rq);
-       update_load_add(&rq->ls.load, p->se.load.weight);
+       update_load_add(&rq->load, p->se.load.weight);
 }
 
 static inline void dec_load(struct rq *rq, const struct task_struct *p)
 {
-       update_curr_load(rq);
-       update_load_sub(&rq->ls.load, p->se.load.weight);
+       update_load_sub(&rq->load, p->se.load.weight);
 }
 
 static void inc_nr_running(struct task_struct *p, struct rq *rq)
@@ -859,8 +835,6 @@ static void dec_nr_running(struct task_struct *p, struct rq *rq)
 
 static void set_load_weight(struct task_struct *p)
 {
-       p->se.wait_runtime = 0;
-
        if (task_has_rt_policy(p)) {
                p->se.load.weight = prio_to_weight[0] * 2;
                p->se.load.inv_weight = prio_to_wmult[0] >> 1;
@@ -989,7 +963,7 @@ inline int task_curr(const struct task_struct *p)
 /* Used instead of source_load when we know the type == 0 */
 unsigned long weighted_cpuload(const int cpu)
 {
-       return cpu_rq(cpu)->ls.load.weight;
+       return cpu_rq(cpu)->load.weight;
 }
 
 static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu)
@@ -1006,15 +980,9 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
 {
        int old_cpu = task_cpu(p);
        struct rq *old_rq = cpu_rq(old_cpu), *new_rq = cpu_rq(new_cpu);
-       u64 clock_offset, fair_clock_offset;
+       u64 clock_offset;
 
        clock_offset = old_rq->clock - new_rq->clock;
-       fair_clock_offset = old_rq->cfs.fair_clock - new_rq->cfs.fair_clock;
-
-       if (p->se.wait_start_fair)
-               p->se.wait_start_fair -= fair_clock_offset;
-       if (p->se.sleep_start_fair)
-               p->se.sleep_start_fair -= fair_clock_offset;
 
 #ifdef CONFIG_SCHEDSTATS
        if (p->se.wait_start)
@@ -1024,6 +992,9 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
        if (p->se.block_start)
                p->se.block_start -= clock_offset;
 #endif
+       if (likely(new_rq->cfs.min_vruntime))
+               p->se.vruntime -= old_rq->cfs.min_vruntime -
+                                               new_rq->cfs.min_vruntime;
 
        __set_task_cpu(p, new_cpu);
 }
@@ -1584,28 +1555,20 @@ int fastcall wake_up_state(struct task_struct *p, unsigned int state)
  */
 static void __sched_fork(struct task_struct *p)
 {
-       p->se.wait_start_fair           = 0;
        p->se.exec_start                = 0;
        p->se.sum_exec_runtime          = 0;
        p->se.prev_sum_exec_runtime     = 0;
-       p->se.delta_exec                = 0;
-       p->se.delta_fair_run            = 0;
-       p->se.delta_fair_sleep          = 0;
-       p->se.wait_runtime              = 0;
-       p->se.sleep_start_fair          = 0;
 
 #ifdef CONFIG_SCHEDSTATS
        p->se.wait_start                = 0;
-       p->se.sum_wait_runtime          = 0;
        p->se.sum_sleep_runtime         = 0;
        p->se.sleep_start               = 0;
        p->se.block_start               = 0;
        p->se.sleep_max                 = 0;
        p->se.block_max                 = 0;
        p->se.exec_max                  = 0;
+       p->se.slice_max                 = 0;
        p->se.wait_max                  = 0;
-       p->se.wait_runtime_overruns     = 0;
-       p->se.wait_runtime_underruns    = 0;
 #endif
 
        INIT_LIST_HEAD(&p->run_list);
@@ -1657,12 +1620,6 @@ void sched_fork(struct task_struct *p, int clone_flags)
        put_cpu();
 }
 
-/*
- * After fork, child runs first. (default) If set to 0 then
- * parent will (try to) run first.
- */
-unsigned int __read_mostly sysctl_sched_child_runs_first = 1;
-
 /*
  * wake_up_new_task - wake up a newly created task for the first time.
  *
@@ -1688,10 +1645,8 @@ void fastcall wake_up_new_task(struct task_struct *p, unsigned long clone_flags)
        else
                p->sched_class = &fair_sched_class;
 
-       if (!p->sched_class->task_new || !sysctl_sched_child_runs_first ||
-                       (clone_flags & CLONE_VM) || task_cpu(p) != this_cpu ||
-                       !current->se.on_rq) {
-
+       if (task_cpu(p) != this_cpu || !p->sched_class->task_new ||
+                                                       !current->se.on_rq) {
                activate_task(rq, p, 0);
        } else {
                /*
@@ -1982,42 +1937,10 @@ unsigned long nr_active(void)
  */
 static void update_cpu_load(struct rq *this_rq)
 {
-       u64 fair_delta64, exec_delta64, idle_delta64, sample_interval64, tmp64;
-       unsigned long total_load = this_rq->ls.load.weight;
-       unsigned long this_load =  total_load;
-       struct load_stat *ls = &this_rq->ls;
+       unsigned long this_load = this_rq->load.weight;
        int i, scale;
 
        this_rq->nr_load_updates++;
-       if (unlikely(!(sysctl_sched_features & SCHED_FEAT_PRECISE_CPU_LOAD)))
-               goto do_avg;
-
-       /* Update delta_fair/delta_exec fields first */
-       update_curr_load(this_rq);
-
-       fair_delta64 = ls->delta_fair + 1;
-       ls->delta_fair = 0;
-
-       exec_delta64 = ls->delta_exec + 1;
-       ls->delta_exec = 0;
-
-       sample_interval64 = this_rq->clock - ls->load_update_last;
-       ls->load_update_last = this_rq->clock;
-
-       if ((s64)sample_interval64 < (s64)TICK_NSEC)
-               sample_interval64 = TICK_NSEC;
-
-       if (exec_delta64 > sample_interval64)
-               exec_delta64 = sample_interval64;
-
-       idle_delta64 = sample_interval64 - exec_delta64;
-
-       tmp64 = div64_64(SCHED_LOAD_SCALE * exec_delta64, fair_delta64);
-       tmp64 = div64_64(tmp64 * exec_delta64, sample_interval64);
-
-       this_load = (unsigned long)tmp64;
-
-do_avg:
 
        /* Update our load: */
        for (i = 0, scale = 1; i < CPU_LOAD_IDX_MAX; i++, scale += scale) {
@@ -2027,7 +1950,13 @@ do_avg:
 
                old_load = this_rq->cpu_load[i];
                new_load = this_load;
-
+               /*
+                * Round up the averaging division if load is increasing. This
+                * prevents us from getting stuck on 9 if the load is 10, for
+                * example.
+                */
+               if (new_load > old_load)
+                       new_load += scale-1;
                this_rq->cpu_load[i] = (old_load*(scale-1) + new_load) >> i;
        }
 }
@@ -3636,10 +3565,9 @@ EXPORT_SYMBOL(default_wake_function);
 static void __wake_up_common(wait_queue_head_t *q, unsigned int mode,
                             int nr_exclusive, int sync, void *key)
 {
-       struct list_head *tmp, *next;
+       wait_queue_t *curr, *next;
 
-       list_for_each_safe(tmp, next, &q->task_list) {
-               wait_queue_t *curr = list_entry(tmp, wait_queue_t, task_list);
+       list_for_each_entry_safe(curr, next, &q->task_list, task_list) {
                unsigned flags = curr->flags;
 
                if (curr->func(curr, mode, sync, key) &&
@@ -4900,32 +4828,6 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu)
  */
 cpumask_t nohz_cpu_mask = CPU_MASK_NONE;
 
-/*
- * Increase the granularity value when there are more CPUs,
- * because with more CPUs the 'effective latency' as visible
- * to users decreases. But the relationship is not linear,
- * so pick a second-best guess by going with the log2 of the
- * number of CPUs.
- *
- * This idea comes from the SD scheduler of Con Kolivas:
- */
-static inline void sched_init_granularity(void)
-{
-       unsigned int factor = 1 + ilog2(num_online_cpus());
-       const unsigned long limit = 100000000;
-
-       sysctl_sched_min_granularity *= factor;
-       if (sysctl_sched_min_granularity > limit)
-               sysctl_sched_min_granularity = limit;
-
-       sysctl_sched_latency *= factor;
-       if (sysctl_sched_latency > limit)
-               sysctl_sched_latency = limit;
-
-       sysctl_sched_runtime_limit = sysctl_sched_latency;
-       sysctl_sched_wakeup_granularity = sysctl_sched_min_granularity / 2;
-}
-
 #ifdef CONFIG_SMP
 /*
  * This is how migration works:
@@ -6493,12 +6395,10 @@ void __init sched_init_smp(void)
        /* Move init over to a non-isolated CPU */
        if (set_cpus_allowed(current, non_isolated_cpus) < 0)
                BUG();
-       sched_init_granularity();
 }
 #else
 void __init sched_init_smp(void)
 {
-       sched_init_granularity();
 }
 #endif /* CONFIG_SMP */
 
@@ -6515,7 +6415,6 @@ int in_sched_functions(unsigned long addr)
 static inline void init_cfs_rq(struct cfs_rq *cfs_rq, struct rq *rq)
 {
        cfs_rq->tasks_timeline = RB_ROOT;
-       cfs_rq->fair_clock = 1;
 #ifdef CONFIG_FAIR_GROUP_SCHED
        cfs_rq->rq = rq;
 #endif
@@ -6523,7 +6422,6 @@ static inline void init_cfs_rq(struct cfs_rq *cfs_rq, struct rq *rq)
 
 void __init sched_init(void)
 {
-       u64 now = sched_clock();
        int highest_cpu = 0;
        int i, j;
 
@@ -6548,8 +6446,6 @@ void __init sched_init(void)
                INIT_LIST_HEAD(&rq->leaf_cfs_rq_list);
                list_add(&rq->cfs.leaf_cfs_rq_list, &rq->leaf_cfs_rq_list);
 #endif
-               rq->ls.load_update_last = now;
-               rq->ls.load_update_start = now;
 
                for (j = 0; j < CPU_LOAD_IDX_MAX; j++)
                        rq->cpu_load[j] = 0;
@@ -6644,16 +6540,12 @@ void normalize_rt_tasks(void)
        read_lock_irq(&tasklist_lock);
        do_each_thread(g, p) {
                p->se.fair_key                  = 0;
-               p->se.wait_runtime              = 0;
                p->se.exec_start                = 0;
-               p->se.wait_start_fair           = 0;
-               p->se.sleep_start_fair          = 0;
 #ifdef CONFIG_SCHEDSTATS
                p->se.wait_start                = 0;
                p->se.sleep_start               = 0;
                p->se.block_start               = 0;
 #endif
-               task_rq(p)->cfs.fair_clock      = 0;
                task_rq(p)->clock               = 0;
 
                if (!rt_task(p)) {