Skip to content

Commit 60eb450

Browse files
committed
Merge tag 'lkmm-scripting.2023.04.07a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu
Pull Linux Kernel Memory Model scripting updates from Paul McKenney: "This improves litmus-test documentation and improves the ability to do before/after tests on the https://github.com/paulmckrcu/litmus repo" * tag 'lkmm-scripting.2023.04.07a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu: (32 commits) tools/memory-model: Remove out-of-date SRCU documentation tools/memory-model: Document LKMM test procedure tools/memory-model: Use "grep -E" instead of "egrep" tools/memory-model: Use "-unroll 0" to keep --hw runs finite tools/memory-model: Make judgelitmus.sh handle scripted Result: tag tools/memory-model: Add data-race capabilities to judgelitmus.sh tools/memory-model: Add checktheselitmus.sh to run specified litmus tests tools/memory-model: Repair parseargs.sh header comment tools/memory-model: Add "--" to parseargs.sh for additional arguments tools/memory-model: Make history-check scripts use mselect7 tools/memory-model: Make checkghlitmus.sh use mselect7 tools/memory-model: Fix scripting --jobs argument tools/memory-model: Implement --hw support for checkghlitmus.sh tools/memory-model: Add -v flag to jingle7 runs tools/memory-model: Make runlitmus.sh check for jingle errors tools/memory-model: Allow herd to deduce CPU type tools/memory-model: Keep assembly-language litmus tests tools/memory-model: Move from .AArch64.litmus.out to .litmus.AArch.out tools/memory-model: Make runlitmus.sh generate .litmus.out for --hw tools/memory-model: Split runlitmus.sh out of checklitmus.sh ...
2 parents 4060373 + cc4a298 commit 60eb450

22 files changed

+924
-116
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
C DCL-broken
2+
3+
(*
4+
* Result: Sometimes
5+
*
6+
* This litmus test demonstrates more than just locking is required to
7+
* correctly implement double-checked locking.
8+
*)
9+
10+
{
11+
int flag;
12+
int data;
13+
}
14+
15+
P0(int *flag, int *data, spinlock_t *lck)
16+
{
17+
int r0;
18+
int r1;
19+
int r2;
20+
21+
r0 = READ_ONCE(*flag);
22+
if (r0 == 0) {
23+
spin_lock(lck);
24+
r1 = READ_ONCE(*flag);
25+
if (r1 == 0) {
26+
WRITE_ONCE(*data, 1);
27+
WRITE_ONCE(*flag, 1);
28+
}
29+
spin_unlock(lck);
30+
}
31+
r2 = READ_ONCE(*data);
32+
}
33+
34+
P1(int *flag, int *data, spinlock_t *lck)
35+
{
36+
int r0;
37+
int r1;
38+
int r2;
39+
40+
r0 = READ_ONCE(*flag);
41+
if (r0 == 0) {
42+
spin_lock(lck);
43+
r1 = READ_ONCE(*flag);
44+
if (r1 == 0) {
45+
WRITE_ONCE(*data, 1);
46+
WRITE_ONCE(*flag, 1);
47+
}
48+
spin_unlock(lck);
49+
}
50+
r2 = READ_ONCE(*data);
51+
}
52+
53+
locations [flag;data;0:r0;0:r1;1:r0;1:r1]
54+
exists (0:r2=0 \/ 1:r2=0)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
C DCL-fixed
2+
3+
(*
4+
* Result: Never
5+
*
6+
* This litmus test demonstrates that double-checked locking can be
7+
* reliable given proper use of smp_load_acquire() and smp_store_release()
8+
* in addition to the locking.
9+
*)
10+
11+
{
12+
int flag;
13+
int data;
14+
}
15+
16+
P0(int *flag, int *data, spinlock_t *lck)
17+
{
18+
int r0;
19+
int r1;
20+
int r2;
21+
22+
r0 = smp_load_acquire(flag);
23+
if (r0 == 0) {
24+
spin_lock(lck);
25+
r1 = READ_ONCE(*flag);
26+
if (r1 == 0) {
27+
WRITE_ONCE(*data, 1);
28+
smp_store_release(flag, 1);
29+
}
30+
spin_unlock(lck);
31+
}
32+
r2 = READ_ONCE(*data);
33+
}
34+
35+
P1(int *flag, int *data, spinlock_t *lck)
36+
{
37+
int r0;
38+
int r1;
39+
int r2;
40+
41+
r0 = smp_load_acquire(flag);
42+
if (r0 == 0) {
43+
spin_lock(lck);
44+
r1 = READ_ONCE(*flag);
45+
if (r1 == 0) {
46+
WRITE_ONCE(*data, 1);
47+
smp_store_release(flag, 1);
48+
}
49+
spin_unlock(lck);
50+
}
51+
r2 = READ_ONCE(*data);
52+
}
53+
54+
locations [flag;data;0:r0;0:r1;1:r0;1:r1]
55+
exists (0:r2=0 \/ 1:r2=0)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
C RM-broken
2+
3+
(*
4+
* Result: DEADLOCK
5+
*
6+
* This litmus test demonstrates that the old "roach motel" approach
7+
* to locking, where code can be freely moved into critical sections,
8+
* cannot be used in the Linux kernel.
9+
*)
10+
11+
{
12+
int x;
13+
atomic_t y;
14+
}
15+
16+
P0(int *x, atomic_t *y, spinlock_t *lck)
17+
{
18+
int r2;
19+
20+
spin_lock(lck);
21+
r2 = atomic_inc_return(y);
22+
WRITE_ONCE(*x, 1);
23+
spin_unlock(lck);
24+
}
25+
26+
P1(int *x, atomic_t *y, spinlock_t *lck)
27+
{
28+
int r0;
29+
int r1;
30+
int r2;
31+
32+
spin_lock(lck);
33+
r0 = READ_ONCE(*x);
34+
r1 = READ_ONCE(*x);
35+
r2 = atomic_inc_return(y);
36+
spin_unlock(lck);
37+
}
38+
39+
locations [x;0:r2;1:r0;1:r1;1:r2]
40+
filter (1:r0=0 /\ 1:r1=1)
41+
exists (1:r2=1)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
C RM-fixed
2+
3+
(*
4+
* Result: Never
5+
*
6+
* This litmus test demonstrates that the old "roach motel" approach
7+
* to locking, where code can be freely moved into critical sections,
8+
* cannot be used in the Linux kernel.
9+
*)
10+
11+
{
12+
int x;
13+
atomic_t y;
14+
}
15+
16+
P0(int *x, atomic_t *y, spinlock_t *lck)
17+
{
18+
int r2;
19+
20+
spin_lock(lck);
21+
r2 = atomic_inc_return(y);
22+
WRITE_ONCE(*x, 1);
23+
spin_unlock(lck);
24+
}
25+
26+
P1(int *x, atomic_t *y, spinlock_t *lck)
27+
{
28+
int r0;
29+
int r1;
30+
int r2;
31+
32+
r0 = READ_ONCE(*x);
33+
r1 = READ_ONCE(*x);
34+
spin_lock(lck);
35+
r2 = atomic_inc_return(y);
36+
spin_unlock(lck);
37+
}
38+
39+
locations [x;0:r2;1:r0;1:r1;1:r2]
40+
filter (1:r0=0 /\ 1:r1=1)
41+
exists (1:r2=1)

tools/memory-model/Documentation/litmus-tests.txt

+1-26
Original file line numberDiff line numberDiff line change
@@ -1028,32 +1028,7 @@ Limitations of the Linux-kernel memory model (LKMM) include:
10281028
additional call_rcu() process to the site of the
10291029
emulated rcu-barrier().
10301030

1031-
e. Although sleepable RCU (SRCU) is now modeled, there
1032-
are some subtle differences between its semantics and
1033-
those in the Linux kernel. For example, the kernel
1034-
might interpret the following sequence as two partially
1035-
overlapping SRCU read-side critical sections:
1036-
1037-
1 r1 = srcu_read_lock(&my_srcu);
1038-
2 do_something_1();
1039-
3 r2 = srcu_read_lock(&my_srcu);
1040-
4 do_something_2();
1041-
5 srcu_read_unlock(&my_srcu, r1);
1042-
6 do_something_3();
1043-
7 srcu_read_unlock(&my_srcu, r2);
1044-
1045-
In contrast, LKMM will interpret this as a nested pair of
1046-
SRCU read-side critical sections, with the outer critical
1047-
section spanning lines 1-7 and the inner critical section
1048-
spanning lines 3-5.
1049-
1050-
This difference would be more of a concern had anyone
1051-
identified a reasonable use case for partially overlapping
1052-
SRCU read-side critical sections. For more information
1053-
on the trickiness of such overlapping, please see:
1054-
https://paulmck.livejournal.com/40593.html
1055-
1056-
f. Reader-writer locking is not modeled. It can be
1031+
e. Reader-writer locking is not modeled. It can be
10571032
emulated in litmus tests using atomic read-modify-write
10581033
operations.
10591034

0 commit comments

Comments
 (0)