Loading Documentation/RCU/checklist.txt +25 −18 Original line number Diff line number Diff line Loading @@ -318,7 +318,7 @@ over a rather long period of time, but improvements are always welcome! 11. Any lock acquired by an RCU callback must be acquired elsewhere with softirq disabled, e.g., via spin_lock_irqsave(), spin_lock_bh(), etc. Failing to disable irq on a given spin_lock_bh(), etc. Failing to disable softirq on a given acquisition of that lock will result in deadlock as soon as the RCU softirq handler happens to run your RCU callback while interrupting that acquisition's critical section. Loading @@ -331,13 +331,16 @@ over a rather long period of time, but improvements are always welcome! must use whatever locking or other synchronization is required to safely access and/or modify that data structure. RCU callbacks are -usually- executed on the same CPU that executed the corresponding call_rcu() or call_srcu(). but are by -no- means guaranteed to be. For example, if a given CPU goes offline while having an RCU callback pending, then that RCU callback will execute on some surviving CPU. (If this was not the case, a self-spawning RCU callback would prevent the victim CPU from ever going offline.) Do not assume that RCU callbacks will be executed on the same CPU that executed the corresponding call_rcu() or call_srcu(). For example, if a given CPU goes offline while having an RCU callback pending, then that RCU callback will execute on some surviving CPU. (If this was not the case, a self-spawning RCU callback would prevent the victim CPU from ever going offline.) Furthermore, CPUs designated by rcu_nocbs= might well -always- have their RCU callbacks executed on some other CPUs, in fact, for some real-time workloads, this is the whole point of using the rcu_nocbs= kernel boot parameter. 13. Unlike other forms of RCU, it -is- permissible to block in an SRCU read-side critical section (demarked by srcu_read_lock() Loading Loading @@ -379,8 +382,9 @@ over a rather long period of time, but improvements are always welcome! never sends IPIs to other CPUs, so it is easier on real-time workloads than is synchronize_rcu_expedited(). Note that rcu_dereference() and rcu_assign_pointer() relate to SRCU just as they do to other forms of RCU. Note that rcu_assign_pointer() relates to SRCU just as it does to other forms of RCU, but instead of rcu_dereference() you should use srcu_dereference() in order to avoid lockdep splats. 14. The whole point of call_rcu(), synchronize_rcu(), and friends is to wait until all pre-existing readers have finished before Loading @@ -400,6 +404,9 @@ over a rather long period of time, but improvements are always welcome! read-side critical sections. It is the responsibility of the RCU update-side primitives to deal with this. For SRCU readers, you can use smp_mb__after_srcu_read_unlock() immediately after an srcu_read_unlock() to get a full barrier. 16. Use CONFIG_PROVE_LOCKING, CONFIG_DEBUG_OBJECTS_RCU_HEAD, and the __rcu sparse checks to validate your RCU code. These can help find problems as follows: Loading @@ -423,15 +430,15 @@ over a rather long period of time, but improvements are always welcome! These debugging aids can help you find problems that are otherwise extremely difficult to spot. 17. If you register a callback using call_rcu() or call_srcu(), and pass in a function defined within a loadable module, then it in necessary to wait for all pending callbacks to be invoked after the last invocation and before unloading that module. Note that it is absolutely -not- sufficient to wait for a grace period! The current (say) synchronize_rcu() implementation waits only for all previous callbacks registered on the CPU that synchronize_rcu() is running on, but it is -not- 17. If you register a callback using call_rcu() or call_srcu(), and pass in a function defined within a loadable module, then it in necessary to wait for all pending callbacks to be invoked after the last invocation and before unloading that module. Note that it is absolutely -not- sufficient to wait for a grace period! The current (say) synchronize_rcu() implementation is -not- guaranteed to wait for callbacks registered on other CPUs. Or even on the current CPU if that CPU recently went offline and came back online. You instead need to use one of the barrier functions: Loading Loading
Documentation/RCU/checklist.txt +25 −18 Original line number Diff line number Diff line Loading @@ -318,7 +318,7 @@ over a rather long period of time, but improvements are always welcome! 11. Any lock acquired by an RCU callback must be acquired elsewhere with softirq disabled, e.g., via spin_lock_irqsave(), spin_lock_bh(), etc. Failing to disable irq on a given spin_lock_bh(), etc. Failing to disable softirq on a given acquisition of that lock will result in deadlock as soon as the RCU softirq handler happens to run your RCU callback while interrupting that acquisition's critical section. Loading @@ -331,13 +331,16 @@ over a rather long period of time, but improvements are always welcome! must use whatever locking or other synchronization is required to safely access and/or modify that data structure. RCU callbacks are -usually- executed on the same CPU that executed the corresponding call_rcu() or call_srcu(). but are by -no- means guaranteed to be. For example, if a given CPU goes offline while having an RCU callback pending, then that RCU callback will execute on some surviving CPU. (If this was not the case, a self-spawning RCU callback would prevent the victim CPU from ever going offline.) Do not assume that RCU callbacks will be executed on the same CPU that executed the corresponding call_rcu() or call_srcu(). For example, if a given CPU goes offline while having an RCU callback pending, then that RCU callback will execute on some surviving CPU. (If this was not the case, a self-spawning RCU callback would prevent the victim CPU from ever going offline.) Furthermore, CPUs designated by rcu_nocbs= might well -always- have their RCU callbacks executed on some other CPUs, in fact, for some real-time workloads, this is the whole point of using the rcu_nocbs= kernel boot parameter. 13. Unlike other forms of RCU, it -is- permissible to block in an SRCU read-side critical section (demarked by srcu_read_lock() Loading Loading @@ -379,8 +382,9 @@ over a rather long period of time, but improvements are always welcome! never sends IPIs to other CPUs, so it is easier on real-time workloads than is synchronize_rcu_expedited(). Note that rcu_dereference() and rcu_assign_pointer() relate to SRCU just as they do to other forms of RCU. Note that rcu_assign_pointer() relates to SRCU just as it does to other forms of RCU, but instead of rcu_dereference() you should use srcu_dereference() in order to avoid lockdep splats. 14. The whole point of call_rcu(), synchronize_rcu(), and friends is to wait until all pre-existing readers have finished before Loading @@ -400,6 +404,9 @@ over a rather long period of time, but improvements are always welcome! read-side critical sections. It is the responsibility of the RCU update-side primitives to deal with this. For SRCU readers, you can use smp_mb__after_srcu_read_unlock() immediately after an srcu_read_unlock() to get a full barrier. 16. Use CONFIG_PROVE_LOCKING, CONFIG_DEBUG_OBJECTS_RCU_HEAD, and the __rcu sparse checks to validate your RCU code. These can help find problems as follows: Loading @@ -423,15 +430,15 @@ over a rather long period of time, but improvements are always welcome! These debugging aids can help you find problems that are otherwise extremely difficult to spot. 17. If you register a callback using call_rcu() or call_srcu(), and pass in a function defined within a loadable module, then it in necessary to wait for all pending callbacks to be invoked after the last invocation and before unloading that module. Note that it is absolutely -not- sufficient to wait for a grace period! The current (say) synchronize_rcu() implementation waits only for all previous callbacks registered on the CPU that synchronize_rcu() is running on, but it is -not- 17. If you register a callback using call_rcu() or call_srcu(), and pass in a function defined within a loadable module, then it in necessary to wait for all pending callbacks to be invoked after the last invocation and before unloading that module. Note that it is absolutely -not- sufficient to wait for a grace period! The current (say) synchronize_rcu() implementation is -not- guaranteed to wait for callbacks registered on other CPUs. Or even on the current CPU if that CPU recently went offline and came back online. You instead need to use one of the barrier functions: Loading