Loading Documentation/RCU/RTFP.txt +14 −11 Original line number Diff line number Diff line Loading @@ -90,16 +90,20 @@ at OLS. The resulting abundance of RCU patches was presented the following year [McKenney02a], and use of RCU in dcache was first described that same year [Linder02a]. Also in 2002, Michael [Michael02b,Michael02a] presented techniques that defer the destruction of data structures to simplify non-blocking synchronization (wait-free synchronization, lock-free synchronization, and obstruction-free synchronization are all examples of non-blocking synchronization). In particular, this technique eliminates locking, reduces contention, reduces memory latency for readers, and parallelizes pipeline stalls and memory latency for writers. However, these techniques still impose significant read-side overhead in the form of memory barriers. Researchers at Sun worked along similar lines in the same timeframe [HerlihyLM02,HerlihyLMS03]. Also in 2002, Michael [Michael02b,Michael02a] presented "hazard-pointer" techniques that defer the destruction of data structures to simplify non-blocking synchronization (wait-free synchronization, lock-free synchronization, and obstruction-free synchronization are all examples of non-blocking synchronization). In particular, this technique eliminates locking, reduces contention, reduces memory latency for readers, and parallelizes pipeline stalls and memory latency for writers. However, these techniques still impose significant read-side overhead in the form of memory barriers. Researchers at Sun worked along similar lines in the same timeframe [HerlihyLM02,HerlihyLMS03]. These techniques can be thought of as inside-out reference counts, where the count is represented by the number of hazard pointers referencing a given data structure (rather than the more conventional counter field within the data structure itself). In 2003, the K42 group described how RCU could be used to create hot-pluggable implementations of operating-system functions. Later that Loading @@ -113,7 +117,6 @@ number of operating-system kernels [PaulEdwardMcKenneyPhD], a paper describing how to make RCU safe for soft-realtime applications [Sarma04c], and a paper describing SELinux performance with RCU [JamesMorris04b]. 2005 has seen further adaptation of RCU to realtime use, permitting preemption of RCU realtime critical sections [PaulMcKenney05a, PaulMcKenney05b]. Loading Documentation/RCU/checklist.txt +6 −0 Original line number Diff line number Diff line Loading @@ -177,3 +177,9 @@ over a rather long period of time, but improvements are always welcome! If you want to wait for some of these other things, you might instead need to use synchronize_irq() or synchronize_sched(). 12. Any lock acquired by an RCU callback must be acquired elsewhere with irq disabled, e.g., via spin_lock_irqsave(). Failing to disable irq on a given acquisition of that lock will result in deadlock as soon as the RCU callback happens to interrupt that acquisition's critical section. Documentation/RCU/listRCU.txt +12 −9 Original line number Diff line number Diff line Loading @@ -275,8 +275,8 @@ flag under the spinlock as follows: { struct audit_entry *e; /* Do not use the _rcu iterator here, since this is the only * deletion routine. */ /* Do not need to use the _rcu iterator here, since this * is the only deletion routine. */ list_for_each_entry(e, list, list) { if (!audit_compare_rule(rule, &e->rule)) { spin_lock(&e->lock); Loading Loading @@ -304,9 +304,12 @@ function to reject newly deleted data. Answer to Quick Quiz If the search function drops the per-entry lock before returning, then the caller will be processing stale data in any case. If it is really OK to be processing stale data, then you don't need a "deleted" flag. If processing stale data really is a problem, then you need to hold the per-entry lock across all of the code that uses the value looked up. Why does the search function need to return holding the per-entry lock for this deleted-flag technique to be helpful? If the search function drops the per-entry lock before returning, then the caller will be processing stale data in any case. If it is really OK to be processing stale data, then you don't need a "deleted" flag. If processing stale data really is a problem, then you need to hold the per-entry lock across all of the code that uses the value that was returned. Documentation/RCU/rcu.txt +5 −0 Original line number Diff line number Diff line Loading @@ -111,6 +111,11 @@ o What are all these files in this directory? You are reading it! rcuref.txt Describes how to combine use of reference counts with RCU. whatisRCU.txt Overview of how the RCU implementation works. Along Loading Documentation/RCU/rcuref.txt +15 −16 Original line number Diff line number Diff line Refcounter design for elements of lists/arrays protected by RCU. Reference-count design for elements of lists/arrays protected by RCU. Refcounting on elements of lists which are protected by traditional reader/writer spinlocks or semaphores are straight forward as in: Reference counting on elements of lists which are protected by traditional reader/writer spinlocks or semaphores are straightforward: 1. 2. add() search_and_reference() Loading @@ -28,12 +28,12 @@ release_referenced() delete() ... } If this list/array is made lock free using rcu as in changing the write_lock in add() and delete() to spin_lock and changing read_lock If this list/array is made lock free using RCU as in changing the write_lock() in add() and delete() to spin_lock and changing read_lock in search_and_reference to rcu_read_lock(), the atomic_get in search_and_reference could potentially hold reference to an element which has already been deleted from the list/array. atomic_inc_not_zero takes care of this scenario. search_and_reference should look as; has already been deleted from the list/array. Use atomic_inc_not_zero() in this scenario as follows: 1. 2. add() search_and_reference() Loading @@ -51,17 +51,16 @@ add() search_and_reference() release_referenced() delete() { { ... write_lock(&list_lock); atomic_dec(&el->rc, relfunc) ... ... delete_element } write_unlock(&list_lock); ... if (atomic_dec_and_test(&el->rc)) ... call_rcu(&el->head, el_free); delete_element ... write_unlock(&list_lock); } ... if (atomic_dec_and_test(&el->rc)) call_rcu(&el->head, el_free); ... } Sometimes, reference to the element need to be obtained in the update (write) stream. In such cases, atomic_inc_not_zero might be an overkill since the spinlock serialising list updates are held. atomic_inc is to be used in such cases. Sometimes, a reference to the element needs to be obtained in the update (write) stream. In such cases, atomic_inc_not_zero() might be overkill, since we hold the update-side spinlock. One might instead use atomic_inc() in such cases. Loading
Documentation/RCU/RTFP.txt +14 −11 Original line number Diff line number Diff line Loading @@ -90,16 +90,20 @@ at OLS. The resulting abundance of RCU patches was presented the following year [McKenney02a], and use of RCU in dcache was first described that same year [Linder02a]. Also in 2002, Michael [Michael02b,Michael02a] presented techniques that defer the destruction of data structures to simplify non-blocking synchronization (wait-free synchronization, lock-free synchronization, and obstruction-free synchronization are all examples of non-blocking synchronization). In particular, this technique eliminates locking, reduces contention, reduces memory latency for readers, and parallelizes pipeline stalls and memory latency for writers. However, these techniques still impose significant read-side overhead in the form of memory barriers. Researchers at Sun worked along similar lines in the same timeframe [HerlihyLM02,HerlihyLMS03]. Also in 2002, Michael [Michael02b,Michael02a] presented "hazard-pointer" techniques that defer the destruction of data structures to simplify non-blocking synchronization (wait-free synchronization, lock-free synchronization, and obstruction-free synchronization are all examples of non-blocking synchronization). In particular, this technique eliminates locking, reduces contention, reduces memory latency for readers, and parallelizes pipeline stalls and memory latency for writers. However, these techniques still impose significant read-side overhead in the form of memory barriers. Researchers at Sun worked along similar lines in the same timeframe [HerlihyLM02,HerlihyLMS03]. These techniques can be thought of as inside-out reference counts, where the count is represented by the number of hazard pointers referencing a given data structure (rather than the more conventional counter field within the data structure itself). In 2003, the K42 group described how RCU could be used to create hot-pluggable implementations of operating-system functions. Later that Loading @@ -113,7 +117,6 @@ number of operating-system kernels [PaulEdwardMcKenneyPhD], a paper describing how to make RCU safe for soft-realtime applications [Sarma04c], and a paper describing SELinux performance with RCU [JamesMorris04b]. 2005 has seen further adaptation of RCU to realtime use, permitting preemption of RCU realtime critical sections [PaulMcKenney05a, PaulMcKenney05b]. Loading
Documentation/RCU/checklist.txt +6 −0 Original line number Diff line number Diff line Loading @@ -177,3 +177,9 @@ over a rather long period of time, but improvements are always welcome! If you want to wait for some of these other things, you might instead need to use synchronize_irq() or synchronize_sched(). 12. Any lock acquired by an RCU callback must be acquired elsewhere with irq disabled, e.g., via spin_lock_irqsave(). Failing to disable irq on a given acquisition of that lock will result in deadlock as soon as the RCU callback happens to interrupt that acquisition's critical section.
Documentation/RCU/listRCU.txt +12 −9 Original line number Diff line number Diff line Loading @@ -275,8 +275,8 @@ flag under the spinlock as follows: { struct audit_entry *e; /* Do not use the _rcu iterator here, since this is the only * deletion routine. */ /* Do not need to use the _rcu iterator here, since this * is the only deletion routine. */ list_for_each_entry(e, list, list) { if (!audit_compare_rule(rule, &e->rule)) { spin_lock(&e->lock); Loading Loading @@ -304,9 +304,12 @@ function to reject newly deleted data. Answer to Quick Quiz If the search function drops the per-entry lock before returning, then the caller will be processing stale data in any case. If it is really OK to be processing stale data, then you don't need a "deleted" flag. If processing stale data really is a problem, then you need to hold the per-entry lock across all of the code that uses the value looked up. Why does the search function need to return holding the per-entry lock for this deleted-flag technique to be helpful? If the search function drops the per-entry lock before returning, then the caller will be processing stale data in any case. If it is really OK to be processing stale data, then you don't need a "deleted" flag. If processing stale data really is a problem, then you need to hold the per-entry lock across all of the code that uses the value that was returned.
Documentation/RCU/rcu.txt +5 −0 Original line number Diff line number Diff line Loading @@ -111,6 +111,11 @@ o What are all these files in this directory? You are reading it! rcuref.txt Describes how to combine use of reference counts with RCU. whatisRCU.txt Overview of how the RCU implementation works. Along Loading
Documentation/RCU/rcuref.txt +15 −16 Original line number Diff line number Diff line Refcounter design for elements of lists/arrays protected by RCU. Reference-count design for elements of lists/arrays protected by RCU. Refcounting on elements of lists which are protected by traditional reader/writer spinlocks or semaphores are straight forward as in: Reference counting on elements of lists which are protected by traditional reader/writer spinlocks or semaphores are straightforward: 1. 2. add() search_and_reference() Loading @@ -28,12 +28,12 @@ release_referenced() delete() ... } If this list/array is made lock free using rcu as in changing the write_lock in add() and delete() to spin_lock and changing read_lock If this list/array is made lock free using RCU as in changing the write_lock() in add() and delete() to spin_lock and changing read_lock in search_and_reference to rcu_read_lock(), the atomic_get in search_and_reference could potentially hold reference to an element which has already been deleted from the list/array. atomic_inc_not_zero takes care of this scenario. search_and_reference should look as; has already been deleted from the list/array. Use atomic_inc_not_zero() in this scenario as follows: 1. 2. add() search_and_reference() Loading @@ -51,17 +51,16 @@ add() search_and_reference() release_referenced() delete() { { ... write_lock(&list_lock); atomic_dec(&el->rc, relfunc) ... ... delete_element } write_unlock(&list_lock); ... if (atomic_dec_and_test(&el->rc)) ... call_rcu(&el->head, el_free); delete_element ... write_unlock(&list_lock); } ... if (atomic_dec_and_test(&el->rc)) call_rcu(&el->head, el_free); ... } Sometimes, reference to the element need to be obtained in the update (write) stream. In such cases, atomic_inc_not_zero might be an overkill since the spinlock serialising list updates are held. atomic_inc is to be used in such cases. Sometimes, a reference to the element needs to be obtained in the update (write) stream. In such cases, atomic_inc_not_zero() might be overkill, since we hold the update-side spinlock. One might instead use atomic_inc() in such cases.