]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'core/rcu' into core/rcu-for-linus
authorIngo Molnar <mingo@elte.hu>
Tue, 15 Jul 2008 19:10:12 +0000 (21:10 +0200)
committerIngo Molnar <mingo@elte.hu>
Tue, 15 Jul 2008 19:10:12 +0000 (21:10 +0200)
1  2 
drivers/infiniband/hw/ipath/ipath_verbs.c
kernel/rcuclassic.c
kernel/rcupreempt.c
kernel/sysctl.c
lib/Kconfig.debug

index 9e23ab0b51a13718cce6b34dc7f7b55fc4dcd053,38c44dec51cac74e9b863ee3b204a33af6010578..55c71882882638508bef3272b97554cc7de334b6
@@@ -35,6 -35,7 +35,7 @@@
  #include <rdma/ib_user_verbs.h>
  #include <linux/io.h>
  #include <linux/utsname.h>
+ #include <linux/rculist.h>
  
  #include "ipath_kernel.h"
  #include "ipath_verbs.h"
@@@ -1497,8 -1498,7 +1498,8 @@@ static int ipath_query_device(struct ib
                IB_DEVICE_SYS_IMAGE_GUID | IB_DEVICE_RC_RNR_NAK_GEN |
                IB_DEVICE_PORT_ACTIVE_EVENT | IB_DEVICE_SRQ_RESIZE;
        props->page_size_cap = PAGE_SIZE;
 -      props->vendor_id = dev->dd->ipath_vendorid;
 +      props->vendor_id =
 +              IPATH_SRC_OUI_1 << 16 | IPATH_SRC_OUI_2 << 8 | IPATH_SRC_OUI_3;
        props->vendor_part_id = dev->dd->ipath_deviceid;
        props->hw_ver = dev->dd->ipath_pcirev;
  
diff --combined kernel/rcuclassic.c
index 65c0906080ef032de9861f2ddd56ffe273deebe6,529190c485fdb9d2c960cd3a2dbacde06c31c169..16eeeaa9d618c7ef4c7ef4f31499fb1195a396b3
@@@ -387,6 -387,10 +387,10 @@@ static void __rcu_offline_cpu(struct rc
        rcu_move_batch(this_rdp, rdp->donelist, rdp->donetail);
        rcu_move_batch(this_rdp, rdp->curlist, rdp->curtail);
        rcu_move_batch(this_rdp, rdp->nxtlist, rdp->nxttail);
+       local_irq_disable();
+       this_rdp->qlen += rdp->qlen;
+       local_irq_enable();
  }
  
  static void rcu_offline_cpu(int cpu)
@@@ -516,10 -520,38 +520,38 @@@ void rcu_check_callbacks(int cpu, int u
        if (user ||
            (idle_cpu(cpu) && !in_softirq() &&
                                hardirq_count() <= (1 << HARDIRQ_SHIFT))) {
+               /*
+                * Get here if this CPU took its interrupt from user
+                * mode or from the idle loop, and if this is not a
+                * nested interrupt.  In this case, the CPU is in
+                * a quiescent state, so count it.
+                *
+                * Also do a memory barrier.  This is needed to handle
+                * the case where writes from a preempt-disable section
+                * of code get reordered into schedule() by this CPU's
+                * write buffer.  The memory barrier makes sure that
+                * the rcu_qsctr_inc() and rcu_bh_qsctr_inc() are see
+                * by other CPUs to happen after any such write.
+                */
+               smp_mb();  /* See above block comment. */
                rcu_qsctr_inc(cpu);
                rcu_bh_qsctr_inc(cpu);
-       } else if (!in_softirq())
+       } else if (!in_softirq()) {
+               /*
+                * Get here if this CPU did not take its interrupt from
+                * softirq, in other words, if it is not interrupting
+                * a rcu_bh read-side critical section.  This is an _bh
+                * critical section, so count it.  The memory barrier
+                * is needed for the same reason as is the above one.
+                */
+               smp_mb();  /* See above block comment. */
                rcu_bh_qsctr_inc(cpu);
+       }
        raise_rcu_softirq();
  }
  
@@@ -543,7 -575,7 +575,7 @@@ static void __cpuinit rcu_online_cpu(in
  
        rcu_init_percpu_data(cpu, &rcu_ctrlblk, rdp);
        rcu_init_percpu_data(cpu, &rcu_bh_ctrlblk, bh_rdp);
 -      open_softirq(RCU_SOFTIRQ, rcu_process_callbacks, NULL);
 +      open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
  }
  
  static int __cpuinit rcu_cpu_notify(struct notifier_block *self,
diff --combined kernel/rcupreempt.c
index 9bf445664457fe99c8f0be5c5097b3b25abb8029,536ce83c55fe08915e59d69894c080a751894af9..6f62b77d93c41978f030e28ef617b6ddfbe0c5e8
  #include <asm/atomic.h>
  #include <linux/bitops.h>
  #include <linux/module.h>
+ #include <linux/kthread.h>
  #include <linux/completion.h>
  #include <linux/moduleparam.h>
  #include <linux/percpu.h>
  #include <linux/notifier.h>
- #include <linux/rcupdate.h>
  #include <linux/cpu.h>
  #include <linux/random.h>
  #include <linux/delay.h>
@@@ -82,14 -82,18 +82,18 @@@ struct rcu_data 
        spinlock_t      lock;           /* Protect rcu_data fields. */
        long            completed;      /* Number of last completed batch. */
        int             waitlistcount;
-       struct tasklet_struct rcu_tasklet;
        struct rcu_head *nextlist;
        struct rcu_head **nexttail;
        struct rcu_head *waitlist[GP_STAGES];
        struct rcu_head **waittail[GP_STAGES];
-       struct rcu_head *donelist;
+       struct rcu_head *donelist;      /* from waitlist & waitschedlist */
        struct rcu_head **donetail;
        long rcu_flipctr[2];
+       struct rcu_head *nextschedlist;
+       struct rcu_head **nextschedtail;
+       struct rcu_head *waitschedlist;
+       struct rcu_head **waitschedtail;
+       int rcu_sched_sleeping;
  #ifdef CONFIG_RCU_TRACE
        struct rcupreempt_trace trace;
  #endif /* #ifdef CONFIG_RCU_TRACE */
@@@ -131,11 -135,24 +135,24 @@@ enum rcu_try_flip_states 
        rcu_try_flip_waitmb_state,
  };
  
+ /*
+  * States for rcu_ctrlblk.rcu_sched_sleep.
+  */
+ enum rcu_sched_sleep_states {
+       rcu_sched_not_sleeping, /* Not sleeping, callbacks need GP.  */
+       rcu_sched_sleep_prep,   /* Thinking of sleeping, rechecking. */
+       rcu_sched_sleeping,     /* Sleeping, awaken if GP needed. */
+ };
  struct rcu_ctrlblk {
        spinlock_t      fliplock;       /* Protect state-machine transitions. */
        long            completed;      /* Number of last completed batch. */
        enum rcu_try_flip_states rcu_try_flip_state; /* The current state of
                                                        the rcu state machine */
+       spinlock_t      schedlock;      /* Protect rcu_sched sleep state. */
+       enum rcu_sched_sleep_states sched_sleep; /* rcu_sched state. */
+       wait_queue_head_t sched_wq;     /* Place for rcu_sched to sleep. */
  };
  
  static DEFINE_PER_CPU(struct rcu_data, rcu_data);
@@@ -143,8 -160,12 +160,12 @@@ static struct rcu_ctrlblk rcu_ctrlblk 
        .fliplock = __SPIN_LOCK_UNLOCKED(rcu_ctrlblk.fliplock),
        .completed = 0,
        .rcu_try_flip_state = rcu_try_flip_idle_state,
+       .schedlock = __SPIN_LOCK_UNLOCKED(rcu_ctrlblk.schedlock),
+       .sched_sleep = rcu_sched_not_sleeping,
+       .sched_wq = __WAIT_QUEUE_HEAD_INITIALIZER(rcu_ctrlblk.sched_wq),
  };
  
+ static struct task_struct *rcu_sched_grace_period_task;
  
  #ifdef CONFIG_RCU_TRACE
  static char *rcu_try_flip_state_names[] =
@@@ -207,6 -228,8 +228,8 @@@ static DEFINE_PER_CPU_SHARED_ALIGNED(en
   */
  #define RCU_TRACE_RDP(f, rdp) RCU_TRACE(f, &((rdp)->trace));
  
+ #define RCU_SCHED_BATCH_TIME (HZ / 50)
  /*
   * Return the number of RCU batches processed thus far.  Useful
   * for debug and statistics.
@@@ -411,32 -434,34 +434,34 @@@ static void __rcu_advance_callbacks(str
        }
  }
  
- #ifdef CONFIG_NO_HZ
+ DEFINE_PER_CPU_SHARED_ALIGNED(struct rcu_dyntick_sched, rcu_dyntick_sched) = {
+       .dynticks = 1,
+ };
  
- DEFINE_PER_CPU(long, dynticks_progress_counter) = 1;
- static DEFINE_PER_CPU(long, rcu_dyntick_snapshot);
+ #ifdef CONFIG_NO_HZ
  static DEFINE_PER_CPU(int, rcu_update_flag);
  
  /**
   * rcu_irq_enter - Called from Hard irq handlers and NMI/SMI.
   *
   * If the CPU was idle with dynamic ticks active, this updates the
-  * dynticks_progress_counter to let the RCU handling know that the
+  * rcu_dyntick_sched.dynticks to let the RCU handling know that the
   * CPU is active.
   */
  void rcu_irq_enter(void)
  {
        int cpu = smp_processor_id();
+       struct rcu_dyntick_sched *rdssp = &per_cpu(rcu_dyntick_sched, cpu);
  
        if (per_cpu(rcu_update_flag, cpu))
                per_cpu(rcu_update_flag, cpu)++;
  
        /*
         * Only update if we are coming from a stopped ticks mode
-        * (dynticks_progress_counter is even).
+        * (rcu_dyntick_sched.dynticks is even).
         */
        if (!in_interrupt() &&
-           (per_cpu(dynticks_progress_counter, cpu) & 0x1) == 0) {
+           (rdssp->dynticks & 0x1) == 0) {
                /*
                 * The following might seem like we could have a race
                 * with NMI/SMIs. But this really isn't a problem.
                 * RCU read-side critical sections on this CPU would
                 * have already completed.
                 */
-               per_cpu(dynticks_progress_counter, cpu)++;
+               rdssp->dynticks++;
                /*
                 * The following memory barrier ensures that any
                 * rcu_read_lock() primitives in the irq handler
                 * are seen by other CPUs to follow the above
-                * increment to dynticks_progress_counter. This is
+                * increment to rcu_dyntick_sched.dynticks. This is
                 * required in order for other CPUs to correctly
                 * determine when it is safe to advance the RCU
                 * grace-period state machine.
                smp_mb(); /* see above block comment. */
                /*
                 * Since we can't determine the dynamic tick mode from
-                * the dynticks_progress_counter after this routine,
+                * the rcu_dyntick_sched.dynticks after this routine,
                 * we use a second flag to acknowledge that we came
                 * from an idle state with ticks stopped.
                 */
                /*
                 * If we take an NMI/SMI now, they will also increment
                 * the rcu_update_flag, and will not update the
-                * dynticks_progress_counter on exit. That is for
+                * rcu_dyntick_sched.dynticks on exit. That is for
                 * this IRQ to do.
                 */
        }
   * rcu_irq_exit - Called from exiting Hard irq context.
   *
   * If the CPU was idle with dynamic ticks active, update the
-  * dynticks_progress_counter to put let the RCU handling be
+  * rcu_dyntick_sched.dynticks to put let the RCU handling be
   * aware that the CPU is going back to idle with no ticks.
   */
  void rcu_irq_exit(void)
  {
        int cpu = smp_processor_id();
+       struct rcu_dyntick_sched *rdssp = &per_cpu(rcu_dyntick_sched, cpu);
  
        /*
         * rcu_update_flag is set if we interrupted the CPU
         * Once this occurs, we keep track of interrupt nesting
         * because a NMI/SMI could also come in, and we still
         * only want the IRQ that started the increment of the
-        * dynticks_progress_counter to be the one that modifies
+        * rcu_dyntick_sched.dynticks to be the one that modifies
         * it on exit.
         */
        if (per_cpu(rcu_update_flag, cpu)) {
  
                /*
                 * If an NMI/SMI happens now we are still
-                * protected by the dynticks_progress_counter being odd.
+                * protected by the rcu_dyntick_sched.dynticks being odd.
                 */
  
                /*
                 * The following memory barrier ensures that any
                 * rcu_read_unlock() primitives in the irq handler
                 * are seen by other CPUs to preceed the following
-                * increment to dynticks_progress_counter. This
+                * increment to rcu_dyntick_sched.dynticks. This
                 * is required in order for other CPUs to determine
                 * when it is safe to advance the RCU grace-period
                 * state machine.
                 */
                smp_mb(); /* see above block comment. */
-               per_cpu(dynticks_progress_counter, cpu)++;
-               WARN_ON(per_cpu(dynticks_progress_counter, cpu) & 0x1);
+               rdssp->dynticks++;
+               WARN_ON(rdssp->dynticks & 0x1);
        }
  }
  
  static void dyntick_save_progress_counter(int cpu)
  {
-       per_cpu(rcu_dyntick_snapshot, cpu) =
-               per_cpu(dynticks_progress_counter, cpu);
+       struct rcu_dyntick_sched *rdssp = &per_cpu(rcu_dyntick_sched, cpu);
+       rdssp->dynticks_snap = rdssp->dynticks;
  }
  
  static inline int
@@@ -544,9 -571,10 +571,10 @@@ rcu_try_flip_waitack_needed(int cpu
  {
        long curr;
        long snap;
+       struct rcu_dyntick_sched *rdssp = &per_cpu(rcu_dyntick_sched, cpu);
  
-       curr = per_cpu(dynticks_progress_counter, cpu);
-       snap = per_cpu(rcu_dyntick_snapshot, cpu);
+       curr = rdssp->dynticks;
+       snap = rdssp->dynticks_snap;
        smp_mb(); /* force ordering with cpu entering/leaving dynticks. */
  
        /*
         * that this CPU already acknowledged the counter.
         */
  
-       if ((curr - snap) > 2 || (snap & 0x1) == 0)
+       if ((curr - snap) > 2 || (curr & 0x1) == 0)
                return 0;
  
        /* We need this CPU to explicitly acknowledge the counter flip. */
@@@ -580,9 -608,10 +608,10 @@@ rcu_try_flip_waitmb_needed(int cpu
  {
        long curr;
        long snap;
+       struct rcu_dyntick_sched *rdssp = &per_cpu(rcu_dyntick_sched, cpu);
  
-       curr = per_cpu(dynticks_progress_counter, cpu);
-       snap = per_cpu(rcu_dyntick_snapshot, cpu);
+       curr = rdssp->dynticks;
+       snap = rdssp->dynticks_snap;
        smp_mb(); /* force ordering with cpu entering/leaving dynticks. */
  
        /*
        return 1;
  }
  
+ static void dyntick_save_progress_counter_sched(int cpu)
+ {
+       struct rcu_dyntick_sched *rdssp = &per_cpu(rcu_dyntick_sched, cpu);
+       rdssp->sched_dynticks_snap = rdssp->dynticks;
+ }
+ static int rcu_qsctr_inc_needed_dyntick(int cpu)
+ {
+       long curr;
+       long snap;
+       struct rcu_dyntick_sched *rdssp = &per_cpu(rcu_dyntick_sched, cpu);
+       curr = rdssp->dynticks;
+       snap = rdssp->sched_dynticks_snap;
+       smp_mb(); /* force ordering with cpu entering/leaving dynticks. */
+       /*
+        * If the CPU remained in dynticks mode for the entire time
+        * and didn't take any interrupts, NMIs, SMIs, or whatever,
+        * then it cannot be in the middle of an rcu_read_lock(), so
+        * the next rcu_read_lock() it executes must use the new value
+        * of the counter.  Therefore, this CPU has been in a quiescent
+        * state the entire time, and we don't need to wait for it.
+        */
+       if ((curr == snap) && ((curr & 0x1) == 0))
+               return 0;
+       /*
+        * If the CPU passed through or entered a dynticks idle phase with
+        * no active irq handlers, then, as above, this CPU has already
+        * passed through a quiescent state.
+        */
+       if ((curr - snap) > 2 || (snap & 0x1) == 0)
+               return 0;
+       /* We need this CPU to go through a quiescent state. */
+       return 1;
+ }
  #else /* !CONFIG_NO_HZ */
  
- # define dyntick_save_progress_counter(cpu)   do { } while (0)
- # define rcu_try_flip_waitack_needed(cpu)     (1)
- # define rcu_try_flip_waitmb_needed(cpu)      (1)
+ # define dyntick_save_progress_counter(cpu)           do { } while (0)
+ # define rcu_try_flip_waitack_needed(cpu)             (1)
+ # define rcu_try_flip_waitmb_needed(cpu)              (1)
+ # define dyntick_save_progress_counter_sched(cpu)     do { } while (0)
+ # define rcu_qsctr_inc_needed_dyntick(cpu)            (1)
  
  #endif /* CONFIG_NO_HZ */
  
+ static void save_qsctr_sched(int cpu)
+ {
+       struct rcu_dyntick_sched *rdssp = &per_cpu(rcu_dyntick_sched, cpu);
+       rdssp->sched_qs_snap = rdssp->sched_qs;
+ }
+ static inline int rcu_qsctr_inc_needed(int cpu)
+ {
+       struct rcu_dyntick_sched *rdssp = &per_cpu(rcu_dyntick_sched, cpu);
+       /*
+        * If there has been a quiescent state, no more need to wait
+        * on this CPU.
+        */
+       if (rdssp->sched_qs != rdssp->sched_qs_snap) {
+               smp_mb(); /* force ordering with cpu entering schedule(). */
+               return 0;
+       }
+       /* We need this CPU to go through a quiescent state. */
+       return 1;
+ }
  /*
   * Get here when RCU is idle.  Decide whether we need to
   * move out of idle state, and return non-zero if so.
@@@ -819,6 -920,26 +920,26 @@@ void rcu_check_callbacks(int cpu, int u
        unsigned long flags;
        struct rcu_data *rdp = RCU_DATA_CPU(cpu);
  
+       /*
+        * If this CPU took its interrupt from user mode or from the
+        * idle loop, and this is not a nested interrupt, then
+        * this CPU has to have exited all prior preept-disable
+        * sections of code.  So increment the counter to note this.
+        *
+        * The memory barrier is needed to handle the case where
+        * writes from a preempt-disable section of code get reordered
+        * into schedule() by this CPU's write buffer.  So the memory
+        * barrier makes sure that the rcu_qsctr_inc() is seen by other
+        * CPUs to happen after any such write.
+        */
+       if (user ||
+           (idle_cpu(cpu) && !in_softirq() &&
+            hardirq_count() <= (1 << HARDIRQ_SHIFT))) {
+               smp_mb();       /* Guard against aggressive schedule(). */
+               rcu_qsctr_inc(cpu);
+       }
        rcu_check_mb(cpu);
        if (rcu_ctrlblk.completed == rdp->completed)
                rcu_try_flip();
@@@ -869,6 -990,8 +990,8 @@@ void rcu_offline_cpu(int cpu
        struct rcu_head *list = NULL;
        unsigned long flags;
        struct rcu_data *rdp = RCU_DATA_CPU(cpu);
+       struct rcu_head *schedlist = NULL;
+       struct rcu_head **schedtail = &schedlist;
        struct rcu_head **tail = &list;
  
        /*
                rcu_offline_cpu_enqueue(rdp->waitlist[i], rdp->waittail[i],
                                                list, tail);
        rcu_offline_cpu_enqueue(rdp->nextlist, rdp->nexttail, list, tail);
+       rcu_offline_cpu_enqueue(rdp->waitschedlist, rdp->waitschedtail,
+                               schedlist, schedtail);
+       rcu_offline_cpu_enqueue(rdp->nextschedlist, rdp->nextschedtail,
+                               schedlist, schedtail);
+       rdp->rcu_sched_sleeping = 0;
        spin_unlock_irqrestore(&rdp->lock, flags);
        rdp->waitlistcount = 0;
  
         * fix.
         */
  
-       local_irq_save(flags);
+       local_irq_save(flags);  /* disable preempt till we know what lock. */
        rdp = RCU_DATA_ME();
        spin_lock(&rdp->lock);
        *rdp->nexttail = list;
        if (list)
                rdp->nexttail = tail;
+       *rdp->nextschedtail = schedlist;
+       if (schedlist)
+               rdp->nextschedtail = schedtail;
        spin_unlock_irqrestore(&rdp->lock, flags);
  }
  
@@@ -936,10 -1067,25 +1067,25 @@@ void rcu_offline_cpu(int cpu
  void __cpuinit rcu_online_cpu(int cpu)
  {
        unsigned long flags;
+       struct rcu_data *rdp;
  
        spin_lock_irqsave(&rcu_ctrlblk.fliplock, flags);
        cpu_set(cpu, rcu_cpu_online_map);
        spin_unlock_irqrestore(&rcu_ctrlblk.fliplock, flags);
+       /*
+        * The rcu_sched grace-period processing might have bypassed
+        * this CPU, given that it was not in the rcu_cpu_online_map
+        * when the grace-period scan started.  This means that the
+        * grace-period task might sleep.  So make sure that if this
+        * should happen, the first callback posted to this CPU will
+        * wake up the grace-period task if need be.
+        */
+       rdp = RCU_DATA_CPU(cpu);
+       spin_lock_irqsave(&rdp->lock, flags);
+       rdp->rcu_sched_sleeping = 1;
+       spin_unlock_irqrestore(&rdp->lock, flags);
  }
  
  static void rcu_process_callbacks(struct softirq_action *unused)
@@@ -982,31 -1128,196 +1128,196 @@@ void call_rcu(struct rcu_head *head, vo
        *rdp->nexttail = head;
        rdp->nexttail = &head->next;
        RCU_TRACE_RDP(rcupreempt_trace_next_add, rdp);
-       spin_unlock(&rdp->lock);
-       local_irq_restore(flags);
+       spin_unlock_irqrestore(&rdp->lock, flags);
  }
  EXPORT_SYMBOL_GPL(call_rcu);
  
+ void call_rcu_sched(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
+ {
+       unsigned long flags;
+       struct rcu_data *rdp;
+       int wake_gp = 0;
+       head->func = func;
+       head->next = NULL;
+       local_irq_save(flags);
+       rdp = RCU_DATA_ME();
+       spin_lock(&rdp->lock);
+       *rdp->nextschedtail = head;
+       rdp->nextschedtail = &head->next;
+       if (rdp->rcu_sched_sleeping) {
+               /* Grace-period processing might be sleeping... */
+               rdp->rcu_sched_sleeping = 0;
+               wake_gp = 1;
+       }
+       spin_unlock_irqrestore(&rdp->lock, flags);
+       if (wake_gp) {
+               /* Wake up grace-period processing, unless someone beat us. */
+               spin_lock_irqsave(&rcu_ctrlblk.schedlock, flags);
+               if (rcu_ctrlblk.sched_sleep != rcu_sched_sleeping)
+                       wake_gp = 0;
+               rcu_ctrlblk.sched_sleep = rcu_sched_not_sleeping;
+               spin_unlock_irqrestore(&rcu_ctrlblk.schedlock, flags);
+               if (wake_gp)
+                       wake_up_interruptible(&rcu_ctrlblk.sched_wq);
+       }
+ }
+ EXPORT_SYMBOL_GPL(call_rcu_sched);
  /*
   * Wait until all currently running preempt_disable() code segments
   * (including hardware-irq-disable segments) complete.  Note that
   * in -rt this does -not- necessarily result in all currently executing
   * interrupt -handlers- having completed.
   */
- void __synchronize_sched(void)
+ synchronize_rcu_xxx(__synchronize_sched, call_rcu_sched)
+ EXPORT_SYMBOL_GPL(__synchronize_sched);
+ /*
+  * kthread function that manages call_rcu_sched grace periods.
+  */
+ static int rcu_sched_grace_period(void *arg)
  {
-       cpumask_t oldmask;
+       int couldsleep;         /* might sleep after current pass. */
+       int couldsleepnext = 0; /* might sleep after next pass. */
        int cpu;
+       unsigned long flags;
+       struct rcu_data *rdp;
+       int ret;
  
-       if (sched_getaffinity(0, &oldmask) < 0)
-               oldmask = cpu_possible_map;
-       for_each_online_cpu(cpu) {
-               sched_setaffinity(0, &cpumask_of_cpu(cpu));
-               schedule();
-       }
-       sched_setaffinity(0, &oldmask);
+       /*
+        * Each pass through the following loop handles one
+        * rcu_sched grace period cycle.
+        */
+       do {
+               /* Save each CPU's current state. */
+               for_each_online_cpu(cpu) {
+                       dyntick_save_progress_counter_sched(cpu);
+                       save_qsctr_sched(cpu);
+               }
+               /*
+                * Sleep for about an RCU grace-period's worth to
+                * allow better batching and to consume less CPU.
+                */
+               schedule_timeout_interruptible(RCU_SCHED_BATCH_TIME);
+               /*
+                * If there was nothing to do last time, prepare to
+                * sleep at the end of the current grace period cycle.
+                */
+               couldsleep = couldsleepnext;
+               couldsleepnext = 1;
+               if (couldsleep) {
+                       spin_lock_irqsave(&rcu_ctrlblk.schedlock, flags);
+                       rcu_ctrlblk.sched_sleep = rcu_sched_sleep_prep;
+                       spin_unlock_irqrestore(&rcu_ctrlblk.schedlock, flags);
+               }
+               /*
+                * Wait on each CPU in turn to have either visited
+                * a quiescent state or been in dynticks-idle mode.
+                */
+               for_each_online_cpu(cpu) {
+                       while (rcu_qsctr_inc_needed(cpu) &&
+                              rcu_qsctr_inc_needed_dyntick(cpu)) {
+                               /* resched_cpu(cpu); @@@ */
+                               schedule_timeout_interruptible(1);
+                       }
+               }
+               /* Advance callbacks for each CPU.  */
+               for_each_online_cpu(cpu) {
+                       rdp = RCU_DATA_CPU(cpu);
+                       spin_lock_irqsave(&rdp->lock, flags);
+                       /*
+                        * We are running on this CPU irq-disabled, so no
+                        * CPU can go offline until we re-enable irqs.
+                        * The current CPU might have already gone
+                        * offline (between the for_each_offline_cpu and
+                        * the spin_lock_irqsave), but in that case all its
+                        * callback lists will be empty, so no harm done.
+                        *
+                        * Advance the callbacks!  We share normal RCU's
+                        * donelist, since callbacks are invoked the
+                        * same way in either case.
+                        */
+                       if (rdp->waitschedlist != NULL) {
+                               *rdp->donetail = rdp->waitschedlist;
+                               rdp->donetail = rdp->waitschedtail;
+                               /*
+                                * Next rcu_check_callbacks() will
+                                * do the required raise_softirq().
+                                */
+                       }
+                       if (rdp->nextschedlist != NULL) {
+                               rdp->waitschedlist = rdp->nextschedlist;
+                               rdp->waitschedtail = rdp->nextschedtail;
+                               couldsleep = 0;
+                               couldsleepnext = 0;
+                       } else {
+                               rdp->waitschedlist = NULL;
+                               rdp->waitschedtail = &rdp->waitschedlist;
+                       }
+                       rdp->nextschedlist = NULL;
+                       rdp->nextschedtail = &rdp->nextschedlist;
+                       /* Mark sleep intention. */
+                       rdp->rcu_sched_sleeping = couldsleep;
+                       spin_unlock_irqrestore(&rdp->lock, flags);
+               }
+               /* If we saw callbacks on the last scan, go deal with them. */
+               if (!couldsleep)
+                       continue;
+               /* Attempt to block... */
+               spin_lock_irqsave(&rcu_ctrlblk.schedlock, flags);
+               if (rcu_ctrlblk.sched_sleep != rcu_sched_sleep_prep) {
+                       /*
+                        * Someone posted a callback after we scanned.
+                        * Go take care of it.
+                        */
+                       spin_unlock_irqrestore(&rcu_ctrlblk.schedlock, flags);
+                       couldsleepnext = 0;
+                       continue;
+               }
+               /* Block until the next person posts a callback. */
+               rcu_ctrlblk.sched_sleep = rcu_sched_sleeping;
+               spin_unlock_irqrestore(&rcu_ctrlblk.schedlock, flags);
+               ret = 0;
+               __wait_event_interruptible(rcu_ctrlblk.sched_wq,
+                       rcu_ctrlblk.sched_sleep != rcu_sched_sleeping,
+                       ret);
+               /*
+                * Signals would prevent us from sleeping, and we cannot
+                * do much with them in any case.  So flush them.
+                */
+               if (ret)
+                       flush_signals(current);
+               couldsleepnext = 0;
+       } while (!kthread_should_stop());
+       return (0);
  }
- EXPORT_SYMBOL_GPL(__synchronize_sched);
  
  /*
   * Check to see if any future RCU-related work will need to be done
@@@ -1023,7 -1334,9 +1334,9 @@@ int rcu_needs_cpu(int cpu
  
        return (rdp->donelist != NULL ||
                !!rdp->waitlistcount ||
-               rdp->nextlist != NULL);
+               rdp->nextlist != NULL ||
+               rdp->nextschedlist != NULL ||
+               rdp->waitschedlist != NULL);
  }
  
  int rcu_pending(int cpu)
  
        if (rdp->donelist != NULL ||
            !!rdp->waitlistcount ||
-           rdp->nextlist != NULL)
+           rdp->nextlist != NULL ||
+           rdp->nextschedlist != NULL ||
+           rdp->waitschedlist != NULL)
                return 1;
  
        /* The RCU core needs an acknowledgement from this CPU. */
@@@ -1101,6 -1416,11 +1416,11 @@@ void __init __rcu_init(void
                rdp->donetail = &rdp->donelist;
                rdp->rcu_flipctr[0] = 0;
                rdp->rcu_flipctr[1] = 0;
+               rdp->nextschedlist = NULL;
+               rdp->nextschedtail = &rdp->nextschedlist;
+               rdp->waitschedlist = NULL;
+               rdp->waitschedtail = &rdp->waitschedlist;
+               rdp->rcu_sched_sleeping = 0;
        }
        register_cpu_notifier(&rcu_nb);
  
        for_each_online_cpu(cpu)
                rcu_cpu_notify(&rcu_nb, CPU_UP_PREPARE, (void *)(long) cpu);
  
 -      open_softirq(RCU_SOFTIRQ, rcu_process_callbacks, NULL);
 +      open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
  }
  
  /*
-  * Deprecated, use synchronize_rcu() or synchronize_sched() instead.
+  * Late-boot-time RCU initialization that must wait until after scheduler
+  * has been initialized.
   */
- void synchronize_kernel(void)
+ void __init rcu_init_sched(void)
  {
-       synchronize_rcu();
+       rcu_sched_grace_period_task = kthread_run(rcu_sched_grace_period,
+                                                 NULL,
+                                                 "rcu_sched_grace_period");
+       WARN_ON(IS_ERR(rcu_sched_grace_period_task));
  }
  
  #ifdef CONFIG_RCU_TRACE
diff --combined kernel/sysctl.c
index 0d562d6531ebc7b394e2552bfe8806d2e0b40aae,c6887cf135c824d9e302727be4d7b590ca39c8f1..6b16e16428d8f57febcb2e67dde5b6c2fd211a4e
@@@ -46,7 -46,6 +46,7 @@@
  #include <linux/nfs_fs.h>
  #include <linux/acpi.h>
  #include <linux/reboot.h>
 +#include <linux/ftrace.h>
  
  #include <asm/uaccess.h>
  #include <asm/processor.h>
@@@ -83,6 -82,9 +83,9 @@@ extern int maps_protect
  extern int sysctl_stat_interval;
  extern int latencytop_enabled;
  extern int sysctl_nr_open_min, sysctl_nr_open_max;
+ #ifdef CONFIG_RCU_TORTURE_TEST
+ extern int rcutorture_runnable;
+ #endif /* #ifdef CONFIG_RCU_TORTURE_TEST */
  
  /* Constants used for minimum and  maximum */
  #if defined(CONFIG_DETECT_SOFTLOCKUP) || defined(CONFIG_HIGHMEM)
@@@ -133,6 -135,8 +136,6 @@@ extern int sysctl_userprocess_debug
  extern int spin_retry;
  #endif
  
 -extern int sysctl_hz_timer;
 -
  #ifdef CONFIG_BSD_PROCESS_ACCT
  extern int acct_parm[];
  #endif
@@@ -263,14 -267,6 +266,14 @@@ static struct ctl_table kern_table[] = 
                .extra1         = &min_wakeup_granularity_ns,
                .extra2         = &max_wakeup_granularity_ns,
        },
 +      {
 +              .ctl_name       = CTL_UNNUMBERED,
 +              .procname       = "sched_shares_ratelimit",
 +              .data           = &sysctl_sched_shares_ratelimit,
 +              .maxlen         = sizeof(unsigned int),
 +              .mode           = 0644,
 +              .proc_handler   = &proc_dointvec,
 +      },
        {
                .ctl_name       = CTL_UNNUMBERED,
                .procname       = "sched_child_runs_first",
                .mode           = 0644,
                .proc_handler   = &proc_dointvec,
        },
 +#ifdef CONFIG_FTRACE
 +      {
 +              .ctl_name       = CTL_UNNUMBERED,
 +              .procname       = "ftrace_enabled",
 +              .data           = &ftrace_enabled,
 +              .maxlen         = sizeof(int),
 +              .mode           = 0644,
 +              .proc_handler   = &ftrace_enable_sysctl,
 +      },
 +#endif
  #ifdef CONFIG_KMOD
        {
                .ctl_name       = KERN_MODPROBE,
                .mode           = 0644,
                .proc_handler   = &proc_dointvec,
        },
 -#endif
 -#ifdef CONFIG_NO_IDLE_HZ
 -      {
 -              .ctl_name       = KERN_HZ_TIMER,
 -              .procname       = "hz_timer",
 -              .data           = &sysctl_hz_timer,
 -              .maxlen         = sizeof(int),
 -              .mode           = 0644,
 -              .proc_handler   = &proc_dointvec,
 -      },
  #endif
        {
                .ctl_name       = KERN_S390_USER_DEBUG_LOGGING,
                .child          = key_sysctls,
        },
  #endif
+ #ifdef CONFIG_RCU_TORTURE_TEST
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "rcutorture_runnable",
+               .data           = &rcutorture_runnable,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+       },
+ #endif
  /*
   * NOTE: do not add new entries to this table unless you have read
   * Documentation/sysctl/ctl_unnumbered.txt
diff --combined lib/Kconfig.debug
index c459e8547bd8cd11ede47e50f44e055fa1d06a6b,c35a86a516a022d553cbc502940e1dd77d5b5e8c..df27132a56f437eacdf53cde9caf93162d87d1d0
@@@ -419,6 -419,7 +419,6 @@@ config DEBUG_LOCKING_API_SELFTEST
  
  config STACKTRACE
        bool
 -      depends on DEBUG_KERNEL
        depends on STACKTRACE_SUPPORT
  
  config DEBUG_KOBJECT
@@@ -530,16 -531,34 +530,34 @@@ config BOOT_PRINTK_DELA
  config RCU_TORTURE_TEST
        tristate "torture tests for RCU"
        depends on DEBUG_KERNEL
-       depends on m
        default n
        help
          This option provides a kernel module that runs torture tests
          on the RCU infrastructure.  The kernel module may be built
          after the fact on the running kernel to be tested, if desired.
  
+         Say Y here if you want RCU torture tests to be built into
+         the kernel.
          Say M if you want the RCU torture tests to build as a module.
          Say N if you are unsure.
  
+ config RCU_TORTURE_TEST_RUNNABLE
+       bool "torture tests for RCU runnable by default"
+       depends on RCU_TORTURE_TEST = y
+       default n
+       help
+         This option provides a way to build the RCU torture tests
+         directly into the kernel without them starting up at boot
+         time.  You can use /proc/sys/kernel/rcutorture_runnable
+         to manually override this setting.  This /proc file is
+         available only when the RCU torture tests have been built
+         into the kernel.
+         Say Y here if you want the RCU torture tests to start during
+         boot (you probably don't).
+         Say N here if you want the RCU torture tests to start only
+         after being manually enabled via /proc.
  config KPROBES_SANITY_TEST
        bool "Kprobes sanity tests"
        depends on DEBUG_KERNEL
@@@ -562,9 -581,6 +580,9 @@@ config BACKTRACE_SELF_TES
          for distributions or general kernels, but only for kernel
          developers working on architecture code.
  
 +        Note that if you want to also test saved backtraces, you will
 +        have to enable STACKTRACE as well.
 +
          Say N if you are unsure.
  
  config LKDTM
@@@ -636,8 -652,6 +654,8 @@@ config LATENCYTO
          Enable this option if you want to use the LatencyTOP tool
          to find out which userspace is blocking on what kernel operations.
  
 +source kernel/trace/Kconfig
 +
  config PROVIDE_OHCI1394_DMA_INIT
        bool "Remote debugging over FireWire early on boot"
        depends on PCI && X86