From: "Paul E. McKenney" <paulmck@linux.ibm.com>
To: Akira Yokosawa <akiyks@gmail.com>
Cc: perfbook@vger.kernel.org
Subject: Re: lockless_dereference() in perfbook
Date: Sat, 1 Dec 2018 17:10:53 -0800 [thread overview]
Message-ID: <20181202011053.GZ4170@linux.ibm.com> (raw)
In-Reply-To: <1bb21303-4d09-a222-e50e-653e4ac22f09@gmail.com>
On Sun, Dec 02, 2018 at 07:25:21AM +0900, Akira Yokosawa wrote:
> On 2018/12/01 10:30:19 -0800, Paul E. McKenney wrote:
> > On Sat, Dec 01, 2018 at 04:48:03PM +0900, Akira Yokosawa wrote:
> >> Hi Paul,
> >>
> >> As LKMM dropped lockless_dereference() when it was merged in v4.17,
> >> CodeSamples/formal/litmus/C-MP+o-wmb-o+ld-addr-o.litmus fails to
> >> be evaluated by "make run-herd7" under CodeSamples/formal/herd.
> >>
> >> lockless_dereference() is still covered by CodeSamples/formal/litmus/api.h
> >> and klitmus7, so the test can be evaluated by litmus7 and "klitmus7 at the
> >> moment.
> >>
> >> In commit 48ec12dac0c3 ("memorder: Update based on v4.15 Linux kernel
> >> de-Alpha-ication"), you added a footnote in Section 15.2.3 saying:
> >>
> >> Note that lockless_dereference() is not needed on v4.15 and later,
> >> and therefore is not available in these later Linux kernels.
> >>
> >> There remain several lockless_dereference()s in perfbook without any
> >> updates.
> >>
> >> In the Answer to Quick Quiz 15.15, lockless_dereference() is mentioned
> >> several times.
> >>
> >> Quick Quiz 15.17 says:
> >>
> >> Why doesn't line 18 of Listing 15.12 need a lockless_dereference()?
> >>
> >> Leading paragraph of Section 15.3.2.1 says:
> >>
> >> The load that heads your dependency chain must use proper ordering,
> >> for example, lockless_dereference(), rcu_dereference(), or a READ_ONCE()
> >> followed by smp_read_barrier_depends().
> >>
> >> In the middle of Section 15.5, there is a sentence:
> >>
> >> Note also that a dependency leading to a load must be headed by a
> >> lockless_dereference() or an rcu_dereference(): READ_ONCE() is not
> >> sufficient.
> >>
> >> Could you look into them?
> >>
> >> One problem in regard to litmus tests might be that there is no means
> >> to indicate plain accesses with no memory barrier in current LKMM.
> >> At the moment, C-MP+o-wmb-o+o-addr-o.litmus behaves identically as
> >> C-MP+o-wmb-o+ld-addr-o.litmus would do.
> >
> > Good catches! How about the following?
> >
> > 1. I remove CodeSamples/formal/litmus/C-MP+o-wmb-o+ld-addr-o.litmus.
> >
> > 2. I add a comment to the lockless_dereference() call in
> > lst:memorder:Enforced Ordering of Message-Passing Address-Dependency Litmus Test
> > stating that this API member is obsolete.
> >
> > 3. I remove the (\path{C-MP+o-wmb-o+ld-addr-o.litmus}) from the
> > discussion. I also add a LaTeX comment stating which commit
> > removed this file for future reference.
> >
> > 4. I remove lockless_dereference() from CodeSamples/formal/litmus/api.h.
> >
> > Does that sound reasonable?
>
> Yes, it does!
>
> Maybe discussion of
> lst:memorder:Message-Passing Address-Dependency Litmus Test (No Ordering)
> needs further tweaks, including the update of its caption, i.e.,
> it is now _ordered_. Quick Quiz 15.13 looks odd as of now.
>
> And the caption to
> lst:memorder:Enforced Ordering of Message-Passing Address-Dependency Litmus Test
> also needs update to indicate it is not necessary any more.
>
> Looking forward to seeing the update.
How about the following?
Thanx, Paul
------------------------------------------------------------------------
commit c9a15859a4451ee449b8d46dc9845e050acf5760
Author: Paul E. McKenney <paulmck@linux.ibm.com>
Date: Sat Dec 1 17:07:35 2018 -0800
memorder: Clean up reference to lockless_dereference()
The lockless_dereference() primitive has been obsolete since Linux
kernel version v4.15, but it is mentioned in several places in the
memory-ordering chapter and in a litmus test. This commit removes that
litmus test, removes the definition of lockless_dereference(), makes
READ_ONCE() work properly on DEC Alpha, and clearly labels remaining
instances of lockless_dereference() in the text as obsolete.
Reported-by: Akira Yokosawa <akiyks@gmail.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.ibm.com>
diff --git a/CodeSamples/formal/litmus/C-MP+o-wmb-o+ld-addr-o.litmus b/CodeSamples/formal/litmus/C-MP+o-wmb-o+ld-addr-o.litmus
deleted file mode 100644
index 117a6e3ffda8..000000000000
--- a/CodeSamples/formal/litmus/C-MP+o-wmb-o+ld-addr-o.litmus
+++ /dev/null
@@ -1,30 +0,0 @@
-C C-MP+o-wmb-o+ld-ad-o
-
-{
-int y=1;
-int *x1 = &y;
-}
-
-{
-#include "api.h"
-}
-
-P0(int* x0, int** x1) {
-
- WRITE_ONCE(*x0, 2);
- smp_wmb();
- WRITE_ONCE(*x1, x0);
-
-}
-
-P1(int** x1) {
-
- int *r2;
- int r3;
-
- r2 = lockless_dereference(*x1);
- r3 = READ_ONCE(*r2);
-
-}
-
-exists (1:r2=x0 /\ 1:r3=1)
diff --git a/CodeSamples/formal/litmus/api.h b/CodeSamples/formal/litmus/api.h
index 0f14a48dd128..8bf0ba629a9e 100644
--- a/CodeSamples/formal/litmus/api.h
+++ b/CodeSamples/formal/litmus/api.h
@@ -1,7 +1,12 @@
#ifndef __API_H__
#define __API_H__
#ifndef READ_ONCE
-#define READ_ONCE(x) __atomic_load_n((typeof(x) *)&(x), __ATOMIC_RELAXED)
+#define __READ_ONCE(x) __atomic_load_n((typeof(x) *)&(x), __ATOMIC_RELAXED)
+#ifdef __alpha__
+#define READ_ONCE(x) ({ typeof(x) ___x = __READ_ONCE(x); smp_mb(); ___x; })
+#else
+#define READ_ONCE(x) __READ_ONCE(x)
+#endif
#define WRITE_ONCE(x, v) __atomic_store_n((typeof(x) *)&(x), (v), __ATOMIC_RELAXED)
#define smp_mb() __atomic_thread_fence(__ATOMIC_SEQ_CST)
#define smp_rmb() __atomic_thread_fence(__ATOMIC_ACQUIRE) /* outside std. */
@@ -14,10 +19,5 @@
__atomic_compare_exchange_n((x), &__old, (n), 1, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED); \
__old; \
})
-#ifdef __alpha__
-#define lockless_dereference(x) ({ typeof(x) ___x = READ_ONCE(x); smp_mb(); ___x; })
-#else
-#define lockless_dereference(x) READ_ONCE(x)
-#endif
#endif
#endif
diff --git a/memorder/memorder.tex b/memorder/memorder.tex
index 943c3af3fe6f..bdeaba10e0b2 100644
--- a/memorder/memorder.tex
+++ b/memorder/memorder.tex
@@ -590,8 +590,7 @@ are at most two threads involved.
Section~\ref{sec:memorder:Address- and Data-Dependency Difficulties}.
The \co{*_dereference()} row captures the address and data
- dependency ordering provided by \co{lockless_dereference()},
- \co{rcu_dereference()}, and friends.
+ dependency ordering provided by \co{rcu_dereference()} and friends.
The ``Successful \co{*_acquire()}'' row captures the fact that many
CPUs have special ``acquire'' forms of loads and of atomic RMW
@@ -1411,7 +1410,7 @@ P1(int** x1) {
int *r2;
int r3;
- r2 = lockless_dereference(*x1);
+ r2 = lockless_dereference(*x1); // Obsolete
r3 = READ_ONCE(*r2);
}
@@ -1426,12 +1425,14 @@ exists (1:r2=x0 /\ 1:r3=1)
\end{listing}
Listing~\ref{lst:memorder:Enforced Ordering of Message-Passing Address-Dependency Litmus Test}
-(\path{C-MP+o-wmb-o+ld-addr-o.litmus})
-shows how to make this work reliably on old Linux kernels running on
+% \path{C-MP+o-wmb-o+ld-addr-o.litmus} available at commit bc4b1c3f3b35
+% ("styleguide: Loosen restriction on comment in litmus test")
+shows how to make this work reliably on pre-v4.15 Linux kernels running on
DEC Alpha, by
replacing line~21's \co{READ_ONCE()} with \co{lockless_dereference()},\footnote{
Note that \co{lockless_dereference()} is not needed on v4.15 and
- later, and therefore is not available in these later Linux kernels.}
+ later, and therefore is not available in these later Linux kernels.
+ Nor is it needed in versions of this book containing this sentence.}
which acts like \co{READ_ONCE()} on all platforms other than DEC Alpha,
where it acts like a \co{READ_ONCE()} followed by an \co{smp_mb()},
thereby forcing the required ordering on all platforms, in turn
@@ -1482,8 +1483,7 @@ Because no production-quality platform speculates stores,
it is not possible for the \co{WRITE_ONCE()} on line~10 to overwrite
the \co{WRITE_ONCE()} on line~21, meaning that the \co{exists}
clause on line~25 cannot trigger, even on DEC Alpha, even
-without the \co{lockless_dereference()} that is required in the
-dependent-load case.
+in pre-v4.15 Linux kernels.
\QuickQuiz{}
But how do we know that \emph{all} platforms really avoid
@@ -1520,19 +1520,23 @@ dependent-load case.
There is one (famous) exception to this rule for weakly ordered
platforms, and that exception is DEC Alpha for load-to-load
address dependencies.
- And this is why DEC Alpha requires the explicit memory barrier
- supplied for it by the \co{lockless_dereference()} on line~21 of
+ And this is why, in Linux kernels predating v4.15, DEC Alpha
+ requires the explicit memory barrier supplied for it by the
+ now-obsolete \co{lockless_dereference()} on line~21 of
Listing~\ref{lst:memorder:Enforced Ordering of Message-Passing Address-Dependency Litmus Test}.
However, DEC Alpha does track load-to-store address dependencies,
which is why line~20 of
Listing~\ref{lst:memorder:S Address-Dependency Litmus Test}
- does not have a \co{lockless_dereference()}.
+ does not need a \co{lockless_dereference()}, even in Linux
+ kernels predating v4.15.
To sum up, current platforms either respect address dependencies
implicitly, as is the case for TSO platforms (x86, mainframe,
SPARC,~...), have hardware tracking for address dependencies
- (ARM, PowerPC, MIPS,~...), or have the required memory barriers
- supplied by \co{lockless_dereference()} (DEC Alpha).
+ (ARM, PowerPC, MIPS,~...), have the required memory barriers
+ supplied by \co{READ_ONCE()} (DEC Alpha in Linux kernel v4.15 and
+ later), or require the memory barriers supplied by
+ \co{rcu_dereference()} (DEC Alpha in Linux kernel v4.14 and earlier).
} \QuickQuizEnd
\QuickQuiz{}
@@ -1605,16 +1609,6 @@ The value loaded by line~18 is what line~19 stores.
The ordering provided by this data dependency is sufficient to prevent
the \co{exists} clause from triggering.
-\QuickQuiz{}
- Why doesn't line~18 of
- Listing~\ref{lst:memorder:Load-Buffering Data-Dependency Litmus Test}
- need a \co{lockless_dereference()}?
-\QuickQuizAnswer{
- Data dependencies are always load-to-store dependencies, and
- so all platforms respect them, even DEC Alpha, and for the
- same reasons that they respect load-to-store address dependencies.
-} \QuickQuizEnd
-
Just as with address dependencies, data dependencies are
fragile and can be easily broken by compiler optimizations, as discussed in
Section~\ref{sec:memorder:Address- and Data-Dependency Difficulties}.
@@ -3388,9 +3382,7 @@ your compiler from breaking your dependencies.
\subsubsection{Give your dependency chain a good start}
The load that heads your dependency chain must use proper
-ordering, for example, \co{lockless_dereference()},
-\co{rcu_dereference()}, or
-a \co{READ_ONCE()} followed by \co{smp_read_barrier_depends()}.
+ordering, for example \co{rcu_dereference()} or \co{READ_ONCE()}.
Failure to follow this rule can have serious side effects:
\begin{enumerate}
@@ -4353,8 +4345,7 @@ set of memory-ordering primitives, which are as follows:
that depend on prior operations to be ordered.
This primitive is a no-op on all platforms except Alpha, but
is normally not used directly, but rather as part of
- something like \co{lockless_dereference()} or
- \co{rcu_dereference()}.
+ something like \co{READ_ONCE()} or \co{rcu_dereference()}.
\item [\tco{smp_mb__before_atomic()}] that forces ordering of accesses
preceding the \co{smp_mb__before_atomic()} against accesses following
a later RMW atomic operation.
@@ -5133,8 +5124,8 @@ You can replace a given acquire with a a dependency in environments permitting
this, keeping in mind that the C11 standard's memory model does \emph{not}
permit this.
Note also that a dependency leading to a load must be headed by
-a \co{lockless_dereference()} or an \co{rcu_dereference()}:
-\co{READ_ONCE()} is not sufficient.
+a \co{READ_ONCE()} or an \co{rcu_dereference()}:
+a plain C-language load is not sufficient.
Never forget to carefully review
Sections~\ref{sec:memorder:Address- and Data-Dependency Difficulties}
and~\ref{sec:memorder:Control-Dependency Calamities}, because
next prev parent reply other threads:[~2018-12-02 12:44 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-12-01 7:48 lockless_dereference() in perfbook Akira Yokosawa
2018-12-01 18:30 ` Paul E. McKenney
2018-12-01 22:25 ` Akira Yokosawa
2018-12-02 1:10 ` Paul E. McKenney [this message]
[not found] ` <33ec04ab-3672-0d36-13d1-5f53d9d3bf93@gmail.com>
2018-12-02 16:09 ` Paul E. McKenney
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20181202011053.GZ4170@linux.ibm.com \
--to=paulmck@linux.ibm.com \
--cc=akiyks@gmail.com \
--cc=perfbook@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.