2024-06-04 22:21:57

by Paul E. McKenney

[permalink] [raw]
Subject: [PATCH rcu 0/2] RCU documentation updates for v6.11

Hello!

This series provides documentation updates:

1. Update Tasks RCU and Tasks Rude RCU description in
Requirements.rst.

2. Clarify rcu_assign_pointer() and rcu_dereference() ordering.

Thanx, Paul

------------------------------------------------------------------------

Design/Requirements/Requirements.rst | 16 ++++++++++++++++
whatisRCU.rst | 30 +++++++++++++++++++-----------
2 files changed, 35 insertions(+), 11 deletions(-)


2024-06-04 22:22:16

by Paul E. McKenney

[permalink] [raw]
Subject: [PATCH rcu 1/2] doc: Update Tasks RCU and Tasks Rude RCU description in Requirements.rst

This commit adds more detail to the Tasks RCU and Tasks Rude RCU
descriptions in Requirements.rst. While in the area, add Tasks Trace
RCU to the Tasks-RCU table of contents.

Reported-by: Sebastian Andrzej Siewior <[email protected]>
Signed-off-by: Paul E. McKenney <[email protected]>
---
.../RCU/Design/Requirements/Requirements.rst | 16 ++++++++++++++++
1 file changed, 16 insertions(+)

diff --git a/Documentation/RCU/Design/Requirements/Requirements.rst b/Documentation/RCU/Design/Requirements/Requirements.rst
index cccafdaa1f849..f511476b45506 100644
--- a/Documentation/RCU/Design/Requirements/Requirements.rst
+++ b/Documentation/RCU/Design/Requirements/Requirements.rst
@@ -2357,6 +2357,7 @@ section.
#. `Sched Flavor (Historical)`_
#. `Sleepable RCU`_
#. `Tasks RCU`_
+#. `Tasks Trace RCU`_

Bottom-Half Flavor (Historical)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2610,6 +2611,16 @@ critical sections that are delimited by voluntary context switches, that
is, calls to schedule(), cond_resched(), and
synchronize_rcu_tasks(). In addition, transitions to and from
userspace execution also delimit tasks-RCU read-side critical sections.
+Idle tasks are ignored by Tasks RCU, and Tasks Rude RCU may be used to
+interact with them.
+
+Note well that involuntary context switches are *not* Tasks-RCU quiescent
+states. After all, in preemptible kernels, a task executing code in a
+trampoline might be preempted. In this case, the Tasks-RCU grace period
+clearly cannot end until that task resumes and its execution leaves that
+trampoline. This means, among other things, that cond_resched() does
+not provide a Tasks RCU quiescent state. (Instead, use rcu_softirq_qs()
+from softirq or rcu_tasks_classic_qs() otherwise.)

The tasks-RCU API is quite compact, consisting only of
call_rcu_tasks(), synchronize_rcu_tasks(), and
@@ -2632,6 +2643,11 @@ moniker. And this operation is considered to be quite rude by real-time
workloads that don't want their ``nohz_full`` CPUs receiving IPIs and
by battery-powered systems that don't want their idle CPUs to be awakened.

+Once kernel entry/exit and deep-idle functions have been properly tagged
+``noinstr``, Tasks RCU can start paying attention to idle tasks (except
+those that are idle from RCU's perspective) and then Tasks Rude RCU can
+be removed from the kernel.
+
The tasks-rude-RCU API is also reader-marking-free and thus quite compact,
consisting of call_rcu_tasks_rude(), synchronize_rcu_tasks_rude(),
and rcu_barrier_tasks_rude().
--
2.40.1


2024-06-04 22:30:51

by Paul E. McKenney

[permalink] [raw]
Subject: [PATCH rcu 2/2] doc: Clarify rcu_assign_pointer() and rcu_dereference() ordering

This commit expands on the ordering properties of rcu_assign_pointer()
and rcu_dereference(), outlining their constraints on CPUs and compilers.

Reported-by: Rao Shoaib <[email protected]>
Signed-off-by: Paul E. McKenney <[email protected]>
---
Documentation/RCU/whatisRCU.rst | 30 +++++++++++++++++++-----------
1 file changed, 19 insertions(+), 11 deletions(-)

diff --git a/Documentation/RCU/whatisRCU.rst b/Documentation/RCU/whatisRCU.rst
index 94838c65c7d97..d585a5490aeec 100644
--- a/Documentation/RCU/whatisRCU.rst
+++ b/Documentation/RCU/whatisRCU.rst
@@ -250,21 +250,25 @@ rcu_assign_pointer()
^^^^^^^^^^^^^^^^^^^^
void rcu_assign_pointer(p, typeof(p) v);

- Yes, rcu_assign_pointer() **is** implemented as a macro, though it
- would be cool to be able to declare a function in this manner.
- (Compiler experts will no doubt disagree.)
+ Yes, rcu_assign_pointer() **is** implemented as a macro, though
+ it would be cool to be able to declare a function in this manner.
+ (And there has been some discussion of adding overloaded functions
+ to the C language, so who knows?)

The updater uses this spatial macro to assign a new value to an
RCU-protected pointer, in order to safely communicate the change
in value from the updater to the reader. This is a spatial (as
opposed to temporal) macro. It does not evaluate to an rvalue,
- but it does execute any memory-barrier instructions required
- for a given CPU architecture. Its ordering properties are that
- of a store-release operation.
-
- Perhaps just as important, it serves to document (1) which
- pointers are protected by RCU and (2) the point at which a
- given structure becomes accessible to other CPUs. That said,
+ but it does provide any compiler directives and memory-barrier
+ instructions required for a given compile or CPU architecture.
+ Its ordering properties are that of a store-release operation,
+ that is, any prior loads and stores required to initialize the
+ structure are ordered before the store that publishes the pointer
+ to that structure.
+
+ Perhaps just as important, rcu_assign_pointer() serves to document
+ (1) which pointers are protected by RCU and (2) the point at which
+ a given structure becomes accessible to other CPUs. That said,
rcu_assign_pointer() is most frequently used indirectly, via
the _rcu list-manipulation primitives such as list_add_rcu().

@@ -283,7 +287,11 @@ rcu_dereference()
executes any needed memory-barrier instructions for a given
CPU architecture. Currently, only Alpha needs memory barriers
within rcu_dereference() -- on other CPUs, it compiles to a
- volatile load.
+ volatile load. However, no mainstream C compilers respect
+ address dependencies, so rcu_dereference() uses volatile casts,
+ which, in combination with the coding guidelines listed in
+ rcu_dereference.rst, prevent current compilers from breaking
+ these dependencies.

Common coding practice uses rcu_dereference() to copy an
RCU-protected pointer to a local variable, then dereferences
--
2.40.1


2024-06-05 11:48:03

by Frederic Weisbecker

[permalink] [raw]
Subject: Re: [PATCH rcu 1/2] doc: Update Tasks RCU and Tasks Rude RCU description in Requirements.rst

Le Tue, Jun 04, 2024 at 03:21:54PM -0700, Paul E. McKenney a ?crit :
> This commit adds more detail to the Tasks RCU and Tasks Rude RCU
> descriptions in Requirements.rst. While in the area, add Tasks Trace
> RCU to the Tasks-RCU table of contents.
>
> Reported-by: Sebastian Andrzej Siewior <[email protected]>
> Signed-off-by: Paul E. McKenney <[email protected]>

Reviewed-by: Frederic Weisbecker <[email protected]>

2024-06-05 12:42:44

by Frederic Weisbecker

[permalink] [raw]
Subject: Re: [PATCH rcu 2/2] doc: Clarify rcu_assign_pointer() and rcu_dereference() ordering

Le Tue, Jun 04, 2024 at 03:21:55PM -0700, Paul E. McKenney a ?crit :
> This commit expands on the ordering properties of rcu_assign_pointer()
> and rcu_dereference(), outlining their constraints on CPUs and compilers.
>
> Reported-by: Rao Shoaib <[email protected]>
> Signed-off-by: Paul E. McKenney <[email protected]>
> ---
> Documentation/RCU/whatisRCU.rst | 30 +++++++++++++++++++-----------
> 1 file changed, 19 insertions(+), 11 deletions(-)
>
> diff --git a/Documentation/RCU/whatisRCU.rst b/Documentation/RCU/whatisRCU.rst
> index 94838c65c7d97..d585a5490aeec 100644
> --- a/Documentation/RCU/whatisRCU.rst
> +++ b/Documentation/RCU/whatisRCU.rst
> @@ -250,21 +250,25 @@ rcu_assign_pointer()
> ^^^^^^^^^^^^^^^^^^^^
> void rcu_assign_pointer(p, typeof(p) v);
>
> - Yes, rcu_assign_pointer() **is** implemented as a macro, though it
> - would be cool to be able to declare a function in this manner.
> - (Compiler experts will no doubt disagree.)
> + Yes, rcu_assign_pointer() **is** implemented as a macro, though
> + it would be cool to be able to declare a function in this manner.
> + (And there has been some discussion of adding overloaded functions
> + to the C language, so who knows?)
>
> The updater uses this spatial macro to assign a new value to an
> RCU-protected pointer, in order to safely communicate the change
> in value from the updater to the reader. This is a spatial (as
> opposed to temporal) macro. It does not evaluate to an rvalue,
> - but it does execute any memory-barrier instructions required
> - for a given CPU architecture. Its ordering properties are that
> - of a store-release operation.
> -
> - Perhaps just as important, it serves to document (1) which
> - pointers are protected by RCU and (2) the point at which a
> - given structure becomes accessible to other CPUs. That said,
> + but it does provide any compiler directives and memory-barrier
> + instructions required for a given compile or CPU architecture.
> + Its ordering properties are that of a store-release operation,
> + that is, any prior loads and stores required to initialize the
> + structure are ordered before the store that publishes the pointer
> + to that structure.

About that, why rcu_dereference() isn't a matching load-acquire?

Thanks.

2024-06-05 18:30:23

by Paul E. McKenney

[permalink] [raw]
Subject: Re: [PATCH rcu 1/2] doc: Update Tasks RCU and Tasks Rude RCU description in Requirements.rst

On Wed, Jun 05, 2024 at 01:42:15PM +0200, Frederic Weisbecker wrote:
> Le Tue, Jun 04, 2024 at 03:21:54PM -0700, Paul E. McKenney a ?crit :
> > This commit adds more detail to the Tasks RCU and Tasks Rude RCU
> > descriptions in Requirements.rst. While in the area, add Tasks Trace
> > RCU to the Tasks-RCU table of contents.
> >
> > Reported-by: Sebastian Andrzej Siewior <[email protected]>
> > Signed-off-by: Paul E. McKenney <[email protected]>
>
> Reviewed-by: Frederic Weisbecker <[email protected]>

I will apply this on my next rebase, thank you!

Thanx, Paul

2024-06-05 18:36:28

by Paul E. McKenney

[permalink] [raw]
Subject: Re: [PATCH rcu 2/2] doc: Clarify rcu_assign_pointer() and rcu_dereference() ordering

On Wed, Jun 05, 2024 at 01:56:23PM +0200, Frederic Weisbecker wrote:
> Le Tue, Jun 04, 2024 at 03:21:55PM -0700, Paul E. McKenney a ?crit :
> > This commit expands on the ordering properties of rcu_assign_pointer()
> > and rcu_dereference(), outlining their constraints on CPUs and compilers.
> >
> > Reported-by: Rao Shoaib <[email protected]>
> > Signed-off-by: Paul E. McKenney <[email protected]>
> > ---
> > Documentation/RCU/whatisRCU.rst | 30 +++++++++++++++++++-----------
> > 1 file changed, 19 insertions(+), 11 deletions(-)
> >
> > diff --git a/Documentation/RCU/whatisRCU.rst b/Documentation/RCU/whatisRCU.rst
> > index 94838c65c7d97..d585a5490aeec 100644
> > --- a/Documentation/RCU/whatisRCU.rst
> > +++ b/Documentation/RCU/whatisRCU.rst
> > @@ -250,21 +250,25 @@ rcu_assign_pointer()
> > ^^^^^^^^^^^^^^^^^^^^
> > void rcu_assign_pointer(p, typeof(p) v);
> >
> > - Yes, rcu_assign_pointer() **is** implemented as a macro, though it
> > - would be cool to be able to declare a function in this manner.
> > - (Compiler experts will no doubt disagree.)
> > + Yes, rcu_assign_pointer() **is** implemented as a macro, though
> > + it would be cool to be able to declare a function in this manner.
> > + (And there has been some discussion of adding overloaded functions
> > + to the C language, so who knows?)
> >
> > The updater uses this spatial macro to assign a new value to an
> > RCU-protected pointer, in order to safely communicate the change
> > in value from the updater to the reader. This is a spatial (as
> > opposed to temporal) macro. It does not evaluate to an rvalue,
> > - but it does execute any memory-barrier instructions required
> > - for a given CPU architecture. Its ordering properties are that
> > - of a store-release operation.
> > -
> > - Perhaps just as important, it serves to document (1) which
> > - pointers are protected by RCU and (2) the point at which a
> > - given structure becomes accessible to other CPUs. That said,
> > + but it does provide any compiler directives and memory-barrier
> > + instructions required for a given compile or CPU architecture.
> > + Its ordering properties are that of a store-release operation,
> > + that is, any prior loads and stores required to initialize the
> > + structure are ordered before the store that publishes the pointer
> > + to that structure.
>
> About that, why rcu_dereference() isn't a matching load-acquire?

Here is an example showing the difference:

p = rcu_dereference(gp);
r1 = READ_ONCE(x);
r2 = p->a;

The READ_ONCE() is not ordered against the rcu_dereference(), only the
read from p->a. In contrast, if that rcu_dereference() was instead an
smp_load_acquire(), both of the two later statements would be ordered.

Ah. You are suggesting that this be added to the description of
rcu_dereference()?

Or are you asking that this documentation state that an rcu_dereference()
memory-barrier-pairs with an rcu_assign_pointer()?

Or something else completely?

Thanx, Paul