diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-05-13 20:10:19 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-05-13 20:10:19 +0300 |
commit | ee20260136095c8037d8f94f0471eb9f7e3da99f (patch) | |
tree | a14bd21b289e6f16e293b9ac2f3fbd4746e3a8b6 | |
parent | 2e57d1d6062af11420bc329ca004ebe3f3f6f0ee (diff) | |
parent | 2ba5b4130e3d5d05c95981e1d2e660d57e613fda (diff) | |
download | linux-ee20260136095c8037d8f94f0471eb9f7e3da99f.tar.xz |
Merge tag 'lkmm.2024.05.10a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu
Pull LKMM documentation updates from Paul McKenney:
"This upgrades LKMM documentation, perhaps most notably adding a number
of litmus tests illustrating cmpxchg() ordering properties.
TL;DR: Failing cmpxchg() operations provide no ordering"
* tag 'lkmm.2024.05.10a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu:
Documentation/litmus-tests: Make cmpxchg() tests safe for klitmus
Documentation/atomic_t: Emphasize that failed atomic operations give no ordering
Documentation/litmus-tests: Demonstrate unordered failing cmpxchg
Documentation/litmus-tests: Add locking tests to README
6 files changed, 176 insertions, 2 deletions
diff --git a/Documentation/atomic_t.txt b/Documentation/atomic_t.txt index d7adc6d543db..bee3b1bca9a7 100644 --- a/Documentation/atomic_t.txt +++ b/Documentation/atomic_t.txt @@ -171,14 +171,14 @@ The rule of thumb: - RMW operations that are conditional are unordered on FAILURE, otherwise the above rules apply. -Except of course when an operation has an explicit ordering like: +Except of course when a successful operation has an explicit ordering like: {}_relaxed: unordered {}_acquire: the R of the RMW (or atomic_read) is an ACQUIRE {}_release: the W of the RMW (or atomic_set) is a RELEASE Where 'unordered' is against other memory locations. Address dependencies are -not defeated. +not defeated. Conditional operations are still unordered on FAILURE. Fully ordered primitives are ordered against everything prior and everything subsequent. Therefore a fully ordered primitive is like having an smp_mb() diff --git a/Documentation/litmus-tests/README b/Documentation/litmus-tests/README index 658d37860d39..6c666f3422ea 100644 --- a/Documentation/litmus-tests/README +++ b/Documentation/litmus-tests/README @@ -21,6 +21,51 @@ Atomic-RMW-ops-are-atomic-WRT-atomic_set.litmus Test that atomic_set() cannot break the atomicity of atomic RMWs. NOTE: Require herd7 7.56 or later which supports "(void)expr". +cmpxchg-fail-ordered-1.litmus + Demonstrate that a failing cmpxchg() operation acts as a full barrier + when followed by smp_mb__after_atomic(). + +cmpxchg-fail-ordered-2.litmus + Demonstrate that a failing cmpxchg() operation acts as an acquire + operation when followed by smp_mb__after_atomic(). + +cmpxchg-fail-unordered-1.litmus + Demonstrate that a failing cmpxchg() operation does not act as a + full barrier. + +cmpxchg-fail-unordered-2.litmus + Demonstrate that a failing cmpxchg() operation does not act as an + acquire operation. + + +locking (/locking directory) +---------------------------- + +DCL-broken.litmus + Demonstrates that double-checked locking needs more than just + the obvious lock acquisitions and releases. + +DCL-fixed.litmus + Demonstrates corrected double-checked locking that uses + smp_store_release() and smp_load_acquire() in addition to the + obvious lock acquisitions and releases. + +RM-broken.litmus + Demonstrates problems with "roach motel" locking, where code is + freely moved into lock-based critical sections. This example also + shows how to use the "filter" clause to discard executions that + would be excluded by other code not modeled in the litmus test. + Note also that this "roach motel" optimization is emulated by + physically moving P1()'s two reads from x under the lock. + + What is a roach motel? This is from an old advertisement for + a cockroach trap, much later featured in one of the "Men in + Black" movies. "The roaches check in. They don't check out." + +RM-fixed.litmus + The counterpart to RM-broken.litmus, showing P0()'s two loads from + x safely outside of the critical section. + RCU (/rcu directory) -------------------- diff --git a/Documentation/litmus-tests/atomic/cmpxchg-fail-ordered-1.litmus b/Documentation/litmus-tests/atomic/cmpxchg-fail-ordered-1.litmus new file mode 100644 index 000000000000..c0f93dc07105 --- /dev/null +++ b/Documentation/litmus-tests/atomic/cmpxchg-fail-ordered-1.litmus @@ -0,0 +1,35 @@ +C cmpxchg-fail-ordered-1 + +(* + * Result: Never + * + * Demonstrate that a failing cmpxchg() operation will act as a full + * barrier when followed by smp_mb__after_atomic(). + *) + +{} + +P0(int *x, int *y, int *z) +{ + int r0; + int r1; + + WRITE_ONCE(*x, 1); + r1 = cmpxchg(z, 1, 0); + smp_mb__after_atomic(); + r0 = READ_ONCE(*y); +} + +P1(int *x, int *y, int *z) +{ + int r0; + int r1; + + WRITE_ONCE(*y, 1); + r1 = cmpxchg(z, 1, 0); + smp_mb__after_atomic(); + r0 = READ_ONCE(*x); +} + +locations[0:r1;1:r1] +exists (0:r0=0 /\ 1:r0=0) diff --git a/Documentation/litmus-tests/atomic/cmpxchg-fail-ordered-2.litmus b/Documentation/litmus-tests/atomic/cmpxchg-fail-ordered-2.litmus new file mode 100644 index 000000000000..5c06054f4694 --- /dev/null +++ b/Documentation/litmus-tests/atomic/cmpxchg-fail-ordered-2.litmus @@ -0,0 +1,30 @@ +C cmpxchg-fail-ordered-2 + +(* + * Result: Never + * + * Demonstrate use of smp_mb__after_atomic() to make a failing cmpxchg + * operation have acquire ordering. + *) + +{} + +P0(int *x, int *y) +{ + int r1; + + WRITE_ONCE(*x, 1); + r1 = cmpxchg(y, 0, 1); +} + +P1(int *x, int *y) +{ + int r1; + int r2; + + r1 = cmpxchg(y, 0, 1); + smp_mb__after_atomic(); + r2 = READ_ONCE(*x); +} + +exists (0:r1=0 /\ 1:r1=1 /\ 1:r2=0) diff --git a/Documentation/litmus-tests/atomic/cmpxchg-fail-unordered-1.litmus b/Documentation/litmus-tests/atomic/cmpxchg-fail-unordered-1.litmus new file mode 100644 index 000000000000..39ea1f56a28d --- /dev/null +++ b/Documentation/litmus-tests/atomic/cmpxchg-fail-unordered-1.litmus @@ -0,0 +1,34 @@ +C cmpxchg-fail-unordered-1 + +(* + * Result: Sometimes + * + * Demonstrate that a failing cmpxchg() operation does not act as a + * full barrier. (In contrast, a successful cmpxchg() does act as a + * full barrier.) + *) + +{} + +P0(int *x, int *y, int *z) +{ + int r0; + int r1; + + WRITE_ONCE(*x, 1); + r1 = cmpxchg(z, 1, 0); + r0 = READ_ONCE(*y); +} + +P1(int *x, int *y, int *z) +{ + int r0; + int r1; + + WRITE_ONCE(*y, 1); + r1 = cmpxchg(z, 1, 0); + r0 = READ_ONCE(*x); +} + +locations[0:r1;1:r1] +exists (0:r0=0 /\ 1:r0=0) diff --git a/Documentation/litmus-tests/atomic/cmpxchg-fail-unordered-2.litmus b/Documentation/litmus-tests/atomic/cmpxchg-fail-unordered-2.litmus new file mode 100644 index 000000000000..61aab24a4a64 --- /dev/null +++ b/Documentation/litmus-tests/atomic/cmpxchg-fail-unordered-2.litmus @@ -0,0 +1,30 @@ +C cmpxchg-fail-unordered-2 + +(* + * Result: Sometimes + * + * Demonstrate that a failing cmpxchg() operation does not act as either + * an acquire release operation. (In contrast, a successful cmpxchg() + * does act as both an acquire and a release operation.) + *) + +{} + +P0(int *x, int *y) +{ + int r1; + + WRITE_ONCE(*x, 1); + r1 = cmpxchg(y, 0, 1); +} + +P1(int *x, int *y) +{ + int r1; + int r2; + + r1 = cmpxchg(y, 0, 1); + r2 = READ_ONCE(*x); +} + +exists (0:r1=0 /\ 1:r1=1 /\ 1:r2=0) |