Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
[pandora-kernel.git] / kernel / rcutree.c
index 18e3331..f07d2f0 100644 (file)
@@ -49,6 +49,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/wait.h>
 #include <linux/kthread.h>
+#include <linux/prefetch.h>
 
 #include "rcutree.h"
 
@@ -81,6 +82,8 @@ DEFINE_PER_CPU(struct rcu_data, rcu_sched_data);
 struct rcu_state rcu_bh_state = RCU_STATE_INITIALIZER(rcu_bh_state);
 DEFINE_PER_CPU(struct rcu_data, rcu_bh_data);
 
+static struct rcu_state *rcu_state;
+
 int rcu_scheduler_active __read_mostly;
 EXPORT_SYMBOL_GPL(rcu_scheduler_active);
 
@@ -89,15 +92,30 @@ EXPORT_SYMBOL_GPL(rcu_scheduler_active);
  * handle all flavors of RCU.
  */
 static DEFINE_PER_CPU(struct task_struct *, rcu_cpu_kthread_task);
+DEFINE_PER_CPU(unsigned int, rcu_cpu_kthread_status);
+DEFINE_PER_CPU(int, rcu_cpu_kthread_cpu);
+DEFINE_PER_CPU(unsigned int, rcu_cpu_kthread_loops);
 static DEFINE_PER_CPU(wait_queue_head_t, rcu_cpu_wq);
-static DEFINE_PER_CPU(char, rcu_cpu_has_work);
+DEFINE_PER_CPU(char, rcu_cpu_has_work);
 static char rcu_kthreads_spawnable;
 
-static void rcu_node_kthread_setaffinity(struct rcu_node *rnp);
-static void invoke_rcu_kthread(void);
+static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu);
+static void invoke_rcu_cpu_kthread(void);
 
 #define RCU_KTHREAD_PRIO 1     /* RT priority for per-CPU kthreads. */
 
+/*
+ * Track the rcutorture test sequence number and the update version
+ * number within a given test.  The rcutorture_testseq is incremented
+ * on every rcutorture module load and unload, so has an odd value
+ * when a test is running.  The rcutorture_vernum is set to zero
+ * when rcutorture starts and is incremented on each rcutorture update.
+ * These variables enable correlating rcutorture output with the
+ * RCU tracing information.
+ */
+unsigned long rcutorture_testseq;
+unsigned long rcutorture_vernum;
+
 /*
  * Return true if an RCU grace period is in progress.  The ACCESS_ONCE()s
  * permit this function to be invoked without holding the root rcu_node
@@ -140,11 +158,12 @@ void rcu_note_context_switch(int cpu)
        rcu_sched_qs(cpu);
        rcu_preempt_note_context_switch(cpu);
 }
+EXPORT_SYMBOL_GPL(rcu_note_context_switch);
 
 #ifdef CONFIG_NO_HZ
 DEFINE_PER_CPU(struct rcu_dynticks, rcu_dynticks) = {
        .dynticks_nesting = 1,
-       .dynticks = ATOMIC_INIT(1),
+       .dynticks = 1,
 };
 #endif /* #ifdef CONFIG_NO_HZ */
 
@@ -189,6 +208,31 @@ void rcu_bh_force_quiescent_state(void)
 }
 EXPORT_SYMBOL_GPL(rcu_bh_force_quiescent_state);
 
+/*
+ * Record the number of times rcutorture tests have been initiated and
+ * terminated.  This information allows the debugfs tracing stats to be
+ * correlated to the rcutorture messages, even when the rcutorture module
+ * is being repeatedly loaded and unloaded.  In other words, we cannot
+ * store this state in rcutorture itself.
+ */
+void rcutorture_record_test_transition(void)
+{
+       rcutorture_testseq++;
+       rcutorture_vernum = 0;
+}
+EXPORT_SYMBOL_GPL(rcutorture_record_test_transition);
+
+/*
+ * Record the number of writer passes through the current rcutorture test.
+ * This is also used to correlate debugfs tracing stats with the rcutorture
+ * messages.
+ */
+void rcutorture_record_progress(unsigned long vernum)
+{
+       rcutorture_vernum++;
+}
+EXPORT_SYMBOL_GPL(rcutorture_record_progress);
+
 /*
  * Force a quiescent state for RCU-sched.
  */
@@ -248,8 +292,8 @@ static int rcu_implicit_offline_qs(struct rcu_data *rdp)
                return 1;
        }
 
-       /* If preemptable RCU, no point in sending reschedule IPI. */
-       if (rdp->preemptable)
+       /* If preemptible RCU, no point in sending reschedule IPI. */
+       if (rdp->preemptible)
                return 0;
 
        /* The CPU is online, so send it a reschedule IPI. */
@@ -278,25 +322,13 @@ void rcu_enter_nohz(void)
        unsigned long flags;
        struct rcu_dynticks *rdtp;
 
+       smp_mb(); /* CPUs seeing ++ must see prior RCU read-side crit sects */
        local_irq_save(flags);
        rdtp = &__get_cpu_var(rcu_dynticks);
-       if (--rdtp->dynticks_nesting) {
-               local_irq_restore(flags);
-               return;
-       }
-       /* CPUs seeing atomic_inc() must see prior RCU read-side crit sects */
-       smp_mb__before_atomic_inc();  /* See above. */
-       atomic_inc(&rdtp->dynticks);
-       smp_mb__after_atomic_inc();  /* Force ordering with next sojourn. */
-       WARN_ON_ONCE(atomic_read(&rdtp->dynticks) & 0x1);
+       rdtp->dynticks++;
+       rdtp->dynticks_nesting--;
+       WARN_ON_ONCE(rdtp->dynticks & 0x1);
        local_irq_restore(flags);
-
-       /* If the interrupt queued a callback, get out of dyntick mode. */
-       if (in_irq() &&
-           (__get_cpu_var(rcu_sched_data).nxtlist ||
-            __get_cpu_var(rcu_bh_data).nxtlist ||
-            rcu_preempt_needs_cpu(smp_processor_id())))
-               set_need_resched();
 }
 
 /*
@@ -312,16 +344,11 @@ void rcu_exit_nohz(void)
 
        local_irq_save(flags);
        rdtp = &__get_cpu_var(rcu_dynticks);
-       if (rdtp->dynticks_nesting++) {
-               local_irq_restore(flags);
-               return;
-       }
-       smp_mb__before_atomic_inc();  /* Force ordering w/previous sojourn. */
-       atomic_inc(&rdtp->dynticks);
-       /* CPUs seeing atomic_inc() must see later RCU read-side crit sects */
-       smp_mb__after_atomic_inc();  /* See above. */
-       WARN_ON_ONCE(!(atomic_read(&rdtp->dynticks) & 0x1));
+       rdtp->dynticks++;
+       rdtp->dynticks_nesting++;
+       WARN_ON_ONCE(!(rdtp->dynticks & 0x1));
        local_irq_restore(flags);
+       smp_mb(); /* CPUs seeing ++ must see later RCU read-side crit sects */
 }
 
 /**
@@ -335,15 +362,11 @@ void rcu_nmi_enter(void)
 {
        struct rcu_dynticks *rdtp = &__get_cpu_var(rcu_dynticks);
 
-       if (rdtp->dynticks_nmi_nesting == 0 &&
-           (atomic_read(&rdtp->dynticks) & 0x1))
+       if (rdtp->dynticks & 0x1)
                return;
-       rdtp->dynticks_nmi_nesting++;
-       smp_mb__before_atomic_inc();  /* Force delay from prior write. */
-       atomic_inc(&rdtp->dynticks);
-       /* CPUs seeing atomic_inc() must see later RCU read-side crit sects */
-       smp_mb__after_atomic_inc();  /* See above. */
-       WARN_ON_ONCE(!(atomic_read(&rdtp->dynticks) & 0x1));
+       rdtp->dynticks_nmi++;
+       WARN_ON_ONCE(!(rdtp->dynticks_nmi & 0x1));
+       smp_mb(); /* CPUs seeing ++ must see later RCU read-side crit sects */
 }
 
 /**
@@ -357,14 +380,11 @@ void rcu_nmi_exit(void)
 {
        struct rcu_dynticks *rdtp = &__get_cpu_var(rcu_dynticks);
 
-       if (rdtp->dynticks_nmi_nesting == 0 ||
-           --rdtp->dynticks_nmi_nesting != 0)
+       if (rdtp->dynticks & 0x1)
                return;
-       /* CPUs seeing atomic_inc() must see prior RCU read-side crit sects */
-       smp_mb__before_atomic_inc();  /* See above. */
-       atomic_inc(&rdtp->dynticks);
-       smp_mb__after_atomic_inc();  /* Force delay to next write. */
-       WARN_ON_ONCE(atomic_read(&rdtp->dynticks) & 0x1);
+       smp_mb(); /* CPUs seeing ++ must see prior RCU read-side crit sects */
+       rdtp->dynticks_nmi++;
+       WARN_ON_ONCE(rdtp->dynticks_nmi & 0x1);
 }
 
 /**
@@ -375,7 +395,13 @@ void rcu_nmi_exit(void)
  */
 void rcu_irq_enter(void)
 {
-       rcu_exit_nohz();
+       struct rcu_dynticks *rdtp = &__get_cpu_var(rcu_dynticks);
+
+       if (rdtp->dynticks_nesting++)
+               return;
+       rdtp->dynticks++;
+       WARN_ON_ONCE(!(rdtp->dynticks & 0x1));
+       smp_mb(); /* CPUs seeing ++ must see later RCU read-side crit sects */
 }
 
 /**
@@ -387,7 +413,18 @@ void rcu_irq_enter(void)
  */
 void rcu_irq_exit(void)
 {
-       rcu_enter_nohz();
+       struct rcu_dynticks *rdtp = &__get_cpu_var(rcu_dynticks);
+
+       if (--rdtp->dynticks_nesting)
+               return;
+       smp_mb(); /* CPUs seeing ++ must see prior RCU read-side crit sects */
+       rdtp->dynticks++;
+       WARN_ON_ONCE(rdtp->dynticks & 0x1);
+
+       /* If the interrupt queued a callback, get out of dyntick mode. */
+       if (__this_cpu_read(rcu_sched_data.nxtlist) ||
+           __this_cpu_read(rcu_bh_data.nxtlist))
+               set_need_resched();
 }
 
 #ifdef CONFIG_SMP
@@ -399,8 +436,19 @@ void rcu_irq_exit(void)
  */
 static int dyntick_save_progress_counter(struct rcu_data *rdp)
 {
-       rdp->dynticks_snap = atomic_add_return(0, &rdp->dynticks->dynticks);
-       return 0;
+       int ret;
+       int snap;
+       int snap_nmi;
+
+       snap = rdp->dynticks->dynticks;
+       snap_nmi = rdp->dynticks->dynticks_nmi;
+       smp_mb();       /* Order sampling of snap with end of grace period. */
+       rdp->dynticks_snap = snap;
+       rdp->dynticks_nmi_snap = snap_nmi;
+       ret = ((snap & 0x1) == 0) && ((snap_nmi & 0x1) == 0);
+       if (ret)
+               rdp->dynticks_fqs++;
+       return ret;
 }
 
 /*
@@ -411,11 +459,16 @@ static int dyntick_save_progress_counter(struct rcu_data *rdp)
  */
 static int rcu_implicit_dynticks_qs(struct rcu_data *rdp)
 {
-       unsigned long curr;
-       unsigned long snap;
+       long curr;
+       long curr_nmi;
+       long snap;
+       long snap_nmi;
 
-       curr = (unsigned long)atomic_add_return(0, &rdp->dynticks->dynticks);
-       snap = (unsigned long)rdp->dynticks_snap;
+       curr = rdp->dynticks->dynticks;
+       snap = rdp->dynticks_snap;
+       curr_nmi = rdp->dynticks->dynticks_nmi;
+       snap_nmi = rdp->dynticks_nmi_snap;
+       smp_mb(); /* force ordering with cpu entering/leaving dynticks. */
 
        /*
         * If the CPU passed through or entered a dynticks idle phase with
@@ -425,7 +478,8 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp)
         * read-side critical section that started before the beginning
         * of the current RCU grace period.
         */
-       if ((curr & 0x1) == 0 || ULONG_CMP_GE(curr, snap + 2)) {
+       if ((curr != snap || (curr & 0x1) == 0) &&
+           (curr_nmi != snap_nmi || (curr_nmi & 0x1) == 0)) {
                rdp->dynticks_fqs++;
                return 1;
        }
@@ -539,21 +593,24 @@ static void print_cpu_stall(struct rcu_state *rsp)
 
 static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp)
 {
-       long delta;
+       unsigned long j;
+       unsigned long js;
        struct rcu_node *rnp;
 
        if (rcu_cpu_stall_suppress)
                return;
-       delta = jiffies - ACCESS_ONCE(rsp->jiffies_stall);
+       j = ACCESS_ONCE(jiffies);
+       js = ACCESS_ONCE(rsp->jiffies_stall);
        rnp = rdp->mynode;
-       if ((ACCESS_ONCE(rnp->qsmask) & rdp->grpmask) && delta >= 0) {
+       if ((ACCESS_ONCE(rnp->qsmask) & rdp->grpmask) && ULONG_CMP_GE(j, js)) {
 
                /* We haven't checked in, so go dump stack. */
                print_cpu_stall(rsp);
 
-       } else if (rcu_gp_in_progress(rsp) && delta >= RCU_STALL_RAT_DELAY) {
+       } else if (rcu_gp_in_progress(rsp) &&
+                  ULONG_CMP_GE(j, js + RCU_STALL_RAT_DELAY)) {
 
-               /* They had two time units to dump stack, so complain. */
+               /* They had a few time units to dump stack, so complain. */
                print_other_cpu_stall(rsp);
        }
 }
@@ -791,6 +848,7 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags)
                rnp->completed = rsp->completed;
                rsp->signaled = RCU_SIGNAL_INIT; /* force_quiescent_state OK. */
                rcu_start_gp_per_cpu(rsp, rnp, rdp);
+               rcu_preempt_boost_start_gp(rnp);
                raw_spin_unlock_irqrestore(&rnp->lock, flags);
                return;
        }
@@ -826,6 +884,7 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags)
                rnp->completed = rsp->completed;
                if (rnp == rdp->mynode)
                        rcu_start_gp_per_cpu(rsp, rnp, rdp);
+               rcu_preempt_boost_start_gp(rnp);
                raw_spin_unlock(&rnp->lock);    /* irqs remain disabled. */
        }
 
@@ -846,13 +905,12 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags)
 static void rcu_report_qs_rsp(struct rcu_state *rsp, unsigned long flags)
        __releases(rcu_get_root(rsp)->lock)
 {
-       WARN_ON_ONCE(!rcu_gp_in_progress(rsp));
+       unsigned long gp_duration;
 
-       /*
-        * Ensure that all grace-period and pre-grace-period activity
-        * is seen before the assignment to rsp->completed.
-        */
-       smp_mb(); /* See above block comment. */
+       WARN_ON_ONCE(!rcu_gp_in_progress(rsp));
+       gp_duration = jiffies - rsp->gp_start;
+       if (gp_duration > rsp->gp_max)
+               rsp->gp_max = gp_duration;
        rsp->completed = rsp->gpnum;
        rsp->signaled = RCU_GP_IDLE;
        rcu_start_gp(rsp, flags);  /* releases root node's rnp->lock. */
@@ -882,7 +940,7 @@ rcu_report_qs_rnp(unsigned long mask, struct rcu_state *rsp,
                        return;
                }
                rnp->qsmask &= ~mask;
-               if (rnp->qsmask != 0 || rcu_preempted_readers(rnp)) {
+               if (rnp->qsmask != 0 || rcu_preempt_blocked_readers_cgp(rnp)) {
 
                        /* Other bits still set at this level, so done. */
                        raw_spin_unlock_irqrestore(&rnp->lock, flags);
@@ -1080,19 +1138,7 @@ static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp)
                raw_spin_unlock_irqrestore(&rnp->lock, flags);
        if (need_report & RCU_OFL_TASKS_EXP_GP)
                rcu_report_exp_rnp(rsp, rnp);
-
-       /*
-        * If there are no more online CPUs for this rcu_node structure,
-        * kill the rcu_node structure's kthread.  Otherwise, adjust its
-        * affinity.
-        */
-       t = rnp->node_kthread_task;
-       if (t != NULL &&
-           rnp->qsmaskinit == 0) {
-               kthread_stop(t);
-               rnp->node_kthread_task = NULL;
-       } else
-               rcu_node_kthread_setaffinity(rnp);
+       rcu_node_kthread_setaffinity(rnp, -1);
 }
 
 /*
@@ -1154,7 +1200,7 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp)
                next = list->next;
                prefetch(next);
                debug_rcu_head_unqueue(list);
-               list->func(list);
+               __rcu_reclaim(list);
                list = next;
                if (++count >= rdp->blimit)
                        break;
@@ -1190,7 +1236,7 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp)
 
        /* Re-raise the RCU softirq if there are callbacks remaining. */
        if (cpu_has_callbacks_ready_to_invoke(rdp))
-               invoke_rcu_kthread();
+               invoke_rcu_cpu_kthread();
 }
 
 /*
@@ -1236,7 +1282,7 @@ void rcu_check_callbacks(int cpu, int user)
        }
        rcu_preempt_check_callbacks(cpu);
        if (rcu_pending(cpu))
-               invoke_rcu_kthread();
+               invoke_rcu_cpu_kthread();
 }
 
 #ifdef CONFIG_SMP
@@ -1244,6 +1290,8 @@ void rcu_check_callbacks(int cpu, int user)
 /*
  * Scan the leaf rcu_node structures, processing dyntick state for any that
  * have not yet encountered a quiescent state, using the function specified.
+ * Also initiate boosting for any threads blocked on the root rcu_node.
+ *
  * The caller must have suppressed start of new grace periods.
  */
 static void force_qs_rnp(struct rcu_state *rsp, int (*f)(struct rcu_data *))
@@ -1262,7 +1310,7 @@ static void force_qs_rnp(struct rcu_state *rsp, int (*f)(struct rcu_data *))
                        return;
                }
                if (rnp->qsmask == 0) {
-                       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+                       rcu_initiate_boost(rnp, flags); /* releases rnp->lock */
                        continue;
                }
                cpu = rnp->grplo;
@@ -1280,6 +1328,11 @@ static void force_qs_rnp(struct rcu_state *rsp, int (*f)(struct rcu_data *))
                }
                raw_spin_unlock_irqrestore(&rnp->lock, flags);
        }
+       rnp = rcu_get_root(rsp);
+       if (rnp->qsmask == 0) {
+               raw_spin_lock_irqsave(&rnp->lock, flags);
+               rcu_initiate_boost(rnp, flags); /* releases rnp->lock. */
+       }
 }
 
 /*
@@ -1402,11 +1455,25 @@ __rcu_process_callbacks(struct rcu_state *rsp, struct rcu_data *rdp)
  */
 static void rcu_process_callbacks(void)
 {
+       /*
+        * Memory references from any prior RCU read-side critical sections
+        * executed by the interrupted code must be seen before any RCU
+        * grace-period manipulations below.
+        */
+       smp_mb(); /* See above block comment. */
+
        __rcu_process_callbacks(&rcu_sched_state,
                                &__get_cpu_var(rcu_sched_data));
        __rcu_process_callbacks(&rcu_bh_state, &__get_cpu_var(rcu_bh_data));
        rcu_preempt_process_callbacks();
 
+       /*
+        * Memory references from any later RCU read-side critical sections
+        * executed by the interrupted code must be seen after any RCU
+        * grace-period manipulations above.
+        */
+       smp_mb(); /* See above block comment. */
+
        /* If we are last CPU on way to dyntick-idle mode, accelerate it. */
        rcu_needs_cpu_flush();
 }
@@ -1417,44 +1484,74 @@ static void rcu_process_callbacks(void)
  * the current CPU with interrupts disabled, the rcu_cpu_kthread_task
  * cannot disappear out from under us.
  */
-static void invoke_rcu_kthread(void)
+static void invoke_rcu_cpu_kthread(void)
 {
        unsigned long flags;
-       wait_queue_head_t *q;
-       int cpu;
 
        local_irq_save(flags);
-       cpu = smp_processor_id();
-       per_cpu(rcu_cpu_has_work, cpu) = 1;
-       if (per_cpu(rcu_cpu_kthread_task, cpu) == NULL) {
+       __this_cpu_write(rcu_cpu_has_work, 1);
+       if (__this_cpu_read(rcu_cpu_kthread_task) == NULL) {
                local_irq_restore(flags);
                return;
        }
-       q = &per_cpu(rcu_cpu_wq, cpu);
-       wake_up(q);
+       wake_up(&__get_cpu_var(rcu_cpu_wq));
        local_irq_restore(flags);
 }
 
+/*
+ * Wake up the specified per-rcu_node-structure kthread.
+ * Because the per-rcu_node kthreads are immortal, we don't need
+ * to do anything to keep them alive.
+ */
+static void invoke_rcu_node_kthread(struct rcu_node *rnp)
+{
+       struct task_struct *t;
+
+       t = rnp->node_kthread_task;
+       if (t != NULL)
+               wake_up_process(t);
+}
+
+/*
+ * Set the specified CPU's kthread to run RT or not, as specified by
+ * the to_rt argument.  The CPU-hotplug locks are held, so the task
+ * is not going away.
+ */
+static void rcu_cpu_kthread_setrt(int cpu, int to_rt)
+{
+       int policy;
+       struct sched_param sp;
+       struct task_struct *t;
+
+       t = per_cpu(rcu_cpu_kthread_task, cpu);
+       if (t == NULL)
+               return;
+       if (to_rt) {
+               policy = SCHED_FIFO;
+               sp.sched_priority = RCU_KTHREAD_PRIO;
+       } else {
+               policy = SCHED_NORMAL;
+               sp.sched_priority = 0;
+       }
+       sched_setscheduler_nocheck(t, policy, &sp);
+}
+
 /*
  * Timer handler to initiate the waking up of per-CPU kthreads that
  * have yielded the CPU due to excess numbers of RCU callbacks.
+ * We wake up the per-rcu_node kthread, which in turn will wake up
+ * the booster kthread.
  */
 static void rcu_cpu_kthread_timer(unsigned long arg)
 {
        unsigned long flags;
-       struct rcu_data *rdp = (struct rcu_data *)arg;
+       struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, arg);
        struct rcu_node *rnp = rdp->mynode;
-       struct task_struct *t;
 
        raw_spin_lock_irqsave(&rnp->lock, flags);
        rnp->wakemask |= rdp->grpmask;
-       t = rnp->node_kthread_task;
-       if (t == NULL) {
-               raw_spin_unlock_irqrestore(&rnp->lock, flags);
-               return;
-       }
-       wake_up_process(t);
        raw_spin_unlock_irqrestore(&rnp->lock, flags);
+       invoke_rcu_node_kthread(rnp);
 }
 
 /*
@@ -1463,16 +1560,16 @@ static void rcu_cpu_kthread_timer(unsigned long arg)
  * remain preempted.  Either way, we restore our real-time priority
  * before returning.
  */
-static void rcu_yield(int cpu)
+static void rcu_yield(void (*f)(unsigned long), unsigned long arg)
 {
-       struct rcu_data *rdp = per_cpu_ptr(rcu_sched_state.rda, cpu);
        struct sched_param sp;
        struct timer_list yield_timer;
 
-       setup_timer_on_stack(&yield_timer, rcu_cpu_kthread_timer, (unsigned long)rdp);
+       setup_timer_on_stack(&yield_timer, f, arg);
        mod_timer(&yield_timer, jiffies + 2);
        sp.sched_priority = 0;
        sched_setscheduler_nocheck(current, SCHED_NORMAL, &sp);
+       set_user_nice(current, 19);
        schedule();
        sp.sched_priority = RCU_KTHREAD_PRIO;
        sched_setscheduler_nocheck(current, SCHED_FIFO, &sp);
@@ -1498,12 +1595,15 @@ static int rcu_cpu_kthread_should_stop(int cpu)
               smp_processor_id() != cpu) {
                if (kthread_should_stop())
                        return 1;
+               per_cpu(rcu_cpu_kthread_status, cpu) = RCU_KTHREAD_OFFCPU;
+               per_cpu(rcu_cpu_kthread_cpu, cpu) = raw_smp_processor_id();
                local_bh_enable();
                schedule_timeout_uninterruptible(1);
                if (!cpumask_equal(&current->cpus_allowed, cpumask_of(cpu)))
                        set_cpus_allowed_ptr(current, cpumask_of(cpu));
                local_bh_disable();
        }
+       per_cpu(rcu_cpu_kthread_cpu, cpu) = cpu;
        return 0;
 }
 
@@ -1516,11 +1616,13 @@ static int rcu_cpu_kthread(void *arg)
        int cpu = (int)(long)arg;
        unsigned long flags;
        int spincnt = 0;
+       unsigned int *statusp = &per_cpu(rcu_cpu_kthread_status, cpu);
        wait_queue_head_t *wqp = &per_cpu(rcu_cpu_wq, cpu);
        char work;
        char *workp = &per_cpu(rcu_cpu_has_work, cpu);
 
        for (;;) {
+               *statusp = RCU_KTHREAD_WAITING;
                wait_event_interruptible(*wqp,
                                         *workp != 0 || kthread_should_stop());
                local_bh_disable();
@@ -1528,6 +1630,8 @@ static int rcu_cpu_kthread(void *arg)
                        local_bh_enable();
                        break;
                }
+               *statusp = RCU_KTHREAD_RUNNING;
+               per_cpu(rcu_cpu_kthread_loops, cpu)++;
                local_irq_save(flags);
                work = *workp;
                *workp = 0;
@@ -1540,10 +1644,12 @@ static int rcu_cpu_kthread(void *arg)
                else
                        spincnt = 0;
                if (spincnt > 10) {
-                       rcu_yield(cpu);
+                       *statusp = RCU_KTHREAD_YIELDING;
+                       rcu_yield(rcu_cpu_kthread_timer, (unsigned long)cpu);
                        spincnt = 0;
                }
        }
+       *statusp = RCU_KTHREAD_STOPPED;
        return 0;
 }
 
@@ -1566,6 +1672,7 @@ static int __cpuinit rcu_spawn_one_cpu_kthread(int cpu)
        if (IS_ERR(t))
                return PTR_ERR(t);
        kthread_bind(t, cpu);
+       per_cpu(rcu_cpu_kthread_cpu, cpu) = cpu;
        WARN_ON_ONCE(per_cpu(rcu_cpu_kthread_task, cpu) != NULL);
        per_cpu(rcu_cpu_kthread_task, cpu) = t;
        wake_up_process(t);
@@ -1590,14 +1697,13 @@ static int rcu_node_kthread(void *arg)
        struct task_struct *t;
 
        for (;;) {
-               wait_event_interruptible(rnp->node_wq, rnp->wakemask != 0 ||
-                                                      kthread_should_stop());
-               if (kthread_should_stop())
-                       break;
+               rnp->node_kthread_status = RCU_KTHREAD_WAITING;
+               wait_event_interruptible(rnp->node_wq, rnp->wakemask != 0);
+               rnp->node_kthread_status = RCU_KTHREAD_RUNNING;
                raw_spin_lock_irqsave(&rnp->lock, flags);
                mask = rnp->wakemask;
                rnp->wakemask = 0;
-               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               rcu_initiate_boost(rnp, flags); /* releases rnp->lock. */
                for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++, mask >>= 1) {
                        if ((mask & 0x1) == 0)
                                continue;
@@ -1613,54 +1719,75 @@ static int rcu_node_kthread(void *arg)
                        preempt_enable();
                }
        }
+       /* NOTREACHED */
+       rnp->node_kthread_status = RCU_KTHREAD_STOPPED;
        return 0;
 }
 
 /*
  * Set the per-rcu_node kthread's affinity to cover all CPUs that are
- * served by the rcu_node in question.
+ * served by the rcu_node in question.  The CPU hotplug lock is still
+ * held, so the value of rnp->qsmaskinit will be stable.
+ *
+ * We don't include outgoingcpu in the affinity set, use -1 if there is
+ * no outgoing CPU.  If there are no CPUs left in the affinity set,
+ * this function allows the kthread to execute on any CPU.
  */
-static void rcu_node_kthread_setaffinity(struct rcu_node *rnp)
+static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu)
 {
        cpumask_var_t cm;
        int cpu;
        unsigned long mask = rnp->qsmaskinit;
 
-       if (rnp->node_kthread_task == NULL ||
-           rnp->qsmaskinit == 0)
+       if (rnp->node_kthread_task == NULL)
                return;
        if (!alloc_cpumask_var(&cm, GFP_KERNEL))
                return;
        cpumask_clear(cm);
        for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++, mask >>= 1)
-               if (mask & 0x1)
+               if ((mask & 0x1) && cpu != outgoingcpu)
                        cpumask_set_cpu(cpu, cm);
+       if (cpumask_weight(cm) == 0) {
+               cpumask_setall(cm);
+               for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++)
+                       cpumask_clear_cpu(cpu, cm);
+               WARN_ON_ONCE(cpumask_weight(cm) == 0);
+       }
        set_cpus_allowed_ptr(rnp->node_kthread_task, cm);
+       rcu_boost_kthread_setaffinity(rnp, cm);
        free_cpumask_var(cm);
 }
 
 /*
  * Spawn a per-rcu_node kthread, setting priority and affinity.
+ * Called during boot before online/offline can happen, or, if
+ * during runtime, with the main CPU-hotplug locks held.  So only
+ * one of these can be executing at a time.
  */
 static int __cpuinit rcu_spawn_one_node_kthread(struct rcu_state *rsp,
                                                struct rcu_node *rnp)
 {
+       unsigned long flags;
        int rnp_index = rnp - &rsp->node[0];
        struct sched_param sp;
        struct task_struct *t;
 
        if (!rcu_kthreads_spawnable ||
-           rnp->qsmaskinit == 0 ||
-           rnp->node_kthread_task != NULL)
+           rnp->qsmaskinit == 0)
                return 0;
-       t = kthread_create(rcu_node_kthread, (void *)rnp, "rcun%d", rnp_index);
-       if (IS_ERR(t))
-               return PTR_ERR(t);
-       rnp->node_kthread_task = t;
-       wake_up_process(t);
-       sp.sched_priority = 99;
-       sched_setscheduler_nocheck(t, SCHED_FIFO, &sp);
-       return 0;
+       if (rnp->node_kthread_task == NULL) {
+               t = kthread_create(rcu_node_kthread, (void *)rnp,
+                                  "rcun%d", rnp_index);
+               if (IS_ERR(t))
+                       return PTR_ERR(t);
+               raw_spin_lock_irqsave(&rnp->lock, flags);
+               rnp->node_kthread_task = t;
+               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               wake_up_process(t);
+               sp.sched_priority = 99;
+               sched_setscheduler_nocheck(t, SCHED_FIFO, &sp);
+       }
+       return rcu_spawn_one_boost_kthread(rsp, rnp, rnp_index);
 }
 
 /*
@@ -1678,10 +1805,16 @@ static int __init rcu_spawn_kthreads(void)
                if (cpu_online(cpu))
                        (void)rcu_spawn_one_cpu_kthread(cpu);
        }
-       rcu_for_each_leaf_node(&rcu_sched_state, rnp) {
-               init_waitqueue_head(&rnp->node_wq);
-               (void)rcu_spawn_one_node_kthread(&rcu_sched_state, rnp);
-       }
+       rnp = rcu_get_root(rcu_state);
+       init_waitqueue_head(&rnp->node_wq);
+       rcu_init_boost_waitqueue(rnp);
+       (void)rcu_spawn_one_node_kthread(rcu_state, rnp);
+       if (NUM_RCU_NODES > 1)
+               rcu_for_each_leaf_node(rcu_state, rnp) {
+                       init_waitqueue_head(&rnp->node_wq);
+                       rcu_init_boost_waitqueue(rnp);
+                       (void)rcu_spawn_one_node_kthread(rcu_state, rnp);
+               }
        return 0;
 }
 early_initcall(rcu_spawn_kthreads);
@@ -1711,6 +1844,13 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
        /* Add the callback to our list. */
        *rdp->nxttail[RCU_NEXT_TAIL] = head;
        rdp->nxttail[RCU_NEXT_TAIL] = &head->next;
+       rdp->qlen++;
+
+       /* If interrupts were disabled, don't dive into RCU core. */
+       if (irqs_disabled_flags(flags)) {
+               local_irq_restore(flags);
+               return;
+       }
 
        /*
         * Force the grace period if too many callbacks or too long waiting.
@@ -1719,7 +1859,7 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
         * invoking force_quiescent_state() if the newly enqueued callback
         * is the only one waiting for a grace period to complete.
         */
-       if (unlikely(++rdp->qlen > rdp->qlen_last_fqs_check + qhimark)) {
+       if (unlikely(rdp->qlen > rdp->qlen_last_fqs_check + qhimark)) {
 
                /* Are we ignoring a completed grace period? */
                rcu_process_gp_end(rsp, rdp);
@@ -1855,7 +1995,7 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp)
                 * or RCU-bh, force a local reschedule.
                 */
                rdp->n_rp_qs_pending++;
-               if (!rdp->preemptable &&
+               if (!rdp->preemptible &&
                    ULONG_CMP_LT(ACCESS_ONCE(rsp->jiffies_force_qs) - 1,
                                 jiffies))
                        set_need_resched();
@@ -2032,7 +2172,7 @@ rcu_boot_init_percpu_data(int cpu, struct rcu_state *rsp)
  * that this CPU cannot possibly have any RCU callbacks in flight yet.
  */
 static void __cpuinit
-rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptable)
+rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible)
 {
        unsigned long flags;
        unsigned long mask;
@@ -2044,7 +2184,7 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptable)
        rdp->passed_quiesc = 0;  /* We could be racing with new GP, */
        rdp->qs_pending = 1;     /*  so set up to respond to current GP. */
        rdp->beenonline = 1;     /* We have now been online. */
-       rdp->preemptable = preemptable;
+       rdp->preemptible = preemptible;
        rdp->qlen_last_fqs_check = 0;
        rdp->n_force_qs_snap = rsp->n_force_qs;
        rdp->blimit = blimit;
@@ -2087,14 +2227,14 @@ static void __cpuinit rcu_online_cpu(int cpu)
 
 static void __cpuinit rcu_online_kthreads(int cpu)
 {
-       struct rcu_data *rdp = per_cpu_ptr(rcu_sched_state.rda, cpu);
+       struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, cpu);
        struct rcu_node *rnp = rdp->mynode;
 
        /* Fire up the incoming CPU's kthread and leaf rcu_node kthread. */
        if (rcu_kthreads_spawnable) {
                (void)rcu_spawn_one_cpu_kthread(cpu);
                if (rnp->node_kthread_task == NULL)
-                       (void)rcu_spawn_one_node_kthread(&rcu_sched_state, rnp);
+                       (void)rcu_spawn_one_node_kthread(rcu_state, rnp);
        }
 }
 
@@ -2105,7 +2245,7 @@ static int __cpuinit rcu_cpu_notify(struct notifier_block *self,
                                    unsigned long action, void *hcpu)
 {
        long cpu = (long)hcpu;
-       struct rcu_data *rdp = per_cpu_ptr(rcu_sched_state.rda, cpu);
+       struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, cpu);
        struct rcu_node *rnp = rdp->mynode;
 
        switch (action) {
@@ -2115,7 +2255,13 @@ static int __cpuinit rcu_cpu_notify(struct notifier_block *self,
                rcu_online_kthreads(cpu);
                break;
        case CPU_ONLINE:
-               rcu_node_kthread_setaffinity(rnp);
+       case CPU_DOWN_FAILED:
+               rcu_node_kthread_setaffinity(rnp, -1);
+               rcu_cpu_kthread_setrt(cpu, 1);
+               break;
+       case CPU_DOWN_PREPARE:
+               rcu_node_kthread_setaffinity(rnp, cpu);
+               rcu_cpu_kthread_setrt(cpu, 0);
                break;
        case CPU_DYING:
        case CPU_DYING_FROZEN: