Merge branch 'linus' into timers/core
[pandora-kernel.git] / Documentation / RCU / NMI-RCU.txt
index c64158e..a8536cb 100644 (file)
@@ -34,7 +34,7 @@ NMI handler.
                cpu = smp_processor_id();
                ++nmi_count(cpu);
 
-               if (!rcu_dereference(nmi_callback)(regs, cpu))
+               if (!rcu_dereference_sched(nmi_callback)(regs, cpu))
                        default_do_nmi(regs);
 
                nmi_exit();
@@ -47,12 +47,13 @@ function pointer.  If this handler returns zero, do_nmi() invokes the
 default_do_nmi() function to handle a machine-specific NMI.  Finally,
 preemption is restored.
 
-Strictly speaking, rcu_dereference() is not needed, since this code runs
-only on i386, which does not need rcu_dereference() anyway.  However,
-it is a good documentation aid, particularly for anyone attempting to
-do something similar on Alpha.
+In theory, rcu_dereference_sched() is not needed, since this code runs
+only on i386, which in theory does not need rcu_dereference_sched()
+anyway.  However, in practice it is a good documentation aid, particularly
+for anyone attempting to do something similar on Alpha or on systems
+with aggressive optimizing compilers.
 
-Quick Quiz:  Why might the rcu_dereference() be necessary on Alpha,
+Quick Quiz:  Why might the rcu_dereference_sched() be necessary on Alpha,
             given that the code referenced by the pointer is read-only?
 
 
@@ -93,20 +94,27 @@ Since NMI handlers disable preemption, synchronize_sched() is guaranteed
 not to return until all ongoing NMI handlers exit.  It is therefore safe
 to free up the handler's data as soon as synchronize_sched() returns.
 
+Important note: for this to work, the architecture in question must
+invoke irq_enter() and irq_exit() on NMI entry and exit, respectively.
+
 
 Answer to Quick Quiz
 
-       Why might the rcu_dereference() be necessary on Alpha, given
+       Why might the rcu_dereference_sched() be necessary on Alpha, given
        that the code referenced by the pointer is read-only?
 
        Answer: The caller to set_nmi_callback() might well have
-               initialized some data that is to be used by the
-               new NMI handler.  In this case, the rcu_dereference()
-               would be needed, because otherwise a CPU that received
-               an NMI just after the new handler was set might see
-               the pointer to the new NMI handler, but the old
-               pre-initialized version of the handler's data.
-
-               More important, the rcu_dereference() makes it clear
-               to someone reading the code that the pointer is being
-               protected by RCU.
+               initialized some data that is to be used by the new NMI
+               handler.  In this case, the rcu_dereference_sched() would
+               be needed, because otherwise a CPU that received an NMI
+               just after the new handler was set might see the pointer
+               to the new NMI handler, but the old pre-initialized
+               version of the handler's data.
+
+               This same sad story can happen on other CPUs when using
+               a compiler with aggressive pointer-value speculation
+               optimizations.
+
+               More important, the rcu_dereference_sched() makes it
+               clear to someone reading the code that the pointer is
+               being protected by RCU-sched.