Merge commit 'v2.6.31-rc6' into core/rcu
authorIngo Molnar <mingo@elte.hu>
Sat, 15 Aug 2009 16:55:58 +0000 (18:55 +0200)
committerIngo Molnar <mingo@elte.hu>
Sat, 15 Aug 2009 16:56:13 +0000 (18:56 +0200)
Merge reason: the branch was on pre-rc1 .30, update to latest.

Signed-off-by: Ingo Molnar <mingo@elte.hu>
1  2 
init/Kconfig
kernel/Makefile
kernel/sched.c

diff --combined init/Kconfig
@@@ -316,13 -316,21 +316,13 @@@ choic
        prompt "RCU Implementation"
        default TREE_RCU
  
 -config CLASSIC_RCU
 -      bool "Classic RCU"
 -      help
 -        This option selects the classic RCU implementation that is
 -        designed for best read-side performance on non-realtime
 -        systems.
 -
 -        Select this option if you are unsure.
 -
  config TREE_RCU
        bool "Tree-based hierarchical RCU"
        help
          This option selects the RCU implementation that is
          designed for very large SMP system with hundreds or
 -        thousands of CPUs.
 +        thousands of CPUs.  It also scales down nicely to
 +        smaller systems.
  
  config PREEMPT_RCU
        bool "Preemptible RCU"
@@@ -932,6 -940,7 +932,7 @@@ menu "Performance Counters
  
  config PERF_COUNTERS
        bool "Kernel Performance Counters"
+       default y if PROFILING
        depends on HAVE_PERF_COUNTERS
        select ANON_INODES
        help
          Say Y if unsure.
  
  config EVENT_PROFILE
-       bool "Tracepoint profile sources"
-       depends on PERF_COUNTERS && EVENT_TRACER
+       bool "Tracepoint profiling sources"
+       depends on PERF_COUNTERS && EVENT_TRACING
        default y
+       help
+        Allow the use of tracepoints as software performance counters.
+        When this is enabled, you can create perf counters based on
+        tracepoints using PERF_TYPE_TRACEPOINT and the tracepoint ID
+        found in debugfs://tracing/events/*/*/id. (The -e/--events
+        option to the perf tool can parse and interpret symbolic
+        tracepoints, in the subsystem:tracepoint_name format.)
  
  endmenu
  
diff --combined kernel/Makefile
@@@ -69,7 -69,7 +69,7 @@@ obj-$(CONFIG_IKCONFIG) += configs.
  obj-$(CONFIG_RESOURCE_COUNTERS) += res_counter.o
  obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
  obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o
- obj-$(CONFIG_AUDIT) += audit.o auditfilter.o
+ obj-$(CONFIG_AUDIT) += audit.o auditfilter.o audit_watch.o
  obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
  obj-$(CONFIG_GCOV_KERNEL) += gcov/
  obj-$(CONFIG_AUDIT_TREE) += audit_tree.o
@@@ -80,6 -80,7 +80,6 @@@ obj-$(CONFIG_DETECT_HUNG_TASK) += hung_
  obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
  obj-$(CONFIG_SECCOMP) += seccomp.o
  obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
 -obj-$(CONFIG_CLASSIC_RCU) += rcuclassic.o
  obj-$(CONFIG_TREE_RCU) += rcutree.o
  obj-$(CONFIG_PREEMPT_RCU) += rcupreempt.o
  obj-$(CONFIG_TREE_RCU_TRACE) += rcutree_trace.o
@@@ -95,6 -96,7 +95,7 @@@ obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT
  obj-$(CONFIG_FUNCTION_TRACER) += trace/
  obj-$(CONFIG_TRACING) += trace/
  obj-$(CONFIG_X86_DS) += trace/
+ obj-$(CONFIG_RING_BUFFER) += trace/
  obj-$(CONFIG_SMP) += sched_cpupri.o
  obj-$(CONFIG_SLOW_WORK) += slow-work.o
  obj-$(CONFIG_PERF_COUNTERS) += perf_counter.o
diff --combined kernel/sched.c
@@@ -493,6 -493,7 +493,7 @@@ struct rt_rq 
  #endif
  #ifdef CONFIG_SMP
        unsigned long rt_nr_migratory;
+       unsigned long rt_nr_total;
        int overloaded;
        struct plist_head pushable_tasks;
  #endif
@@@ -2571,15 -2572,37 +2572,37 @@@ static void __sched_fork(struct task_st
        p->se.avg_wakeup                = sysctl_sched_wakeup_granularity;
  
  #ifdef CONFIG_SCHEDSTATS
-       p->se.wait_start                = 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_start                        = 0;
+       p->se.wait_max                          = 0;
+       p->se.wait_count                        = 0;
+       p->se.wait_sum                          = 0;
+       p->se.sleep_start                       = 0;
+       p->se.sleep_max                         = 0;
+       p->se.sum_sleep_runtime                 = 0;
+       p->se.block_start                       = 0;
+       p->se.block_max                         = 0;
+       p->se.exec_max                          = 0;
+       p->se.slice_max                         = 0;
+       p->se.nr_migrations_cold                = 0;
+       p->se.nr_failed_migrations_affine       = 0;
+       p->se.nr_failed_migrations_running      = 0;
+       p->se.nr_failed_migrations_hot          = 0;
+       p->se.nr_forced_migrations              = 0;
+       p->se.nr_forced2_migrations             = 0;
+       p->se.nr_wakeups                        = 0;
+       p->se.nr_wakeups_sync                   = 0;
+       p->se.nr_wakeups_migrate                = 0;
+       p->se.nr_wakeups_local                  = 0;
+       p->se.nr_wakeups_remote                 = 0;
+       p->se.nr_wakeups_affine                 = 0;
+       p->se.nr_wakeups_affine_attempts        = 0;
+       p->se.nr_wakeups_passive                = 0;
+       p->se.nr_wakeups_idle                   = 0;
  #endif
  
        INIT_LIST_HEAD(&p->rt.run_list);
@@@ -6541,6 -6564,11 +6564,11 @@@ SYSCALL_DEFINE0(sched_yield
        return 0;
  }
  
+ static inline int should_resched(void)
+ {
+       return need_resched() && !(preempt_count() & PREEMPT_ACTIVE);
+ }
  static void __cond_resched(void)
  {
  #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
  
  int __sched _cond_resched(void)
  {
-       if (need_resched() && !(preempt_count() & PREEMPT_ACTIVE) &&
-                                       system_state == SYSTEM_RUNNING) {
+       if (should_resched()) {
                __cond_resched();
                return 1;
        }
@@@ -6579,12 -6606,12 +6606,12 @@@ EXPORT_SYMBOL(_cond_resched)
   */
  int cond_resched_lock(spinlock_t *lock)
  {
-       int resched = need_resched() && system_state == SYSTEM_RUNNING;
+       int resched = should_resched();
        int ret = 0;
  
        if (spin_needbreak(lock) || resched) {
                spin_unlock(lock);
-               if (resched && need_resched())
+               if (resched)
                        __cond_resched();
                else
                        cpu_relax();
@@@ -6599,7 -6626,7 +6626,7 @@@ int __sched cond_resched_softirq(void
  {
        BUG_ON(!in_softirq());
  
-       if (need_resched() && system_state == SYSTEM_RUNNING) {
+       if (should_resched()) {
                local_bh_enable();
                __cond_resched();
                local_bh_disable();
@@@ -7024,11 -7051,6 +7051,11 @@@ fail
        return ret;
  }
  
 +#define RCU_MIGRATION_IDLE    0
 +#define RCU_MIGRATION_NEED_QS 1
 +#define RCU_MIGRATION_GOT_QS  2
 +#define RCU_MIGRATION_MUST_SYNC       3
 +
  /*
   * migration_thread - this is a highprio system thread that performs
   * thread migration by bumping thread off CPU then 'pushing' onto
   */
  static int migration_thread(void *data)
  {
 +      int badcpu;
        int cpu = (long)data;
        struct rq *rq;
  
                req = list_entry(head->next, struct migration_req, list);
                list_del_init(head->next);
  
 -              spin_unlock(&rq->lock);
 -              __migrate_task(req->task, cpu, req->dest_cpu);
 +              if (req->task != NULL) {
 +                      spin_unlock(&rq->lock);
 +                      __migrate_task(req->task, cpu, req->dest_cpu);
 +              } else if (likely(cpu == (badcpu = smp_processor_id()))) {
 +                      req->dest_cpu = RCU_MIGRATION_GOT_QS;
 +                      spin_unlock(&rq->lock);
 +              } else {
 +                      req->dest_cpu = RCU_MIGRATION_MUST_SYNC;
 +                      spin_unlock(&rq->lock);
 +                      WARN_ONCE(1, "migration_thread() on CPU %d, expected %d\n", badcpu, cpu);
 +              }
                local_irq_enable();
  
                complete(&req->done);
@@@ -7277,6 -7289,7 +7304,7 @@@ static void migrate_dead_tasks(unsigne
  static void calc_global_load_remove(struct rq *rq)
  {
        atomic_long_sub(rq->calc_load_active, &calc_load_tasks);
+       rq->calc_load_active = 0;
  }
  #endif /* CONFIG_HOTPLUG_CPU */
  
@@@ -7503,6 -7516,7 +7531,7 @@@ migration_call(struct notifier_block *n
                task_rq_unlock(rq, &flags);
                get_task_struct(p);
                cpu_rq(cpu)->migration_thread = p;
+               rq->calc_load_update = calc_load_update;
                break;
  
        case CPU_ONLINE:
                /* Update our root-domain */
                rq = cpu_rq(cpu);
                spin_lock_irqsave(&rq->lock, flags);
-               rq->calc_load_update = calc_load_update;
-               rq->calc_load_active = 0;
                if (rq->rd) {
                        BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span));
  
@@@ -9085,7 -9097,7 +9112,7 @@@ static void init_rt_rq(struct rt_rq *rt
  #ifdef CONFIG_SMP
        rt_rq->rt_nr_migratory = 0;
        rt_rq->overloaded = 0;
-       plist_head_init(&rq->rt.pushable_tasks, &rq->lock);
+       plist_head_init(&rt_rq->pushable_tasks, &rq->lock);
  #endif
  
        rt_rq->rt_time = 0;
@@@ -10569,113 -10581,3 +10596,113 @@@ struct cgroup_subsys cpuacct_subsys = 
        .subsys_id = cpuacct_subsys_id,
  };
  #endif        /* CONFIG_CGROUP_CPUACCT */
 +
 +#ifndef CONFIG_SMP
 +
 +int rcu_expedited_torture_stats(char *page)
 +{
 +      return 0;
 +}
 +EXPORT_SYMBOL_GPL(rcu_expedited_torture_stats);
 +
 +void synchronize_sched_expedited(void)
 +{
 +}
 +EXPORT_SYMBOL_GPL(synchronize_sched_expedited);
 +
 +#else /* #ifndef CONFIG_SMP */
 +
 +static DEFINE_PER_CPU(struct migration_req, rcu_migration_req);
 +static DEFINE_MUTEX(rcu_sched_expedited_mutex);
 +
 +#define RCU_EXPEDITED_STATE_POST -2
 +#define RCU_EXPEDITED_STATE_IDLE -1
 +
 +static int rcu_expedited_state = RCU_EXPEDITED_STATE_IDLE;
 +
 +int rcu_expedited_torture_stats(char *page)
 +{
 +      int cnt = 0;
 +      int cpu;
 +
 +      cnt += sprintf(&page[cnt], "state: %d /", rcu_expedited_state);
 +      for_each_online_cpu(cpu) {
 +               cnt += sprintf(&page[cnt], " %d:%d",
 +                              cpu, per_cpu(rcu_migration_req, cpu).dest_cpu);
 +      }
 +      cnt += sprintf(&page[cnt], "\n");
 +      return cnt;
 +}
 +EXPORT_SYMBOL_GPL(rcu_expedited_torture_stats);
 +
 +static long synchronize_sched_expedited_count;
 +
 +/*
 + * Wait for an rcu-sched grace period to elapse, but use "big hammer"
 + * approach to force grace period to end quickly.  This consumes
 + * significant time on all CPUs, and is thus not recommended for
 + * any sort of common-case code.
 + *
 + * Note that it is illegal to call this function while holding any
 + * lock that is acquired by a CPU-hotplug notifier.  Failing to
 + * observe this restriction will result in deadlock.
 + */
 +void synchronize_sched_expedited(void)
 +{
 +      int cpu;
 +      unsigned long flags;
 +      bool need_full_sync = 0;
 +      struct rq *rq;
 +      struct migration_req *req;
 +      long snap;
 +      int trycount = 0;
 +
 +      smp_mb();  /* ensure prior mod happens before capturing snap. */
 +      snap = ACCESS_ONCE(synchronize_sched_expedited_count) + 1;
 +      get_online_cpus();
 +      while (!mutex_trylock(&rcu_sched_expedited_mutex)) {
 +              put_online_cpus();
 +              if (trycount++ < 10)
 +                      udelay(trycount * num_online_cpus());
 +              else {
 +                      synchronize_sched();
 +                      return;
 +              }
 +              if (ACCESS_ONCE(synchronize_sched_expedited_count) - snap > 0) {
 +                      smp_mb(); /* ensure test happens before caller kfree */
 +                      return;
 +              }
 +              get_online_cpus();
 +      }
 +      rcu_expedited_state = RCU_EXPEDITED_STATE_POST;
 +      for_each_online_cpu(cpu) {
 +              rq = cpu_rq(cpu);
 +              req = &per_cpu(rcu_migration_req, cpu);
 +              init_completion(&req->done);
 +              req->task = NULL;
 +              req->dest_cpu = RCU_MIGRATION_NEED_QS;
 +              spin_lock_irqsave(&rq->lock, flags);
 +              list_add(&req->list, &rq->migration_queue);
 +              spin_unlock_irqrestore(&rq->lock, flags);
 +              wake_up_process(rq->migration_thread);
 +      }
 +      for_each_online_cpu(cpu) {
 +              rcu_expedited_state = cpu;
 +              req = &per_cpu(rcu_migration_req, cpu);
 +              rq = cpu_rq(cpu);
 +              wait_for_completion(&req->done);
 +              spin_lock_irqsave(&rq->lock, flags);
 +              if (unlikely(req->dest_cpu == RCU_MIGRATION_MUST_SYNC))
 +                      need_full_sync = 1;
 +              req->dest_cpu = RCU_MIGRATION_IDLE;
 +              spin_unlock_irqrestore(&rq->lock, flags);
 +      }
 +      rcu_expedited_state = RCU_EXPEDITED_STATE_IDLE;
 +      mutex_unlock(&rcu_sched_expedited_mutex);
 +      put_online_cpus();
 +      if (need_full_sync)
 +              synchronize_sched();
 +}
 +EXPORT_SYMBOL_GPL(synchronize_sched_expedited);
 +
 +#endif /* #else #ifndef CONFIG_SMP */