Merge branch 'sched-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
Linus Torvalds [Sat, 5 Dec 2009 23:30:49 +0000 (15:30 -0800)]
* 'sched-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (35 commits)
  sched, cputime: Introduce thread_group_times()
  sched, cputime: Cleanups related to task_times()
  Revert "sched, x86: Optimize branch hint in __switch_to()"
  sched: Fix isolcpus boot option
  sched: Revert 498657a478c60be092208422fefa9c7b248729c2
  sched, time: Define nsecs_to_jiffies()
  sched: Remove task_{u,s,g}time()
  sched: Introduce task_times() to replace task_{u,s}time() pair
  sched: Limit the number of scheduler debug messages
  sched.c: Call debug_show_all_locks() when dumping all tasks
  sched, x86: Optimize branch hint in __switch_to()
  sched: Optimize branch hint in context_switch()
  sched: Optimize branch hint in pick_next_task_fair()
  sched_feat_write(): Update ppos instead of file->f_pos
  sched: Sched_rt_periodic_timer vs cpu hotplug
  sched, kvm: Fix race condition involving sched_in_preempt_notifers
  sched: More generic WAKE_AFFINE vs select_idle_sibling()
  sched: Cleanup select_task_rq_fair()
  sched: Fix granularity of task_u/stime()
  sched: Fix/add missing update_rq_clock() calls
  ...

1  2 
Documentation/kernel-parameters.txt
fs/proc/array.c
include/linux/sched.h
kernel/exit.c
kernel/sched.c

@@@ -85,6 -85,7 +85,6 @@@ parameter is applicable
        PPT     Parallel port support is enabled.
        PS2     Appropriate PS/2 support is enabled.
        RAM     RAM disk support is enabled.
 -      ROOTPLUG The example Root Plug LSM is enabled.
        S390    S390 architecture is enabled.
        SCSI    Appropriate SCSI support is enabled.
                        A lot of drivers has their options described inside of
@@@ -778,13 -779,6 +778,13 @@@ and is between 256 and 4096 characters
                        by the set_ftrace_notrace file in the debugfs
                        tracing directory.
  
 +      ftrace_graph_filter=[function-list]
 +                      [FTRACE] Limit the top level callers functions traced
 +                      by the function graph tracer at boot up.
 +                      function-list is a comma separated list of functions
 +                      that can be changed at run time by the
 +                      set_graph_function file in the debugfs tracing directory.
 +
        gamecon.map[2|3]=
                        [HW,JOY] Multisystem joystick and NES/SNES/PSX pad
                        support via parallel port (up to 5 devices per port)
  
        print-fatal-signals=
                        [KNL] debug: print fatal signals
 -                      print-fatal-signals=1: print segfault info to
 -                      the kernel console.
 +
 +                      If enabled, warn about various signal handling
 +                      related application anomalies: too many signals,
 +                      too many POSIX.1 timers, fatal signals causing a
 +                      coredump - etc.
 +
 +                      If you hit the warning due to signal overflow,
 +                      you might want to try "ulimit -i unlimited".
 +
                        default: off.
  
        printk.time=    Show timing data prefixed to each printk message line
                        Useful for devices that are detected asynchronously
                        (e.g. USB and MMC devices).
  
 -      root_plug.vendor_id=
 -                      [ROOTPLUG] Override the default vendor ID
 -
 -      root_plug.product_id=
 -                      [ROOTPLUG] Override the default product ID
 -
 -      root_plug.debug=
 -                      [ROOTPLUG] Enable debugging output
 -
        rw              [KNL] Mount root device read-write on boot
  
        S               [KNL] Run init in single mode
  
        sbni=           [NET] Granch SBNI12 leased line adapter
  
+       sched_debug     [KNL] Enables verbose scheduler debug messages.
        sc1200wdt=      [HW,WDT] SC1200 WDT (watchdog) driver
                        Format: <io>[,<timeout>[,<isapnp>]]
  
diff --combined fs/proc/array.c
@@@ -410,6 -410,16 +410,16 @@@ static void task_show_stack_usage(struc
  }
  #endif                /* CONFIG_MMU */
  
+ static void task_cpus_allowed(struct seq_file *m, struct task_struct *task)
+ {
+       seq_printf(m, "Cpus_allowed:\t");
+       seq_cpumask(m, &task->cpus_allowed);
+       seq_printf(m, "\n");
+       seq_printf(m, "Cpus_allowed_list:\t");
+       seq_cpumask_list(m, &task->cpus_allowed);
+       seq_printf(m, "\n");
+ }
  int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
                        struct pid *pid, struct task_struct *task)
  {
        }
        task_sig(m, task);
        task_cap(m, task);
+       task_cpus_allowed(m, task);
        cpuset_task_status_allowed(m, task);
  #if defined(CONFIG_S390)
        task_show_regs(m, task);
@@@ -495,20 -506,17 +506,17 @@@ static int do_task_stat(struct seq_fil
  
                /* add up live thread stats at the group level */
                if (whole) {
-                       struct task_cputime cputime;
                        struct task_struct *t = task;
                        do {
                                min_flt += t->min_flt;
                                maj_flt += t->maj_flt;
-                               gtime = cputime_add(gtime, task_gtime(t));
+                               gtime = cputime_add(gtime, t->gtime);
                                t = next_thread(t);
                        } while (t != task);
  
                        min_flt += sig->min_flt;
                        maj_flt += sig->maj_flt;
-                       thread_group_cputime(task, &cputime);
-                       utime = cputime.utime;
-                       stime = cputime.stime;
+                       thread_group_times(task, &utime, &stime);
                        gtime = cputime_add(gtime, sig->gtime);
                }
  
        if (!whole) {
                min_flt = task->min_flt;
                maj_flt = task->maj_flt;
-               utime = task_utime(task);
-               stime = task_stime(task);
-               gtime = task_gtime(task);
+               task_times(task, &utime, &stime);
+               gtime = task->gtime;
        }
  
        /* scale priority and nice values from timeslices to -20..20 */
                rsslim,
                mm ? mm->start_code : 0,
                mm ? mm->end_code : 0,
 -              (permitted) ? task->stack_start : 0,
 +              (permitted && mm) ? task->stack_start : 0,
                esp,
                eip,
                /* The signal information here is obsolete.
diff --combined include/linux/sched.h
@@@ -145,7 -145,6 +145,6 @@@ extern unsigned long this_cpu_load(void
  
  
  extern void calc_global_load(void);
- extern u64 cpu_nr_migrations(int cpu);
  
  extern unsigned long get_parent_ip(unsigned long addr);
  
@@@ -171,8 -170,6 +170,6 @@@ print_cfs_rq(struct seq_file *m, int cp
  }
  #endif
  
- extern unsigned long long time_sync_thresh;
  /*
   * Task state bitmask. NOTE! These bits are also
   * encoded in fs/proc/array.c: get_task_state().
@@@ -349,7 -346,6 +346,6 @@@ extern signed long schedule_timeout(sig
  extern signed long schedule_timeout_interruptible(signed long timeout);
  extern signed long schedule_timeout_killable(signed long timeout);
  extern signed long schedule_timeout_uninterruptible(signed long timeout);
- asmlinkage void __schedule(void);
  asmlinkage void schedule(void);
  extern int mutex_spin_on_owner(struct mutex *lock, struct thread_info *owner);
  
@@@ -628,6 -624,9 +624,9 @@@ struct signal_struct 
        cputime_t utime, stime, cutime, cstime;
        cputime_t gtime;
        cputime_t cgtime;
+ #ifndef CONFIG_VIRT_CPU_ACCOUNTING
+       cputime_t prev_utime, prev_stime;
+ #endif
        unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw;
        unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt;
        unsigned long inblock, oublock, cinblock, coublock;
@@@ -1013,9 -1012,13 +1012,13 @@@ static inline struct cpumask *sched_dom
        return to_cpumask(sd->span);
  }
  
- extern void partition_sched_domains(int ndoms_new, struct cpumask *doms_new,
+ extern void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[],
                                    struct sched_domain_attr *dattr_new);
  
+ /* Allocate an array of sched domains, for partition_sched_domains(). */
+ cpumask_var_t *alloc_sched_domains(unsigned int ndoms);
+ void free_sched_domains(cpumask_var_t doms[], unsigned int ndoms);
  /* Test a flag in parent sched domain */
  static inline int test_sd_parent(struct sched_domain *sd, int flag)
  {
@@@ -1033,7 -1036,7 +1036,7 @@@ unsigned long default_scale_smt_power(s
  struct sched_domain_attr;
  
  static inline void
- partition_sched_domains(int ndoms_new, struct cpumask *doms_new,
+ partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[],
                        struct sched_domain_attr *dattr_new)
  {
  }
@@@ -1331,7 -1334,9 +1334,9 @@@ struct task_struct 
  
        cputime_t utime, stime, utimescaled, stimescaled;
        cputime_t gtime;
+ #ifndef CONFIG_VIRT_CPU_ACCOUNTING
        cputime_t prev_utime, prev_stime;
+ #endif
        unsigned long nvcsw, nivcsw; /* context switch counts */
        struct timespec start_time;             /* monotonic time */
        struct timespec real_start_time;        /* boot based time */
  #endif
  #ifdef CONFIG_TRACE_IRQFLAGS
        unsigned int irq_events;
 -      int hardirqs_enabled;
        unsigned long hardirq_enable_ip;
 -      unsigned int hardirq_enable_event;
        unsigned long hardirq_disable_ip;
 +      unsigned int hardirq_enable_event;
        unsigned int hardirq_disable_event;
 -      int softirqs_enabled;
 +      int hardirqs_enabled;
 +      int hardirq_context;
        unsigned long softirq_disable_ip;
 -      unsigned int softirq_disable_event;
        unsigned long softirq_enable_ip;
 +      unsigned int softirq_disable_event;
        unsigned int softirq_enable_event;
 -      int hardirq_context;
 +      int softirqs_enabled;
        int softirq_context;
  #endif
  #ifdef CONFIG_LOCKDEP
@@@ -1720,9 -1725,8 +1725,8 @@@ static inline void put_task_struct(stru
                __put_task_struct(t);
  }
  
- extern cputime_t task_utime(struct task_struct *p);
- extern cputime_t task_stime(struct task_struct *p);
- extern cputime_t task_gtime(struct task_struct *p);
+ extern void task_times(struct task_struct *p, cputime_t *ut, cputime_t *st);
+ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st);
  
  /*
   * Per process flags
@@@ -2086,18 -2090,11 +2090,18 @@@ static inline int is_si_special(const s
        return info <= SEND_SIG_FORCED;
  }
  
 -/* True if we are on the alternate signal stack.  */
 -
 +/*
 + * True if we are on the alternate signal stack.
 + */
  static inline int on_sig_stack(unsigned long sp)
  {
 -      return (sp - current->sas_ss_sp < current->sas_ss_size);
 +#ifdef CONFIG_STACK_GROWSUP
 +      return sp >= current->sas_ss_sp &&
 +              sp - current->sas_ss_sp < current->sas_ss_size;
 +#else
 +      return sp > current->sas_ss_sp &&
 +              sp - current->sas_ss_sp <= current->sas_ss_size;
 +#endif
  }
  
  static inline int sas_ss_flags(unsigned long sp)
diff --combined kernel/exit.c
@@@ -49,7 -49,6 +49,7 @@@
  #include <linux/init_task.h>
  #include <linux/perf_event.h>
  #include <trace/events/sched.h>
 +#include <linux/hw_breakpoint.h>
  
  #include <asm/uaccess.h>
  #include <asm/unistd.h>
@@@ -111,9 -110,9 +111,9 @@@ static void __exit_signal(struct task_s
                 * We won't ever get here for the group leader, since it
                 * will have been the last reference on the signal_struct.
                 */
-               sig->utime = cputime_add(sig->utime, task_utime(tsk));
-               sig->stime = cputime_add(sig->stime, task_stime(tsk));
-               sig->gtime = cputime_add(sig->gtime, task_gtime(tsk));
+               sig->utime = cputime_add(sig->utime, tsk->utime);
+               sig->stime = cputime_add(sig->stime, tsk->stime);
+               sig->gtime = cputime_add(sig->gtime, tsk->gtime);
                sig->min_flt += tsk->min_flt;
                sig->maj_flt += tsk->maj_flt;
                sig->nvcsw += tsk->nvcsw;
@@@ -979,10 -978,6 +979,10 @@@ NORET_TYPE void do_exit(long code
        proc_exit_connector(tsk);
  
        /*
 +       * FIXME: do that only when needed, using sched_exit tracepoint
 +       */
 +      flush_ptrace_hw_breakpoint(tsk);
 +      /*
         * Flush inherited counters to the parent - before the parent
         * gets woken up by child-exit notifications.
         */
@@@ -1210,6 -1205,7 +1210,7 @@@ static int wait_task_zombie(struct wait
                struct signal_struct *psig;
                struct signal_struct *sig;
                unsigned long maxrss;
+               cputime_t tgutime, tgstime;
  
                /*
                 * The resource counters for the group leader are in its
                 * need to protect the access to parent->signal fields,
                 * as other threads in the parent group can be right
                 * here reaping other children at the same time.
+                *
+                * We use thread_group_times() to get times for the thread
+                * group, which consolidates times for all threads in the
+                * group including the group leader.
                 */
+               thread_group_times(p, &tgutime, &tgstime);
                spin_lock_irq(&p->real_parent->sighand->siglock);
                psig = p->real_parent->signal;
                sig = p->signal;
                psig->cutime =
                        cputime_add(psig->cutime,
-                       cputime_add(p->utime,
-                       cputime_add(sig->utime,
-                                   sig->cutime)));
+                       cputime_add(tgutime,
+                                   sig->cutime));
                psig->cstime =
                        cputime_add(psig->cstime,
-                       cputime_add(p->stime,
-                       cputime_add(sig->stime,
-                                   sig->cstime)));
+                       cputime_add(tgstime,
+                                   sig->cstime));
                psig->cgtime =
                        cputime_add(psig->cgtime,
                        cputime_add(p->gtime,
diff --combined kernel/sched.c
@@@ -535,14 -535,12 +535,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;
  
        u64 rt_avg;
        u64 age_stamp;
+       u64 idle_stamp;
+       u64 avg_idle;
  #endif
  
        /* calc_load related fields */
@@@ -772,7 -772,7 +772,7 @@@ sched_feat_write(struct file *filp, con
        if (!sched_feat_names[i])
                return -EINVAL;
  
-       filp->f_pos += cnt;
+       *ppos += cnt;
  
        return cnt;
  }
@@@ -2017,6 -2017,7 +2017,7 @@@ void kthread_bind(struct task_struct *p
        }
  
        spin_lock_irqsave(&rq->lock, flags);
+       update_rq_clock(rq);
        set_task_cpu(p, cpu);
        p->cpus_allowed = cpumask_of_cpu(cpu);
        p->rt.nr_cpus_allowed = 1;
@@@ -2078,7 -2079,6 +2079,6 @@@ void set_task_cpu(struct task_struct *p
  #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);
@@@ -2115,6 -2115,7 +2115,7 @@@ migrate_task(struct task_struct *p, in
         * it is sufficient to simply update the task's cpu field.
         */
        if (!p->se.on_rq && !task_running(rq, p)) {
+               update_rq_clock(rq);
                set_task_cpu(p, dest_cpu);
                return 0;
        }
@@@ -2376,14 -2377,15 +2377,15 @@@ static int try_to_wake_up(struct task_s
        task_rq_unlock(rq, &flags);
  
        cpu = p->sched_class->select_task_rq(p, SD_BALANCE_WAKE, wake_flags);
-       if (cpu != orig_cpu)
+       if (cpu != orig_cpu) {
+               local_irq_save(flags);
+               rq = cpu_rq(cpu);
+               update_rq_clock(rq);
                set_task_cpu(p, cpu);
+               local_irq_restore(flags);
+       }
        rq = task_rq_lock(p, &flags);
  
-       if (rq != orig_rq)
-               update_rq_clock(rq);
        WARN_ON(p->state != TASK_WAKING);
        cpu = task_cpu(p);
  
@@@ -2440,6 -2442,17 +2442,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);
@@@ -2545,6 -2558,7 +2558,7 @@@ static void __sched_fork(struct task_st
  void sched_fork(struct task_struct *p, int clone_flags)
  {
        int cpu = get_cpu();
+       unsigned long flags;
  
        __sched_fork(p);
  
  #ifdef CONFIG_SMP
        cpu = p->sched_class->select_task_rq(p, SD_BALANCE_FORK, 0);
  #endif
+       local_irq_save(flags);
+       update_rq_clock(cpu_rq(cpu));
        set_task_cpu(p, cpu);
+       local_irq_restore(flags);
  
  #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
        if (likely(sched_info_on()))
@@@ -2848,14 -2865,14 +2865,14 @@@ context_switch(struct rq *rq, struct ta
         */
        arch_start_context_switch(prev);
  
-       if (unlikely(!mm)) {
+       if (likely(!mm)) {
                next->active_mm = oldmm;
                atomic_inc(&oldmm->mm_count);
                enter_lazy_tlb(oldmm, next);
        } else
                switch_mm(oldmm, mm, next);
  
-       if (unlikely(!prev->mm)) {
+       if (likely(!prev->mm)) {
                prev->active_mm = NULL;
                rq->prev_mm = oldmm;
        }
@@@ -3018,15 -3035,6 +3035,6 @@@ static void calc_load_account_active(st
  }
  
  /*
-  * 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).
   */
@@@ -4126,7 -4134,7 +4134,7 @@@ static int load_balance(int this_cpu, s
        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
@@@ -4289,7 -4297,7 +4297,7 @@@ load_balance_newidle(int this_cpu, stru
        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
@@@ -4429,6 -4437,11 +4437,11 @@@ static void idle_balance(int this_cpu, 
        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;
  
                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)) {
                /*
@@@ -5046,8 -5061,13 +5061,13 @@@ static void account_guest_time(struct t
        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);
+       }
  }
  
  /*
@@@ -5162,60 -5182,86 +5182,86 @@@ void account_idle_ticks(unsigned long t
   * Use precise platform statistics if available:
   */
  #ifdef CONFIG_VIRT_CPU_ACCOUNTING
- cputime_t task_utime(struct task_struct *p)
+ void task_times(struct task_struct *p, cputime_t *ut, cputime_t *st)
  {
-       return p->utime;
+       *ut = p->utime;
+       *st = p->stime;
  }
  
- cputime_t task_stime(struct task_struct *p)
+ void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st)
  {
-       return p->stime;
+       struct task_cputime cputime;
+       thread_group_cputime(p, &cputime);
+       *ut = cputime.utime;
+       *st = cputime.stime;
  }
  #else
- cputime_t task_utime(struct task_struct *p)
+ #ifndef nsecs_to_cputime
+ # define nsecs_to_cputime(__nsecs)    nsecs_to_jiffies(__nsecs)
+ #endif
+ void task_times(struct task_struct *p, cputime_t *ut, cputime_t *st)
  {
-       clock_t utime = cputime_to_clock_t(p->utime),
-               total = utime + cputime_to_clock_t(p->stime);
-       u64 temp;
+       cputime_t rtime, utime = p->utime, total = cputime_add(utime, p->stime);
  
        /*
         * Use CFS's precise accounting:
         */
-       temp = (u64)nsec_to_clock_t(p->se.sum_exec_runtime);
+       rtime = nsecs_to_cputime(p->se.sum_exec_runtime);
  
        if (total) {
-               temp *= utime;
+               u64 temp;
+               temp = (u64)(rtime * utime);
                do_div(temp, total);
-       }
-       utime = (clock_t)temp;
+               utime = (cputime_t)temp;
+       } else
+               utime = rtime;
+       /*
+        * Compare with previous values, to keep monotonicity:
+        */
+       p->prev_utime = max(p->prev_utime, utime);
+       p->prev_stime = max(p->prev_stime, cputime_sub(rtime, p->prev_utime));
  
-       p->prev_utime = max(p->prev_utime, clock_t_to_cputime(utime));
-       return p->prev_utime;
+       *ut = p->prev_utime;
+       *st = p->prev_stime;
  }
  
- cputime_t task_stime(struct task_struct *p)
+ /*
+  * Must be called with siglock held.
+  */
+ void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st)
  {
-       clock_t stime;
+       struct signal_struct *sig = p->signal;
+       struct task_cputime cputime;
+       cputime_t rtime, utime, total;
  
-       /*
-        * 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));
+       thread_group_cputime(p, &cputime);
  
-       if (stime >= 0)
-               p->prev_stime = max(p->prev_stime, clock_t_to_cputime(stime));
+       total = cputime_add(cputime.utime, cputime.stime);
+       rtime = nsecs_to_cputime(cputime.sum_exec_runtime);
  
-       return p->prev_stime;
- }
- #endif
+       if (total) {
+               u64 temp;
  
- inline cputime_t task_gtime(struct task_struct *p)
- {
-       return p->gtime;
+               temp = (u64)(rtime * cputime.utime);
+               do_div(temp, total);
+               utime = (cputime_t)temp;
+       } else
+               utime = rtime;
+       sig->prev_utime = max(sig->prev_utime, utime);
+       sig->prev_stime = max(sig->prev_stime,
+                             cputime_sub(rtime, sig->prev_utime));
+       *ut = sig->prev_utime;
+       *st = sig->prev_stime;
  }
+ #endif
  
  /*
   * This function gets called by the timer code, with HZ frequency.
@@@ -5481,7 -5527,7 +5527,7 @@@ need_resched_nonpreemptible
  }
  EXPORT_SYMBOL(schedule);
  
 -#ifdef CONFIG_SMP
 +#ifdef CONFIG_MUTEX_SPIN_ON_OWNER
  /*
   * Look out! "owner" is an entirely speculative pointer
   * access and not reliable.
@@@ -6175,22 -6221,14 +6221,14 @@@ __setscheduler(struct rq *rq, struct ta
        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);
  }
  
@@@ -6935,7 -6973,7 +6973,7 @@@ void show_state_filter(unsigned long st
        /*
         * Only show locks if all tasks are dumped:
         */
-       if (state_filter == -1)
+       if (!state_filter)
                debug_show_all_locks();
  }
  
@@@ -7740,6 -7778,16 +7778,16 @@@ early_initcall(migration_init)
  
  #ifdef CONFIG_SCHED_DEBUG
  
+ static __read_mostly int sched_domain_debug_enabled;
+ static int __init sched_domain_debug_setup(char *str)
+ {
+       sched_domain_debug_enabled = 1;
+       return 0;
+ }
+ early_param("sched_debug", sched_domain_debug_setup);
  static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level,
                                  struct cpumask *groupmask)
  {
@@@ -7826,6 -7874,9 +7874,9 @@@ static void sched_domain_debug(struct s
        cpumask_var_t groupmask;
        int level = 0;
  
+       if (!sched_domain_debug_enabled)
+               return;
        if (!sd) {
                printk(KERN_DEBUG "CPU%d attaching NULL sched-domain.\n", cpu);
                return;
@@@ -7905,6 -7956,8 +7956,8 @@@ sd_parent_degenerate(struct sched_domai
  
  static void free_rootdomain(struct root_domain *rd)
  {
+       synchronize_sched();
        cpupri_cleanup(&rd->cpupri);
  
        free_cpumask_var(rd->rto_mask);
@@@ -8045,6 -8098,7 +8098,7 @@@ static cpumask_var_t cpu_isolated_map
  /* Setup the mask of cpus configured for isolated domains */
  static int __init isolated_cpu_setup(char *str)
  {
+       alloc_bootmem_cpumask_var(&cpu_isolated_map);
        cpulist_parse(str, cpu_isolated_map);
        return 1;
  }
@@@ -8881,7 -8935,7 +8935,7 @@@ static int build_sched_domains(const st
        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' */
@@@ -8903,6 -8957,31 +8957,31 @@@ int __attribute__((weak)) arch_update_c
        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
@@@ -8914,12 -8993,12 +8993,12 @@@ static int arch_init_sched_domains(cons
  
        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;
@@@ -8969,19 -9048,19 +9048,19 @@@ static int dattrs_equal(struct sched_do
   * 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,
   *
   * 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;
        /* 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;
@@@ -9364,10 -9442,6 +9442,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);
  
                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
        zalloc_cpumask_var(&nohz.cpu_mask, GFP_NOWAIT);
        alloc_cpumask_var(&nohz.ilb_grp_nohz_mask, GFP_NOWAIT);
  #endif
-       zalloc_cpumask_var(&cpu_isolated_map, GFP_NOWAIT);
+       /* May be allocated at isolcpus cmdline parse time */
+       if (cpu_isolated_map == NULL)
+               zalloc_cpumask_var(&cpu_isolated_map, GFP_NOWAIT);
  #endif /* SMP */
  
        perf_event_init();
@@@ -10901,7 -10979,6 +10979,7 @@@ void synchronize_sched_expedited(void
                spin_unlock_irqrestore(&rq->lock, flags);
        }
        rcu_expedited_state = RCU_EXPEDITED_STATE_IDLE;
 +      synchronize_sched_expedited_count++;
        mutex_unlock(&rcu_sched_expedited_mutex);
        put_online_cpus();
        if (need_full_sync)