Merge branch 'sched-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
Linus Torvalds [Fri, 2 Jul 2010 16:52:58 +0000 (09:52 -0700)]
* 'sched-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  sched: Cure nr_iowait_cpu() users
  init: Fix comment
  init, sched: Fix race between init and kthreadd

1  2 
init/main.c
kernel/sched.c
kernel/time/tick-sched.c

diff --combined init/main.c
@@@ -125,9 -125,7 +125,9 @@@ static char *ramdisk_execute_command
  
  #ifdef CONFIG_SMP
  /* Setup configured maximum number of CPUs to activate */
 -unsigned int __initdata setup_max_cpus = NR_CPUS;
 +unsigned int setup_max_cpus = NR_CPUS;
 +EXPORT_SYMBOL(setup_max_cpus);
 +
  
  /*
   * Setup routine for controlling SMP activation
@@@ -424,18 -422,26 +424,26 @@@ static void __init setup_command_line(c
   * gcc-3.4 accidentally inlines this function, so use noinline.
   */
  
+ static __initdata DECLARE_COMPLETION(kthreadd_done);
  static noinline void __init_refok rest_init(void)
        __releases(kernel_lock)
  {
        int pid;
  
        rcu_scheduler_starting();
+       /*
+        * We need to spawn init first so that it obtains pid 1, however
+        * the init task will end up wanting to create kthreads, which, if
+        * we schedule it before we create kthreadd, will OOPS.
+        */
        kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
        numa_default_policy();
        pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
        rcu_read_lock();
        kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
        rcu_read_unlock();
+       complete(&kthreadd_done);
        unlock_kernel();
  
        /*
@@@ -857,6 -863,10 +865,10 @@@ static noinline int init_post(void
  
  static int __init kernel_init(void * unused)
  {
+       /*
+        * Wait until kthreadd is all set-up.
+        */
+       wait_for_completion(&kthreadd_done);
        lock_kernel();
  
        /*
diff --combined kernel/sched.c
@@@ -2494,16 -2494,7 +2494,16 @@@ void sched_fork(struct task_struct *p, 
        if (p->sched_class->task_fork)
                p->sched_class->task_fork(p);
  
 +      /*
 +       * The child is not yet in the pid-hash so no cgroup attach races,
 +       * and the cgroup is pinned to this child due to cgroup_fork()
 +       * is ran before sched_fork().
 +       *
 +       * Silence PROVE_RCU.
 +       */
 +      rcu_read_lock();
        set_task_cpu(p, cpu);
 +      rcu_read_unlock();
  
  #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
        if (likely(sched_info_on()))
@@@ -2873,9 -2864,9 +2873,9 @@@ unsigned long nr_iowait(void
        return sum;
  }
  
- unsigned long nr_iowait_cpu(void)
+ unsigned long nr_iowait_cpu(int cpu)
  {
-       struct rq *this = this_rq();
+       struct rq *this = cpu_rq(cpu);
        return atomic_read(&this->nr_iowait);
  }
  
diff --combined kernel/time/tick-sched.c
@@@ -154,14 -154,14 +154,14 @@@ static void tick_nohz_update_jiffies(kt
   * Updates the per cpu time idle statistics counters
   */
  static void
- update_ts_time_stats(struct tick_sched *ts, ktime_t now, u64 *last_update_time)
+ update_ts_time_stats(int cpu, struct tick_sched *ts, ktime_t now, u64 *last_update_time)
  {
        ktime_t delta;
  
        if (ts->idle_active) {
                delta = ktime_sub(now, ts->idle_entrytime);
                ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta);
-               if (nr_iowait_cpu() > 0)
+               if (nr_iowait_cpu(cpu) > 0)
                        ts->iowait_sleeptime = ktime_add(ts->iowait_sleeptime, delta);
                ts->idle_entrytime = now;
        }
@@@ -175,19 -175,19 +175,19 @@@ static void tick_nohz_stop_idle(int cpu
  {
        struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
  
-       update_ts_time_stats(ts, now, NULL);
+       update_ts_time_stats(cpu, ts, now, NULL);
        ts->idle_active = 0;
  
        sched_clock_idle_wakeup_event(0);
  }
  
- static ktime_t tick_nohz_start_idle(struct tick_sched *ts)
+ static ktime_t tick_nohz_start_idle(int cpu, struct tick_sched *ts)
  {
        ktime_t now;
  
        now = ktime_get();
  
-       update_ts_time_stats(ts, now, NULL);
+       update_ts_time_stats(cpu, ts, now, NULL);
  
        ts->idle_entrytime = now;
        ts->idle_active = 1;
@@@ -216,7 -216,7 +216,7 @@@ u64 get_cpu_idle_time_us(int cpu, u64 *
        if (!tick_nohz_enabled)
                return -1;
  
-       update_ts_time_stats(ts, ktime_get(), last_update_time);
+       update_ts_time_stats(cpu, ts, ktime_get(), last_update_time);
  
        return ktime_to_us(ts->idle_sleeptime);
  }
@@@ -242,7 -242,7 +242,7 @@@ u64 get_cpu_iowait_time_us(int cpu, u6
        if (!tick_nohz_enabled)
                return -1;
  
-       update_ts_time_stats(ts, ktime_get(), last_update_time);
+       update_ts_time_stats(cpu, ts, ktime_get(), last_update_time);
  
        return ktime_to_us(ts->iowait_sleeptime);
  }
@@@ -284,7 -284,7 +284,7 @@@ void tick_nohz_stop_sched_tick(int inid
         */
        ts->inidle = 1;
  
-       now = tick_nohz_start_idle(ts);
+       now = tick_nohz_start_idle(cpu, ts);
  
        /*
         * If this cpu is offline and it is the one which updates
                goto end;
        }
  
 -      if (nohz_ratelimit(cpu))
 -              goto end;
 -
        ts->idle_calls++;
        /* Read jiffies and the time when jiffies were updated last */
        do {
        } while (read_seqretry(&xtime_lock, seq));
  
        if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu) ||
 -          arch_needs_cpu(cpu)) {
 +          arch_needs_cpu(cpu) || nohz_ratelimit(cpu)) {
                next_jiffies = last_jiffies + 1;
                delta_jiffies = 1;
        } else {