Merge tag 'pm-for-3.4-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
[linux-flexiantxendom0-3.2.10.git] / kernel / rcutree.c
index 708469a..d0c5baf 100644 (file)
@@ -198,7 +198,7 @@ void rcu_note_context_switch(int cpu)
 EXPORT_SYMBOL_GPL(rcu_note_context_switch);
 
 DEFINE_PER_CPU(struct rcu_dynticks, rcu_dynticks) = {
-       .dynticks_nesting = DYNTICK_TASK_NESTING,
+       .dynticks_nesting = DYNTICK_TASK_EXIT_IDLE,
        .dynticks = ATOMIC_INIT(1),
 };
 
@@ -394,10 +394,15 @@ void rcu_idle_enter(void)
        local_irq_save(flags);
        rdtp = &__get_cpu_var(rcu_dynticks);
        oldval = rdtp->dynticks_nesting;
-       rdtp->dynticks_nesting = 0;
+       WARN_ON_ONCE((oldval & DYNTICK_TASK_NEST_MASK) == 0);
+       if ((oldval & DYNTICK_TASK_NEST_MASK) == DYNTICK_TASK_NEST_VALUE)
+               rdtp->dynticks_nesting = 0;
+       else
+               rdtp->dynticks_nesting -= DYNTICK_TASK_NEST_VALUE;
        rcu_idle_enter_common(rdtp, oldval);
        local_irq_restore(flags);
 }
+EXPORT_SYMBOL_GPL(rcu_idle_enter);
 
 /**
  * rcu_irq_exit - inform RCU that current CPU is exiting irq towards idle
@@ -467,7 +472,7 @@ static void rcu_idle_exit_common(struct rcu_dynticks *rdtp, long long oldval)
  * Exit idle mode, in other words, -enter- the mode in which RCU
  * read-side critical sections can occur.
  *
- * We crowbar the ->dynticks_nesting field to DYNTICK_TASK_NESTING to
+ * We crowbar the ->dynticks_nesting field to DYNTICK_TASK_NEST to
  * allow for the possibility of usermode upcalls messing up our count
  * of interrupt nesting level during the busy period that is just
  * now starting.
@@ -481,11 +486,15 @@ void rcu_idle_exit(void)
        local_irq_save(flags);
        rdtp = &__get_cpu_var(rcu_dynticks);
        oldval = rdtp->dynticks_nesting;
-       WARN_ON_ONCE(oldval != 0);
-       rdtp->dynticks_nesting = DYNTICK_TASK_NESTING;
+       WARN_ON_ONCE(oldval < 0);
+       if (oldval & DYNTICK_TASK_NEST_MASK)
+               rdtp->dynticks_nesting += DYNTICK_TASK_NEST_VALUE;
+       else
+               rdtp->dynticks_nesting = DYNTICK_TASK_EXIT_IDLE;
        rcu_idle_exit_common(rdtp, oldval);
        local_irq_restore(flags);
 }
+EXPORT_SYMBOL_GPL(rcu_idle_exit);
 
 /**
  * rcu_irq_enter - inform RCU that current CPU is entering irq away from idle
@@ -1811,7 +1820,6 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
         * a quiescent state betweentimes.
         */
        local_irq_save(flags);
-       WARN_ON_ONCE(cpu_is_offline(smp_processor_id()));
        rdp = this_cpu_ptr(rsp->rda);
 
        /* Add the callback to our list. */
@@ -1961,15 +1969,21 @@ static int synchronize_sched_expedited_cpu_stop(void *data)
        return 0;
 }
 
-/*
- * 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.
+/**
+ * synchronize_sched_expedited - Brute-force RCU-sched grace period
+ *
+ * Wait for an RCU-sched grace period to elapse, but use a "big hammer"
+ * approach to force the grace period to end quickly.  This consumes
+ * significant time on all CPUs and is unfriendly to real-time workloads,
+ * so is thus not recommended for any sort of common-case code.  In fact,
+ * if you are using synchronize_sched_expedited() in a loop, please
+ * restructure your code to batch your updates, and then use a single
+ * synchronize_sched() instead.
  *
- * 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.
+ * Note that it is illegal to call this function while holding any lock
+ * that is acquired by a CPU-hotplug notifier.  And yes, it is also illegal
+ * to call this function from a CPU-hotplug notifier.  Failing to observe
+ * these restriction will result in deadlock.
  *
  * This implementation can be thought of as an application of ticket
  * locking to RCU, with sync_sched_expedited_started and
@@ -1999,7 +2013,7 @@ void synchronize_sched_expedited(void)
        /* Note that atomic_inc_return() implies full memory barrier. */
        firstsnap = snap = atomic_inc_return(&sync_sched_expedited_started);
        get_online_cpus();
-       WARN_ON_ONCE(cpu_is_offline(smp_processor_id()));
+       WARN_ON_ONCE(cpu_is_offline(raw_smp_processor_id()));
 
        /*
         * Each pass through the following loop attempts to force a
@@ -2247,7 +2261,7 @@ rcu_boot_init_percpu_data(int cpu, struct rcu_state *rsp)
        rdp->qlen_lazy = 0;
        rdp->qlen = 0;
        rdp->dynticks = &per_cpu(rcu_dynticks, cpu);
-       WARN_ON_ONCE(rdp->dynticks->dynticks_nesting != DYNTICK_TASK_NESTING);
+       WARN_ON_ONCE(rdp->dynticks->dynticks_nesting != DYNTICK_TASK_EXIT_IDLE);
        WARN_ON_ONCE(atomic_read(&rdp->dynticks->dynticks) != 1);
        rdp->cpu = cpu;
        rdp->rsp = rsp;
@@ -2275,7 +2289,7 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible)
        rdp->qlen_last_fqs_check = 0;
        rdp->n_force_qs_snap = rsp->n_force_qs;
        rdp->blimit = blimit;
-       rdp->dynticks->dynticks_nesting = DYNTICK_TASK_NESTING;
+       rdp->dynticks->dynticks_nesting = DYNTICK_TASK_EXIT_IDLE;
        atomic_set(&rdp->dynticks->dynticks,
                   (atomic_read(&rdp->dynticks->dynticks) & ~0x1) + 1);
        rcu_prepare_for_idle_init(cpu);