Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1341505 > unrolled thread

[PATCH tip/core/rcu 0/14] Documentation updates for 4.6

Started by"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
First post2016-02-24 06:10 +0100
Last post2016-02-24 06:20 +0100
Articles 20 on this page of 22 — 4 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH tip/core/rcu 0/14] Documentation updates for 4.6 "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> - 2016-02-24 06:10 +0100
    [PATCH tip/core/rcu 01/14] documentation:  Add real-time requirements from CPU-bound workloads "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> - 2016-02-24 06:10 +0100
    [PATCH tip/core/rcu 14/14] documentation: Clarify compiler store-fusion example "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> - 2016-02-24 06:10 +0100
    [PATCH tip/core/rcu 12/14] documentation: Document illegality of call_rcu() from offline CPUs "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> - 2016-02-24 06:10 +0100
    [PATCH tip/core/rcu 07/14] documentation: Distinguish between local and global transitivity "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> - 2016-02-24 06:10 +0100
    [PATCH tip/core/rcu 05/14] documentation: Remove obsolete reference to RCU-protected indexes "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> - 2016-02-24 06:10 +0100
    [PATCH tip/core/rcu 08/14] documentation:  Add alternative release-acquire outcome "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> - 2016-02-24 06:10 +0100
    [PATCH tip/core/rcu 11/14] documentation: Transitivity is not cumulativity "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> - 2016-02-24 06:10 +0100
    [PATCH tip/core/rcu 04/14] documentation: Add synchronize_rcu_mult() to the requirements "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> - 2016-02-24 06:10 +0100
    [PATCH tip/core/rcu 13/14] documentation: Explain how RCU's combining tree fights contention "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> - 2016-02-24 06:20 +0100
    [PATCH tip/core/rcu 10/14] documentation: Explain why rcu_read_lock() needs no barrier() "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> - 2016-02-24 06:20 +0100
    [PATCH tip/core/rcu 03/14] documentation: Fix memory-barriers.txt section references "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> - 2016-02-24 06:20 +0100
    [PATCH tip/core/rcu 02/14] documentation: Fix control dependency and identical stores "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> - 2016-02-24 06:20 +0100
      Re: [PATCH tip/core/rcu 02/14] documentation: Fix control  dependency and identical stores Mathieu Desnoyers <mathieu.desnoyers@efficios.com> - 2016-02-24 22:20 +0100
        Re: [PATCH tip/core/rcu 02/14] documentation: Fix control dependency  and identical stores "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> - 2016-02-24 22:50 +0100
          Re: [PATCH tip/core/rcu 02/14] documentation: Fix control dependency  and identical stores Jianyu Zhan <nasa4836@gmail.com> - 2016-02-25 07:50 +0100
            Re: [PATCH tip/core/rcu 02/14] documentation: Fix control dependency  and identical stores "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> - 2016-02-25 15:10 +0100
          Re: [PATCH tip/core/rcu 02/14] documentation: Fix control dependency  and identical stores Peter Zijlstra <peterz@infradead.org> - 2016-02-25 09:30 +0100
            Re: [PATCH tip/core/rcu 02/14] documentation: Fix control dependency  and identical stores "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> - 2016-02-25 15:10 +0100
              Re: [PATCH tip/core/rcu 02/14] documentation: Fix control dependency  and identical stores Peter Zijlstra <peterz@infradead.org> - 2016-02-25 15:50 +0100
                Re: [PATCH tip/core/rcu 02/14] documentation: Fix control dependency  and identical stores "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> - 2016-02-25 16:50 +0100
    [PATCH tip/core/rcu 06/14] documentation: Subsequent writes ordered by rcu_dereference() "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> - 2016-02-24 06:20 +0100

Page 1 of 2  [1] 2  Next page →


#1341505 — [PATCH tip/core/rcu 0/14] Documentation updates for 4.6

From"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Date2016-02-24 06:10 +0100
Subject[PATCH tip/core/rcu 0/14] Documentation updates for 4.6
Message-ID<r5zS2-84d-11@gated-at.bofh.it>
Hello!

This series contains documentation updates as follows:

1.	Update the requirements design-level documentation to record RCU's
	responsibility to avoid injecting OS jitter onto nohz_full CPUs.

2.	Fix control-dependency summary of memory-barriers.txt to
	note that barrier() does not always prevent code reordering
	when both legs of an "if" statement begin with identical code.

3.	Fix memory-barriers.txt section references.

4.	Update the requirements design-level documentation to add
	synchronize_rcu_mult().

5.	Remove obsolete references to RCU-protected array indexes from
	memory-barriers.txt.

6.	Update memory-barriers.txt to explicitly state that
	rcu_dereference() orders writes to as well as reads from
	the RCU-protected data item.

7.	Update memory-barriers.txt to distinguish between local and
	global transitivity.

8.	Update memory-barriers.txt to add alternative outcome from
	release-acquire chain.

9.	Add design-level documentation for RCU's major data structures.

10.	Update the requirements design-level documentation to explain
	why rcu_read_lock() needs no barrier() for PREEMPT=n.

11.	Remove misleading statement that transitivity is cumulativity
	from memory-barriers.txt.

12.	Update the requirements design-level documentation to explicitly
	state that it is illegal to invoke call_rcu() from an offline CPU.

13.	Add text to the design-level documentation for RCU's major data
	structures stating how the combining tree keeps lock contention
	under control.

14.	Clarify compiler store-fusion example in memory-barriers.txt.

							Thanx, Paul

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

 RCU/Design/Data-Structures/BigTreeClassicRCU.svg            |  474 ++++
 RCU/Design/Data-Structures/BigTreeClassicRCUBH.svg          |  499 ++++
 RCU/Design/Data-Structures/BigTreeClassicRCUBHdyntick.svg   |  695 +++++
 RCU/Design/Data-Structures/BigTreePreemptRCUBHdyntick.svg   |  741 ++++++
 RCU/Design/Data-Structures/BigTreePreemptRCUBHdyntickCB.svg |  858 +++++++
 RCU/Design/Data-Structures/Data-Structures.html             | 1395 ++++++++++++
 RCU/Design/Data-Structures/Data-Structures.htmlx            | 1295 +++++++++++
 RCU/Design/Data-Structures/HugeTreeClassicRCU.svg           |  939 ++++++++
 RCU/Design/Data-Structures/TreeLevel.svg                    |  828 +++++++
 RCU/Design/Data-Structures/TreeMapping.svg                  |  305 ++
 RCU/Design/Data-Structures/TreeMappingLevel.svg             |  380 +++
 RCU/Design/Data-Structures/blkd_task.svg                    |  843 +++++++
 RCU/Design/Data-Structures/nxtlist.svg                      |  396 +++
 RCU/Design/Requirements/Requirements.html                   |  235 +-
 RCU/Design/Requirements/Requirements.htmlx                  |  121 +
 memory-barriers.txt                                         |  141 -
 16 files changed, 10074 insertions(+), 71 deletions(-)

[toc] | [next] | [standalone]


#1341507 — [PATCH tip/core/rcu 01/14] documentation: Add real-time requirements from CPU-bound workloads

From"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Date2016-02-24 06:10 +0100
Subject[PATCH tip/core/rcu 01/14] documentation: Add real-time requirements from CPU-bound workloads
Message-ID<r5zS2-84d-13@gated-at.bofh.it>
In reply to#1341505
This commit records RCU's responsibility to avoid degrading latencies
of CPUs running tight loops within properly configured workloads,
both in kernel and in userspace.

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 Documentation/RCU/Design/Requirements/Requirements.html  | 10 +++++++++-
 Documentation/RCU/Design/Requirements/Requirements.htmlx |  8 ++++++++
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/Documentation/RCU/Design/Requirements/Requirements.html b/Documentation/RCU/Design/Requirements/Requirements.html
index a725f9900ec8..3004baa71bcc 100644
--- a/Documentation/RCU/Design/Requirements/Requirements.html
+++ b/Documentation/RCU/Design/Requirements/Requirements.html
@@ -1,5 +1,5 @@
 <!-- DO NOT HAND EDIT. -->
-<!-- Instead, edit Documentation/RCU/Design/Requirements/Requirements.htmlx and run 'sh htmlqqz.sh Documentation/RCU/Design/Requirements/Requirements' -->
+<!-- Instead, edit Requirements.htmlx and run 'sh htmlqqz.sh Requirements' -->
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
         "http://www.w3.org/TR/html4/loose.dtd">
         <html>
@@ -2171,6 +2171,14 @@ This real-time requirement motivated the grace-period kthread, which
 also simplified handling of a number of race conditions.
 
 <p>
+RCU must avoid degrading real-time response for CPU-bound threads, whether
+executing in usermode (which is one use case for
+<tt>CONFIG_NO_HZ_FULL=y</tt>) or in the kernel.
+That said, CPU-bound loops in the kernel must execute
+<tt>cond_resched_rcu_qs()</tt> at least once per few tens of milliseconds
+in order to avoid receiving an IPI from RCU.
+
+<p>
 Finally, RCU's status as a synchronization primitive means that
 any RCU failure can result in arbitrary memory corruption that can be
 extremely difficult to debug.
diff --git a/Documentation/RCU/Design/Requirements/Requirements.htmlx b/Documentation/RCU/Design/Requirements/Requirements.htmlx
index 3a97ba490c42..61caffc86823 100644
--- a/Documentation/RCU/Design/Requirements/Requirements.htmlx
+++ b/Documentation/RCU/Design/Requirements/Requirements.htmlx
@@ -2338,6 +2338,14 @@ This real-time requirement motivated the grace-period kthread, which
 also simplified handling of a number of race conditions.
 
 <p>
+RCU must avoid degrading real-time response for CPU-bound threads, whether
+executing in usermode (which is one use case for
+<tt>CONFIG_NO_HZ_FULL=y</tt>) or in the kernel.
+That said, CPU-bound loops in the kernel must execute
+<tt>cond_resched_rcu_qs()</tt> at least once per few tens of milliseconds
+in order to avoid receiving an IPI from RCU.
+
+<p>
 Finally, RCU's status as a synchronization primitive means that
 any RCU failure can result in arbitrary memory corruption that can be
 extremely difficult to debug.
-- 
2.5.2

[toc] | [prev] | [next] | [standalone]


#1341512 — [PATCH tip/core/rcu 14/14] documentation: Clarify compiler store-fusion example

From"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Date2016-02-24 06:10 +0100
Subject[PATCH tip/core/rcu 14/14] documentation: Clarify compiler store-fusion example
Message-ID<r5zS2-84d-23@gated-at.bofh.it>
In reply to#1341505
From: SeongJae Park <sj38.park@gmail.com>

The compiler store-fusion example in memory-barriers.txt uses a C
comment to represent arbitrary code that does not update a given
variable.  Unfortunately, someone could reasonably interpret the
comment as instead referring to the following line of code.  This
commit therefore replaces the comment with a string that more
clearly represents the arbitrary code.

Signed-off-by: SeongJae Park <sj38.park@gmail.com>
Acked-by: David Howells <dhowells@redhat.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 Documentation/memory-barriers.txt | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index 8367d393cba2..3729cbe60e41 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -1550,7 +1550,7 @@ of optimizations:
      the following:
 
 	a = 0;
-	/* Code that does not store to variable a. */
+	... Code that does not store to variable a ...
 	a = 0;
 
      The compiler sees that the value of variable 'a' is already zero, so
@@ -1562,7 +1562,7 @@ of optimizations:
      wrong guess:
 
 	WRITE_ONCE(a, 0);
-	/* Code that does not store to variable a. */
+	... Code that does not store to variable a ...
 	WRITE_ONCE(a, 0);
 
  (*) The compiler is within its rights to reorder memory accesses unless
-- 
2.5.2

[toc] | [prev] | [next] | [standalone]


#1341513 — [PATCH tip/core/rcu 12/14] documentation: Document illegality of call_rcu() from offline CPUs

From"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Date2016-02-24 06:10 +0100
Subject[PATCH tip/core/rcu 12/14] documentation: Document illegality of call_rcu() from offline CPUs
Message-ID<r5zS2-84d-29@gated-at.bofh.it>
In reply to#1341505
There is already a blanket statement about no member of RCU's API
being legal from an offline CPU, but add an explicit note where it
states that it is illegal to invoke call_rcu() from an NMI handler.

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 Documentation/RCU/Design/Requirements/Requirements.html  | 3 ++-
 Documentation/RCU/Design/Requirements/Requirements.htmlx | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/Documentation/RCU/Design/Requirements/Requirements.html b/Documentation/RCU/Design/Requirements/Requirements.html
index 2a56031bfdd4..01e12b86e81f 100644
--- a/Documentation/RCU/Design/Requirements/Requirements.html
+++ b/Documentation/RCU/Design/Requirements/Requirements.html
@@ -1354,7 +1354,8 @@ situations where neither <tt>synchronize_rcu()</tt> nor
 <tt>synchronize_rcu_expedited()</tt> would be legal,
 including within preempt-disable code, <tt>local_bh_disable()</tt> code,
 interrupt-disable code, and interrupt handlers.
-However, even <tt>call_rcu()</tt> is illegal within NMI handlers.
+However, even <tt>call_rcu()</tt> is illegal within NMI handlers
+and from offline CPUs.
 The callback function (<tt>remove_gp_cb()</tt> in this case) will be
 executed within softirq (software interrupt) environment within the
 Linux kernel,
diff --git a/Documentation/RCU/Design/Requirements/Requirements.htmlx b/Documentation/RCU/Design/Requirements/Requirements.htmlx
index 98da30ca84c4..3355f1f9384c 100644
--- a/Documentation/RCU/Design/Requirements/Requirements.htmlx
+++ b/Documentation/RCU/Design/Requirements/Requirements.htmlx
@@ -1513,7 +1513,8 @@ situations where neither <tt>synchronize_rcu()</tt> nor
 <tt>synchronize_rcu_expedited()</tt> would be legal,
 including within preempt-disable code, <tt>local_bh_disable()</tt> code,
 interrupt-disable code, and interrupt handlers.
-However, even <tt>call_rcu()</tt> is illegal within NMI handlers.
+However, even <tt>call_rcu()</tt> is illegal within NMI handlers
+and from offline CPUs.
 The callback function (<tt>remove_gp_cb()</tt> in this case) will be
 executed within softirq (software interrupt) environment within the
 Linux kernel,
-- 
2.5.2

[toc] | [prev] | [next] | [standalone]


#1341515 — [PATCH tip/core/rcu 07/14] documentation: Distinguish between local and global transitivity

From"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Date2016-02-24 06:10 +0100
Subject[PATCH tip/core/rcu 07/14] documentation: Distinguish between local and global transitivity
Message-ID<r5zS3-84d-33@gated-at.bofh.it>
In reply to#1341505
The introduction of smp_load_acquire() and smp_store_release() had
the side effect of introducing a weaker notion of transitivity:
The transitivity of full smp_mb() barriers is global, but that
of smp_store_release()/smp_load_acquire() chains is local.  This
commit therefore introduces the notion of local transitivity and
gives an example.

Reported-by: Peter Zijlstra <peterz@infradead.org>
Reported-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 Documentation/memory-barriers.txt | 78 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 76 insertions(+), 2 deletions(-)

diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index e9ebeb3b1077..ae9d306725ba 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -1318,8 +1318,82 @@ or a level of cache, CPU 2 might have early access to CPU 1's writes.
 General barriers are therefore required to ensure that all CPUs agree
 on the combined order of CPU 1's and CPU 2's accesses.
 
-To reiterate, if your code requires transitivity, use general barriers
-throughout.
+General barriers provide "global transitivity", so that all CPUs will
+agree on the order of operations.  In contrast, a chain of release-acquire
+pairs provides only "local transitivity", so that only those CPUs on
+the chain are guaranteed to agree on the combined order of the accesses.
+For example, switching to C code in deference to Herman Hollerith:
+
+	int u, v, x, y, z;
+
+	void cpu0(void)
+	{
+		r0 = smp_load_acquire(&x);
+		WRITE_ONCE(u, 1);
+		smp_store_release(&y, 1);
+	}
+
+	void cpu1(void)
+	{
+		r1 = smp_load_acquire(&y);
+		r4 = READ_ONCE(v);
+		r5 = READ_ONCE(u);
+		smp_store_release(&z, 1);
+	}
+
+	void cpu2(void)
+	{
+		r2 = smp_load_acquire(&z);
+		smp_store_release(&x, 1);
+	}
+
+	void cpu3(void)
+	{
+		WRITE_ONCE(v, 1);
+		smp_mb();
+		r3 = READ_ONCE(u);
+	}
+
+Because cpu0(), cpu1(), and cpu2() participate in a local transitive
+chain of smp_store_release()/smp_load_acquire() pairs, the following
+outcome is prohibited:
+
+	r0 == 1 && r1 == 1 && r2 == 1
+
+Furthermore, because of the release-acquire relationship between cpu0()
+and cpu1(), cpu1() must see cpu0()'s writes, so that the following
+outcome is prohibited:
+
+	r1 == 1 && r5 == 0
+
+However, the transitivity of release-acquire is local to the participating
+CPUs and does not apply to cpu3().  Therefore, the following outcome
+is possible:
+
+	r0 == 0 && r1 == 1 && r2 == 1 && r3 == 0 && r4 == 0
+
+Although cpu0(), cpu1(), and cpu2() will see their respective reads and
+writes in order, CPUs not involved in the release-acquire chain might
+well disagree on the order.  This disagreement stems from the fact that
+the weak memory-barrier instructions used to implement smp_load_acquire()
+and smp_store_release() are not required to order prior stores against
+subsequent loads in all cases.  This means that cpu3() can see cpu0()'s
+store to u as happening -after- cpu1()'s load from v, even though
+both cpu0() and cpu1() agree that these two operations occurred in the
+intended order.
+
+However, please keep in mind that smp_load_acquire() is not magic.
+In particular, it simply reads from its argument with ordering.  It does
+-not- ensure that any particular value will be read.  Therefore, the
+following outcome is possible:
+
+	r0 == 0 && r1 == 0 && r2 == 0 && r5 == 0
+
+Note that this outcome can happen even on a mythical sequentially
+consistent system where nothing is ever reordered.
+
+To reiterate, if your code requires global transitivity, use general
+barriers throughout.
 
 
 ========================
-- 
2.5.2

[toc] | [prev] | [next] | [standalone]


#1341517 — [PATCH tip/core/rcu 05/14] documentation: Remove obsolete reference to RCU-protected indexes

From"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Date2016-02-24 06:10 +0100
Subject[PATCH tip/core/rcu 05/14] documentation: Remove obsolete reference to RCU-protected indexes
Message-ID<r5zS3-84d-37@gated-at.bofh.it>
In reply to#1341505
Commit #1ebee8017d84 (rcu: Eliminate array-index-based RCU primitives)
eliminated the primitives supporting RCU-protected array indexes, but
failed to update Documentation/memory-barriers.txt accordingly.  This
commit therefore removes the discussion of RCU-protected array indexes.

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 Documentation/memory-barriers.txt | 15 ---------------
 1 file changed, 15 deletions(-)

diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index c90922b9b294..6bee0a2c43ab 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -565,21 +565,6 @@ odd-numbered bank is idle, one can see the new value of the pointer P (&B),
 but the old value of the variable B (2).
 
 
-Another example of where data dependency barriers might be required is where a
-number is read from memory and then used to calculate the index for an array
-access:
-
-	CPU 1		      CPU 2
-	===============	      ===============
-	{ M[0] == 1, M[1] == 2, M[3] = 3, P == 0, Q == 3 }
-	M[1] = 4;
-	<write barrier>
-	WRITE_ONCE(P, 1);
-			      Q = READ_ONCE(P);
-			      <data dependency barrier>
-			      D = M[Q];
-
-
 The data dependency barrier is very important to the RCU system,
 for example.  See rcu_assign_pointer() and rcu_dereference() in
 include/linux/rcupdate.h.  This permits the current target of an RCU'd
-- 
2.5.2

[toc] | [prev] | [next] | [standalone]


#1341519 — [PATCH tip/core/rcu 08/14] documentation: Add alternative release-acquire outcome

From"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Date2016-02-24 06:10 +0100
Subject[PATCH tip/core/rcu 08/14] documentation: Add alternative release-acquire outcome
Message-ID<r5zS3-84d-41@gated-at.bofh.it>
In reply to#1341505
The memory-barriers.txt discussion of local transitivity and
release-acquire chains leaves out discussion of the outcome of
the read from "u".  This commit therefore adds an outcome showing
that you can get a "1" from this read even if the release-acquire
pairs don't line up.

Reported-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 Documentation/memory-barriers.txt | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index ae9d306725ba..57e4a4b053c5 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -1372,6 +1372,10 @@ is possible:
 
 	r0 == 0 && r1 == 1 && r2 == 1 && r3 == 0 && r4 == 0
 
+As an aside, the following outcome is also possible:
+
+	r0 == 0 && r1 == 1 && r2 == 1 && r3 == 0 && r4 == 0 && r5 == 1
+
 Although cpu0(), cpu1(), and cpu2() will see their respective reads and
 writes in order, CPUs not involved in the release-acquire chain might
 well disagree on the order.  This disagreement stems from the fact that
-- 
2.5.2

[toc] | [prev] | [next] | [standalone]


#1341530 — [PATCH tip/core/rcu 11/14] documentation: Transitivity is not cumulativity

From"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Date2016-02-24 06:10 +0100
Subject[PATCH tip/core/rcu 11/14] documentation: Transitivity is not cumulativity
Message-ID<r5zS4-84d-61@gated-at.bofh.it>
In reply to#1341505
The "transitivity" section mentions cumulativity in a potentially
confusing way.  Contrary to the current wording, cumulativity is
not transitivity, but rather a hardware discipline that can be used
to implement transitivity on ARM and PowerPC CPUs.  This commit
therefore deletes the mention of cumulativity.

Reported-by: Luc Maranget <luc.maranget@inria.fr>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 Documentation/memory-barriers.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index 57e4a4b053c5..8367d393cba2 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -1270,7 +1270,7 @@ TRANSITIVITY
 
 Transitivity is a deeply intuitive notion about ordering that is not
 always provided by real computer systems.  The following example
-demonstrates transitivity (also called "cumulativity"):
+demonstrates transitivity:
 
 	CPU 1			CPU 2			CPU 3
 	=======================	=======================	=======================
-- 
2.5.2

[toc] | [prev] | [next] | [standalone]


#1341533 — [PATCH tip/core/rcu 04/14] documentation: Add synchronize_rcu_mult() to the requirements

From"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Date2016-02-24 06:10 +0100
Subject[PATCH tip/core/rcu 04/14] documentation: Add synchronize_rcu_mult() to the requirements
Message-ID<r5zS4-84d-69@gated-at.bofh.it>
In reply to#1341505
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 .../RCU/Design/Requirements/Requirements.html      | 92 ++++++++++++++++++++++
 .../RCU/Design/Requirements/Requirements.htmlx     | 82 +++++++++++++++++++
 2 files changed, 174 insertions(+)

diff --git a/Documentation/RCU/Design/Requirements/Requirements.html b/Documentation/RCU/Design/Requirements/Requirements.html
index 3004baa71bcc..59acd82e67d4 100644
--- a/Documentation/RCU/Design/Requirements/Requirements.html
+++ b/Documentation/RCU/Design/Requirements/Requirements.html
@@ -2231,6 +2231,8 @@ described in a separate section.
 <li>	<a href="#Sched Flavor">Sched Flavor</a>
 <li>	<a href="#Sleepable RCU">Sleepable RCU</a>
 <li>	<a href="#Tasks RCU">Tasks RCU</a>
+<li>	<a href="#Waiting for Multiple Grace Periods">
+	Waiting for Multiple Grace Periods</a>
 </ol>
 
 <h3><a name="Bottom-Half Flavor">Bottom-Half Flavor</a></h3>
@@ -2480,6 +2482,81 @@ The tasks-RCU API is quite compact, consisting only of
 <tt>synchronize_rcu_tasks()</tt>, and
 <tt>rcu_barrier_tasks()</tt>.
 
+<h3><a name="Waiting for Multiple Grace Periods">
+Waiting for Multiple Grace Periods</a></h3>
+
+<p>
+Perhaps you have an RCU protected data structure that is accessed from
+RCU read-side critical sections, from softirq handlers, and from
+hardware interrupt handlers.
+That is three flavors of RCU, the normal flavor, the bottom-half flavor,
+and the sched flavor.
+How to wait for a compound grace period?
+
+<p>
+The best approach is usually to &ldquo;just say no!&rdquo; and
+insert <tt>rcu_read_lock()</tt> and <tt>rcu_read_unlock()</tt>
+around each RCU read-side critical section, regardless of what
+environment it happens to be in.
+But suppose that some of the RCU read-side critical sections are
+on extremely hot code paths, and that use of <tt>CONFIG_PREEMPT=n</tt>
+is not a viable option, so that <tt>rcu_read_lock()</tt> and
+<tt>rcu_read_unlock()</tt> are not free.
+What then?
+
+<p>
+You <i>could</i> wait on all three grace periods in succession, as follows:
+
+<blockquote>
+<pre>
+ 1 synchronize_rcu();
+ 2 synchronize_rcu_bh();
+ 3 synchronize_sched();
+</pre>
+</blockquote>
+
+<p>
+This works, but triples the update-side latency penalty.
+In cases where this is not acceptable, <tt>synchronize_rcu_mult()</tt>
+may be used to wait on all three flavors of grace period concurrently:
+
+<blockquote>
+<pre>
+ 1 synchronize_rcu_mult(call_rcu, call_rcu_bh, call_rcu_sched);
+</pre>
+</blockquote>
+
+<p>
+But what if it is necessary to also wait on SRCU?
+This can be done as follows:
+
+<blockquote>
+<pre>
+ 1 static void call_my_srcu(struct rcu_head *head,
+ 2        void (*func)(struct rcu_head *head))
+ 3 {
+ 4   call_srcu(&amp;my_srcu, head, func);
+ 5 }
+ 6
+ 7 synchronize_rcu_mult(call_rcu, call_rcu_bh, call_rcu_sched, call_my_srcu);
+</pre>
+</blockquote>
+
+<p>
+If you needed to wait on multiple different flavors of SRCU
+(but why???), you would need to create a wrapper function resembling
+<tt>call_my_srcu()</tt> for each SRCU flavor.
+
+<p><a name="Quick Quiz 15"><b>Quick Quiz 15</b>:</a>
+But what if I need to wait for multiple RCU flavors, but I also need
+the grace periods to be expedited?
+<br><a href="#qq15answer">Answer</a>
+
+<p>
+Again, it is usually better to adjust the RCU read-side critical sections
+to use a single flavor of RCU, but when this is not feasible, you can use
+<tt>synchronize_rcu_mult()</tt>.
+
 <h2><a name="Possible Future Changes">Possible Future Changes</a></h2>
 
 <p>
@@ -2901,5 +2978,20 @@ during scheduler initialization.
 
 </p><p><a href="#Quick%20Quiz%2014"><b>Back to Quick Quiz 14</b>.</a>
 
+<a name="qq15answer"></a>
+<p><b>Quick Quiz 15</b>:
+But what if I need to wait for multiple RCU flavors, but I also need
+the grace periods to be expedited?
+
+
+</p><p><b>Answer</b>:
+If you are using expedited grace periods, there should be less penalty
+for waiting on them in succession.
+But if that is nevertheless a problem, you can use workqueues or multiple
+kthreads to wait on the various expedited grace periods concurrently.
+
+
+</p><p><a href="#Quick%20Quiz%2015"><b>Back to Quick Quiz 15</b>.</a>
+
 
 </body></html>
diff --git a/Documentation/RCU/Design/Requirements/Requirements.htmlx b/Documentation/RCU/Design/Requirements/Requirements.htmlx
index 61caffc86823..6ff4966672e2 100644
--- a/Documentation/RCU/Design/Requirements/Requirements.htmlx
+++ b/Documentation/RCU/Design/Requirements/Requirements.htmlx
@@ -2398,6 +2398,8 @@ described in a separate section.
 <li>	<a href="#Sched Flavor">Sched Flavor</a>
 <li>	<a href="#Sleepable RCU">Sleepable RCU</a>
 <li>	<a href="#Tasks RCU">Tasks RCU</a>
+<li>	<a href="#Waiting for Multiple Grace Periods">
+	Waiting for Multiple Grace Periods</a>
 </ol>
 
 <h3><a name="Bottom-Half Flavor">Bottom-Half Flavor</a></h3>
@@ -2647,6 +2649,86 @@ The tasks-RCU API is quite compact, consisting only of
 <tt>synchronize_rcu_tasks()</tt>, and
 <tt>rcu_barrier_tasks()</tt>.
 
+<h3><a name="Waiting for Multiple Grace Periods">
+Waiting for Multiple Grace Periods</a></h3>
+
+<p>
+Perhaps you have an RCU protected data structure that is accessed from
+RCU read-side critical sections, from softirq handlers, and from
+hardware interrupt handlers.
+That is three flavors of RCU, the normal flavor, the bottom-half flavor,
+and the sched flavor.
+How to wait for a compound grace period?
+
+<p>
+The best approach is usually to &ldquo;just say no!&rdquo; and
+insert <tt>rcu_read_lock()</tt> and <tt>rcu_read_unlock()</tt>
+around each RCU read-side critical section, regardless of what
+environment it happens to be in.
+But suppose that some of the RCU read-side critical sections are
+on extremely hot code paths, and that use of <tt>CONFIG_PREEMPT=n</tt>
+is not a viable option, so that <tt>rcu_read_lock()</tt> and
+<tt>rcu_read_unlock()</tt> are not free.
+What then?
+
+<p>
+You <i>could</i> wait on all three grace periods in succession, as follows:
+
+<blockquote>
+<pre>
+ 1 synchronize_rcu();
+ 2 synchronize_rcu_bh();
+ 3 synchronize_sched();
+</pre>
+</blockquote>
+
+<p>
+This works, but triples the update-side latency penalty.
+In cases where this is not acceptable, <tt>synchronize_rcu_mult()</tt>
+may be used to wait on all three flavors of grace period concurrently:
+
+<blockquote>
+<pre>
+ 1 synchronize_rcu_mult(call_rcu, call_rcu_bh, call_rcu_sched);
+</pre>
+</blockquote>
+
+<p>
+But what if it is necessary to also wait on SRCU?
+This can be done as follows:
+
+<blockquote>
+<pre>
+ 1 static void call_my_srcu(struct rcu_head *head,
+ 2        void (*func)(struct rcu_head *head))
+ 3 {
+ 4   call_srcu(&amp;my_srcu, head, func);
+ 5 }
+ 6
+ 7 synchronize_rcu_mult(call_rcu, call_rcu_bh, call_rcu_sched, call_my_srcu);
+</pre>
+</blockquote>
+
+<p>
+If you needed to wait on multiple different flavors of SRCU
+(but why???), you would need to create a wrapper function resembling
+<tt>call_my_srcu()</tt> for each SRCU flavor.
+
+<p>@@QQ@@
+But what if I need to wait for multiple RCU flavors, but I also need
+the grace periods to be expedited?
+<p>@@QQA@@
+If you are using expedited grace periods, there should be less penalty
+for waiting on them in succession.
+But if that is nevertheless a problem, you can use workqueues or multiple
+kthreads to wait on the various expedited grace periods concurrently.
+<p>@@QQE@@
+
+<p>
+Again, it is usually better to adjust the RCU read-side critical sections
+to use a single flavor of RCU, but when this is not feasible, you can use
+<tt>synchronize_rcu_mult()</tt>.
+
 <h2><a name="Possible Future Changes">Possible Future Changes</a></h2>
 
 <p>
-- 
2.5.2

[toc] | [prev] | [next] | [standalone]


#1341548 — [PATCH tip/core/rcu 13/14] documentation: Explain how RCU's combining tree fights contention

From"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Date2016-02-24 06:20 +0100
Subject[PATCH tip/core/rcu 13/14] documentation: Explain how RCU's combining tree fights contention
Message-ID<r5A1I-87D-27@gated-at.bofh.it>
In reply to#1341505
This commit adds a couple of paragraphs to the description of RCU's
combining tree explaining how the combining tree keeps lock contention
acceptably low, despite RCU grace periods being global operations.

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 .../Design/Data-Structures/Data-Structures.html    | 23 ++++++++++++++++++++++
 .../Design/Data-Structures/Data-Structures.htmlx   | 23 ++++++++++++++++++++++
 2 files changed, 46 insertions(+)

diff --git a/Documentation/RCU/Design/Data-Structures/Data-Structures.html b/Documentation/RCU/Design/Data-Structures/Data-Structures.html
index ba9fbb5177f6..d15744b87b99 100644
--- a/Documentation/RCU/Design/Data-Structures/Data-Structures.html
+++ b/Documentation/RCU/Design/Data-Structures/Data-Structures.html
@@ -100,6 +100,29 @@ On the other hand, you can set <tt>CONFIG_RCU_FANOUT</tt> to be
 as small as 2 if you wish, which would permit only 16 CPUs, which
 is useful for testing.
 
+</p><p>This multi-level combining tree allows us to get most of the
+performance and scalability
+benefits of partitioning, even though RCU grace-period detection is
+inherently a global operation.
+The trick here is that only the last CPU to report a quiescent state
+into a given <tt>rcu_node</tt> structure need advance to the <tt>rcu_node</tt>
+structure at the next level up the tree.
+This means that at the leaf-level <tt>rcu_node</tt> structure, only
+one access out of sixteen will progress up the tree.
+For the internal <tt>rcu_node</tt> structures, the situation is even
+more extreme:  Only one access out of sixty-four will progress up
+the tree.
+Because the vast majority of the CPUs do not progress up the tree,
+the lock contention remains roughly constant up the tree.
+No matter how many CPUs there are in the system, at most 64 quiescent-state
+reports per grace period will progress all the way to the root
+<tt>rcu_node</tt> structure, thus ensuring that the lock contention
+on that root <tt>rcu_node</tt> structure remains acceptably low.
+
+</p><p>In effect, the combining tree acts like a big shock absorber,
+keeping lock contention under control at all tree levels regardless
+of the level of loading on the system.
+
 </p><p>The Linux kernel actually supports multiple flavors of RCU
 running concurrently, so RCU builds separate data structures for each
 flavor.
diff --git a/Documentation/RCU/Design/Data-Structures/Data-Structures.htmlx b/Documentation/RCU/Design/Data-Structures/Data-Structures.htmlx
index c08fd8e9574a..8e88e3e7e2ef 100644
--- a/Documentation/RCU/Design/Data-Structures/Data-Structures.htmlx
+++ b/Documentation/RCU/Design/Data-Structures/Data-Structures.htmlx
@@ -121,6 +121,29 @@ On the other hand, you can set <tt>CONFIG_RCU_FANOUT</tt> to be
 as small as 2 if you wish, which would permit only 16 CPUs, which
 is useful for testing.
 
+</p><p>This multi-level combining tree allows us to get most of the
+performance and scalability
+benefits of partitioning, even though RCU grace-period detection is
+inherently a global operation.
+The trick here is that only the last CPU to report a quiescent state
+into a given <tt>rcu_node</tt> structure need advance to the <tt>rcu_node</tt>
+structure at the next level up the tree.
+This means that at the leaf-level <tt>rcu_node</tt> structure, only
+one access out of sixteen will progress up the tree.
+For the internal <tt>rcu_node</tt> structures, the situation is even
+more extreme:  Only one access out of sixty-four will progress up
+the tree.
+Because the vast majority of the CPUs do not progress up the tree,
+the lock contention remains roughly constant up the tree.
+No matter how many CPUs there are in the system, at most 64 quiescent-state
+reports per grace period will progress all the way to the root
+<tt>rcu_node</tt> structure, thus ensuring that the lock contention
+on that root <tt>rcu_node</tt> structure remains acceptably low.
+
+</p><p>In effect, the combining tree acts like a big shock absorber,
+keeping lock contention under control at all tree levels regardless
+of the level of loading on the system.
+
 </p><p>The Linux kernel actually supports multiple flavors of RCU
 running concurrently, so RCU builds separate data structures for each
 flavor.
-- 
2.5.2

[toc] | [prev] | [next] | [standalone]


#1341549 — [PATCH tip/core/rcu 10/14] documentation: Explain why rcu_read_lock() needs no barrier()

From"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Date2016-02-24 06:20 +0100
Subject[PATCH tip/core/rcu 10/14] documentation: Explain why rcu_read_lock() needs no barrier()
Message-ID<r5A1I-87D-29@gated-at.bofh.it>
In reply to#1341505
This commit adds a Quick Quiz whose answer explains why the compiler
code reordering enabled by CONFIG_PREEMPT=n's empty rcu_read_lock()
and rcu_read_unlock() functions does not hinder RCU's ability to figure
out which RCU read-side critical sections have completed and not.

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 .../RCU/Design/Requirements/Requirements.html      | 130 ++++++++++++++-------
 .../RCU/Design/Requirements/Requirements.htmlx     |  28 +++++
 2 files changed, 115 insertions(+), 43 deletions(-)

diff --git a/Documentation/RCU/Design/Requirements/Requirements.html b/Documentation/RCU/Design/Requirements/Requirements.html
index 59acd82e67d4..2a56031bfdd4 100644
--- a/Documentation/RCU/Design/Requirements/Requirements.html
+++ b/Documentation/RCU/Design/Requirements/Requirements.html
@@ -583,6 +583,17 @@ The first and second guarantees require unbelievably strict ordering!
 Are all these memory barriers <i> really</i> required?
 <br><a href="#qq6answer">Answer</a>
 
+<p><a name="Quick Quiz 7"><b>Quick Quiz 7</b>:</a>
+You claim that <tt>rcu_read_lock()</tt> and <tt>rcu_read_unlock()</tt>
+generate absolutely no code in some kernel builds.
+This means that the compiler might arbitrarily rearrange consecutive
+RCU read-side critical sections.
+Given such rearrangement, if a given RCU read-side critical section
+is done, how can you be sure that all prior RCU read-side critical
+sections are done?
+Won't the compiler rearrangements make that impossible to determine?
+<br><a href="#qq7answer">Answer</a>
+
 <p>
 Note that these memory-barrier requirements do not replace the fundamental
 RCU requirement that a grace period wait for all pre-existing readers.
@@ -626,9 +637,9 @@ inconvenience can be avoided through use of the
 <tt>call_rcu()</tt> and <tt>kfree_rcu()</tt> API members
 described later in this document.
 
-<p><a name="Quick Quiz 7"><b>Quick Quiz 7</b>:</a>
+<p><a name="Quick Quiz 8"><b>Quick Quiz 8</b>:</a>
 But how does the upgrade-to-write operation exclude other readers?
-<br><a href="#qq7answer">Answer</a>
+<br><a href="#qq8answer">Answer</a>
 
 <p>
 This guarantee allows lookup code to be shared between read-side
@@ -714,9 +725,9 @@ to do significant reordering.
 This is by design:  Any significant ordering constraints would slow down
 these fast-path APIs.
 
-<p><a name="Quick Quiz 8"><b>Quick Quiz 8</b>:</a>
+<p><a name="Quick Quiz 9"><b>Quick Quiz 9</b>:</a>
 Can't the compiler also reorder this code?
-<br><a href="#qq8answer">Answer</a>
+<br><a href="#qq9answer">Answer</a>
 
 <h3><a name="Readers Do Not Exclude Updaters">Readers Do Not Exclude Updaters</a></h3>
 
@@ -769,10 +780,10 @@ new readers can start immediately after <tt>synchronize_rcu()</tt>
 starts, and <tt>synchronize_rcu()</tt> is under no
 obligation to wait for these new readers.
 
-<p><a name="Quick Quiz 9"><b>Quick Quiz 9</b>:</a>
+<p><a name="Quick Quiz 10"><b>Quick Quiz 10</b>:</a>
 Suppose that synchronize_rcu() did wait until all readers had completed.
 Would the updater be able to rely on this?
-<br><a href="#qq9answer">Answer</a>
+<br><a href="#qq10answer">Answer</a>
 
 <h3><a name="Grace Periods Don't Partition Read-Side Critical Sections">
 Grace Periods Don't Partition Read-Side Critical Sections</a></h3>
@@ -969,11 +980,11 @@ grace period.
 As a result, an RCU read-side critical section cannot partition a pair
 of RCU grace periods.
 
-<p><a name="Quick Quiz 10"><b>Quick Quiz 10</b>:</a>
+<p><a name="Quick Quiz 11"><b>Quick Quiz 11</b>:</a>
 How long a sequence of grace periods, each separated by an RCU read-side
 critical section, would be required to partition the RCU read-side
 critical sections at the beginning and end of the chain?
-<br><a href="#qq10answer">Answer</a>
+<br><a href="#qq11answer">Answer</a>
 
 <h3><a name="Disabling Preemption Does Not Block Grace Periods">
 Disabling Preemption Does Not Block Grace Periods</a></h3>
@@ -1127,9 +1138,9 @@ synchronization primitives be legal within RCU read-side critical sections,
 including spinlocks, sequence locks, atomic operations, reference
 counters, and memory barriers.
 
-<p><a name="Quick Quiz 11"><b>Quick Quiz 11</b>:</a>
+<p><a name="Quick Quiz 12"><b>Quick Quiz 12</b>:</a>
 What about sleeping locks?
-<br><a href="#qq11answer">Answer</a>
+<br><a href="#qq12answer">Answer</a>
 
 <p>
 It often comes as a surprise that many algorithms do not require a
@@ -1354,12 +1365,12 @@ write an RCU callback function that takes too long.
 Long-running operations should be relegated to separate threads or
 (in the Linux kernel) workqueues.
 
-<p><a name="Quick Quiz 12"><b>Quick Quiz 12</b>:</a>
+<p><a name="Quick Quiz 13"><b>Quick Quiz 13</b>:</a>
 Why does line&nbsp;19 use <tt>rcu_access_pointer()</tt>?
 After all, <tt>call_rcu()</tt> on line&nbsp;25 stores into the
 structure, which would interact badly with concurrent insertions.
 Doesn't this mean that <tt>rcu_dereference()</tt> is required?
-<br><a href="#qq12answer">Answer</a>
+<br><a href="#qq13answer">Answer</a>
 
 <p>
 However, all that <tt>remove_gp_cb()</tt> is doing is
@@ -1406,14 +1417,14 @@ This was due to the fact that RCU was not heavily used within DYNIX/ptx,
 so the very few places that needed something like
 <tt>synchronize_rcu()</tt> simply open-coded it.
 
-<p><a name="Quick Quiz 13"><b>Quick Quiz 13</b>:</a>
+<p><a name="Quick Quiz 14"><b>Quick Quiz 14</b>:</a>
 Earlier it was claimed that <tt>call_rcu()</tt> and
 <tt>kfree_rcu()</tt> allowed updaters to avoid being blocked
 by readers.
 But how can that be correct, given that the invocation of the callback
 and the freeing of the memory (respectively) must still wait for
 a grace period to elapse?
-<br><a href="#qq13answer">Answer</a>
+<br><a href="#qq14answer">Answer</a>
 
 <p>
 But what if the updater must wait for the completion of code to be
@@ -1838,11 +1849,11 @@ kthreads to be spawned.
 Therefore, invoking <tt>synchronize_rcu()</tt> during scheduler
 initialization can result in deadlock.
 
-<p><a name="Quick Quiz 14"><b>Quick Quiz 14</b>:</a>
+<p><a name="Quick Quiz 15"><b>Quick Quiz 15</b>:</a>
 So what happens with <tt>synchronize_rcu()</tt> during
 scheduler initialization for <tt>CONFIG_PREEMPT=n</tt>
 kernels?
-<br><a href="#qq14answer">Answer</a>
+<br><a href="#qq15answer">Answer</a>
 
 <p>
 I learned of these boot-time requirements as a result of a series of
@@ -2547,10 +2558,10 @@ If you needed to wait on multiple different flavors of SRCU
 (but why???), you would need to create a wrapper function resembling
 <tt>call_my_srcu()</tt> for each SRCU flavor.
 
-<p><a name="Quick Quiz 15"><b>Quick Quiz 15</b>:</a>
+<p><a name="Quick Quiz 16"><b>Quick Quiz 16</b>:</a>
 But what if I need to wait for multiple RCU flavors, but I also need
 the grace periods to be expedited?
-<br><a href="#qq15answer">Answer</a>
+<br><a href="#qq16answer">Answer</a>
 
 <p>
 Again, it is usually better to adjust the RCU read-side critical sections
@@ -2827,18 +2838,51 @@ adhered to the as-if rule than it is to actually adhere to it!
 
 <a name="qq7answer"></a>
 <p><b>Quick Quiz 7</b>:
-But how does the upgrade-to-write operation exclude other readers?
+You claim that <tt>rcu_read_lock()</tt> and <tt>rcu_read_unlock()</tt>
+generate absolutely no code in some kernel builds.
+This means that the compiler might arbitrarily rearrange consecutive
+RCU read-side critical sections.
+Given such rearrangement, if a given RCU read-side critical section
+is done, how can you be sure that all prior RCU read-side critical
+sections are done?
+Won't the compiler rearrangements make that impossible to determine?
 
 
 </p><p><b>Answer</b>:
-It doesn't, just like normal RCU updates, which also do not exclude
-RCU readers.
+In cases where <tt>rcu_read_lock()</tt> and <tt>rcu_read_unlock()</tt>
+generate absolutely no code, RCU infers quiescent states only at
+special locations, for example, within the scheduler.
+Because calls to <tt>schedule()</tt> had better prevent calling-code
+accesses to shared variables from being rearranged across the call to
+<tt>schedule()</tt>, if RCU detects the end of a given RCU read-side
+critical section, it will necessarily detect the end of all prior
+RCU read-side critical sections, no matter how aggressively the
+compiler scrambles the code.
+
+<p>
+Again, this all assumes that the compiler cannot scramble code across
+calls to the scheduler, out of interrupt handlers, into the idle loop,
+into user-mode code, and so on.
+But if your kernel build allows that sort of scrambling, you have broken
+far more than just RCU!
 
 
 </p><p><a href="#Quick%20Quiz%207"><b>Back to Quick Quiz 7</b>.</a>
 
 <a name="qq8answer"></a>
 <p><b>Quick Quiz 8</b>:
+But how does the upgrade-to-write operation exclude other readers?
+
+
+</p><p><b>Answer</b>:
+It doesn't, just like normal RCU updates, which also do not exclude
+RCU readers.
+
+
+</p><p><a href="#Quick%20Quiz%208"><b>Back to Quick Quiz 8</b>.</a>
+
+<a name="qq9answer"></a>
+<p><b>Quick Quiz 9</b>:
 Can't the compiler also reorder this code?
 
 
@@ -2848,10 +2892,10 @@ No, the volatile casts in <tt>READ_ONCE()</tt> and
 this particular case.
 
 
-</p><p><a href="#Quick%20Quiz%208"><b>Back to Quick Quiz 8</b>.</a>
+</p><p><a href="#Quick%20Quiz%209"><b>Back to Quick Quiz 9</b>.</a>
 
-<a name="qq9answer"></a>
-<p><b>Quick Quiz 9</b>:
+<a name="qq10answer"></a>
+<p><b>Quick Quiz 10</b>:
 Suppose that synchronize_rcu() did wait until all readers had completed.
 Would the updater be able to rely on this?
 
@@ -2866,10 +2910,10 @@ Therefore, the code following
 in any case.
 
 
-</p><p><a href="#Quick%20Quiz%209"><b>Back to Quick Quiz 9</b>.</a>
+</p><p><a href="#Quick%20Quiz%2010"><b>Back to Quick Quiz 10</b>.</a>
 
-<a name="qq10answer"></a>
-<p><b>Quick Quiz 10</b>:
+<a name="qq11answer"></a>
+<p><b>Quick Quiz 11</b>:
 How long a sequence of grace periods, each separated by an RCU read-side
 critical section, would be required to partition the RCU read-side
 critical sections at the beginning and end of the chain?
@@ -2883,10 +2927,10 @@ Therefore, even in practice, RCU users must abide by the theoretical rather
 than the practical answer.
 
 
-</p><p><a href="#Quick%20Quiz%2010"><b>Back to Quick Quiz 10</b>.</a>
+</p><p><a href="#Quick%20Quiz%2011"><b>Back to Quick Quiz 11</b>.</a>
 
-<a name="qq11answer"></a>
-<p><b>Quick Quiz 11</b>:
+<a name="qq12answer"></a>
+<p><b>Quick Quiz 12</b>:
 What about sleeping locks?
 
 
@@ -2914,10 +2958,10 @@ the mutex was not immediately available.
 Either way, <tt>mutex_trylock()</tt> returns immediately without sleeping.
 
 
-</p><p><a href="#Quick%20Quiz%2011"><b>Back to Quick Quiz 11</b>.</a>
+</p><p><a href="#Quick%20Quiz%2012"><b>Back to Quick Quiz 12</b>.</a>
 
-<a name="qq12answer"></a>
-<p><b>Quick Quiz 12</b>:
+<a name="qq13answer"></a>
+<p><b>Quick Quiz 13</b>:
 Why does line&nbsp;19 use <tt>rcu_access_pointer()</tt>?
 After all, <tt>call_rcu()</tt> on line&nbsp;25 stores into the
 structure, which would interact badly with concurrent insertions.
@@ -2933,10 +2977,10 @@ is released on line&nbsp;25, which in turn means that
 <tt>rcu_access_pointer()</tt> suffices.
 
 
-</p><p><a href="#Quick%20Quiz%2012"><b>Back to Quick Quiz 12</b>.</a>
+</p><p><a href="#Quick%20Quiz%2013"><b>Back to Quick Quiz 13</b>.</a>
 
-<a name="qq13answer"></a>
-<p><b>Quick Quiz 13</b>:
+<a name="qq14answer"></a>
+<p><b>Quick Quiz 14</b>:
 Earlier it was claimed that <tt>call_rcu()</tt> and
 <tt>kfree_rcu()</tt> allowed updaters to avoid being blocked
 by readers.
@@ -2957,10 +3001,10 @@ next update as soon as it has invoked <tt>call_rcu()</tt> or
 grace period.
 
 
-</p><p><a href="#Quick%20Quiz%2013"><b>Back to Quick Quiz 13</b>.</a>
+</p><p><a href="#Quick%20Quiz%2014"><b>Back to Quick Quiz 14</b>.</a>
 
-<a name="qq14answer"></a>
-<p><b>Quick Quiz 14</b>:
+<a name="qq15answer"></a>
+<p><b>Quick Quiz 15</b>:
 So what happens with <tt>synchronize_rcu()</tt> during
 scheduler initialization for <tt>CONFIG_PREEMPT=n</tt>
 kernels?
@@ -2976,10 +3020,10 @@ so it is still necessary to avoid invoking <tt>synchronize_rcu()</tt>
 during scheduler initialization.
 
 
-</p><p><a href="#Quick%20Quiz%2014"><b>Back to Quick Quiz 14</b>.</a>
+</p><p><a href="#Quick%20Quiz%2015"><b>Back to Quick Quiz 15</b>.</a>
 
-<a name="qq15answer"></a>
-<p><b>Quick Quiz 15</b>:
+<a name="qq16answer"></a>
+<p><b>Quick Quiz 16</b>:
 But what if I need to wait for multiple RCU flavors, but I also need
 the grace periods to be expedited?
 
@@ -2991,7 +3035,7 @@ But if that is nevertheless a problem, you can use workqueues or multiple
 kthreads to wait on the various expedited grace periods concurrently.
 
 
-</p><p><a href="#Quick%20Quiz%2015"><b>Back to Quick Quiz 15</b>.</a>
+</p><p><a href="#Quick%20Quiz%2016"><b>Back to Quick Quiz 16</b>.</a>
 
 
 </body></html>
diff --git a/Documentation/RCU/Design/Requirements/Requirements.htmlx b/Documentation/RCU/Design/Requirements/Requirements.htmlx
index 6ff4966672e2..98da30ca84c4 100644
--- a/Documentation/RCU/Design/Requirements/Requirements.htmlx
+++ b/Documentation/RCU/Design/Requirements/Requirements.htmlx
@@ -682,6 +682,34 @@ That said, it is much easier to fool yourself into believing that you have
 adhered to the as-if rule than it is to actually adhere to it!
 <p>@@QQE@@
 
+<p>@@QQ@@
+You claim that <tt>rcu_read_lock()</tt> and <tt>rcu_read_unlock()</tt>
+generate absolutely no code in some kernel builds.
+This means that the compiler might arbitrarily rearrange consecutive
+RCU read-side critical sections.
+Given such rearrangement, if a given RCU read-side critical section
+is done, how can you be sure that all prior RCU read-side critical
+sections are done?
+Won't the compiler rearrangements make that impossible to determine?
+<p>@@QQA@@
+In cases where <tt>rcu_read_lock()</tt> and <tt>rcu_read_unlock()</tt>
+generate absolutely no code, RCU infers quiescent states only at
+special locations, for example, within the scheduler.
+Because calls to <tt>schedule()</tt> had better prevent calling-code
+accesses to shared variables from being rearranged across the call to
+<tt>schedule()</tt>, if RCU detects the end of a given RCU read-side
+critical section, it will necessarily detect the end of all prior
+RCU read-side critical sections, no matter how aggressively the
+compiler scrambles the code.
+
+<p>
+Again, this all assumes that the compiler cannot scramble code across
+calls to the scheduler, out of interrupt handlers, into the idle loop,
+into user-mode code, and so on.
+But if your kernel build allows that sort of scrambling, you have broken
+far more than just RCU!
+<p>@@QQE@@
+
 <p>
 Note that these memory-barrier requirements do not replace the fundamental
 RCU requirement that a grace period wait for all pre-existing readers.
-- 
2.5.2

[toc] | [prev] | [next] | [standalone]


#1341552 — [PATCH tip/core/rcu 03/14] documentation: Fix memory-barriers.txt section references

From"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Date2016-02-24 06:20 +0100
Subject[PATCH tip/core/rcu 03/14] documentation: Fix memory-barriers.txt section references
Message-ID<r5A1J-87D-33@gated-at.bofh.it>
In reply to#1341505
This commit fixes a couple of "Compiler Barrier" section references to
be "COMPILER BARRIER".  This makes it easier to find the section in
the usual text editors.

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 Documentation/memory-barriers.txt | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index e26058d3e253..c90922b9b294 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -232,7 +232,7 @@ And there are a number of things that _must_ or _must_not_ be assumed:
      with memory references that are not protected by READ_ONCE() and
      WRITE_ONCE().  Without them, the compiler is within its rights to
      do all sorts of "creative" transformations, which are covered in
-     the Compiler Barrier section.
+     the COMPILER BARRIER section.
 
  (*) It _must_not_ be assumed that independent loads and stores will be issued
      in the order given.  This means that for:
@@ -818,7 +818,7 @@ In summary:
   (*) Control dependencies require that the compiler avoid reordering the
       dependency into nonexistence.  Careful use of READ_ONCE() or
       atomic{,64}_read() can help to preserve your control dependency.
-      Please see the Compiler Barrier section for more information.
+      Please see the COMPILER BARRIER section for more information.
 
   (*) Control dependencies pair normally with other types of barriers.
 
-- 
2.5.2

[toc] | [prev] | [next] | [standalone]


#1341554 — [PATCH tip/core/rcu 02/14] documentation: Fix control dependency and identical stores

From"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Date2016-02-24 06:20 +0100
Subject[PATCH tip/core/rcu 02/14] documentation: Fix control dependency and identical stores
Message-ID<r5A1J-87D-37@gated-at.bofh.it>
In reply to#1341505
The summary of the "CONTROL DEPENDENCIES" section incorrectly states that
barrier() may be used to prevent compiler reordering when more than one
leg of the control-dependent "if" statement start with identical stores.
This is incorrect at high optimization levels.  This commit therefore
updates the summary to match the detailed description.

Reported by: Jianyu Zhan <nasa4836@gmail.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 Documentation/memory-barriers.txt | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index 904ee42d078e..e26058d3e253 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -800,9 +800,13 @@ In summary:
       use smp_rmb(), smp_wmb(), or, in the case of prior stores and
       later loads, smp_mb().
 
-  (*) If both legs of the "if" statement begin with identical stores
-      to the same variable, a barrier() statement is required at the
-      beginning of each leg of the "if" statement.
+  (*) If both legs of the "if" statement begin with identical stores to
+      the same variable, then those stores must be ordered, either by
+      preceding both of them with smp_mb() or by using smp_store_release()
+      to carry out the stores.  Please note that it is -not- sufficient
+      to use barrier() at beginning of each leg of the "if" statement,
+      as optimizing compilers do not necessarily respect barrier()
+      in this case.
 
   (*) Control dependencies require at least one run-time conditional
       between the prior load and the subsequent store, and this
-- 
2.5.2

[toc] | [prev] | [next] | [standalone]


#1342441 — Re: [PATCH tip/core/rcu 02/14] documentation: Fix control dependency and identical stores

FromMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Date2016-02-24 22:20 +0100
SubjectRe: [PATCH tip/core/rcu 02/14] documentation: Fix control dependency and identical stores
Message-ID<r5P0K-1T4-9@gated-at.bofh.it>
In reply to#1341554
----- On Feb 24, 2016, at 12:00 AM, Paul E. McKenney paulmck@linux.vnet.ibm.com wrote:

> The summary of the "CONTROL DEPENDENCIES" section incorrectly states that
> barrier() may be used to prevent compiler reordering when more than one
> leg of the control-dependent "if" statement start with identical stores.
> This is incorrect at high optimization levels.  This commit therefore
> updates the summary to match the detailed description.
> 
> Reported by: Jianyu Zhan <nasa4836@gmail.com>
> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
> ---
> Documentation/memory-barriers.txt | 10 +++++++---
> 1 file changed, 7 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/memory-barriers.txt
> b/Documentation/memory-barriers.txt
> index 904ee42d078e..e26058d3e253 100644
> --- a/Documentation/memory-barriers.txt
> +++ b/Documentation/memory-barriers.txt
> @@ -800,9 +800,13 @@ In summary:
>       use smp_rmb(), smp_wmb(), or, in the case of prior stores and
>       later loads, smp_mb().
> 
> -  (*) If both legs of the "if" statement begin with identical stores
> -      to the same variable, a barrier() statement is required at the
> -      beginning of each leg of the "if" statement.
> +  (*) If both legs of the "if" statement begin with identical stores to
> +      the same variable, then those stores must be ordered, either by
> +      preceding both of them with smp_mb() or by using smp_store_release()
> +      to carry out the stores.  Please note that it is -not- sufficient
> +      to use barrier() at beginning of each leg of the "if" statement,
> +      as optimizing compilers do not necessarily respect barrier()
> +      in this case.

Hrm, I really don't understand this one.

One caveat, as stated here, would be that optimizing compilers
can reorder instruction with respect to barrier() placed at the
beginning of if/else legs that start with identical stores.

It goes on stating that "smp_mb() or smp_store_release()" should
be used rather than barrier() in those cases.

I don't get how, from a compiler optimization perspective,
barrier() is any different from smp_mb().

#define barrier() __asm__ __volatile__("": : :"memory")

vs

#define mb()    asm volatile("mfence":::"memory")

What the compiler would observe is a "memory" clobber in both
cases.

Now if the stated cause of this issue would have been
internal reordering of those identical stores within the
processor, I would understand that smp_mb() has an
effect which differs from the compiler barrier, but since
the paragraph begins by stating that this is purely for
compiler optimizations, I'm confused.

What am I missing there ?

Thanks,

Mathieu


> 
>   (*) Control dependencies require at least one run-time conditional
>       between the prior load and the subsequent store, and this
> --
> 2.5.2

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

[toc] | [prev] | [next] | [standalone]


#1342459 — Re: [PATCH tip/core/rcu 02/14] documentation: Fix control dependency and identical stores

From"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Date2016-02-24 22:50 +0100
SubjectRe: [PATCH tip/core/rcu 02/14] documentation: Fix control dependency and identical stores
Message-ID<r5PtM-2bk-7@gated-at.bofh.it>
In reply to#1342441
On Wed, Feb 24, 2016 at 09:12:04PM +0000, Mathieu Desnoyers wrote:
> ----- On Feb 24, 2016, at 12:00 AM, Paul E. McKenney paulmck@linux.vnet.ibm.com wrote:
> 
> > The summary of the "CONTROL DEPENDENCIES" section incorrectly states that
> > barrier() may be used to prevent compiler reordering when more than one
> > leg of the control-dependent "if" statement start with identical stores.
> > This is incorrect at high optimization levels.  This commit therefore
> > updates the summary to match the detailed description.
> > 
> > Reported by: Jianyu Zhan <nasa4836@gmail.com>
> > Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
> > ---
> > Documentation/memory-barriers.txt | 10 +++++++---
> > 1 file changed, 7 insertions(+), 3 deletions(-)
> > 
> > diff --git a/Documentation/memory-barriers.txt
> > b/Documentation/memory-barriers.txt
> > index 904ee42d078e..e26058d3e253 100644
> > --- a/Documentation/memory-barriers.txt
> > +++ b/Documentation/memory-barriers.txt
> > @@ -800,9 +800,13 @@ In summary:
> >       use smp_rmb(), smp_wmb(), or, in the case of prior stores and
> >       later loads, smp_mb().
> > 
> > -  (*) If both legs of the "if" statement begin with identical stores
> > -      to the same variable, a barrier() statement is required at the
> > -      beginning of each leg of the "if" statement.
> > +  (*) If both legs of the "if" statement begin with identical stores to
> > +      the same variable, then those stores must be ordered, either by
> > +      preceding both of them with smp_mb() or by using smp_store_release()
> > +      to carry out the stores.  Please note that it is -not- sufficient
> > +      to use barrier() at beginning of each leg of the "if" statement,
> > +      as optimizing compilers do not necessarily respect barrier()
> > +      in this case.
> 
> Hrm, I really don't understand this one.
> 
> One caveat, as stated here, would be that optimizing compilers
> can reorder instruction with respect to barrier() placed at the
> beginning of if/else legs that start with identical stores.
> 
> It goes on stating that "smp_mb() or smp_store_release()" should
> be used rather than barrier() in those cases.
> 
> I don't get how, from a compiler optimization perspective,
> barrier() is any different from smp_mb().
> 
> #define barrier() __asm__ __volatile__("": : :"memory")
> 
> vs
> 
> #define mb()    asm volatile("mfence":::"memory")
> 
> What the compiler would observe is a "memory" clobber in both
> cases.
> 
> Now if the stated cause of this issue would have been
> internal reordering of those identical stores within the
> processor, I would understand that smp_mb() has an
> effect which differs from the compiler barrier, but since
> the paragraph begins by stating that this is purely for
> compiler optimizations, I'm confused.
> 
> What am I missing there ?
> 
> Thanks,
> 
> Mathieu
> 
> 
> > 
> >   (*) Control dependencies require at least one run-time conditional
> >       between the prior load and the subsequent store, and this

Let's take the example, replace barrier() with smp_mb(), and see what
happens:

	q = READ_ONCE(a);
	if (q) {
		smp_mb();
		WRITE_ONCE(b, p);
		do_something();
	} else {
		smp_mb();
		WRITE_ONCE(b, p);
		do_something_else();
	}

Given the same compiler transformation:

	q = READ_ONCE(a);
	smp_mb();
	WRITE_ONCE(b, p);  /* BUG: No ordering vs. load from a!!! */
	if (q) {
		/* WRITE_ONCE(b, p); -- moved up, BUG!!! */
		do_something();
	} else {
		/* WRITE_ONCE(b, p); -- moved up, BUG!!! */
		do_something_else();
	}

So ordering between the read from "a" and the write to "b" is still
preserved.  The reason this works is that the smp_mb() does all the
ordering, so the fact that the control dependency has been eliminated
is irrelevant.

							Thanx, Paul

[toc] | [prev] | [next] | [standalone]


#1342882 — Re: [PATCH tip/core/rcu 02/14] documentation: Fix control dependency and identical stores

FromJianyu Zhan <nasa4836@gmail.com>
Date2016-02-25 07:50 +0100
SubjectRe: [PATCH tip/core/rcu 02/14] documentation: Fix control dependency and identical stores
Message-ID<r5XUm-8jN-13@gated-at.bofh.it>
In reply to#1342459
On Thu, Feb 25, 2016 at 5:40 AM, Paul E. McKenney
<paulmck@linux.vnet.ibm.com> wrote:
> So ordering between the read from "a" and the write to "b" is still
> preserved.  The reason this works is that the smp_mb() does all the
> ordering, so the fact that the control dependency has been eliminated
> is irrelevant.


Thanks, Paul,  nice clarification.

I thinks this example qualifies as an good example to demonstrate the subtle
scope of effect of these two level barriers.

A vivid example is always better for understanding instead of learning
"barrier() is compiler-level
barrier, and smp_*mb() is processor-level barrier" by rote ,
especially for the new comers to memory-barriers.txt. ;-)




Thanks,
Jianyu Zhan

[toc] | [prev] | [next] | [standalone]


#1343185 — Re: [PATCH tip/core/rcu 02/14] documentation: Fix control dependency and identical stores

From"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Date2016-02-25 15:10 +0100
SubjectRe: [PATCH tip/core/rcu 02/14] documentation: Fix control dependency and identical stores
Message-ID<r64Mb-4WY-25@gated-at.bofh.it>
In reply to#1342882
On Thu, Feb 25, 2016 at 02:41:07PM +0800, Jianyu Zhan wrote:
> On Thu, Feb 25, 2016 at 5:40 AM, Paul E. McKenney
> <paulmck@linux.vnet.ibm.com> wrote:
> > So ordering between the read from "a" and the write to "b" is still
> > preserved.  The reason this works is that the smp_mb() does all the
> > ordering, so the fact that the control dependency has been eliminated
> > is irrelevant.
> 
> 
> Thanks, Paul,  nice clarification.
> 
> I thinks this example qualifies as an good example to demonstrate the subtle
> scope of effect of these two level barriers.
> 
> A vivid example is always better for understanding instead of learning
> "barrier() is compiler-level
> barrier, and smp_*mb() is processor-level barrier" by rote ,
> especially for the new comers to memory-barriers.txt. ;-)

Glad you like it.  ;-)

							Thanx, Paul

[toc] | [prev] | [next] | [standalone]


#1342962 — Re: [PATCH tip/core/rcu 02/14] documentation: Fix control dependency and identical stores

FromPeter Zijlstra <peterz@infradead.org>
Date2016-02-25 09:30 +0100
SubjectRe: [PATCH tip/core/rcu 02/14] documentation: Fix control dependency and identical stores
Message-ID<r5Zt8-120-19@gated-at.bofh.it>
In reply to#1342459
On Wed, Feb 24, 2016 at 01:40:13PM -0800, Paul E. McKenney wrote:
> > > +  (*) If both legs of the "if" statement begin with identical stores to
> > > +      the same variable, then those stores must be ordered, either by
> > > +      preceding both of them with smp_mb() or by using smp_store_release()
> > > +      to carry out the stores.  Please note that it is -not- sufficient
> > > +      to use barrier() at beginning of each leg of the "if" statement,
> > > +      as optimizing compilers do not necessarily respect barrier()
> > > +      in this case.

> Let's take the example, replace barrier() with smp_mb(), and see what
> happens:
> 
> 	q = READ_ONCE(a);
> 	if (q) {
> 		smp_mb();
> 		WRITE_ONCE(b, p);
> 		do_something();
> 	} else {
> 		smp_mb();
> 		WRITE_ONCE(b, p);
> 		do_something_else();
> 	}

Why would an optimizing compiler be allowed to lift _anything_ over a
barrier() ? Isn't that a bug?

I thought the whole point of barrier() was to tell the compiler to not
do such things.

[toc] | [prev] | [next] | [standalone]


#1343184 — Re: [PATCH tip/core/rcu 02/14] documentation: Fix control dependency and identical stores

From"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Date2016-02-25 15:10 +0100
SubjectRe: [PATCH tip/core/rcu 02/14] documentation: Fix control dependency and identical stores
Message-ID<r64Mb-4WY-21@gated-at.bofh.it>
In reply to#1342962
On Thu, Feb 25, 2016 at 09:21:43AM +0100, Peter Zijlstra wrote:
> On Wed, Feb 24, 2016 at 01:40:13PM -0800, Paul E. McKenney wrote:
> > > > +  (*) If both legs of the "if" statement begin with identical stores to
> > > > +      the same variable, then those stores must be ordered, either by
> > > > +      preceding both of them with smp_mb() or by using smp_store_release()
> > > > +      to carry out the stores.  Please note that it is -not- sufficient
> > > > +      to use barrier() at beginning of each leg of the "if" statement,
> > > > +      as optimizing compilers do not necessarily respect barrier()
> > > > +      in this case.
> 
> > Let's take the example, replace barrier() with smp_mb(), and see what
> > happens:
> > 
> > 	q = READ_ONCE(a);
> > 	if (q) {
> > 		smp_mb();
> > 		WRITE_ONCE(b, p);
> > 		do_something();
> > 	} else {
> > 		smp_mb();
> > 		WRITE_ONCE(b, p);
> > 		do_something_else();
> > 	}
> 
> Why would an optimizing compiler be allowed to lift _anything_ over a
> barrier() ? Isn't that a bug?
> 
> I thought the whole point of barrier() was to tell the compiler to not
> do such things.

Still bad wording...

It hasn't actually moved anything over the barrier().  It has instead
moved both the barrier() and the WRITE_ONCE(b, p) to precede the "if
(q)".  Mathieu mentioned this over IRC yesterday, and I queue a change
so that the paragraph now reads as follows:

  (*) If both legs of the "if" statement begin with identical stores to
      the same variable, then those stores must be ordered, either by
      preceding both of them with smp_mb() or by using smp_store_release()
      to carry out the stores.  Please note that it is -not- sufficient
      to use barrier() at beginning of each leg of the "if" statement
      because, as shown by the example above, optimizing compilers can
      destroy the control dependency while respecting the letter of the
      barrier() law.

Does hat help?

							Thanx, Paul

[toc] | [prev] | [next] | [standalone]


#1343217 — Re: [PATCH tip/core/rcu 02/14] documentation: Fix control dependency and identical stores

FromPeter Zijlstra <peterz@infradead.org>
Date2016-02-25 15:50 +0100
SubjectRe: [PATCH tip/core/rcu 02/14] documentation: Fix control dependency and identical stores
Message-ID<r65oS-5fy-25@gated-at.bofh.it>
In reply to#1343184
On Thu, Feb 25, 2016 at 06:07:03AM -0800, Paul E. McKenney wrote:
> Still bad wording...
> 
> It hasn't actually moved anything over the barrier().  It has instead
> moved both the barrier() and the WRITE_ONCE(b, p) to precede the "if
> (q)".  Mathieu mentioned this over IRC yesterday, and I queue a change
> so that the paragraph now reads as follows:
> 
>   (*) If both legs of the "if" statement begin with identical stores to
>       the same variable, then those stores must be ordered, either by
>       preceding both of them with smp_mb() or by using smp_store_release()
>       to carry out the stores.  Please note that it is -not- sufficient
>       to use barrier() at beginning of each leg of the "if" statement
>       because, as shown by the example above, optimizing compilers can
>       destroy the control dependency while respecting the letter of the
>       barrier() law.
> 
> Does hat help?

Maybe.. I still feel the compiler should not do this; but I'm having a
hard time explaining why.

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | linux.kernel


csiph-web