From: Akira Yokosawa <akiyks@gmail.com>
To: "Paul E. McKenney" <paulmck@kernel.org>, parri.andrea@gmail.com
Cc: stern@rowland.harvard.edu, will@kernel.org, peterz@infradead.org,
boqun.feng@gmail.com, npiggin@gmail.com, dhowells@redhat.com,
j.alglave@ucl.ac.uk, luc.maranget@inria.fr,
linux-kernel@vger.kernel.org, linux-arch@vger.kernel.org,
kernel-team@meta.com, mingo@kernel.org,
Akira Yokosawa <akiyks@gmail.com>
Subject: Re: [PATCH memory-model scripts 01/31] tools/memory-model: Document locking corner cases
Date: Thu, 23 Mar 2023 11:52:57 +0900 [thread overview]
Message-ID: <f940cb6c-4aa6-41a4-d9d7-330becd5427a@gmail.com> (raw)
In-Reply-To: <20230321010549.51296-1-paulmck@kernel.org>
Hi Paul,
On Mon, 20 Mar 2023 18:05:19 -0700, Paul E. McKenney wrote:
> Most Linux-kernel uses of locking are straightforward, but there are
> corner-case uses that rely on less well-known aspects of the lock and
> unlock primitives. This commit therefore adds a locking.txt and litmus
> tests in Documentation/litmus-tests/locking to explain these corner-case
> uses.
>
> Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
> ---
> .../litmus-tests/locking/DCL-broken.litmus | 55 +++
> .../litmus-tests/locking/DCL-fixed.litmus | 56 +++
> .../litmus-tests/locking/RM-broken.litmus | 42 +++
> .../litmus-tests/locking/RM-fixed.litmus | 42 +++
> tools/memory-model/Documentation/locking.txt | 320 ++++++++++++++++++
I think the documentation needs adjustment to cope with Andrea's change
of litmus tests.
Also, coding style of code snippets taken from litmus tests look somewhat
inconsistent with other snippets taken from MP+... litmus tests:
- Simple function signature such as "void CPU0(void)".
- No declaration of local variables.
- Indirection level of global variables.
- No "locations" clause
How about applying the diff below?
Thanks, Akira
-----
diff --git a/tools/memory-model/Documentation/locking.txt b/tools/memory-model/Documentation/locking.txt
index 4e05c6d53ab7..65c898c64a93 100644
--- a/tools/memory-model/Documentation/locking.txt
+++ b/tools/memory-model/Documentation/locking.txt
@@ -91,25 +91,21 @@ double-checked locking work correctly, This litmus test illustrates
one incorrect approach:
/* See Documentation/litmus-tests/locking/DCL-broken.litmus. */
- P0(int *flag, int *data, int *lck)
+ void CPU0(void)
{
- int r0;
- int r1;
- int r2;
-
- r0 = READ_ONCE(*flag);
+ r0 = READ_ONCE(flag);
if (r0 == 0) {
- spin_lock(lck);
- r1 = READ_ONCE(*flag);
+ spin_lock(&lck);
+ r1 = READ_ONCE(flag);
if (r1 == 0) {
- WRITE_ONCE(*data, 1);
- WRITE_ONCE(*flag, 1);
+ WRITE_ONCE(data, 1);
+ WRITE_ONCE(flag, 1);
}
- spin_unlock(lck);
+ spin_unlock(&lck);
}
- r2 = READ_ONCE(*data);
+ r2 = READ_ONCE(data);
}
- /* P1() is the exactly the same as P0(). */
+ /* CPU1() is the exactly the same as CPU0(). */
There are two problems. First, there is no ordering between the first
READ_ONCE() of "flag" and the READ_ONCE() of "data". Second, there is
@@ -120,25 +116,21 @@ One way to fix this is to use smp_load_acquire() and smp_store_release()
as shown in this corrected version:
/* See Documentation/litmus-tests/locking/DCL-fixed.litmus. */
- P0(int *flag, int *data, int *lck)
+ void CPU0(void)
{
- int r0;
- int r1;
- int r2;
-
- r0 = smp_load_acquire(flag);
+ r0 = smp_load_acquire(&flag);
if (r0 == 0) {
- spin_lock(lck);
- r1 = READ_ONCE(*flag);
+ spin_lock(&lck);
+ r1 = READ_ONCE(flag);
if (r1 == 0) {
- WRITE_ONCE(*data, 1);
- smp_store_release(flag, 1);
+ WRITE_ONCE(data, 1);
+ smp_store_release(&flag, 1);
}
- spin_unlock(lck);
+ spin_unlock(&lck);
}
- r2 = READ_ONCE(*data);
+ r2 = READ_ONCE(data);
}
- /* P1() is the exactly the same as P0(). */
+ /* CPU1() is the exactly the same as CPU0(). */
The smp_load_acquire() guarantees that its load from "flags" will
be ordered before the READ_ONCE() from data, thus solving the first
@@ -238,81 +230,67 @@ loads, with a "filter" clause to constrain the first to return the
initial value and the second to return the updated value, as shown below:
/* See Documentation/litmus-tests/locking/RM-fixed.litmus. */
- P0(int *x, int *y, int *lck)
+ void CPU0(void)
{
- int r2;
-
- spin_lock(lck);
- r2 = atomic_inc_return(y);
- WRITE_ONCE(*x, 1);
- spin_unlock(lck);
+ spin_lock(&lck);
+ r2 = atomic_inc_return(&y);
+ WRITE_ONCE(x, 1);
+ spin_unlock(&lck);
}
- P1(int *x, int *y, int *lck)
+ void CPU1(void)
{
- int r0;
- int r1;
- int r2;
-
- r0 = READ_ONCE(*x);
- r1 = READ_ONCE(*x);
- spin_lock(lck);
- r2 = atomic_inc_return(y);
- spin_unlock(lck);
+ r0 = READ_ONCE(x);
+ r1 = READ_ONCE(x);
+ spin_lock(&lck);
+ r2 = atomic_inc_return(&y);
+ spin_unlock(&lck);
}
- filter (y=2 /\ 1:r0=0 /\ 1:r1=1)
+ filter (1:r0=0 /\ 1:r1=1)
exists (1:r2=1)
The variable "x" is the control variable for the emulated spin loop.
-P0() sets it to "1" while holding the lock, and P1() emulates the
+CPU0() sets it to "1" while holding the lock, and CPU1() emulates the
spin loop by reading it twice, first into "1:r0" (which should get the
initial value "0") and then into "1:r1" (which should get the updated
value "1").
-The purpose of the variable "y" is to reject deadlocked executions.
-Only those executions where the final value of "y" have avoided deadlock.
+The "filter" clause takes this into account, constraining "1:r0" to
+equal "0" and "1:r1" to equal 1.
-The "filter" clause takes all this into account, constraining "y" to
-equal "2", "1:r0" to equal "0", and "1:r1" to equal 1.
-
-Then the "exists" clause checks to see if P1() acquired its lock first,
-which should not happen given the filter clause because P0() updates
+Then the "exists" clause checks to see if CPU1() acquired its lock first,
+which should not happen given the filter clause because CPU0() updates
"x" while holding the lock. And herd7 confirms this.
But suppose that the compiler was permitted to reorder the spin loop
-into P1()'s critical section, like this:
+into CPU1()'s critical section, like this:
/* See Documentation/litmus-tests/locking/RM-broken.litmus. */
- P0(int *x, int *y, int *lck)
+ void CPU0(void)
{
int r2;
- spin_lock(lck);
- r2 = atomic_inc_return(y);
- WRITE_ONCE(*x, 1);
- spin_unlock(lck);
+ spin_lock(&lck);
+ r2 = atomic_inc_return(&y);
+ WRITE_ONCE(x, 1);
+ spin_unlock(&lck);
}
- P1(int *x, int *y, int *lck)
+ void CPU1(void)
{
- int r0;
- int r1;
- int r2;
-
- spin_lock(lck);
- r0 = READ_ONCE(*x);
- r1 = READ_ONCE(*x);
- r2 = atomic_inc_return(y);
- spin_unlock(lck);
+ spin_lock(&lck);
+ r0 = READ_ONCE(x);
+ r1 = READ_ONCE(x);
+ r2 = atomic_inc_return(&y);
+ spin_unlock(&lck);
}
- locations [x;lck;0:r2;1:r0;1:r1;1:r2]
- filter (y=2 /\ 1:r0=0 /\ 1:r1=1)
+ filter (1:r0=0 /\ 1:r1=1)
exists (1:r2=1)
-If "1:r0" is equal to "0", "1:r1" can never equal "1" because P0()
-cannot update "x" while P1() holds the lock. And herd7 confirms this,
+If "1:r0" is equal to "0", "1:r1" can never equal "1" because CPU0()
+cannot update "x" while CPU1() holds the lock. And herd7 confirms this,
showing zero executions matching the "filter" criteria.
And this is why Linux-kernel lock and unlock primitives must prevent
next prev parent reply other threads:[~2023-03-23 2:53 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-03-21 1:05 [PATCH memory-model 0/31] LKMM scripting updates for v6.4 Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 01/31] tools/memory-model: Document locking corner cases Paul E. McKenney
2023-03-22 8:59 ` Andrea Parri
2023-03-22 19:14 ` Paul E. McKenney
2023-03-23 1:42 ` Andrea Parri
2023-03-23 2:52 ` Akira Yokosawa [this message]
2023-03-23 18:52 ` Paul E. McKenney
2023-03-23 23:30 ` Akira Yokosawa
2023-03-23 23:49 ` Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 02/31] tools/memory-model: Make judgelitmus.sh note timeouts Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 03/31] tools/memory-model: Make cmplitmushist.sh " Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 04/31] tools/memory-model: Make judgelitmus.sh identify bad macros Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 05/31] tools/memory-model: Make judgelitmus.sh detect hard deadlocks Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 06/31] tools/memory-model: Fix paulmck email address on pre-existing scripts Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 07/31] tools/memory-model: Update parseargs.sh for hardware verification Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 08/31] tools/memory-model: Make judgelitmus.sh handle hardware verifications Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 09/31] tools/memory-model: Add simpletest.sh to check locking, RCU, and SRCU Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 10/31] tools/memory-model: Fix checkalllitmus.sh comment Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 11/31] tools/memory-model: Hardware checking for check{,all}litmus.sh Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 12/31] tools/memory-model: Make judgelitmus.sh ransack .litmus.out files Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 13/31] tools/memory-model: Split runlitmus.sh out of checklitmus.sh Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 14/31] tools/memory-model: Make runlitmus.sh generate .litmus.out for --hw Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 15/31] tools/memory-model: Move from .AArch64.litmus.out to .litmus.AArch.out Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 16/31] tools/memory-model: Keep assembly-language litmus tests Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 17/31] tools/memory-model: Allow herd to deduce CPU type Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 18/31] tools/memory-model: Make runlitmus.sh check for jingle errors Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 19/31] tools/memory-model: Add -v flag to jingle7 runs Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 20/31] tools/memory-model: Implement --hw support for checkghlitmus.sh Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 21/31] tools/memory-model: Fix scripting --jobs argument Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 22/31] tools/memory-model: Make checkghlitmus.sh use mselect7 Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 23/31] tools/memory-model: Make history-check scripts " Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 24/31] tools/memory-model: Add "--" to parseargs.sh for additional arguments Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 25/31] tools/memory-model: Repair parseargs.sh header comment Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 26/31] tools/memory-model: Add checktheselitmus.sh to run specified litmus tests Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 27/31] tools/memory-model: Add data-race capabilities to judgelitmus.sh Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 28/31] tools/memory-model: Make judgelitmus.sh handle scripted Result: tag Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 29/31] tools/memory-model: Use "-unroll 0" to keep --hw runs finite Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 30/31] tools/memory-model: Use "grep -E" instead of "egrep" Paul E. McKenney
2023-03-21 1:05 ` [PATCH memory-model scripts 31/31] tools/memory-model: Document LKMM test procedure 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=f940cb6c-4aa6-41a4-d9d7-330becd5427a@gmail.com \
--to=akiyks@gmail.com \
--cc=boqun.feng@gmail.com \
--cc=dhowells@redhat.com \
--cc=j.alglave@ucl.ac.uk \
--cc=kernel-team@meta.com \
--cc=linux-arch@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=luc.maranget@inria.fr \
--cc=mingo@kernel.org \
--cc=npiggin@gmail.com \
--cc=parri.andrea@gmail.com \
--cc=paulmck@kernel.org \
--cc=peterz@infradead.org \
--cc=stern@rowland.harvard.edu \
--cc=will@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox