diff options
Diffstat (limited to 'Documentation')
-rw-r--r-- | Documentation/RCU/whatisRCU.rst | 90 |
1 files changed, 82 insertions, 8 deletions
diff --git a/Documentation/RCU/whatisRCU.rst b/Documentation/RCU/whatisRCU.rst index 17e95ab2a201..c34d2212eaca 100644 --- a/Documentation/RCU/whatisRCU.rst +++ b/Documentation/RCU/whatisRCU.rst @@ -39,9 +39,11 @@ different paths, as follows: :ref:`6. ANALOGY WITH READER-WRITER LOCKING <6_whatisRCU>` -:ref:`7. FULL LIST OF RCU APIs <7_whatisRCU>` +:ref:`7. ANALOGY WITH REFERENCE COUNTING <7_whatisRCU>` -:ref:`8. ANSWERS TO QUICK QUIZZES <8_whatisRCU>` +:ref:`8. FULL LIST OF RCU APIs <8_whatisRCU>` + +:ref:`9. ANSWERS TO QUICK QUIZZES <9_whatisRCU>` People who prefer starting with a conceptual overview should focus on Section 1, though most readers will profit by reading this section at @@ -677,7 +679,7 @@ Quick Quiz #1: occur when using this algorithm in a real-world Linux kernel? How could this deadlock be avoided? -:ref:`Answers to Quick Quiz <8_whatisRCU>` +:ref:`Answers to Quick Quiz <9_whatisRCU>` 5B. "TOY" EXAMPLE #2: CLASSIC RCU ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -732,7 +734,7 @@ Quick Quiz #2: Give an example where Classic RCU's read-side overhead is **negative**. -:ref:`Answers to Quick Quiz <8_whatisRCU>` +:ref:`Answers to Quick Quiz <9_whatisRCU>` .. _quiz_3: @@ -741,7 +743,7 @@ Quick Quiz #3: critical section, what the heck do you do in CONFIG_PREEMPT_RT, where normal spinlocks can block??? -:ref:`Answers to Quick Quiz <8_whatisRCU>` +:ref:`Answers to Quick Quiz <9_whatisRCU>` .. _6_whatisRCU: @@ -872,7 +874,79 @@ be used in place of synchronize_rcu(). .. _7_whatisRCU: -7. FULL LIST OF RCU APIs +7. ANALOGY WITH REFERENCE COUNTING +----------------------------------- + +The reader-writer analogy (illustrated by the previous section) is not +always the best way to think about using RCU. Another helpful analogy +considers RCU an effective reference count on everything which is +protected by RCU. + +A reference count typically does not prevent the referenced object's +values from changing, but does prevent changes to type -- particularly the +gross change of type that happens when that object's memory is freed and +re-allocated for some other purpose. Once a type-safe reference to the +object is obtained, some other mechanism is needed to ensure consistent +access to the data in the object. This could involve taking a spinlock, +but with RCU the typical approach is to perform reads with SMP-aware +operations such as smp_load_acquire(), to perform updates with atomic +read-modify-write operations, and to provide the necessary ordering. +RCU provides a number of support functions that embed the required +operations and ordering, such as the list_for_each_entry_rcu() macro +used in the previous section. + +A more focused view of the reference counting behavior is that, +between rcu_read_lock() and rcu_read_unlock(), any reference taken with +rcu_dereference() on a pointer marked as ``__rcu`` can be treated as +though a reference-count on that object has been temporarily increased. +This prevents the object from changing type. Exactly what this means +will depend on normal expectations of objects of that type, but it +typically includes that spinlocks can still be safely locked, normal +reference counters can be safely manipulated, and ``__rcu`` pointers +can be safely dereferenced. + +Some operations that one might expect to see on an object for +which an RCU reference is held include: + + - Copying out data that is guaranteed to be stable by the object's type. + - Using kref_get_unless_zero() or similar to get a longer-term + reference. This may fail of course. + - Acquiring a spinlock in the object, and checking if the object still + is the expected object and if so, manipulating it freely. + +The understanding that RCU provides a reference that only prevents a +change of type is particularly visible with objects allocated from a +slab cache marked ``SLAB_TYPESAFE_BY_RCU``. RCU operations may yield a +reference to an object from such a cache that has been concurrently +freed and the memory reallocated to a completely different object, +though of the same type. In this case RCU doesn't even protect the +identity of the object from changing, only its type. So the object +found may not be the one expected, but it will be one where it is safe +to take a reference or spinlock and then confirm that the identity +matches the expectations. + +With traditional reference counting -- such as that implemented by the +kref library in Linux -- there is typically code that runs when the last +reference to an object is dropped. With kref, this is the function +passed to kref_put(). When RCU is being used, such finalization code +must not be run until all ``__rcu`` pointers referencing the object have +been updated, and then a grace period has passed. Every remaining +globally visible pointer to the object must be considered to be a +potential counted reference, and the finalization code is typically run +using call_rcu() only after all those pointers have been changed. + +To see how to choose between these two analogies -- of RCU as a +reader-writer lock and RCU as a reference counting system -- it is useful +to reflect on the scale of the thing being protected. The reader-writer +lock analogy looks at larger multi-part objects such as a linked list +and shows how RCU can facilitate concurrency while elements are added +to, and removed from, the list. The reference-count analogy looks at +the individual objects and looks at how they can be accessed safely +within whatever whole they are a part of. + +.. _8_whatisRCU: + +8. FULL LIST OF RCU APIs ------------------------- The RCU APIs are documented in docbook-format header comments in the @@ -1035,9 +1109,9 @@ g. Otherwise, use RCU. Of course, this all assumes that you have determined that RCU is in fact the right tool for your job. -.. _8_whatisRCU: +.. _9_whatisRCU: -8. ANSWERS TO QUICK QUIZZES +9. ANSWERS TO QUICK QUIZZES ---------------------------- Quick Quiz #1: |