From mboxrd@z Thu Jan 1 00:00:00 1970 From: madhuparnabhowmik04 at gmail.com (Madhuparna Bhowmik) Date: Sat, 2 Nov 2019 14:01:16 +0530 Subject: [Linux-kernel-mentees] [PATCH] Doc: convert whatisRCU.txt to rst In-Reply-To: <20191030233128.14997-1-tranmanphong@gmail.com> References: <20191030233128.14997-1-tranmanphong@gmail.com> Message-ID: List-Id: I reviewed this patch, and I have the following suggestions: On Thu, Oct 31, 2019 at 5:04 AM Phong Tran wrote: > Sync the format with current state of kernel documentation. > This change base on rcu-dev branch > what changed: > - Format bullet lists > - Add literal blocks > > Signed-off-by: Phong Tran > --- > Documentation/RCU/index.rst | 1 + > .../RCU/{whatisRCU.txt => whatisRCU.rst} | 150 +++++++++++------- > 2 files changed, 90 insertions(+), 61 deletions(-) > rename Documentation/RCU/{whatisRCU.txt => whatisRCU.rst} (91%) > > diff --git a/Documentation/RCU/index.rst b/Documentation/RCU/index.rst > index 627128c230dc..b9b11481c727 100644 > --- a/Documentation/RCU/index.rst > +++ b/Documentation/RCU/index.rst > @@ -8,6 +8,7 @@ RCU concepts > :maxdepth: 3 > > arrayRCU > + whatisRCU > rcu > listRCU > NMI-RCU > diff --git a/Documentation/RCU/whatisRCU.txt > b/Documentation/RCU/whatisRCU.rst > similarity index 91% > rename from Documentation/RCU/whatisRCU.txt > rename to Documentation/RCU/whatisRCU.rst > index 58ba05c4d97f..70d0e4c21917 100644 > --- a/Documentation/RCU/whatisRCU.txt > +++ b/Documentation/RCU/whatisRCU.rst > @@ -1,15 +1,18 @@ > +.. _rcu_doc: > + > What is RCU? -- "Read, Copy, Update" > +====================================== > > Please note that the "What is RCU?" LWN series is an excellent place > to start learning about RCU: > > -1. What is RCU, Fundamentally? http://lwn.net/Articles/262464/ > -2. What is RCU? Part 2: Usage http://lwn.net/Articles/263130/ > -3. RCU part 3: the RCU API http://lwn.net/Articles/264090/ > -4. The RCU API, 2010 Edition http://lwn.net/Articles/418853/ > - 2010 Big API Table http://lwn.net/Articles/419086/ > -5. The RCU API, 2014 Edition http://lwn.net/Articles/609904/ > - 2014 Big API Table http://lwn.net/Articles/609973/ > +| 1. What is RCU, Fundamentally? http://lwn.net/Articles/262464/ > +| 2. What is RCU? Part 2: Usage http://lwn.net/Articles/263130/ > +| 3. RCU part 3: the RCU API http://lwn.net/Articles/264090/ > +| 4. The RCU API, 2010 Edition http://lwn.net/Articles/418853/ > +| 2010 Big API Table http://lwn.net/Articles/419086/ > +| 5. The RCU API, 2014 Edition http://lwn.net/Articles/609904/ > +| 2014 Big API Table http://lwn.net/Articles/609973/ > > Adding an external link here would be better. like this : `text `_ What is RCU? > @@ -51,6 +54,7 @@ never need this document anyway. ;-) > > > There is a list of topics that are covered in this documentation. Like this: 1. RCU OVERVIEW 2. WHAT IS RCU?S CORE API? 3. WHAT ARE SOME EXAMPLE USES OF CORE RCU API? 4. WHAT IF MY UPDATING THREAD CANNOT BLOCK? ... since this document is quite big adding cross-references to the above would be helpful. > 1. RCU OVERVIEW > +---------------- > > The basic idea behind RCU is to split updates into "removal" and > "reclamation" phases. The removal phase removes references to data items > @@ -118,6 +122,7 @@ Read on to learn about how RCU's API makes this easy. > > > 2. WHAT IS RCU'S CORE API? > +--------------------------- > > The core RCU API is quite small: > > @@ -166,7 +171,7 @@ synchronize_rcu() > read-side critical sections on all CPUs have completed. > Note that synchronize_rcu() will -not- necessarily wait for > any subsequent RCU read-side critical sections to complete. > - For example, consider the following sequence of events: > + For example, consider the following sequence of events:: > > CPU 0 CPU 1 CPU 2 > ----------------- ------------------------- --------------- > @@ -248,13 +253,13 @@ rcu_dereference() > > Common coding practice uses rcu_dereference() to copy an > RCU-protected pointer to a local variable, then dereferences > - this local variable, for example as follows: > + this local variable, for example as follows:: > > p = rcu_dereference(head.next); > return p->data; > > However, in this case, one could just as easily combine these > - into one statement: > + into one statement:: > > return rcu_dereference(head.next)->data; > > @@ -267,7 +272,7 @@ rcu_dereference() > > Note that the value returned by rcu_dereference() is valid > only within the enclosing RCU read-side critical section [1]. > - For example, the following is -not- legal: > + For example, the following is -not- legal:: > > rcu_read_lock(); > p = rcu_dereference(head.next); > @@ -315,6 +320,7 @@ rcu_dereference() > > The following diagram shows how each API communicates among the > reader, updater, and reclaimer. > +:: > > > rcu_assign_pointer() > @@ -377,10 +383,12 @@ for specialized uses, but are relatively uncommon. > > > 3. WHAT ARE SOME EXAMPLE USES OF CORE RCU API? > +----------------------------------------------- > > This section shows a simple use of the core RCU API to protect a > global pointer to a dynamically allocated structure. More-typical > uses of RCU may be found in listRCU.txt, arrayRCU.txt, and NMI-RCU.txt. > +:: > > struct foo { > int a; > @@ -467,13 +475,14 @@ arrayRCU.txt, and NMI-RCU.txt. > > > 4. WHAT IF MY UPDATING THREAD CANNOT BLOCK? > +-------------------------------------------- > > In the example above, foo_update_a() blocks until a grace period elapses. > This is quite simple, but in some cases one cannot afford to wait so > long -- there might be other high-priority work to be done. > > In such cases, one uses call_rcu() rather than synchronize_rcu(). > -The call_rcu() API is as follows: > +The call_rcu() API is as follows:: > > void call_rcu(struct rcu_head * head, > void (*func)(struct rcu_head *head)); > @@ -481,7 +490,7 @@ The call_rcu() API is as follows: > This function invokes func(head) after a grace period has elapsed. > This invocation might happen from either softirq or process context, > so the function is not permitted to block. The foo struct needs to > -have an rcu_head structure added, perhaps as follows: > +have an rcu_head structure added, perhaps as follows:: > > struct foo { > int a; > @@ -490,7 +499,7 @@ have an rcu_head structure added, perhaps as follows: > struct rcu_head rcu; > }; > > -The foo_update_a() function might then be written as follows: > +The foo_update_a() function might then be written as follows:: > > /* > * Create a new struct foo that is the same as the one currently > @@ -520,7 +529,7 @@ The foo_update_a() function might then be written as > follows: > call_rcu(&old_fp->rcu, foo_reclaim); > } > > -The foo_reclaim() function might appear as follows: > +The foo_reclaim() function might appear as follows:: > > void foo_reclaim(struct rcu_head *rp) > { > @@ -552,7 +561,7 @@ o Use call_rcu() -after- removing a data element > from an > > If the callback for call_rcu() is not doing anything more than calling > kfree() on the structure, you can use kfree_rcu() instead of call_rcu() > -to avoid having to write your own callback: > +to avoid having to write your own callback:: > > kfree_rcu(old_fp, rcu); > > @@ -560,6 +569,7 @@ Again, see checklist.txt for additional rules > governing the use of RCU. > > > 5. WHAT ARE SOME SIMPLE IMPLEMENTATIONS OF RCU? > +------------------------------------------------ > > One of the nice things about RCU is that it has extremely simple "toy" > implementations that are a good first step towards understanding the > @@ -591,7 +601,7 @@ you allow nested rcu_read_lock() calls, you can > deadlock. > However, it is probably the easiest implementation to relate to, so is > a good starting point. > > -It is extremely simple: > +It is extremely simple:: > > static DEFINE_RWLOCK(rcu_gp_mutex); > > @@ -614,7 +624,7 @@ It is extremely simple: > > [You can ignore rcu_assign_pointer() and rcu_dereference() without missing > much. But here are simplified versions anyway. And whatever you do, > -don't forget about them when submitting patches making use of RCU!] > +don't forget about them when submitting patches making use of RCU!]:: > > #define rcu_assign_pointer(p, v) \ > ({ \ > @@ -659,6 +669,7 @@ This section presents a "toy" RCU implementation that > is based on > on features such as hotplug CPU and the ability to run in CONFIG_PREEMPT > kernels. The definitions of rcu_dereference() and rcu_assign_pointer() > are the same as those shown in the preceding section, so they are omitted. > +:: > > void rcu_read_lock(void) { } > > @@ -707,10 +718,12 @@ Quick Quiz #3: If it is illegal to block in an RCU > read-side > > > 6. ANALOGY WITH READER-WRITER LOCKING > +-------------------------------------- > > Although RCU can be used in many different ways, a very common use of > RCU is analogous to reader-writer locking. The following unified > diff shows how closely related RCU and reader-writer locking can be. > +:: > > @@ -5,5 +5,5 @@ struct el { > int data; > @@ -762,7 +775,7 @@ diff shows how closely related RCU and reader-writer > locking can be. > return 0; > } > > -Or, for those who prefer a side-by-side listing: > +Or, for those who prefer a side-by-side listing:: > > 1 struct el { 1 struct el { > 2 struct list_head list; 2 struct list_head list; > @@ -774,40 +787,44 @@ Or, for those who prefer a side-by-side listing: > 8 rwlock_t listmutex; 8 spinlock_t listmutex; > 9 struct el head; 9 struct el head; > > - 1 int search(long key, int *result) 1 int search(long key, int > *result) > - 2 { 2 { > - 3 struct list_head *lp; 3 struct list_head *lp; > - 4 struct el *p; 4 struct el *p; > - 5 5 > - 6 read_lock(&listmutex); 6 rcu_read_lock(); > - 7 list_for_each_entry(p, head, lp) { 7 list_for_each_entry_rcu(p, > head, lp) { > - 8 if (p->key == key) { 8 if (p->key == key) { > - 9 *result = p->data; 9 *result = p->data; > -10 read_unlock(&listmutex); 10 rcu_read_unlock(); > -11 return 1; 11 return 1; > -12 } 12 } > -13 } 13 } > -14 read_unlock(&listmutex); 14 rcu_read_unlock(); > -15 return 0; 15 return 0; > -16 } 16 } > - > - 1 int delete(long key) 1 int delete(long key) > - 2 { 2 { > - 3 struct el *p; 3 struct el *p; > - 4 4 > - 5 write_lock(&listmutex); 5 spin_lock(&listmutex); > - 6 list_for_each_entry(p, head, lp) { 6 list_for_each_entry(p, head, > lp) { > - 7 if (p->key == key) { 7 if (p->key == key) { > - 8 list_del(&p->list); 8 list_del_rcu(&p->list); > - 9 write_unlock(&listmutex); 9 spin_unlock(&listmutex); > - 10 synchronize_rcu(); > -10 kfree(p); 11 kfree(p); > -11 return 1; 12 return 1; > -12 } 13 } > -13 } 14 } > -14 write_unlock(&listmutex); 15 spin_unlock(&listmutex); > -15 return 0; 16 return 0; > -16 } 17 } > +:: > + > + 1 int search(long key, int *result) 1 int search(long key, int > *result) > + 2 { 2 { > + 3 struct list_head *lp; 3 struct list_head *lp; > + 4 struct el *p; 4 struct el *p; > + 5 5 > + 6 read_lock(&listmutex); 6 rcu_read_lock(); > + 7 list_for_each_entry(p, head, lp) { 7 list_for_each_entry_rcu(p, > head, lp) { > + 8 if (p->key == key) { 8 if (p->key == key) { > + 9 *result = p->data; 9 *result = p->data; > + 10 read_unlock(&listmutex); 10 rcu_read_unlock(); > + 11 return 1; 11 return 1; > + 12 } 12 } > + 13 } 13 } > + 14 read_unlock(&listmutex); 14 rcu_read_unlock(); > + 15 return 0; 15 return 0; > + 16 } 16 } > + > +:: > + > + 1 int delete(long key) 1 int delete(long key) > + 2 { 2 { > + 3 struct el *p; 3 struct el *p; > + 4 4 > + 5 write_lock(&listmutex); 5 spin_lock(&listmutex); > + 6 list_for_each_entry(p, head, lp) { 6 list_for_each_entry(p, head, > lp) { > + 7 if (p->key == key) { 7 if (p->key == key) { > + 8 list_del(&p->list); 8 list_del_rcu(&p->list); > + 9 write_unlock(&listmutex); 9 spin_unlock(&listmutex); > + 10 synchronize_rcu(); > + 10 kfree(p); 11 kfree(p); > + 11 return 1; 12 return 1; > + 12 } 13 } > + 13 } 14 } > + 14 write_unlock(&listmutex); 15 spin_unlock(&listmutex); > + 15 return 0; 16 return 0; > + 16 } 17 } > > Either way, the differences are quite small. Read-side locking moves > to rcu_read_lock() and rcu_read_unlock, update-side locking moves from > @@ -827,13 +844,14 @@ be used in place of synchronize_rcu(). > > > 7. FULL LIST OF RCU APIs > +------------------------- > > The RCU APIs are documented in docbook-format header comments in the > Linux-kernel source code, but it helps to have a full list of the > APIs, since there does not appear to be a way to categorize them > in docbook. Here is the list, by category. > > -RCU list traversal: > +RCU list traversal:: > > list_entry_rcu > list_first_entry_rcu > @@ -854,7 +872,7 @@ RCU list traversal: > hlist_bl_first_rcu > hlist_bl_for_each_entry_rcu > > -RCU pointer/list update: > +RCU pointer/list udate:: > > rcu_assign_pointer > list_add_rcu > @@ -876,7 +894,9 @@ RCU pointer/list update: > hlist_bl_del_rcu > hlist_bl_set_first_rcu > > -RCU: Critical sections Grace period Barrier > +RCU:: > + > + Critical sections Grace period Barrier > > rcu_read_lock synchronize_net rcu_barrier > rcu_read_unlock synchronize_rcu > @@ -885,7 +905,9 @@ RCU: Critical sections Grace period > Barrier > rcu_dereference_check kfree_rcu > rcu_dereference_protected > > -bh: Critical sections Grace period Barrier > +bh:: > + > + Critical sections Grace period Barrier > > rcu_read_lock_bh call_rcu rcu_barrier > rcu_read_unlock_bh synchronize_rcu > @@ -896,7 +918,9 @@ bh: Critical sections Grace period > Barrier > rcu_dereference_bh_protected > rcu_read_lock_bh_held > > -sched: Critical sections Grace period Barrier > +sched:: > + > + Critical sections Grace period Barrier > > rcu_read_lock_sched call_rcu rcu_barrier > rcu_read_unlock_sched synchronize_rcu > @@ -910,7 +934,9 @@ sched: Critical sections Grace period > Barrier > rcu_read_lock_sched_held > > > -SRCU: Critical sections Grace period Barrier > +SRCU:: > + > + Critical sections Grace period Barrier > > srcu_read_lock call_srcu srcu_barrier > srcu_read_unlock synchronize_srcu > @@ -918,13 +944,14 @@ SRCU: Critical sections Grace period > Barrier > srcu_dereference_check > srcu_read_lock_held > > -SRCU: Initialization/cleanup > +SRCU: Initialization/cleanup:: > + > DEFINE_SRCU > DEFINE_STATIC_SRCU > init_srcu_struct > cleanup_srcu_struct > > -All: lockdep-checked RCU-protected pointer access > +All: lockdep-checked RCU-protected pointer access:: > > rcu_access_pointer > rcu_dereference_raw > @@ -976,6 +1003,7 @@ the right tool for your job. > > > 8. ANSWERS TO QUICK QUIZZES > +---------------------------- > > Quick Quiz #1: Why is this argument naive? How could a deadlock > occur when using this algorithm in a real-world Linux > Here, the formatting is not proper. In the rst file, the question should be added in the next line after Quick Quiz #1. Currently, half of the question appears in bold and the rest half does not. Also, as followed in all the documents there should be a cross-reference to the answer to this question. As this document is quite big having references would be helpful. The same applies to all other quick quiz questions in this document and in the Answers section as well the questions do not appear properly, half in bold text and half not bold. Apart from this, the other added changes look good! Thank you Madhuparna -- > 2.20.1 > > _______________________________________________ > Linux-kernel-mentees mailing list > Linux-kernel-mentees at lists.linuxfoundation.org > https://lists.linuxfoundation.org/mailman/listinfo/linux-kernel-mentees > ? -------------- next part -------------- An HTML attachment was scrubbed... URL: From mboxrd@z Thu Jan 1 00:00:00 1970 From: madhuparnabhowmik04@gmail.com (Madhuparna Bhowmik) Date: Sat, 2 Nov 2019 14:01:16 +0530 Subject: [Linux-kernel-mentees] [PATCH] Doc: convert whatisRCU.txt to rst In-Reply-To: <20191030233128.14997-1-tranmanphong@gmail.com> References: <20191030233128.14997-1-tranmanphong@gmail.com> Message-ID: List-Id: Content-Type: text/plain; charset="UTF-8" Message-ID: <20191102083116.9yXHNM67yvSGnaG2OwUqIjdD8QQeZL2VHuDJTOTtfYs@z> I reviewed this patch, and I have the following suggestions: On Thu, Oct 31, 2019 at 5:04 AM Phong Tran wrote: > Sync the format with current state of kernel documentation. > This change base on rcu-dev branch > what changed: > - Format bullet lists > - Add literal blocks > > Signed-off-by: Phong Tran > --- > Documentation/RCU/index.rst | 1 + > .../RCU/{whatisRCU.txt => whatisRCU.rst} | 150 +++++++++++------- > 2 files changed, 90 insertions(+), 61 deletions(-) > rename Documentation/RCU/{whatisRCU.txt => whatisRCU.rst} (91%) > > diff --git a/Documentation/RCU/index.rst b/Documentation/RCU/index.rst > index 627128c230dc..b9b11481c727 100644 > --- a/Documentation/RCU/index.rst > +++ b/Documentation/RCU/index.rst > @@ -8,6 +8,7 @@ RCU concepts > :maxdepth: 3 > > arrayRCU > + whatisRCU > rcu > listRCU > NMI-RCU > diff --git a/Documentation/RCU/whatisRCU.txt > b/Documentation/RCU/whatisRCU.rst > similarity index 91% > rename from Documentation/RCU/whatisRCU.txt > rename to Documentation/RCU/whatisRCU.rst > index 58ba05c4d97f..70d0e4c21917 100644 > --- a/Documentation/RCU/whatisRCU.txt > +++ b/Documentation/RCU/whatisRCU.rst > @@ -1,15 +1,18 @@ > +.. _rcu_doc: > + > What is RCU? -- "Read, Copy, Update" > +====================================== > > Please note that the "What is RCU?" LWN series is an excellent place > to start learning about RCU: > > -1. What is RCU, Fundamentally? http://lwn.net/Articles/262464/ > -2. What is RCU? Part 2: Usage http://lwn.net/Articles/263130/ > -3. RCU part 3: the RCU API http://lwn.net/Articles/264090/ > -4. The RCU API, 2010 Edition http://lwn.net/Articles/418853/ > - 2010 Big API Table http://lwn.net/Articles/419086/ > -5. The RCU API, 2014 Edition http://lwn.net/Articles/609904/ > - 2014 Big API Table http://lwn.net/Articles/609973/ > +| 1. What is RCU, Fundamentally? http://lwn.net/Articles/262464/ > +| 2. What is RCU? Part 2: Usage http://lwn.net/Articles/263130/ > +| 3. RCU part 3: the RCU API http://lwn.net/Articles/264090/ > +| 4. The RCU API, 2010 Edition http://lwn.net/Articles/418853/ > +| 2010 Big API Table http://lwn.net/Articles/419086/ > +| 5. The RCU API, 2014 Edition http://lwn.net/Articles/609904/ > +| 2014 Big API Table http://lwn.net/Articles/609973/ > > Adding an external link here would be better. like this : `text `_ What is RCU? > @@ -51,6 +54,7 @@ never need this document anyway. ;-) > > > There is a list of topics that are covered in this documentation. Like this: 1. RCU OVERVIEW 2. WHAT IS RCU?S CORE API? 3. WHAT ARE SOME EXAMPLE USES OF CORE RCU API? 4. WHAT IF MY UPDATING THREAD CANNOT BLOCK? ... since this document is quite big adding cross-references to the above would be helpful. > 1. RCU OVERVIEW > +---------------- > > The basic idea behind RCU is to split updates into "removal" and > "reclamation" phases. The removal phase removes references to data items > @@ -118,6 +122,7 @@ Read on to learn about how RCU's API makes this easy. > > > 2. WHAT IS RCU'S CORE API? > +--------------------------- > > The core RCU API is quite small: > > @@ -166,7 +171,7 @@ synchronize_rcu() > read-side critical sections on all CPUs have completed. > Note that synchronize_rcu() will -not- necessarily wait for > any subsequent RCU read-side critical sections to complete. > - For example, consider the following sequence of events: > + For example, consider the following sequence of events:: > > CPU 0 CPU 1 CPU 2 > ----------------- ------------------------- --------------- > @@ -248,13 +253,13 @@ rcu_dereference() > > Common coding practice uses rcu_dereference() to copy an > RCU-protected pointer to a local variable, then dereferences > - this local variable, for example as follows: > + this local variable, for example as follows:: > > p = rcu_dereference(head.next); > return p->data; > > However, in this case, one could just as easily combine these > - into one statement: > + into one statement:: > > return rcu_dereference(head.next)->data; > > @@ -267,7 +272,7 @@ rcu_dereference() > > Note that the value returned by rcu_dereference() is valid > only within the enclosing RCU read-side critical section [1]. > - For example, the following is -not- legal: > + For example, the following is -not- legal:: > > rcu_read_lock(); > p = rcu_dereference(head.next); > @@ -315,6 +320,7 @@ rcu_dereference() > > The following diagram shows how each API communicates among the > reader, updater, and reclaimer. > +:: > > > rcu_assign_pointer() > @@ -377,10 +383,12 @@ for specialized uses, but are relatively uncommon. > > > 3. WHAT ARE SOME EXAMPLE USES OF CORE RCU API? > +----------------------------------------------- > > This section shows a simple use of the core RCU API to protect a > global pointer to a dynamically allocated structure. More-typical > uses of RCU may be found in listRCU.txt, arrayRCU.txt, and NMI-RCU.txt. > +:: > > struct foo { > int a; > @@ -467,13 +475,14 @@ arrayRCU.txt, and NMI-RCU.txt. > > > 4. WHAT IF MY UPDATING THREAD CANNOT BLOCK? > +-------------------------------------------- > > In the example above, foo_update_a() blocks until a grace period elapses. > This is quite simple, but in some cases one cannot afford to wait so > long -- there might be other high-priority work to be done. > > In such cases, one uses call_rcu() rather than synchronize_rcu(). > -The call_rcu() API is as follows: > +The call_rcu() API is as follows:: > > void call_rcu(struct rcu_head * head, > void (*func)(struct rcu_head *head)); > @@ -481,7 +490,7 @@ The call_rcu() API is as follows: > This function invokes func(head) after a grace period has elapsed. > This invocation might happen from either softirq or process context, > so the function is not permitted to block. The foo struct needs to > -have an rcu_head structure added, perhaps as follows: > +have an rcu_head structure added, perhaps as follows:: > > struct foo { > int a; > @@ -490,7 +499,7 @@ have an rcu_head structure added, perhaps as follows: > struct rcu_head rcu; > }; > > -The foo_update_a() function might then be written as follows: > +The foo_update_a() function might then be written as follows:: > > /* > * Create a new struct foo that is the same as the one currently > @@ -520,7 +529,7 @@ The foo_update_a() function might then be written as > follows: > call_rcu(&old_fp->rcu, foo_reclaim); > } > > -The foo_reclaim() function might appear as follows: > +The foo_reclaim() function might appear as follows:: > > void foo_reclaim(struct rcu_head *rp) > { > @@ -552,7 +561,7 @@ o Use call_rcu() -after- removing a data element > from an > > If the callback for call_rcu() is not doing anything more than calling > kfree() on the structure, you can use kfree_rcu() instead of call_rcu() > -to avoid having to write your own callback: > +to avoid having to write your own callback:: > > kfree_rcu(old_fp, rcu); > > @@ -560,6 +569,7 @@ Again, see checklist.txt for additional rules > governing the use of RCU. > > > 5. WHAT ARE SOME SIMPLE IMPLEMENTATIONS OF RCU? > +------------------------------------------------ > > One of the nice things about RCU is that it has extremely simple "toy" > implementations that are a good first step towards understanding the > @@ -591,7 +601,7 @@ you allow nested rcu_read_lock() calls, you can > deadlock. > However, it is probably the easiest implementation to relate to, so is > a good starting point. > > -It is extremely simple: > +It is extremely simple:: > > static DEFINE_RWLOCK(rcu_gp_mutex); > > @@ -614,7 +624,7 @@ It is extremely simple: > > [You can ignore rcu_assign_pointer() and rcu_dereference() without missing > much. But here are simplified versions anyway. And whatever you do, > -don't forget about them when submitting patches making use of RCU!] > +don't forget about them when submitting patches making use of RCU!]:: > > #define rcu_assign_pointer(p, v) \ > ({ \ > @@ -659,6 +669,7 @@ This section presents a "toy" RCU implementation that > is based on > on features such as hotplug CPU and the ability to run in CONFIG_PREEMPT > kernels. The definitions of rcu_dereference() and rcu_assign_pointer() > are the same as those shown in the preceding section, so they are omitted. > +:: > > void rcu_read_lock(void) { } > > @@ -707,10 +718,12 @@ Quick Quiz #3: If it is illegal to block in an RCU > read-side > > > 6. ANALOGY WITH READER-WRITER LOCKING > +-------------------------------------- > > Although RCU can be used in many different ways, a very common use of > RCU is analogous to reader-writer locking. The following unified > diff shows how closely related RCU and reader-writer locking can be. > +:: > > @@ -5,5 +5,5 @@ struct el { > int data; > @@ -762,7 +775,7 @@ diff shows how closely related RCU and reader-writer > locking can be. > return 0; > } > > -Or, for those who prefer a side-by-side listing: > +Or, for those who prefer a side-by-side listing:: > > 1 struct el { 1 struct el { > 2 struct list_head list; 2 struct list_head list; > @@ -774,40 +787,44 @@ Or, for those who prefer a side-by-side listing: > 8 rwlock_t listmutex; 8 spinlock_t listmutex; > 9 struct el head; 9 struct el head; > > - 1 int search(long key, int *result) 1 int search(long key, int > *result) > - 2 { 2 { > - 3 struct list_head *lp; 3 struct list_head *lp; > - 4 struct el *p; 4 struct el *p; > - 5 5 > - 6 read_lock(&listmutex); 6 rcu_read_lock(); > - 7 list_for_each_entry(p, head, lp) { 7 list_for_each_entry_rcu(p, > head, lp) { > - 8 if (p->key == key) { 8 if (p->key == key) { > - 9 *result = p->data; 9 *result = p->data; > -10 read_unlock(&listmutex); 10 rcu_read_unlock(); > -11 return 1; 11 return 1; > -12 } 12 } > -13 } 13 } > -14 read_unlock(&listmutex); 14 rcu_read_unlock(); > -15 return 0; 15 return 0; > -16 } 16 } > - > - 1 int delete(long key) 1 int delete(long key) > - 2 { 2 { > - 3 struct el *p; 3 struct el *p; > - 4 4 > - 5 write_lock(&listmutex); 5 spin_lock(&listmutex); > - 6 list_for_each_entry(p, head, lp) { 6 list_for_each_entry(p, head, > lp) { > - 7 if (p->key == key) { 7 if (p->key == key) { > - 8 list_del(&p->list); 8 list_del_rcu(&p->list); > - 9 write_unlock(&listmutex); 9 spin_unlock(&listmutex); > - 10 synchronize_rcu(); > -10 kfree(p); 11 kfree(p); > -11 return 1; 12 return 1; > -12 } 13 } > -13 } 14 } > -14 write_unlock(&listmutex); 15 spin_unlock(&listmutex); > -15 return 0; 16 return 0; > -16 } 17 } > +:: > + > + 1 int search(long key, int *result) 1 int search(long key, int > *result) > + 2 { 2 { > + 3 struct list_head *lp; 3 struct list_head *lp; > + 4 struct el *p; 4 struct el *p; > + 5 5 > + 6 read_lock(&listmutex); 6 rcu_read_lock(); > + 7 list_for_each_entry(p, head, lp) { 7 list_for_each_entry_rcu(p, > head, lp) { > + 8 if (p->key == key) { 8 if (p->key == key) { > + 9 *result = p->data; 9 *result = p->data; > + 10 read_unlock(&listmutex); 10 rcu_read_unlock(); > + 11 return 1; 11 return 1; > + 12 } 12 } > + 13 } 13 } > + 14 read_unlock(&listmutex); 14 rcu_read_unlock(); > + 15 return 0; 15 return 0; > + 16 } 16 } > + > +:: > + > + 1 int delete(long key) 1 int delete(long key) > + 2 { 2 { > + 3 struct el *p; 3 struct el *p; > + 4 4 > + 5 write_lock(&listmutex); 5 spin_lock(&listmutex); > + 6 list_for_each_entry(p, head, lp) { 6 list_for_each_entry(p, head, > lp) { > + 7 if (p->key == key) { 7 if (p->key == key) { > + 8 list_del(&p->list); 8 list_del_rcu(&p->list); > + 9 write_unlock(&listmutex); 9 spin_unlock(&listmutex); > + 10 synchronize_rcu(); > + 10 kfree(p); 11 kfree(p); > + 11 return 1; 12 return 1; > + 12 } 13 } > + 13 } 14 } > + 14 write_unlock(&listmutex); 15 spin_unlock(&listmutex); > + 15 return 0; 16 return 0; > + 16 } 17 } > > Either way, the differences are quite small. Read-side locking moves > to rcu_read_lock() and rcu_read_unlock, update-side locking moves from > @@ -827,13 +844,14 @@ be used in place of synchronize_rcu(). > > > 7. FULL LIST OF RCU APIs > +------------------------- > > The RCU APIs are documented in docbook-format header comments in the > Linux-kernel source code, but it helps to have a full list of the > APIs, since there does not appear to be a way to categorize them > in docbook. Here is the list, by category. > > -RCU list traversal: > +RCU list traversal:: > > list_entry_rcu > list_first_entry_rcu > @@ -854,7 +872,7 @@ RCU list traversal: > hlist_bl_first_rcu > hlist_bl_for_each_entry_rcu > > -RCU pointer/list update: > +RCU pointer/list udate:: > > rcu_assign_pointer > list_add_rcu > @@ -876,7 +894,9 @@ RCU pointer/list update: > hlist_bl_del_rcu > hlist_bl_set_first_rcu > > -RCU: Critical sections Grace period Barrier > +RCU:: > + > + Critical sections Grace period Barrier > > rcu_read_lock synchronize_net rcu_barrier > rcu_read_unlock synchronize_rcu > @@ -885,7 +905,9 @@ RCU: Critical sections Grace period > Barrier > rcu_dereference_check kfree_rcu > rcu_dereference_protected > > -bh: Critical sections Grace period Barrier > +bh:: > + > + Critical sections Grace period Barrier > > rcu_read_lock_bh call_rcu rcu_barrier > rcu_read_unlock_bh synchronize_rcu > @@ -896,7 +918,9 @@ bh: Critical sections Grace period > Barrier > rcu_dereference_bh_protected > rcu_read_lock_bh_held > > -sched: Critical sections Grace period Barrier > +sched:: > + > + Critical sections Grace period Barrier > > rcu_read_lock_sched call_rcu rcu_barrier > rcu_read_unlock_sched synchronize_rcu > @@ -910,7 +934,9 @@ sched: Critical sections Grace period > Barrier > rcu_read_lock_sched_held > > > -SRCU: Critical sections Grace period Barrier > +SRCU:: > + > + Critical sections Grace period Barrier > > srcu_read_lock call_srcu srcu_barrier > srcu_read_unlock synchronize_srcu > @@ -918,13 +944,14 @@ SRCU: Critical sections Grace period > Barrier > srcu_dereference_check > srcu_read_lock_held > > -SRCU: Initialization/cleanup > +SRCU: Initialization/cleanup:: > + > DEFINE_SRCU > DEFINE_STATIC_SRCU > init_srcu_struct > cleanup_srcu_struct > > -All: lockdep-checked RCU-protected pointer access > +All: lockdep-checked RCU-protected pointer access:: > > rcu_access_pointer > rcu_dereference_raw > @@ -976,6 +1003,7 @@ the right tool for your job. > > > 8. ANSWERS TO QUICK QUIZZES > +---------------------------- > > Quick Quiz #1: Why is this argument naive? How could a deadlock > occur when using this algorithm in a real-world Linux > Here, the formatting is not proper. In the rst file, the question should be added in the next line after Quick Quiz #1. Currently, half of the question appears in bold and the rest half does not. Also, as followed in all the documents there should be a cross-reference to the answer to this question. As this document is quite big having references would be helpful. The same applies to all other quick quiz questions in this document and in the Answers section as well the questions do not appear properly, half in bold text and half not bold. Apart from this, the other added changes look good! Thank you Madhuparna -- > 2.20.1 > > _______________________________________________ > Linux-kernel-mentees mailing list > Linux-kernel-mentees at lists.linuxfoundation.org > https://lists.linuxfoundation.org/mailman/listinfo/linux-kernel-mentees > ? -------------- next part -------------- An HTML attachment was scrubbed... URL: From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.4 required=3.0 tests=DKIM_ADSP_CUSTOM_MED, DKIM_INVALID,DKIM_SIGNED,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,HTML_FONT_LOW_CONTRAST,HTML_MESSAGE, INCLUDES_PATCH,MAILING_LIST_MULTI,MIME_HTML_MOSTLY,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F29E2CA9EC7 for ; Sat, 2 Nov 2019 08:31:33 +0000 (UTC) Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id ADC652085B for ; Sat, 2 Nov 2019 08:31:33 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Vi1B8XAl" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org ADC652085B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=linux-kernel-mentees-bounces@lists.linuxfoundation.org Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 6DAEEE36; Sat, 2 Nov 2019 08:31:33 +0000 (UTC) Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id EE2F0E35 for ; Sat, 2 Nov 2019 08:31:32 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-oi1-f196.google.com (mail-oi1-f196.google.com [209.85.167.196]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 2B52863D for ; Sat, 2 Nov 2019 08:31:30 +0000 (UTC) Received: by mail-oi1-f196.google.com with SMTP id m193so10151904oig.0 for ; Sat, 02 Nov 2019 01:31:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=mNCNsyudeR0UWipX3UKRbdYacm4SSv2kHoBO44yGmhM=; b=Vi1B8XAlig58iYGUn1XbK/nSm9qLU4aao0/lscEB+QCG1pCxDStBbf/UHnqOJ51cGW tFVc9XREi+k0sW/tt6iE/xt0JjFajDhtQsga6iQzvxqo03b5s7x9N0SZupKZRkN9uQOo fHqW4fHAhh39XQGsDHV0Dd7+uV7x3S+pHILnkJlaHKTguFmUS81Bg4g2Y3hkOPP5dyB7 7d7lxfAIwvxJM0gXG0ncFeSrxejhneiMWHDj7aWcpajwHB2TkE+3of+XigTBjgD6iB4O pZFm0dU2LrstB1f7GhS/1WMYzS6IhaKKEmES9W79RSgi2dySaXLPhEpdzihWmKIBxRbr EHhg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=mNCNsyudeR0UWipX3UKRbdYacm4SSv2kHoBO44yGmhM=; b=b7FVoxA8O2Q0DJqadebimFXKvcmWnkT8rN3b/IyLXIY8i8tEaFydfr5S5pkZT42vEY mDOoCp5oM6KC4B0rMtHwTpdIA25WVwgge7U1FcooZmYZ8VNRaH6/1PYhwAYzTNuUNsfh AwfZonFyl2oIFTxGn7KYvlYudbXkUWw5yvNHe2lNW8EKrespbnt3CBSX5jInpGnMcvKa knf05W+cQB+nEgEFBVAadHfUvTLBV8ornYK5JsK77/iP3z12yE4tM1+YcsukFN6jyiTr BTN9TOQKXQ2qH0p4IVvwc4S9eh19KiOtrfYSSWb8pakHvLwpz49YdLn2wtSfgHQ8Dbh/ 5Y9A== X-Gm-Message-State: APjAAAVtARtN06dbtmBBYzAuSj1vxs4cBprmmJYxRK38y3zp6phiuX1B JYser7o7r+S+IOEdWc1udXMLtlIpkcT5HsHRc6I= X-Google-Smtp-Source: APXvYqyeODdmId0M3j20ZjUlTzgqJYbOmMNZNvz56QaZ4hfzBfDddIzEZmx9vSFQ7Ga8G61c3ram4OjKEIUcDADLP6c= X-Received: by 2002:aca:210e:: with SMTP id 14mr587884oiz.109.1572683488781; Sat, 02 Nov 2019 01:31:28 -0700 (PDT) MIME-Version: 1.0 References: <20191030233128.14997-1-tranmanphong@gmail.com> In-Reply-To: <20191030233128.14997-1-tranmanphong@gmail.com> From: Madhuparna Bhowmik Date: Sat, 2 Nov 2019 14:01:16 +0530 Message-ID: To: Phong Tran Cc: paulmck@kernel.org, corbet@lwn.net, linux-doc@vger.kernel.org, jiangshanlai@gmail.com, josh@joshtriplett.org, rostedt@goodmis.org, linux-kernel@vger.kernel.org, rcu@vger.kernel.org, mathieu.desnoyers@efficios.com, Joel Fernandes , linux-kernel-mentees@lists.linuxfoundation.org Subject: Re: [Linux-kernel-mentees] [PATCH] Doc: convert whatisRCU.txt to rst X-BeenThere: linux-kernel-mentees@lists.linuxfoundation.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: multipart/mixed; boundary="===============4845696162972177543==" Sender: linux-kernel-mentees-bounces@lists.linuxfoundation.org Errors-To: linux-kernel-mentees-bounces@lists.linuxfoundation.org Message-ID: <20191102083116.YbFobIkxZPa0ie_lsCUlI_b93oVTYlLzUTecDKXbRQA@z> --===============4845696162972177543== Content-Type: multipart/alternative; boundary="000000000000b16bb8059658e84b" --000000000000b16bb8059658e84b Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable I reviewed this patch, and I have the following suggestions: On Thu, Oct 31, 2019 at 5:04 AM Phong Tran wrote: > Sync the format with current state of kernel documentation. > This change base on rcu-dev branch > what changed: > - Format bullet lists > - Add literal blocks > > Signed-off-by: Phong Tran > --- > Documentation/RCU/index.rst | 1 + > .../RCU/{whatisRCU.txt =3D> whatisRCU.rst} | 150 +++++++++++------- > 2 files changed, 90 insertions(+), 61 deletions(-) > rename Documentation/RCU/{whatisRCU.txt =3D> whatisRCU.rst} (91%) > > diff --git a/Documentation/RCU/index.rst b/Documentation/RCU/index.rst > index 627128c230dc..b9b11481c727 100644 > --- a/Documentation/RCU/index.rst > +++ b/Documentation/RCU/index.rst > @@ -8,6 +8,7 @@ RCU concepts > :maxdepth: 3 > > arrayRCU > + whatisRCU > rcu > listRCU > NMI-RCU > diff --git a/Documentation/RCU/whatisRCU.txt > b/Documentation/RCU/whatisRCU.rst > similarity index 91% > rename from Documentation/RCU/whatisRCU.txt > rename to Documentation/RCU/whatisRCU.rst > index 58ba05c4d97f..70d0e4c21917 100644 > --- a/Documentation/RCU/whatisRCU.txt > +++ b/Documentation/RCU/whatisRCU.rst > @@ -1,15 +1,18 @@ > +.. _rcu_doc: > + > What is RCU? -- "Read, Copy, Update" > +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > > Please note that the "What is RCU?" LWN series is an excellent place > to start learning about RCU: > > -1. What is RCU, Fundamentally? http://lwn.net/Articles/262464/ > -2. What is RCU? Part 2: Usage http://lwn.net/Articles/263130/ > -3. RCU part 3: the RCU API http://lwn.net/Articles/264090/ > -4. The RCU API, 2010 Edition http://lwn.net/Articles/418853/ > - 2010 Big API Table http://lwn.net/Articles/419086/ > -5. The RCU API, 2014 Edition http://lwn.net/Articles/609904/ > - 2014 Big API Table http://lwn.net/Articles/609973/ > +| 1. What is RCU, Fundamentally? http://lwn.net/Articles/262464/ > +| 2. What is RCU? Part 2: Usage http://lwn.net/Articles/263130/ > +| 3. RCU part 3: the RCU API http://lwn.net/Articles/264090/ > +| 4. The RCU API, 2010 Edition http://lwn.net/Articles/418853/ > +| 2010 Big API Table http://lwn.net/Articles/419086/ > +| 5. The RCU API, 2014 Edition http://lwn.net/Articles/609904/ > +| 2014 Big API Table http://lwn.net/Articles/609973/ > > Adding an external link here would be better. like this : `text `_ What is RCU? > @@ -51,6 +54,7 @@ never need this document anyway. ;-) > > > There is a list of topics that are covered in this documentation. Like this: 1. RCU OVERVIEW 2. WHAT IS RCU=E2=80=99S CORE API? 3. WHAT ARE SOME EXAMPLE USES OF CORE RCU API? 4. WHAT IF MY UPDATING THREAD CANNOT BLOCK? ... since this document is quite big adding cross-references to the above would be helpful. > 1. RCU OVERVIEW > +---------------- > > The basic idea behind RCU is to split updates into "removal" and > "reclamation" phases. The removal phase removes references to data item= s > @@ -118,6 +122,7 @@ Read on to learn about how RCU's API makes this easy. > > > 2. WHAT IS RCU'S CORE API? > +--------------------------- > > The core RCU API is quite small: > > @@ -166,7 +171,7 @@ synchronize_rcu() > read-side critical sections on all CPUs have completed. > Note that synchronize_rcu() will -not- necessarily wait for > any subsequent RCU read-side critical sections to complete. > - For example, consider the following sequence of events: > + For example, consider the following sequence of events:: > > CPU 0 CPU 1 CPU 2 > ----------------- ------------------------- --------------- > @@ -248,13 +253,13 @@ rcu_dereference() > > Common coding practice uses rcu_dereference() to copy an > RCU-protected pointer to a local variable, then dereferences > - this local variable, for example as follows: > + this local variable, for example as follows:: > > p =3D rcu_dereference(head.next); > return p->data; > > However, in this case, one could just as easily combine these > - into one statement: > + into one statement:: > > return rcu_dereference(head.next)->data; > > @@ -267,7 +272,7 @@ rcu_dereference() > > Note that the value returned by rcu_dereference() is valid > only within the enclosing RCU read-side critical section [1]. > - For example, the following is -not- legal: > + For example, the following is -not- legal:: > > rcu_read_lock(); > p =3D rcu_dereference(head.next); > @@ -315,6 +320,7 @@ rcu_dereference() > > The following diagram shows how each API communicates among the > reader, updater, and reclaimer. > +:: > > > rcu_assign_pointer() > @@ -377,10 +383,12 @@ for specialized uses, but are relatively uncommon. > > > 3. WHAT ARE SOME EXAMPLE USES OF CORE RCU API? > +----------------------------------------------- > > This section shows a simple use of the core RCU API to protect a > global pointer to a dynamically allocated structure. More-typical > uses of RCU may be found in listRCU.txt, arrayRCU.txt, and NMI-RCU.txt. > +:: > > struct foo { > int a; > @@ -467,13 +475,14 @@ arrayRCU.txt, and NMI-RCU.txt. > > > 4. WHAT IF MY UPDATING THREAD CANNOT BLOCK? > +-------------------------------------------- > > In the example above, foo_update_a() blocks until a grace period elapses= . > This is quite simple, but in some cases one cannot afford to wait so > long -- there might be other high-priority work to be done. > > In such cases, one uses call_rcu() rather than synchronize_rcu(). > -The call_rcu() API is as follows: > +The call_rcu() API is as follows:: > > void call_rcu(struct rcu_head * head, > void (*func)(struct rcu_head *head)); > @@ -481,7 +490,7 @@ The call_rcu() API is as follows: > This function invokes func(head) after a grace period has elapsed. > This invocation might happen from either softirq or process context, > so the function is not permitted to block. The foo struct needs to > -have an rcu_head structure added, perhaps as follows: > +have an rcu_head structure added, perhaps as follows:: > > struct foo { > int a; > @@ -490,7 +499,7 @@ have an rcu_head structure added, perhaps as follows: > struct rcu_head rcu; > }; > > -The foo_update_a() function might then be written as follows: > +The foo_update_a() function might then be written as follows:: > > /* > * Create a new struct foo that is the same as the one currently > @@ -520,7 +529,7 @@ The foo_update_a() function might then be written as > follows: > call_rcu(&old_fp->rcu, foo_reclaim); > } > > -The foo_reclaim() function might appear as follows: > +The foo_reclaim() function might appear as follows:: > > void foo_reclaim(struct rcu_head *rp) > { > @@ -552,7 +561,7 @@ o Use call_rcu() -after- removing a data element > from an > > If the callback for call_rcu() is not doing anything more than calling > kfree() on the structure, you can use kfree_rcu() instead of call_rcu() > -to avoid having to write your own callback: > +to avoid having to write your own callback:: > > kfree_rcu(old_fp, rcu); > > @@ -560,6 +569,7 @@ Again, see checklist.txt for additional rules > governing the use of RCU. > > > 5. WHAT ARE SOME SIMPLE IMPLEMENTATIONS OF RCU? > +------------------------------------------------ > > One of the nice things about RCU is that it has extremely simple "toy" > implementations that are a good first step towards understanding the > @@ -591,7 +601,7 @@ you allow nested rcu_read_lock() calls, you can > deadlock. > However, it is probably the easiest implementation to relate to, so is > a good starting point. > > -It is extremely simple: > +It is extremely simple:: > > static DEFINE_RWLOCK(rcu_gp_mutex); > > @@ -614,7 +624,7 @@ It is extremely simple: > > [You can ignore rcu_assign_pointer() and rcu_dereference() without missi= ng > much. But here are simplified versions anyway. And whatever you do, > -don't forget about them when submitting patches making use of RCU!] > +don't forget about them when submitting patches making use of RCU!]:: > > #define rcu_assign_pointer(p, v) \ > ({ \ > @@ -659,6 +669,7 @@ This section presents a "toy" RCU implementation that > is based on > on features such as hotplug CPU and the ability to run in CONFIG_PREEMPT > kernels. The definitions of rcu_dereference() and rcu_assign_pointer() > are the same as those shown in the preceding section, so they are omitte= d. > +:: > > void rcu_read_lock(void) { } > > @@ -707,10 +718,12 @@ Quick Quiz #3: If it is illegal to block in an RCU > read-side > > > 6. ANALOGY WITH READER-WRITER LOCKING > +-------------------------------------- > > Although RCU can be used in many different ways, a very common use of > RCU is analogous to reader-writer locking. The following unified > diff shows how closely related RCU and reader-writer locking can be. > +:: > > @@ -5,5 +5,5 @@ struct el { > int data; > @@ -762,7 +775,7 @@ diff shows how closely related RCU and reader-writer > locking can be. > return 0; > } > > -Or, for those who prefer a side-by-side listing: > +Or, for those who prefer a side-by-side listing:: > > 1 struct el { 1 struct el { > 2 struct list_head list; 2 struct list_head list; > @@ -774,40 +787,44 @@ Or, for those who prefer a side-by-side listing: > 8 rwlock_t listmutex; 8 spinlock_t listmutex; > 9 struct el head; 9 struct el head; > > - 1 int search(long key, int *result) 1 int search(long key, int > *result) > - 2 { 2 { > - 3 struct list_head *lp; 3 struct list_head *lp; > - 4 struct el *p; 4 struct el *p; > - 5 5 > - 6 read_lock(&listmutex); 6 rcu_read_lock(); > - 7 list_for_each_entry(p, head, lp) { 7 list_for_each_entry_rcu(p, > head, lp) { > - 8 if (p->key =3D=3D key) { 8 if (p->key =3D=3D key)= { > - 9 *result =3D p->data; 9 *result =3D p->data; > -10 read_unlock(&listmutex); 10 rcu_read_unlock(); > -11 return 1; 11 return 1; > -12 } 12 } > -13 } 13 } > -14 read_unlock(&listmutex); 14 rcu_read_unlock(); > -15 return 0; 15 return 0; > -16 } 16 } > - > - 1 int delete(long key) 1 int delete(long key) > - 2 { 2 { > - 3 struct el *p; 3 struct el *p; > - 4 4 > - 5 write_lock(&listmutex); 5 spin_lock(&listmutex); > - 6 list_for_each_entry(p, head, lp) { 6 list_for_each_entry(p, head, > lp) { > - 7 if (p->key =3D=3D key) { 7 if (p->key =3D=3D key)= { > - 8 list_del(&p->list); 8 list_del_rcu(&p->list); > - 9 write_unlock(&listmutex); 9 spin_unlock(&listmutex); > - 10 synchronize_rcu(); > -10 kfree(p); 11 kfree(p); > -11 return 1; 12 return 1; > -12 } 13 } > -13 } 14 } > -14 write_unlock(&listmutex); 15 spin_unlock(&listmutex); > -15 return 0; 16 return 0; > -16 } 17 } > +:: > + > + 1 int search(long key, int *result) 1 int search(long key, int > *result) > + 2 { 2 { > + 3 struct list_head *lp; 3 struct list_head *lp; > + 4 struct el *p; 4 struct el *p; > + 5 5 > + 6 read_lock(&listmutex); 6 rcu_read_lock(); > + 7 list_for_each_entry(p, head, lp) { 7 list_for_each_entry_rcu(p, > head, lp) { > + 8 if (p->key =3D=3D key) { 8 if (p->key =3D=3D key= ) { > + 9 *result =3D p->data; 9 *result =3D p->data; > + 10 read_unlock(&listmutex); 10 rcu_read_unlock(); > + 11 return 1; 11 return 1; > + 12 } 12 } > + 13 } 13 } > + 14 read_unlock(&listmutex); 14 rcu_read_unlock(); > + 15 return 0; 15 return 0; > + 16 } 16 } > + > +:: > + > + 1 int delete(long key) 1 int delete(long key) > + 2 { 2 { > + 3 struct el *p; 3 struct el *p; > + 4 4 > + 5 write_lock(&listmutex); 5 spin_lock(&listmutex); > + 6 list_for_each_entry(p, head, lp) { 6 list_for_each_entry(p, head= , > lp) { > + 7 if (p->key =3D=3D key) { 7 if (p->key =3D=3D key= ) { > + 8 list_del(&p->list); 8 list_del_rcu(&p->list); > + 9 write_unlock(&listmutex); 9 spin_unlock(&listmutex)= ; > + 10 synchronize_rcu(); > + 10 kfree(p); 11 kfree(p); > + 11 return 1; 12 return 1; > + 12 } 13 } > + 13 } 14 } > + 14 write_unlock(&listmutex); 15 spin_unlock(&listmutex); > + 15 return 0; 16 return 0; > + 16 } 17 } > > Either way, the differences are quite small. Read-side locking moves > to rcu_read_lock() and rcu_read_unlock, update-side locking moves from > @@ -827,13 +844,14 @@ be used in place of synchronize_rcu(). > > > 7. FULL LIST OF RCU APIs > +------------------------- > > The RCU APIs are documented in docbook-format header comments in the > Linux-kernel source code, but it helps to have a full list of the > APIs, since there does not appear to be a way to categorize them > in docbook. Here is the list, by category. > > -RCU list traversal: > +RCU list traversal:: > > list_entry_rcu > list_first_entry_rcu > @@ -854,7 +872,7 @@ RCU list traversal: > hlist_bl_first_rcu > hlist_bl_for_each_entry_rcu > > -RCU pointer/list update: > +RCU pointer/list udate:: > > rcu_assign_pointer > list_add_rcu > @@ -876,7 +894,9 @@ RCU pointer/list update: > hlist_bl_del_rcu > hlist_bl_set_first_rcu > > -RCU: Critical sections Grace period Barrier > +RCU:: > + > + Critical sections Grace period Barrier > > rcu_read_lock synchronize_net rcu_barrier > rcu_read_unlock synchronize_rcu > @@ -885,7 +905,9 @@ RCU: Critical sections Grace period > Barrier > rcu_dereference_check kfree_rcu > rcu_dereference_protected > > -bh: Critical sections Grace period Barrier > +bh:: > + > + Critical sections Grace period Barrier > > rcu_read_lock_bh call_rcu rcu_barrier > rcu_read_unlock_bh synchronize_rcu > @@ -896,7 +918,9 @@ bh: Critical sections Grace period > Barrier > rcu_dereference_bh_protected > rcu_read_lock_bh_held > > -sched: Critical sections Grace period Barrier > +sched:: > + > + Critical sections Grace period Barrier > > rcu_read_lock_sched call_rcu rcu_barrier > rcu_read_unlock_sched synchronize_rcu > @@ -910,7 +934,9 @@ sched: Critical sections Grace period > Barrier > rcu_read_lock_sched_held > > > -SRCU: Critical sections Grace period Barrier > +SRCU:: > + > + Critical sections Grace period Barrier > > srcu_read_lock call_srcu srcu_barrier > srcu_read_unlock synchronize_srcu > @@ -918,13 +944,14 @@ SRCU: Critical sections Grace period > Barrier > srcu_dereference_check > srcu_read_lock_held > > -SRCU: Initialization/cleanup > +SRCU: Initialization/cleanup:: > + > DEFINE_SRCU > DEFINE_STATIC_SRCU > init_srcu_struct > cleanup_srcu_struct > > -All: lockdep-checked RCU-protected pointer access > +All: lockdep-checked RCU-protected pointer access:: > > rcu_access_pointer > rcu_dereference_raw > @@ -976,6 +1003,7 @@ the right tool for your job. > > > 8. ANSWERS TO QUICK QUIZZES > +---------------------------- > > Quick Quiz #1: Why is this argument naive? How could a deadlock > occur when using this algorithm in a real-world Linux > Here, the formatting is not proper. In the rst file, the question should be added in the next line after Quick Quiz #1. Currently, half of the question appears in bold and the rest half does not. Also, as followed in all the documents there should be a cross-reference to the answer to this question. As this document is quite big having references would be helpful. The same applies to all other quick quiz questions in this document and in the Answers section as well the questions do not appear properly, half in bold text and half not bold. Apart from this, the other added changes look good! Thank you Madhuparna --=20 > 2.20.1 > > _______________________________________________ > Linux-kernel-mentees mailing list > Linux-kernel-mentees@lists.linuxfoundation.org > https://lists.linuxfoundation.org/mailman/listinfo/linux-kernel-mentees > =E1=90=A7 --000000000000b16bb8059658e84b Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
I reviewed this patch, and I have the following sugge= stions:

On Thu, Oct 31, 2019 at 5:04 AM Phong Tran <tranmanphong@gmail.com> wrote:
Sync the format with current sta= te of kernel documentation.
This change base on rcu-dev branch
what changed:
- Format bullet lists
- Add literal blocks

Signed-off-by: Phong Tran <tranmanphong@gmail.com>
---
=C2=A0Documentation/RCU/index.rst=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0|=C2=A0 =C2=A01 +
=C2=A0.../RCU/{whatisRCU.txt =3D> whatisRCU.rst}=C2=A0 =C2=A0 =C2=A0 | 1= 50 +++++++++++-------
=C2=A02 files changed, 90 insertions(+), 61 deletions(-)
=C2=A0rename Documentation/RCU/{whatisRCU.txt =3D> whatisRCU.rst} (91%)<= br>
diff --git a/Documentation/RCU/index.rst b/Documentation/RCU/index.rst
index 627128c230dc..b9b11481c727 100644
--- a/Documentation/RCU/index.rst
+++ b/Documentation/RCU/index.rst
@@ -8,6 +8,7 @@ RCU concepts
=C2=A0 =C2=A0 :maxdepth: 3

=C2=A0 =C2=A0 arrayRCU
+=C2=A0 =C2=A0whatisRCU
=C2=A0 =C2=A0 rcu
=C2=A0 =C2=A0 listRCU
=C2=A0 =C2=A0 NMI-RCU
diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.= rst
similarity index 91%
rename from Documentation/RCU/whatisRCU.txt
rename to Documentation/RCU/whatisRCU.rst
index 58ba05c4d97f..70d0e4c21917 100644
--- a/Documentation/RCU/whatisRCU.txt
+++ b/Documentation/RCU/whatisRCU.rst
@@ -1,15 +1,18 @@
+.. _rcu_doc:
+
=C2=A0What is RCU?=C2=A0 --=C2=A0 "Read, Copy, Update"
+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

=C2=A0Please note that the "What is RCU?" LWN series is an excell= ent place
=C2=A0to start learning about RCU:

-1.=C2=A0 =C2=A0 =C2=A0What is RCU, Fundamentally?=C2=A0 http://lwn.n= et/Articles/262464/
-2.=C2=A0 =C2=A0 =C2=A0What is RCU? Part 2: Usage=C2=A0 =C2=A0http://= lwn.net/Articles/263130/
-3.=C2=A0 =C2=A0 =C2=A0RCU part 3: the RCU API=C2=A0 =C2=A0 =C2=A0 h= ttp://lwn.net/Articles/264090/
-4.=C2=A0 =C2=A0 =C2=A0The RCU API, 2010 Edition=C2=A0 =C2=A0 http://= lwn.net/Articles/418853/
-=C2=A0 =C2=A0 =C2=A0 =C2=A02010 Big API Table=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0http://lwn.net/Articles/419086/
-5.=C2=A0 =C2=A0 =C2=A0The RCU API, 2014 Edition=C2=A0 =C2=A0 http://= lwn.net/Articles/609904/
-=C2=A0 =C2=A0 =C2=A0 =C2=A02014 Big API Table=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0http://lwn.net/Articles/609973/
+| 1.=C2=A0 =C2=A0What is RCU, Fundamentally?=C2=A0 http://lwn.net/Ar= ticles/262464/
+| 2.=C2=A0 =C2=A0What is RCU? Part 2: Usage=C2=A0 =C2=A0http://lwn.n= et/Articles/263130/
+| 3.=C2=A0 =C2=A0RCU part 3: the RCU API=C2=A0 =C2=A0 =C2=A0 http://= lwn.net/Articles/264090/
+| 4.=C2=A0 =C2=A0The RCU API, 2010 Edition=C2=A0 =C2=A0 http://lwn.n= et/Articles/418853/
+|=C2=A0 =C2=A0 =C2=A0 2010 Big API Table=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0http://lwn.net/Articles/419086/
+| 5.=C2=A0 =C2=A0The RCU API, 2014 Edition=C2=A0 =C2=A0 http://lwn.n= et/Articles/609904/
+|=C2=A0 =C2=A0 =C2=A0 2014 Big API Table=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0http://lwn.net/Articles/609973/

<= br>
Adding an external link here would be better.
like = this :=C2=A0=C2=A0`text=C2=A0<link URL>`_=C2=A0

=C2=A0What is RCU?
@@ -51,6 +54,7 @@ never need this document anyway.=C2=A0 ;-)



There is a list of topics that are cov= ered in this documentation.
Like this:

1= . RCU OVERVIEW
2. WHAT IS RCU=E2=80=99S CORE API?
3. WHAT ARE SOME EX= AMPLE USES OF CORE RCU API?
4. WHAT IF MY UPDATING THREAD CANNOT BLOCK?<= br>
...

=C2=A0since this document is qui= te big adding cross-references to the above would be helpful.
=C2= =A0
=C2=A01.=C2=A0 RCU OVERVIEW
+----------------

=C2=A0The basic idea behind RCU is to split updates into "removal"= ; and
=C2=A0"reclamation" phases.=C2=A0 The removal phase removes refer= ences to data items
@@ -118,6 +122,7 @@ Read on to learn about how RCU's API makes this eas= y.


=C2=A02.=C2=A0 WHAT IS RCU'S CORE API?
+---------------------------

=C2=A0The core RCU API is quite small:

@@ -166,7 +171,7 @@ synchronize_rcu()
=C2=A0 =C2=A0 =C2=A0 =C2=A0 read-side critical sections on all CPUs have co= mpleted.
=C2=A0 =C2=A0 =C2=A0 =C2=A0 Note that synchronize_rcu() will -not- necessar= ily wait for
=C2=A0 =C2=A0 =C2=A0 =C2=A0 any subsequent RCU read-side critical sections = to complete.
-=C2=A0 =C2=A0 =C2=A0 =C2=A0For example, consider the following sequence of= events:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0For example, consider the following sequence of= events::

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0CPU 0=C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 CPU 1=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0CPU 2
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0----------------- ---------= ---------------- ---------------
@@ -248,13 +253,13 @@ rcu_dereference()

=C2=A0 =C2=A0 =C2=A0 =C2=A0 Common coding practice uses rcu_dereference() t= o copy an
=C2=A0 =C2=A0 =C2=A0 =C2=A0 RCU-protected pointer to a local variable, then= dereferences
-=C2=A0 =C2=A0 =C2=A0 =C2=A0this local variable, for example as follows: +=C2=A0 =C2=A0 =C2=A0 =C2=A0this local variable, for example as follows::
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 p =3D rcu_dereferen= ce(head.next);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return p->data;<= br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 However, in this case, one could just as easily= combine these
-=C2=A0 =C2=A0 =C2=A0 =C2=A0into one statement:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0into one statement::

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return rcu_derefere= nce(head.next)->data;

@@ -267,7 +272,7 @@ rcu_dereference()

=C2=A0 =C2=A0 =C2=A0 =C2=A0 Note that the value returned by rcu_dereference= () is valid
=C2=A0 =C2=A0 =C2=A0 =C2=A0 only within the enclosing RCU read-side critica= l section [1].
-=C2=A0 =C2=A0 =C2=A0 =C2=A0For example, the following is -not- legal:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0For example, the following is -not- legal::

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 rcu_read_lock(); =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 p =3D rcu_dereferen= ce(head.next);
@@ -315,6 +320,7 @@ rcu_dereference()

=C2=A0The following diagram shows how each API communicates among the
=C2=A0reader, updater, and reclaimer.
+::


=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 rcu_assign_pointer()
@@ -377,10 +383,12 @@ for specialized uses, but are relatively uncommon.

=C2=A03.=C2=A0 WHAT ARE SOME EXAMPLE USES OF CORE RCU API?
+-----------------------------------------------

=C2=A0This section shows a simple use of the core RCU API to protect a
=C2=A0global pointer to a dynamically allocated structure.=C2=A0 More-typic= al
=C2=A0uses of RCU may be found in listRCU.txt, arrayRCU.txt, and NMI-RCU.tx= t.
+::

=C2=A0 =C2=A0 =C2=A0 =C2=A0 struct foo {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 int a;
@@ -467,13 +475,14 @@ arrayRCU.txt, and NMI-RCU.txt.


=C2=A04.=C2=A0 WHAT IF MY UPDATING THREAD CANNOT BLOCK?
+--------------------------------------------

=C2=A0In the example above, foo_update_a() blocks until a grace period elap= ses.
=C2=A0This is quite simple, but in some cases one cannot afford to wait so<= br> =C2=A0long -- there might be other high-priority work to be done.

=C2=A0In such cases, one uses call_rcu() rather than synchronize_rcu().
-The call_rcu() API is as follows:
+The call_rcu() API is as follows::

=C2=A0 =C2=A0 =C2=A0 =C2=A0 void call_rcu(struct rcu_head * head,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 void (*func)(struct rcu_head *head));
@@ -481,7 +490,7 @@ The call_rcu() API is as follows:
=C2=A0This function invokes func(head) after a grace period has elapsed. =C2=A0This invocation might happen from either softirq or process context,<= br> =C2=A0so the function is not permitted to block.=C2=A0 The foo struct needs= to
-have an rcu_head structure added, perhaps as follows:
+have an rcu_head structure added, perhaps as follows::

=C2=A0 =C2=A0 =C2=A0 =C2=A0 struct foo {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 int a;
@@ -490,7 +499,7 @@ have an rcu_head structure added, perhaps as follows: =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 struct rcu_head rcu= ;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 };

-The foo_update_a() function might then be written as follows:
+The foo_update_a() function might then be written as follows::

=C2=A0 =C2=A0 =C2=A0 =C2=A0 /*
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0* Create a new struct foo that is the sam= e as the one currently
@@ -520,7 +529,7 @@ The foo_update_a() function might then be written as fo= llows:
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 call_rcu(&old_f= p->rcu, foo_reclaim);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

-The foo_reclaim() function might appear as follows:
+The foo_reclaim() function might appear as follows::

=C2=A0 =C2=A0 =C2=A0 =C2=A0 void foo_reclaim(struct rcu_head *rp)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 {
@@ -552,7 +561,7 @@ o=C2=A0 =C2=A0Use call_rcu() -after- removing a data el= ement from an

=C2=A0If the callback for call_rcu() is not doing anything more than callin= g
=C2=A0kfree() on the structure, you can use kfree_rcu() instead of call_rcu= ()
-to avoid having to write your own callback:
+to avoid having to write your own callback::

=C2=A0 =C2=A0 =C2=A0 =C2=A0 kfree_rcu(old_fp, rcu);

@@ -560,6 +569,7 @@ Again, see checklist.txt for additional rules governing= the use of RCU.


=C2=A05.=C2=A0 WHAT ARE SOME SIMPLE IMPLEMENTATIONS OF RCU?
+------------------------------------------------

=C2=A0One of the nice things about RCU is that it has extremely simple &quo= t;toy"
=C2=A0implementations that are a good first step towards understanding the<= br> @@ -591,7 +601,7 @@ you allow nested rcu_read_lock() calls, you can deadloc= k.
=C2=A0However, it is probably the easiest implementation to relate to, so i= s
=C2=A0a good starting point.

-It is extremely simple:
+It is extremely simple::

=C2=A0 =C2=A0 =C2=A0 =C2=A0 static DEFINE_RWLOCK(rcu_gp_mutex);

@@ -614,7 +624,7 @@ It is extremely simple:

=C2=A0[You can ignore rcu_assign_pointer() and rcu_dereference() without mi= ssing
=C2=A0much.=C2=A0 But here are simplified versions anyway.=C2=A0 And whatev= er you do,
-don't forget about them when submitting patches making use of RCU!] +don't forget about them when submitting patches making use of RCU!]::<= br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 #define rcu_assign_pointer(p, v) \
=C2=A0 =C2=A0 =C2=A0 =C2=A0 ({ \
@@ -659,6 +669,7 @@ This section presents a "toy" RCU implementat= ion that is based on
=C2=A0on features such as hotplug CPU and the ability to run in CONFIG_PREE= MPT
=C2=A0kernels.=C2=A0 The definitions of rcu_dereference() and rcu_assign_po= inter()
=C2=A0are the same as those shown in the preceding section, so they are omi= tted.
+::

=C2=A0 =C2=A0 =C2=A0 =C2=A0 void rcu_read_lock(void) { }

@@ -707,10 +718,12 @@ Quick Quiz #3:=C2=A0 If it is illegal to block in an = RCU read-side


=C2=A06.=C2=A0 ANALOGY WITH READER-WRITER LOCKING
+--------------------------------------

=C2=A0Although RCU can be used in many different ways, a very common use of=
=C2=A0RCU is analogous to reader-writer locking.=C2=A0 The following unifie= d
=C2=A0diff shows how closely related RCU and reader-writer locking can be.<= br> +::

=C2=A0 =C2=A0 =C2=A0 =C2=A0 @@ -5,5 +5,5 @@ struct el {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 int data;
@@ -762,7 +775,7 @@ diff shows how closely related RCU and reader-writer lo= cking can be.
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return 0;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}

-Or, for those who prefer a side-by-side listing:
+Or, for those who prefer a side-by-side listing::

=C2=A0 1 struct el {=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 1 struct el {
=C2=A0 2=C2=A0 =C2=A0struct list_head list;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A02=C2=A0 =C2=A0struct list_head list;
@@ -774,40 +787,44 @@ Or, for those who prefer a side-by-side listing:
=C2=A0 8 rwlock_t listmutex;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 8 spinlock_t listmutex;
=C2=A0 9 struct el head;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 9 struct el head;

- 1 int search(long key, int *result)=C2=A0 =C2=A0 1 int search(long key, i= nt *result)
- 2 {=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 2 {
- 3=C2=A0 =C2=A0struct list_head *lp;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 3=C2=A0 =C2=A0struct list_head *lp;
- 4=C2=A0 =C2=A0struct el *p;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 4=C2=A0 =C2=A0struct el *p;
- 5=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 5
- 6=C2=A0 =C2=A0read_lock(&listmutex);=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A06=C2=A0 =C2=A0rcu_read_lock();
- 7=C2=A0 =C2=A0list_for_each_entry(p, head, lp) { 7=C2=A0 =C2=A0list_for_e= ach_entry_rcu(p, head, lp) {
- 8=C2=A0 =C2=A0 =C2=A0if (p->key =3D=3D key) {=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A08=C2=A0 =C2=A0 =C2=A0if (p->key =3D=3D key) { - 9=C2=A0 =C2=A0 =C2=A0 =C2=A0*result =3D p->data;=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A09=C2=A0 =C2=A0 =C2=A0 =C2=A0*result =3D p->da= ta;
-10=C2=A0 =C2=A0 =C2=A0 =C2=A0read_unlock(&listmutex);=C2=A0 =C2=A0 =C2= =A0 10=C2=A0 =C2=A0 =C2=A0 =C2=A0rcu_read_unlock();
-11=C2=A0 =C2=A0 =C2=A0 =C2=A0return 1;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A011=C2=A0 =C2=A0 =C2=A0 =C2=A0retur= n 1;
-12=C2=A0 =C2=A0 =C2=A0}=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A012=C2=A0 =C2= =A0 =C2=A0}
-13=C2=A0 =C2=A0}=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A013=C2=A0 =C2= =A0}
-14=C2=A0 =C2=A0read_unlock(&listmutex);=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 14=C2=A0 =C2=A0rcu_read_unlock();
-15=C2=A0 =C2=A0return 0;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A015=C2=A0 =C2=A0return 0;
-16 }=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A016 }
-
- 1 int delete(long key)=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A01 int delete(long key)
- 2 {=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 2 {
- 3=C2=A0 =C2=A0struct el *p;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 3=C2=A0 =C2=A0struct el *p;
- 4=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 4
- 5=C2=A0 =C2=A0write_lock(&listmutex);=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 5=C2=A0 =C2=A0spin_lock(&listmutex);
- 6=C2=A0 =C2=A0list_for_each_entry(p, head, lp) { 6=C2=A0 =C2=A0list_for_e= ach_entry(p, head, lp) {
- 7=C2=A0 =C2=A0 =C2=A0if (p->key =3D=3D key) {=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A07=C2=A0 =C2=A0 =C2=A0if (p->key =3D=3D key) { - 8=C2=A0 =C2=A0 =C2=A0 =C2=A0list_del(&p->list);=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 8=C2=A0 =C2=A0 =C2=A0 =C2=A0list_del_rcu(&p-&g= t;list);
- 9=C2=A0 =C2=A0 =C2=A0 =C2=A0write_unlock(&listmutex);=C2=A0 =C2=A0 = =C2=A0 9=C2=A0 =C2=A0 =C2=A0 =C2=A0spin_unlock(&listmutex);
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A010=C2=A0 = =C2=A0 =C2=A0 =C2=A0synchronize_rcu();
-10=C2=A0 =C2=A0 =C2=A0 =C2=A0kfree(p);=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A011=C2=A0 =C2=A0 =C2=A0 =C2=A0kfree= (p);
-11=C2=A0 =C2=A0 =C2=A0 =C2=A0return 1;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A012=C2=A0 =C2=A0 =C2=A0 =C2=A0retur= n 1;
-12=C2=A0 =C2=A0 =C2=A0}=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A013=C2=A0 =C2= =A0 =C2=A0}
-13=C2=A0 =C2=A0}=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A014=C2=A0 =C2= =A0}
-14=C2=A0 =C2=A0write_unlock(&listmutex);=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A015=C2=A0 =C2=A0spin_unlock(&listmutex);
-15=C2=A0 =C2=A0return 0;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A016=C2=A0 =C2=A0return 0;
-16 }=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A017 }
+::
+
+=C2=A0 1 int search(long key, int *result)=C2=A0 =C2=A0 1 int search(long = key, int *result)
+=C2=A0 2 {=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 2 {
+=C2=A0 3=C2=A0 =C2=A0struct list_head *lp;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 3=C2=A0 =C2=A0struct list_head *lp;
+=C2=A0 4=C2=A0 =C2=A0struct el *p;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 4=C2=A0 =C2=A0struct el *p;
+=C2=A0 5=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 5
+=C2=A0 6=C2=A0 =C2=A0read_lock(&listmutex);=C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A06=C2=A0 =C2=A0rcu_read_lock();
+=C2=A0 7=C2=A0 =C2=A0list_for_each_entry(p, head, lp) { 7=C2=A0 =C2=A0list= _for_each_entry_rcu(p, head, lp) {
+=C2=A0 8=C2=A0 =C2=A0 =C2=A0if (p->key =3D=3D key) {=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A08=C2=A0 =C2=A0 =C2=A0if (p->key =3D=3D ke= y) {
+=C2=A0 9=C2=A0 =C2=A0 =C2=A0 =C2=A0*result =3D p->data;=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A09=C2=A0 =C2=A0 =C2=A0 =C2=A0*result =3D p= ->data;
+ 10=C2=A0 =C2=A0 =C2=A0 =C2=A0read_unlock(&listmutex);=C2=A0 =C2=A0 = =C2=A0 10=C2=A0 =C2=A0 =C2=A0 =C2=A0rcu_read_unlock();
+ 11=C2=A0 =C2=A0 =C2=A0 =C2=A0return 1;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A011=C2=A0 =C2=A0 =C2=A0 =C2=A0retur= n 1;
+ 12=C2=A0 =C2=A0 =C2=A0}=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A012=C2=A0 =C2= =A0 =C2=A0}
+ 13=C2=A0 =C2=A0}=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A013=C2=A0 =C2= =A0}
+ 14=C2=A0 =C2=A0read_unlock(&listmutex);=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 14=C2=A0 =C2=A0rcu_read_unlock();
+ 15=C2=A0 =C2=A0return 0;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A015=C2=A0 =C2=A0return 0;
+ 16 }=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A016 }
+
+::
+
+=C2=A0 1 int delete(long key)=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A01 int delete(long key)
+=C2=A0 2 {=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 2 {
+=C2=A0 3=C2=A0 =C2=A0struct el *p;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 3=C2=A0 =C2=A0struct el *p;
+=C2=A0 4=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 4
+=C2=A0 5=C2=A0 =C2=A0write_lock(&listmutex);=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 5=C2=A0 =C2=A0spin_lock(&listmutex);
+=C2=A0 6=C2=A0 =C2=A0list_for_each_entry(p, head, lp) { 6=C2=A0 =C2=A0list= _for_each_entry(p, head, lp) {
+=C2=A0 7=C2=A0 =C2=A0 =C2=A0if (p->key =3D=3D key) {=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A07=C2=A0 =C2=A0 =C2=A0if (p->key =3D=3D ke= y) {
+=C2=A0 8=C2=A0 =C2=A0 =C2=A0 =C2=A0list_del(&p->list);=C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 8=C2=A0 =C2=A0 =C2=A0 =C2=A0list_del_rcu(&= p->list);
+=C2=A0 9=C2=A0 =C2=A0 =C2=A0 =C2=A0write_unlock(&listmutex);=C2=A0 =C2= =A0 =C2=A0 9=C2=A0 =C2=A0 =C2=A0 =C2=A0spin_unlock(&listmutex);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 10=C2=A0= =C2=A0 =C2=A0 =C2=A0synchronize_rcu();
+ 10=C2=A0 =C2=A0 =C2=A0 =C2=A0kfree(p);=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A011=C2=A0 =C2=A0 =C2=A0 =C2=A0kfree= (p);
+ 11=C2=A0 =C2=A0 =C2=A0 =C2=A0return 1;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A012=C2=A0 =C2=A0 =C2=A0 =C2=A0retur= n 1;
+ 12=C2=A0 =C2=A0 =C2=A0}=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A013=C2=A0 =C2= =A0 =C2=A0}
+ 13=C2=A0 =C2=A0}=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A014=C2=A0 =C2= =A0}
+ 14=C2=A0 =C2=A0write_unlock(&listmutex);=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A015=C2=A0 =C2=A0spin_unlock(&listmutex);
+ 15=C2=A0 =C2=A0return 0;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A016=C2=A0 =C2=A0return 0;
+ 16 }=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A017 }

=C2=A0Either way, the differences are quite small.=C2=A0 Read-side locking = moves
=C2=A0to rcu_read_lock() and rcu_read_unlock, update-side locking moves fro= m
@@ -827,13 +844,14 @@ be used in place of synchronize_rcu().


=C2=A07.=C2=A0 FULL LIST OF RCU APIs
+-------------------------

=C2=A0The RCU APIs are documented in docbook-format header comments in the<= br> =C2=A0Linux-kernel source code, but it helps to have a full list of the
=C2=A0APIs, since there does not appear to be a way to categorize them
=C2=A0in docbook.=C2=A0 Here is the list, by category.

-RCU list traversal:
+RCU list traversal::

=C2=A0 =C2=A0 =C2=A0 =C2=A0 list_entry_rcu
=C2=A0 =C2=A0 =C2=A0 =C2=A0 list_first_entry_rcu
@@ -854,7 +872,7 @@ RCU list traversal:
=C2=A0 =C2=A0 =C2=A0 =C2=A0 hlist_bl_first_rcu
=C2=A0 =C2=A0 =C2=A0 =C2=A0 hlist_bl_for_each_entry_rcu

-RCU pointer/list update:
+RCU pointer/list udate::

=C2=A0 =C2=A0 =C2=A0 =C2=A0 rcu_assign_pointer
=C2=A0 =C2=A0 =C2=A0 =C2=A0 list_add_rcu
@@ -876,7 +894,9 @@ RCU pointer/list update:
=C2=A0 =C2=A0 =C2=A0 =C2=A0 hlist_bl_del_rcu
=C2=A0 =C2=A0 =C2=A0 =C2=A0 hlist_bl_set_first_rcu

-RCU:=C2=A0 =C2=A0Critical sections=C2=A0 =C2=A0 =C2=A0 =C2=A0Grace period= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Barrier
+RCU::
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0Critical sections=C2=A0 =C2=A0 =C2=A0 =C2=A0Gra= ce period=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Barrier

=C2=A0 =C2=A0 =C2=A0 =C2=A0 rcu_read_lock=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0synchronize_net=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0rcu_barrier
=C2=A0 =C2=A0 =C2=A0 =C2=A0 rcu_read_unlock=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0synchronize_rcu
@@ -885,7 +905,9 @@ RCU:=C2=A0 =C2=A0 =C2=A0 =C2=A0 Critical sections=C2=A0= =C2=A0 =C2=A0 =C2=A0Grace period=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = Barrier
=C2=A0 =C2=A0 =C2=A0 =C2=A0 rcu_dereference_check=C2=A0 =C2=A0kfree_rcu
=C2=A0 =C2=A0 =C2=A0 =C2=A0 rcu_dereference_protected

-bh:=C2=A0 =C2=A0 Critical sections=C2=A0 =C2=A0 =C2=A0 =C2=A0Grace period= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Barrier
+bh::
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0Critical sections=C2=A0 =C2=A0 =C2=A0 =C2=A0Gra= ce period=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Barrier

=C2=A0 =C2=A0 =C2=A0 =C2=A0 rcu_read_lock_bh=C2=A0 =C2=A0 =C2=A0 =C2=A0 cal= l_rcu=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 rcu_barrier =C2=A0 =C2=A0 =C2=A0 =C2=A0 rcu_read_unlock_bh=C2=A0 =C2=A0 =C2=A0 synchron= ize_rcu
@@ -896,7 +918,9 @@ bh: Critical sections=C2=A0 =C2=A0 =C2=A0 =C2=A0Grace p= eriod=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Barrier
=C2=A0 =C2=A0 =C2=A0 =C2=A0 rcu_dereference_bh_protected
=C2=A0 =C2=A0 =C2=A0 =C2=A0 rcu_read_lock_bh_held

-sched: Critical sections=C2=A0 =C2=A0 =C2=A0 =C2=A0Grace period=C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Barrier
+sched::
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0Critical sections=C2=A0 =C2=A0 =C2=A0 =C2=A0Gra= ce period=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Barrier

=C2=A0 =C2=A0 =C2=A0 =C2=A0 rcu_read_lock_sched=C2=A0 =C2=A0 =C2=A0call_rcu= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 rcu_barrier
=C2=A0 =C2=A0 =C2=A0 =C2=A0 rcu_read_unlock_sched=C2=A0 =C2=A0synchronize_r= cu
@@ -910,7 +934,9 @@ sched:=C2=A0 =C2=A0 =C2=A0 Critical sections=C2=A0 =C2= =A0 =C2=A0 =C2=A0Grace period=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Barr= ier
=C2=A0 =C2=A0 =C2=A0 =C2=A0 rcu_read_lock_sched_held


-SRCU:=C2=A0 Critical sections=C2=A0 =C2=A0 =C2=A0 =C2=A0Grace period=C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Barrier
+SRCU::
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0Critical sections=C2=A0 =C2=A0 =C2=A0 =C2=A0Gra= ce period=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Barrier

=C2=A0 =C2=A0 =C2=A0 =C2=A0 srcu_read_lock=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 call_srcu=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0srcu_ba= rrier
=C2=A0 =C2=A0 =C2=A0 =C2=A0 srcu_read_unlock=C2=A0 =C2=A0 =C2=A0 =C2=A0 syn= chronize_srcu
@@ -918,13 +944,14 @@ SRCU:=C2=A0 =C2=A0 =C2=A0Critical sections=C2=A0 =C2= =A0 =C2=A0 =C2=A0Grace period=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Barr= ier
=C2=A0 =C2=A0 =C2=A0 =C2=A0 srcu_dereference_check
=C2=A0 =C2=A0 =C2=A0 =C2=A0 srcu_read_lock_held

-SRCU:=C2=A0 Initialization/cleanup
+SRCU: Initialization/cleanup::
+
=C2=A0 =C2=A0 =C2=A0 =C2=A0 DEFINE_SRCU
=C2=A0 =C2=A0 =C2=A0 =C2=A0 DEFINE_STATIC_SRCU
=C2=A0 =C2=A0 =C2=A0 =C2=A0 init_srcu_struct
=C2=A0 =C2=A0 =C2=A0 =C2=A0 cleanup_srcu_struct

-All:=C2=A0 lockdep-checked RCU-protected pointer access
+All: lockdep-checked RCU-protected pointer access::

=C2=A0 =C2=A0 =C2=A0 =C2=A0 rcu_access_pointer
=C2=A0 =C2=A0 =C2=A0 =C2=A0 rcu_dereference_raw
@@ -976,6 +1003,7 @@ the right tool for your job.


=C2=A08.=C2=A0 ANSWERS TO QUICK QUIZZES
+----------------------------

=C2=A0Quick Quiz #1: Why is this argument naive?=C2=A0 How could a deadlock=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 occur when using th= is algorithm in a real-world Linux

Here= , the formatting is not proper. In the rst file, the question should be add= ed in the next line after Quick Quiz #1. Currently, half of the question ap= pears in bold and the rest half does not.
Also, as followed in al= l the documents there should be a cross-reference to the answer to this que= stion. As this document is quite big having references would be helpful.
The same applies to all other quick quiz questions in this document= and in the Answers section as well the questions do not appear properly, h= alf in bold text and half not bold.

Apart from thi= s, the other added changes look good!

Thank you
Madhuparna

--
2.20.1

_______________________________________________
Linux-kernel-mentees mailing list
Linux-kernel-mentees@lists.linuxfoundation.org
https://lists.linuxfoundation= .org/mailman/listinfo/linux-kernel-mentees
3D""=E1=90=A7
--000000000000b16bb8059658e84b-- --===============4845696162972177543== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Linux-kernel-mentees mailing list Linux-kernel-mentees@lists.linuxfoundation.org https://lists.linuxfoundation.org/mailman/listinfo/linux-kernel-mentees --===============4845696162972177543==--