sched_feat_write(): Update ppos instead of file->f_pos
[pandora-kernel.git] / kernel / sched.c
index 8d25be0..93474a7 100644 (file)
@@ -534,14 +534,12 @@ struct rq {
        #define CPU_LOAD_IDX_MAX 5
        unsigned long cpu_load[CPU_LOAD_IDX_MAX];
 #ifdef CONFIG_NO_HZ
-       unsigned long last_tick_seen;
        unsigned char in_nohz_recently;
 #endif
        /* capture load from *all* tasks on this cpu: */
        struct load_weight load;
        unsigned long nr_load_updates;
        u64 nr_switches;
-       u64 nr_migrations_in;
 
        struct cfs_rq cfs;
        struct rt_rq rt;
@@ -590,6 +588,8 @@ struct rq {
 
        u64 rt_avg;
        u64 age_stamp;
+       u64 idle_stamp;
+       u64 avg_idle;
 #endif
 
        /* calc_load related fields */
@@ -676,6 +676,7 @@ inline void update_rq_clock(struct rq *rq)
 
 /**
  * runqueue_is_locked
+ * @cpu: the processor in question.
  *
  * Returns true if the current cpu runqueue is locked.
  * This interface allows printk to be called with the runqueue lock
@@ -770,7 +771,7 @@ sched_feat_write(struct file *filp, const char __user *ubuf,
        if (!sched_feat_names[i])
                return -EINVAL;
 
-       filp->f_pos += cnt;
+       *ppos += cnt;
 
        return cnt;
 }
@@ -2048,7 +2049,6 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
 #endif
        if (old_cpu != new_cpu) {
                p->se.nr_migrations++;
-               new_rq->nr_migrations_in++;
 #ifdef CONFIG_SCHEDSTATS
                if (task_hot(p, old_rq->clock, NULL))
                        schedstat_inc(p, se.nr_forced2_migrations);
@@ -2311,7 +2311,7 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state,
 {
        int cpu, orig_cpu, this_cpu, success = 0;
        unsigned long flags;
-       struct rq *rq;
+       struct rq *rq, *orig_rq;
 
        if (!sched_feat(SYNC_WAKEUPS))
                wake_flags &= ~WF_SYNC;
@@ -2319,7 +2319,7 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state,
        this_cpu = get_cpu();
 
        smp_wmb();
-       rq = task_rq_lock(p, &flags);
+       rq = orig_rq = task_rq_lock(p, &flags);
        update_rq_clock(rq);
        if (!(p->state & state))
                goto out;
@@ -2350,6 +2350,10 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state,
                set_task_cpu(p, cpu);
 
        rq = task_rq_lock(p, &flags);
+
+       if (rq != orig_rq)
+               update_rq_clock(rq);
+
        WARN_ON(p->state != TASK_WAKING);
        cpu = task_cpu(p);
 
@@ -2406,6 +2410,17 @@ out_running:
 #ifdef CONFIG_SMP
        if (p->sched_class->task_wake_up)
                p->sched_class->task_wake_up(rq, p);
+
+       if (unlikely(rq->idle_stamp)) {
+               u64 delta = rq->clock - rq->idle_stamp;
+               u64 max = 2*sysctl_sched_migration_cost;
+
+               if (delta > max)
+                       rq->avg_idle = max;
+               else
+                       update_avg(&rq->avg_idle, delta);
+               rq->idle_stamp = 0;
+       }
 #endif
 out:
        task_rq_unlock(rq, &flags);
@@ -2983,15 +2998,6 @@ static void calc_load_account_active(struct rq *this_rq)
        }
 }
 
-/*
- * Externally visible per-cpu scheduler statistics:
- * cpu_nr_migrations(cpu) - number of migrations into that cpu
- */
-u64 cpu_nr_migrations(int cpu)
-{
-       return cpu_rq(cpu)->nr_migrations_in;
-}
-
 /*
  * Update rq->cpu_load[] statistics. This function is usually called every
  * scheduler tick (TICK_NSEC).
@@ -3656,6 +3662,7 @@ static void update_group_power(struct sched_domain *sd, int cpu)
 
 /**
  * update_sg_lb_stats - Update sched_group's statistics for load balancing.
+ * @sd: The sched_domain whose statistics are to be updated.
  * @group: sched_group whose statistics are to be updated.
  * @this_cpu: Cpu for which load balance is currently performed.
  * @idle: Idle status of this_cpu
@@ -4091,7 +4098,7 @@ static int load_balance(int this_cpu, struct rq *this_rq,
        unsigned long flags;
        struct cpumask *cpus = __get_cpu_var(load_balance_tmpmask);
 
-       cpumask_setall(cpus);
+       cpumask_copy(cpus, cpu_online_mask);
 
        /*
         * When power savings policy is enabled for the parent domain, idle
@@ -4254,7 +4261,7 @@ load_balance_newidle(int this_cpu, struct rq *this_rq, struct sched_domain *sd)
        int all_pinned = 0;
        struct cpumask *cpus = __get_cpu_var(load_balance_tmpmask);
 
-       cpumask_setall(cpus);
+       cpumask_copy(cpus, cpu_online_mask);
 
        /*
         * When power savings policy is enabled for the parent domain, idle
@@ -4394,6 +4401,11 @@ static void idle_balance(int this_cpu, struct rq *this_rq)
        int pulled_task = 0;
        unsigned long next_balance = jiffies + HZ;
 
+       this_rq->idle_stamp = this_rq->clock;
+
+       if (this_rq->avg_idle < sysctl_sched_migration_cost)
+               return;
+
        for_each_domain(this_cpu, sd) {
                unsigned long interval;
 
@@ -4408,8 +4420,10 @@ static void idle_balance(int this_cpu, struct rq *this_rq)
                interval = msecs_to_jiffies(sd->balance_interval);
                if (time_after(next_balance, sd->last_balance + interval))
                        next_balance = sd->last_balance + interval;
-               if (pulled_task)
+               if (pulled_task) {
+                       this_rq->idle_stamp = 0;
                        break;
+               }
        }
        if (pulled_task || time_after(jiffies, this_rq->next_balance)) {
                /*
@@ -5011,8 +5025,13 @@ static void account_guest_time(struct task_struct *p, cputime_t cputime,
        p->gtime = cputime_add(p->gtime, cputime);
 
        /* Add guest time to cpustat. */
-       cpustat->user = cputime64_add(cpustat->user, tmp);
-       cpustat->guest = cputime64_add(cpustat->guest, tmp);
+       if (TASK_NICE(p) > 0) {
+               cpustat->nice = cputime64_add(cpustat->nice, tmp);
+               cpustat->guest_nice = cputime64_add(cpustat->guest_nice, tmp);
+       } else {
+               cpustat->user = cputime64_add(cpustat->user, tmp);
+               cpustat->guest = cputime64_add(cpustat->guest, tmp);
+       }
 }
 
 /*
@@ -5137,41 +5156,45 @@ cputime_t task_stime(struct task_struct *p)
        return p->stime;
 }
 #else
+
+#ifndef nsecs_to_cputime
+# define nsecs_to_cputime(__nsecs) \
+       msecs_to_cputime(div_u64((__nsecs), NSEC_PER_MSEC))
+#endif
+
 cputime_t task_utime(struct task_struct *p)
 {
-       clock_t utime = cputime_to_clock_t(p->utime),
-               total = utime + cputime_to_clock_t(p->stime);
+       cputime_t utime = p->utime, total = utime + p->stime;
        u64 temp;
 
        /*
         * Use CFS's precise accounting:
         */
-       temp = (u64)nsec_to_clock_t(p->se.sum_exec_runtime);
+       temp = (u64)nsecs_to_cputime(p->se.sum_exec_runtime);
 
        if (total) {
                temp *= utime;
                do_div(temp, total);
        }
-       utime = (clock_t)temp;
+       utime = (cputime_t)temp;
 
-       p->prev_utime = max(p->prev_utime, clock_t_to_cputime(utime));
+       p->prev_utime = max(p->prev_utime, utime);
        return p->prev_utime;
 }
 
 cputime_t task_stime(struct task_struct *p)
 {
-       clock_t stime;
+       cputime_t stime;
 
        /*
         * Use CFS's precise accounting. (we subtract utime from
         * the total, to make sure the total observed by userspace
         * grows monotonically - apps rely on that):
         */
-       stime = nsec_to_clock_t(p->se.sum_exec_runtime) -
-                       cputime_to_clock_t(task_utime(p));
+       stime = nsecs_to_cputime(p->se.sum_exec_runtime) - task_utime(p);
 
        if (stime >= 0)
-               p->prev_stime = max(p->prev_stime, clock_t_to_cputime(stime));
+               p->prev_stime = max(p->prev_stime, stime);
 
        return p->prev_stime;
 }
@@ -6140,22 +6163,14 @@ __setscheduler(struct rq *rq, struct task_struct *p, int policy, int prio)
        BUG_ON(p->se.on_rq);
 
        p->policy = policy;
-       switch (p->policy) {
-       case SCHED_NORMAL:
-       case SCHED_BATCH:
-       case SCHED_IDLE:
-               p->sched_class = &fair_sched_class;
-               break;
-       case SCHED_FIFO:
-       case SCHED_RR:
-               p->sched_class = &rt_sched_class;
-               break;
-       }
-
        p->rt_priority = prio;
        p->normal_prio = normal_prio(p);
        /* we are holding p->pi_lock already */
        p->prio = rt_mutex_getprio(p);
+       if (rt_prio(p->prio))
+               p->sched_class = &rt_sched_class;
+       else
+               p->sched_class = &fair_sched_class;
        set_load_weight(p);
 }
 
@@ -8846,7 +8861,7 @@ static int build_sched_domains(const struct cpumask *cpu_map)
        return __build_sched_domains(cpu_map, NULL);
 }
 
-static struct cpumask *doms_cur;       /* current sched domains */
+static cpumask_var_t *doms_cur;        /* current sched domains */
 static int ndoms_cur;          /* number of sched domains in 'doms_cur' */
 static struct sched_domain_attr *dattr_cur;
                                /* attribues of custom domains in 'doms_cur' */
@@ -8868,6 +8883,31 @@ int __attribute__((weak)) arch_update_cpu_topology(void)
        return 0;
 }
 
+cpumask_var_t *alloc_sched_domains(unsigned int ndoms)
+{
+       int i;
+       cpumask_var_t *doms;
+
+       doms = kmalloc(sizeof(*doms) * ndoms, GFP_KERNEL);
+       if (!doms)
+               return NULL;
+       for (i = 0; i < ndoms; i++) {
+               if (!alloc_cpumask_var(&doms[i], GFP_KERNEL)) {
+                       free_sched_domains(doms, i);
+                       return NULL;
+               }
+       }
+       return doms;
+}
+
+void free_sched_domains(cpumask_var_t doms[], unsigned int ndoms)
+{
+       unsigned int i;
+       for (i = 0; i < ndoms; i++)
+               free_cpumask_var(doms[i]);
+       kfree(doms);
+}
+
 /*
  * Set up scheduler domains and groups. Callers must hold the hotplug lock.
  * For now this just excludes isolated cpus, but could be used to
@@ -8879,12 +8919,12 @@ static int arch_init_sched_domains(const struct cpumask *cpu_map)
 
        arch_update_cpu_topology();
        ndoms_cur = 1;
-       doms_cur = kmalloc(cpumask_size(), GFP_KERNEL);
+       doms_cur = alloc_sched_domains(ndoms_cur);
        if (!doms_cur)
-               doms_cur = fallback_doms;
-       cpumask_andnot(doms_cur, cpu_map, cpu_isolated_map);
+               doms_cur = &fallback_doms;
+       cpumask_andnot(doms_cur[0], cpu_map, cpu_isolated_map);
        dattr_cur = NULL;
-       err = build_sched_domains(doms_cur);
+       err = build_sched_domains(doms_cur[0]);
        register_sched_domain_sysctl();
 
        return err;
@@ -8934,19 +8974,19 @@ static int dattrs_equal(struct sched_domain_attr *cur, int idx_cur,
  * doms_new[] to the current sched domain partitioning, doms_cur[].
  * It destroys each deleted domain and builds each new domain.
  *
- * 'doms_new' is an array of cpumask's of length 'ndoms_new'.
+ * 'doms_new' is an array of cpumask_var_t's of length 'ndoms_new'.
  * The masks don't intersect (don't overlap.) We should setup one
  * sched domain for each mask. CPUs not in any of the cpumasks will
  * not be load balanced. If the same cpumask appears both in the
  * current 'doms_cur' domains and in the new 'doms_new', we can leave
  * it as it is.
  *
- * The passed in 'doms_new' should be kmalloc'd. This routine takes
- * ownership of it and will kfree it when done with it. If the caller
- * failed the kmalloc call, then it can pass in doms_new == NULL &&
- * ndoms_new == 1, and partition_sched_domains() will fallback to
- * the single partition 'fallback_doms', it also forces the domains
- * to be rebuilt.
+ * The passed in 'doms_new' should be allocated using
+ * alloc_sched_domains.  This routine takes ownership of it and will
+ * free_sched_domains it when done with it. If the caller failed the
+ * alloc call, then it can pass in doms_new == NULL && ndoms_new == 1,
+ * and partition_sched_domains() will fallback to the single partition
+ * 'fallback_doms', it also forces the domains to be rebuilt.
  *
  * If doms_new == NULL it will be replaced with cpu_online_mask.
  * ndoms_new == 0 is a special case for destroying existing domains,
@@ -8954,8 +8994,7 @@ static int dattrs_equal(struct sched_domain_attr *cur, int idx_cur,
  *
  * Call with hotplug lock held
  */
-/* FIXME: Change to struct cpumask *doms_new[] */
-void partition_sched_domains(int ndoms_new, struct cpumask *doms_new,
+void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[],
                             struct sched_domain_attr *dattr_new)
 {
        int i, j, n;
@@ -8974,40 +9013,40 @@ void partition_sched_domains(int ndoms_new, struct cpumask *doms_new,
        /* Destroy deleted domains */
        for (i = 0; i < ndoms_cur; i++) {
                for (j = 0; j < n && !new_topology; j++) {
-                       if (cpumask_equal(&doms_cur[i], &doms_new[j])
+                       if (cpumask_equal(doms_cur[i], doms_new[j])
                            && dattrs_equal(dattr_cur, i, dattr_new, j))
                                goto match1;
                }
                /* no match - a current sched domain not in new doms_new[] */
-               detach_destroy_domains(doms_cur + i);
+               detach_destroy_domains(doms_cur[i]);
 match1:
                ;
        }
 
        if (doms_new == NULL) {
                ndoms_cur = 0;
-               doms_new = fallback_doms;
-               cpumask_andnot(&doms_new[0], cpu_online_mask, cpu_isolated_map);
+               doms_new = &fallback_doms;
+               cpumask_andnot(doms_new[0], cpu_online_mask, cpu_isolated_map);
                WARN_ON_ONCE(dattr_new);
        }
 
        /* Build new domains */
        for (i = 0; i < ndoms_new; i++) {
                for (j = 0; j < ndoms_cur && !new_topology; j++) {
-                       if (cpumask_equal(&doms_new[i], &doms_cur[j])
+                       if (cpumask_equal(doms_new[i], doms_cur[j])
                            && dattrs_equal(dattr_new, i, dattr_cur, j))
                                goto match2;
                }
                /* no match - add a new doms_new */
-               __build_sched_domains(doms_new + i,
+               __build_sched_domains(doms_new[i],
                                        dattr_new ? dattr_new + i : NULL);
 match2:
                ;
        }
 
        /* Remember the new sched domains */
-       if (doms_cur != fallback_doms)
-               kfree(doms_cur);
+       if (doms_cur != &fallback_doms)
+               free_sched_domains(doms_cur, ndoms_cur);
        kfree(dattr_cur);       /* kfree(NULL) is safe */
        doms_cur = doms_new;
        dattr_cur = dattr_new;
@@ -9329,10 +9368,6 @@ void __init sched_init(void)
 #ifdef CONFIG_CPUMASK_OFFSTACK
        alloc_size += num_possible_cpus() * cpumask_size();
 #endif
-       /*
-        * As sched_init() is called before page_alloc is setup,
-        * we use alloc_bootmem().
-        */
        if (alloc_size) {
                ptr = (unsigned long)kzalloc(alloc_size, GFP_NOWAIT);
 
@@ -9483,6 +9518,8 @@ void __init sched_init(void)
                rq->cpu = i;
                rq->online = 0;
                rq->migration_thread = NULL;
+               rq->idle_stamp = 0;
+               rq->avg_idle = 2*sysctl_sched_migration_cost;
                INIT_LIST_HEAD(&rq->migration_queue);
                rq_attach_root(rq, &def_root_domain);
 #endif