* Re: linux-next: build warning after merge of the rcu tree
2022-11-07 5:02 ` Paul E. McKenney
@ 2022-11-07 9:28 ` Akira Yokosawa
2022-11-07 9:55 ` [PATCH] Documentation: RCU: use code blocks with autogenerated line (was: Re: linux-next: build warning after merge of the rcu tree) Bagas Sanjaya
1 sibling, 0 replies; 9+ messages in thread
From: Akira Yokosawa @ 2022-11-07 9:28 UTC (permalink / raw)
To: Paul E. McKenney; +Cc: linux-kernel, rcu, Akira Yokosawa
[-Cc: sfr, linux-next, +Cc: rcu]
Hi Paul,
On Sun, 6 Nov 2022 21:02:12 -0800, Paul E. McKenney wrote:
> On Mon, Nov 07, 2022 at 02:26:41PM +1100, Stephen Rothwell wrote:
>> Hi all,
>>
>> After merging the rcu tree, today's linux-next build (htmldocs)
>> produced this warning:
>>
>> Documentation/RCU/rcubarrier.rst:205: WARNING: Literal block ends without a blank line; unexpected unindent.
>>
>> Introduced by commit
>>
>> 21c2e3909721 ("doc: Update rcubarrier.rst")
>
> Huh. I guess that numbered code samples are not supposed to have more
> than nine lines?
No, the problem was that line 10 of the snippet had the same indent
level (ie, no indent) as the line above the snippet and was interpreted
as the end of literal block.
> Ah well, easy to fix by going back to left-justified
> numbers. I was wondering about that!
Appended is a POC patch (relative to current dev of -rcu tree) making
them right-justified and compatible with sphinx processing.
Hope this helps, Akira
>
> Apologies for the hassle!
>
> Thanx, Paul
diff --git a/Documentation/RCU/rcubarrier.rst b/Documentation/RCU/rcubarrier.rst
index 5a643e5233d5..9078511ec33d 100644
--- a/Documentation/RCU/rcubarrier.rst
+++ b/Documentation/RCU/rcubarrier.rst
@@ -193,16 +193,16 @@ which point, all earlier RCU callbacks are guaranteed to have completed.
The original code for rcu_barrier() was roughly as follows::
- 1 void rcu_barrier(void)
- 2 {
- 3 BUG_ON(in_interrupt());
- 4 /* Take cpucontrol mutex to protect against CPU hotplug */
- 5 mutex_lock(&rcu_barrier_mutex);
- 6 init_completion(&rcu_barrier_completion);
- 7 atomic_set(&rcu_barrier_cpu_count, 1);
- 8 on_each_cpu(rcu_barrier_func, NULL, 0, 1);
- 9 if (atomic_dec_and_test(&rcu_barrier_cpu_count))
- 10 complete(&rcu_barrier_completion);
+ 1 void rcu_barrier(void)
+ 2 {
+ 3 BUG_ON(in_interrupt());
+ 4 /* Take cpucontrol mutex to protect against CPU hotplug */
+ 5 mutex_lock(&rcu_barrier_mutex);
+ 6 init_completion(&rcu_barrier_completion);
+ 7 atomic_set(&rcu_barrier_cpu_count, 1);
+ 8 on_each_cpu(rcu_barrier_func, NULL, 0, 1);
+ 9 if (atomic_dec_and_test(&rcu_barrier_cpu_count))
+ 10 complete(&rcu_barrier_completion);
11 wait_for_completion(&rcu_barrier_completion);
12 mutex_unlock(&rcu_barrier_mutex);
13 }
--
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH] Documentation: RCU: use code blocks with autogenerated line (was: Re: linux-next: build warning after merge of the rcu tree)
2022-11-07 5:02 ` Paul E. McKenney
2022-11-07 9:28 ` Akira Yokosawa
@ 2022-11-07 9:55 ` Bagas Sanjaya
2022-11-07 11:48 ` Akira Yokosawa
1 sibling, 1 reply; 9+ messages in thread
From: Bagas Sanjaya @ 2022-11-07 9:55 UTC (permalink / raw)
To: Paul E. McKenney
Cc: Stephen Rothwell, Linux Kernel Mailing List,
Linux Next Mailing List, Frederic Weisbecker, Neeraj Upadhyay,
Josh Triplett, Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan,
Joel Fernandes, Jonathan Corbet, rcu, linux-doc
[-- Attachment #1: Type: text/plain, Size: 10295 bytes --]
On Sun, Nov 06, 2022 at 09:02:12PM -0800, Paul E. McKenney wrote:
> On Mon, Nov 07, 2022 at 02:26:41PM +1100, Stephen Rothwell wrote:
> > Hi all,
> >
> > After merging the rcu tree, today's linux-next build (htmldocs)
> > produced this warning:
> >
> > Documentation/RCU/rcubarrier.rst:205: WARNING: Literal block ends without a blank line; unexpected unindent.
> >
> > Introduced by commit
> >
> > 21c2e3909721 ("doc: Update rcubarrier.rst")
>
> Huh. I guess that numbered code samples are not supposed to have more
> than nine lines? Ah well, easy to fix by going back to left-justified
> numbers. I was wondering about that!
>
I think the proper fix is just let Sphinx generates line number:
---- >8 ----
From 5cea54b61b2dbf2ec5e00479c6c8f9e190b49091 Mon Sep 17 00:00:00 2001
From: Bagas Sanjaya <bagasdotme@gmail.com>
Date: Mon, 7 Nov 2022 15:41:31 +0700
Subject: [PATCH] Documentation: RCU: use code blocks with autogenerated line
numbers in RCU barrier doc
Recently Stephen Rothwell reported htmldocs warning in
Documentation/RCU/rcubarrier.rst when merging rcu tree [1], which has been
fixed by left-justifying the culprit line numbers. However, similar
issues can occur when line numbers are manually added without caution.
Instead, use code-block syntax with :linenos: option, which automatically
generates line numbers in code snippets.
Link: https://lore.kernel.org/linux-next/20221107142641.527396ea@canb.auug.org.au/ [1]
Signed-off-by: Bagas Sanjaya <bagasdotme@gmail.com>
---
Documentation/RCU/rcubarrier.rst | 213 +++++++++++++++++--------------
1 file changed, 114 insertions(+), 99 deletions(-)
diff --git a/Documentation/RCU/rcubarrier.rst b/Documentation/RCU/rcubarrier.rst
index 5a643e5233d5f6..79adf39838653e 100644
--- a/Documentation/RCU/rcubarrier.rst
+++ b/Documentation/RCU/rcubarrier.rst
@@ -70,81 +70,87 @@ If your module uses multiple srcu_struct structures, then it must also
use multiple invocations of srcu_barrier() when unloading that module.
For example, if it uses call_rcu(), call_srcu() on srcu_struct_1, and
call_srcu() on srcu_struct_2, then the following three lines of code
-will be required when unloading::
+will be required when unloading:
- 1 rcu_barrier();
- 2 srcu_barrier(&srcu_struct_1);
- 3 srcu_barrier(&srcu_struct_2);
+.. code-block:: c
+ :linenos:
+
+ rcu_barrier();
+ srcu_barrier(&srcu_struct_1);
+ srcu_barrier(&srcu_struct_2);
If latency is of the essence, workqueues could be used to run these
three functions concurrently.
An ancient version of the rcutorture module makes use of rcu_barrier()
-in its exit function as follows::
+in its exit function as follows:
- 1 static void
- 2 rcu_torture_cleanup(void)
- 3 {
- 4 int i;
- 5
- 6 fullstop = 1;
- 7 if (shuffler_task != NULL) {
- 8 VERBOSE_PRINTK_STRING("Stopping rcu_torture_shuffle task");
- 9 kthread_stop(shuffler_task);
- 10 }
- 11 shuffler_task = NULL;
- 12
- 13 if (writer_task != NULL) {
- 14 VERBOSE_PRINTK_STRING("Stopping rcu_torture_writer task");
- 15 kthread_stop(writer_task);
- 16 }
- 17 writer_task = NULL;
- 18
- 19 if (reader_tasks != NULL) {
- 20 for (i = 0; i < nrealreaders; i++) {
- 21 if (reader_tasks[i] != NULL) {
- 22 VERBOSE_PRINTK_STRING(
- 23 "Stopping rcu_torture_reader task");
- 24 kthread_stop(reader_tasks[i]);
- 25 }
- 26 reader_tasks[i] = NULL;
- 27 }
- 28 kfree(reader_tasks);
- 29 reader_tasks = NULL;
- 30 }
- 31 rcu_torture_current = NULL;
- 32
- 33 if (fakewriter_tasks != NULL) {
- 34 for (i = 0; i < nfakewriters; i++) {
- 35 if (fakewriter_tasks[i] != NULL) {
- 36 VERBOSE_PRINTK_STRING(
- 37 "Stopping rcu_torture_fakewriter task");
- 38 kthread_stop(fakewriter_tasks[i]);
- 39 }
- 40 fakewriter_tasks[i] = NULL;
- 41 }
- 42 kfree(fakewriter_tasks);
- 43 fakewriter_tasks = NULL;
- 44 }
- 45
- 46 if (stats_task != NULL) {
- 47 VERBOSE_PRINTK_STRING("Stopping rcu_torture_stats task");
- 48 kthread_stop(stats_task);
- 49 }
- 50 stats_task = NULL;
- 51
- 52 /* Wait for all RCU callbacks to fire. */
- 53 rcu_barrier();
- 54
- 55 rcu_torture_stats_print(); /* -After- the stats thread is stopped! */
- 56
- 57 if (cur_ops->cleanup != NULL)
- 58 cur_ops->cleanup();
- 59 if (atomic_read(&n_rcu_torture_error))
- 60 rcu_torture_print_module_parms("End of test: FAILURE");
- 61 else
- 62 rcu_torture_print_module_parms("End of test: SUCCESS");
- 63 }
+.. code-block:: c
+ :linenos:
+
+ static void
+ rcu_torture_cleanup(void)
+ {
+ int i;
+
+ fullstop = 1;
+ if (shuffler_task != NULL) {
+ VERBOSE_PRINTK_STRING("Stopping rcu_torture_shuffle task");
+ kthread_stop(shuffler_task);
+ }
+ shuffler_task = NULL;
+
+ if (writer_task != NULL) {
+ VERBOSE_PRINTK_STRING("Stopping rcu_torture_writer task");
+ kthread_stop(writer_task);
+ }
+ writer_task = NULL;
+
+ if (reader_tasks != NULL) {
+ for (i = 0; i < nrealreaders; i++) {
+ if (reader_tasks[i] != NULL) {
+ VERBOSE_PRINTK_STRING(
+ "Stopping rcu_torture_reader task");
+ kthread_stop(reader_tasks[i]);
+ }
+ reader_tasks[i] = NULL;
+ }
+ kfree(reader_tasks);
+ reader_tasks = NULL;
+ }
+ rcu_torture_current = NULL;
+
+ if (fakewriter_tasks != NULL) {
+ for (i = 0; i < nfakewriters; i++) {
+ if (fakewriter_tasks[i] != NULL) {
+ VERBOSE_PRINTK_STRING(
+ "Stopping rcu_torture_fakewriter task");
+ kthread_stop(fakewriter_tasks[i]);
+ }
+ fakewriter_tasks[i] = NULL;
+ }
+ kfree(fakewriter_tasks);
+ fakewriter_tasks = NULL;
+ }
+
+ if (stats_task != NULL) {
+ VERBOSE_PRINTK_STRING("Stopping rcu_torture_stats task");
+ kthread_stop(stats_task);
+ }
+ stats_task = NULL;
+
+ /* Wait for all RCU callbacks to fire. */
+ rcu_barrier();
+
+ rcu_torture_stats_print(); /* -After- the stats thread is stopped! */
+
+ if (cur_ops->cleanup != NULL)
+ cur_ops->cleanup();
+ if (atomic_read(&n_rcu_torture_error))
+ rcu_torture_print_module_parms("End of test: FAILURE");
+ else
+ rcu_torture_print_module_parms("End of test: SUCCESS");
+ }
Line 6 sets a global variable that prevents any RCU callbacks from
re-posting themselves. This will not be necessary in most cases, since
@@ -191,21 +197,24 @@ queues. His implementation queues an RCU callback on each of the per-CPU
callback queues, and then waits until they have all started executing, at
which point, all earlier RCU callbacks are guaranteed to have completed.
-The original code for rcu_barrier() was roughly as follows::
+The original code for rcu_barrier() was roughly as follows:
- 1 void rcu_barrier(void)
- 2 {
- 3 BUG_ON(in_interrupt());
- 4 /* Take cpucontrol mutex to protect against CPU hotplug */
- 5 mutex_lock(&rcu_barrier_mutex);
- 6 init_completion(&rcu_barrier_completion);
- 7 atomic_set(&rcu_barrier_cpu_count, 1);
- 8 on_each_cpu(rcu_barrier_func, NULL, 0, 1);
- 9 if (atomic_dec_and_test(&rcu_barrier_cpu_count))
- 10 complete(&rcu_barrier_completion);
- 11 wait_for_completion(&rcu_barrier_completion);
- 12 mutex_unlock(&rcu_barrier_mutex);
- 13 }
+.. code-block:: c
+ :linenos:
+
+ void rcu_barrier(void)
+ {
+ BUG_ON(in_interrupt());
+ /* Take cpucontrol mutex to protect against CPU hotplug */
+ mutex_lock(&rcu_barrier_mutex);
+ init_completion(&rcu_barrier_completion);
+ atomic_set(&rcu_barrier_cpu_count, 1);
+ on_each_cpu(rcu_barrier_func, NULL, 0, 1);
+ if (atomic_dec_and_test(&rcu_barrier_cpu_count))
+ complete(&rcu_barrier_completion);
+ wait_for_completion(&rcu_barrier_completion);
+ mutex_unlock(&rcu_barrier_mutex);
+ }
Line 3 verifies that the caller is in process context, and lines 5 and 12
use rcu_barrier_mutex to ensure that only one rcu_barrier() is using the
@@ -230,18 +239,21 @@ This code was rewritten in 2008 and several times thereafter, but this
still gives the general idea.
The rcu_barrier_func() runs on each CPU, where it invokes call_rcu()
-to post an RCU callback, as follows::
+to post an RCU callback, as follows:
- 1 static void rcu_barrier_func(void *notused)
- 2 {
- 3 int cpu = smp_processor_id();
- 4 struct rcu_data *rdp = &per_cpu(rcu_data, cpu);
- 5 struct rcu_head *head;
- 6
- 7 head = &rdp->barrier;
- 8 atomic_inc(&rcu_barrier_cpu_count);
- 9 call_rcu(head, rcu_barrier_callback);
- 10 }
+.. code-block:: c
+ :linenos:
+
+ static void rcu_barrier_func(void *notused)
+ {
+ int cpu = smp_processor_id();
+ struct rcu_data *rdp = &per_cpu(rcu_data, cpu);
+ struct rcu_head *head;
+
+ head = &rdp->barrier;
+ atomic_inc(&rcu_barrier_cpu_count);
+ call_rcu(head, rcu_barrier_callback);
+ }
Lines 3 and 4 locate RCU's internal per-CPU rcu_data structure,
which contains the struct rcu_head that needed for the later call to
@@ -252,13 +264,16 @@ the current CPU's queue.
The rcu_barrier_callback() function simply atomically decrements the
rcu_barrier_cpu_count variable and finalizes the completion when it
-reaches zero, as follows::
+reaches zero, as follows:
- 1 static void rcu_barrier_callback(struct rcu_head *notused)
- 2 {
- 3 if (atomic_dec_and_test(&rcu_barrier_cpu_count))
- 4 complete(&rcu_barrier_completion);
- 5 }
+.. code-block:: c
+ :linenos:
+
+ static void rcu_barrier_callback(struct rcu_head *notused)
+ {
+ if (atomic_dec_and_test(&rcu_barrier_cpu_count))
+ complete(&rcu_barrier_completion);
+ }
.. _rcubarrier_quiz_3:
base-commit: 2c9ea2f2e0a56cbf6931992812bffe47506f23d0
Thanks.
--
An old man doll... just what I always wanted! - Clara
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply related [flat|nested] 9+ messages in thread