Hi Paul, Hello Neil, Please find inline comments below on minor issues I noticed while testing "make htmldocs" on this patch. Thu, Thu, 28 Oct 2021 12:03:36 -0700 Paul E. McKenney wrote: > I could not resist the urge to do a small amount of wordsmithing, so > please check below in case I messed something up. > > Thanx, Paul > > ------------------------------------------------------------------------- > > commit 25ce7d081265ce4d29cb2a537a932813df1b7697 > Author: NeilBrown <neilb@xxxxxxx> > Date: Tue Oct 26 15:53:38 2021 +1100 > > Documentation: Add refcount analogy to What is RCU > > The reader-writer-lock analogy is a useful way to think about RCU, but > it is not always applicable. It is useful to have other analogies to > work with, and particularly to emphasise that no single analogy is emphasize > perfect. > > This patch add a "RCU as reference count" to the "what is RCU" document. > > See https://lwn.net/Articles/872559/ > > Signed-off-by: NeilBrown <neilb@xxxxxxx> > Signed-off-by: Paul E. McKenney <paulmck@xxxxxxxxxx> > > diff --git a/Documentation/RCU/whatisRCU.rst b/Documentation/RCU/whatisRCU.rst > index 17e95ab2a201..798f92c050cc 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:`...`) > > -: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,78 @@ 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 a effective reference count on everything which is protected an > +by RCU. > + > +A reference count typically does not prevent the referenced object's > +values from changing, but does prevent changes to type - particularly the -- (convention in this doc) > +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 behaviour is that, behavior (American spelling) > +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: Without an empty line here, "make htmldocs" will complain. > + - 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 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 it typically run is (???) > +using call_rcu() only after all those pointers have been changed. > + > +To see how to choose between there two analogies - of RCU as a these -- > +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. Hope this helps. With these comments addressed, please feel free to add: Reviewed-by: Akira Yokosawa <akiyks@xxxxxxxxx> Thanks, Akira > + > +.. _8_whatisRCU: > + > +8. FULL LIST OF RCU APIs > ------------------------- > > The RCU APIs are documented in docbook-format header comments in the > @@ -1035,9 +1108,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: