Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
[safe/jmp/linux-2.6] / kernel / rcutree_plugin.h
index 5f94619..1cee04f 100644 (file)
@@ -117,9 +117,9 @@ static void rcu_preempt_note_context_switch(int cpu)
                 * on line!
                 */
                WARN_ON_ONCE((rdp->grpmask & rnp->qsmaskinit) == 0);
-               phase = !(rnp->qsmask & rdp->grpmask) ^ (rnp->gpnum & 0x1);
+               WARN_ON_ONCE(!list_empty(&t->rcu_node_entry));
+               phase = (rnp->gpnum + !(rnp->qsmask & rdp->grpmask)) & 0x1;
                list_add(&t->rcu_node_entry, &rnp->blocked_tasks[phase]);
-               smp_mb();  /* Ensure later ctxt swtch seen after above. */
                spin_unlock_irqrestore(&rnp->lock, flags);
        }
 
@@ -133,7 +133,9 @@ static void rcu_preempt_note_context_switch(int cpu)
         * means that we continue to block the current grace period.
         */
        rcu_preempt_qs(cpu);
+       local_irq_save(flags);
        t->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS;
+       local_irq_restore(flags);
 }
 
 /*
@@ -189,10 +191,10 @@ static void rcu_read_unlock_special(struct task_struct *t)
                 */
                for (;;) {
                        rnp = t->rcu_blocked_node;
-                       spin_lock(&rnp->lock);
+                       spin_lock(&rnp->lock);  /* irqs already disabled. */
                        if (rnp == t->rcu_blocked_node)
                                break;
-                       spin_unlock(&rnp->lock);
+                       spin_unlock(&rnp->lock);  /* irqs remain disabled. */
                }
                empty = list_empty(&rnp->blocked_tasks[rnp->gpnum & 0x1]);
                list_del_init(&t->rcu_node_entry);
@@ -368,9 +370,8 @@ static void rcu_preempt_check_callbacks(int cpu)
                rcu_preempt_qs(cpu);
                return;
        }
-       if (per_cpu(rcu_preempt_data, cpu).qs_pending) {
+       if (per_cpu(rcu_preempt_data, cpu).qs_pending)
                t->rcu_read_unlock_special |= RCU_READ_UNLOCK_NEED_QS;
-       }
 }
 
 /*
@@ -474,10 +475,12 @@ static void rcu_print_task_stall(struct rcu_node *rnp)
 
 /*
  * Because there is no preemptable RCU, there can be no readers blocked,
- * so there is no need to check for blocked tasks.
+ * so there is no need to check for blocked tasks.  So check only for
+ * bogus qsmask values.
  */
 static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp)
 {
+       WARN_ON_ONCE(rnp->qsmask);
 }
 
 /*