-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of #6025 - thomcc:compare_exchange_atomics, r=flip1995
Extend invalid_atomic_ordering for compare_exchange{,_weak} and fetch_update changelog: The invalid_atomic_ordering lint can now detect misuse of `compare_exchange`, `compare_exchange_weak`, and `fetch_update`. --- I was surprised not to find an issue or existing support here, since these are the functions which are always hardest to get the ordering right on for me (as the allowed orderings for `fail` depend on the `success` parameter). I believe this lint now covers all atomic methods which care about their ordering now, but I could be wrong. Hopefully I didn't forget to do anything for the PR!
- Loading branch information
Showing
8 changed files
with
631 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
#![warn(clippy::invalid_atomic_ordering)] | ||
|
||
use std::sync::atomic::{AtomicUsize, Ordering}; | ||
|
||
fn main() { | ||
// `compare_exchange` (not weak) testing | ||
let x = AtomicUsize::new(0); | ||
|
||
// Allowed ordering combos | ||
let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::Relaxed); | ||
let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::Acquire); | ||
let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::Relaxed); | ||
let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::Relaxed); | ||
let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::Acquire); | ||
let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::Relaxed); | ||
let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::Relaxed); | ||
let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::Acquire); | ||
let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::SeqCst); | ||
|
||
// AcqRel is always forbidden as a failure ordering | ||
let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::AcqRel); | ||
let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::AcqRel); | ||
let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::AcqRel); | ||
let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::AcqRel); | ||
let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::AcqRel); | ||
|
||
// Release is always forbidden as a failure ordering | ||
let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::Release); | ||
let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::Release); | ||
let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::Release); | ||
let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::Release); | ||
let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::Release); | ||
|
||
// Release success order forbids failure order of Acquire or SeqCst | ||
let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::Acquire); | ||
let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::SeqCst); | ||
|
||
// Relaxed success order also forbids failure order of Acquire or SeqCst | ||
let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::SeqCst); | ||
let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::Acquire); | ||
|
||
// Acquire/AcqRel forbids failure order of SeqCst | ||
let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::SeqCst); | ||
let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::SeqCst); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
error: compare_exchange's failure ordering may not be `Release` or `AcqRel` | ||
--> $DIR/atomic_ordering_exchange.rs:21:57 | ||
| | ||
LL | let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::AcqRel); | ||
| ^^^^^^^^^^^^^^^^ | ||
| | ||
= note: `-D clippy::invalid-atomic-ordering` implied by `-D warnings` | ||
= help: consider using ordering mode `Relaxed` instead | ||
|
||
error: compare_exchange's failure ordering may not be `Release` or `AcqRel` | ||
--> $DIR/atomic_ordering_exchange.rs:22:57 | ||
| | ||
LL | let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::AcqRel); | ||
| ^^^^^^^^^^^^^^^^ | ||
| | ||
= help: consider using ordering modes `Acquire` or `Relaxed` instead | ||
|
||
error: compare_exchange's failure ordering may not be `Release` or `AcqRel` | ||
--> $DIR/atomic_ordering_exchange.rs:23:57 | ||
| | ||
LL | let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::AcqRel); | ||
| ^^^^^^^^^^^^^^^^ | ||
| | ||
= help: consider using ordering mode `Relaxed` instead | ||
|
||
error: compare_exchange's failure ordering may not be `Release` or `AcqRel` | ||
--> $DIR/atomic_ordering_exchange.rs:24:56 | ||
| | ||
LL | let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::AcqRel); | ||
| ^^^^^^^^^^^^^^^^ | ||
| | ||
= help: consider using ordering modes `Acquire` or `Relaxed` instead | ||
|
||
error: compare_exchange's failure ordering may not be `Release` or `AcqRel` | ||
--> $DIR/atomic_ordering_exchange.rs:25:56 | ||
| | ||
LL | let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::AcqRel); | ||
| ^^^^^^^^^^^^^^^^ | ||
| | ||
= help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` instead | ||
|
||
error: compare_exchange's failure ordering may not be `Release` or `AcqRel` | ||
--> $DIR/atomic_ordering_exchange.rs:28:57 | ||
| | ||
LL | let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::Release); | ||
| ^^^^^^^^^^^^^^^^^ | ||
| | ||
= help: consider using ordering mode `Relaxed` instead | ||
|
||
error: compare_exchange's failure ordering may not be `Release` or `AcqRel` | ||
--> $DIR/atomic_ordering_exchange.rs:29:57 | ||
| | ||
LL | let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::Release); | ||
| ^^^^^^^^^^^^^^^^^ | ||
| | ||
= help: consider using ordering modes `Acquire` or `Relaxed` instead | ||
|
||
error: compare_exchange's failure ordering may not be `Release` or `AcqRel` | ||
--> $DIR/atomic_ordering_exchange.rs:30:57 | ||
| | ||
LL | let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::Release); | ||
| ^^^^^^^^^^^^^^^^^ | ||
| | ||
= help: consider using ordering mode `Relaxed` instead | ||
|
||
error: compare_exchange's failure ordering may not be `Release` or `AcqRel` | ||
--> $DIR/atomic_ordering_exchange.rs:31:56 | ||
| | ||
LL | let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::Release); | ||
| ^^^^^^^^^^^^^^^^^ | ||
| | ||
= help: consider using ordering modes `Acquire` or `Relaxed` instead | ||
|
||
error: compare_exchange's failure ordering may not be `Release` or `AcqRel` | ||
--> $DIR/atomic_ordering_exchange.rs:32:56 | ||
| | ||
LL | let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::Release); | ||
| ^^^^^^^^^^^^^^^^^ | ||
| | ||
= help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` instead | ||
|
||
error: compare_exchange's failure ordering may not be stronger than the success ordering of `Release` | ||
--> $DIR/atomic_ordering_exchange.rs:35:57 | ||
| | ||
LL | let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::Acquire); | ||
| ^^^^^^^^^^^^^^^^^ | ||
| | ||
= help: consider using ordering mode `Relaxed` instead | ||
|
||
error: compare_exchange's failure ordering may not be stronger than the success ordering of `Release` | ||
--> $DIR/atomic_ordering_exchange.rs:36:57 | ||
| | ||
LL | let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::SeqCst); | ||
| ^^^^^^^^^^^^^^^^ | ||
| | ||
= help: consider using ordering mode `Relaxed` instead | ||
|
||
error: compare_exchange's failure ordering may not be stronger than the success ordering of `Relaxed` | ||
--> $DIR/atomic_ordering_exchange.rs:39:57 | ||
| | ||
LL | let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::SeqCst); | ||
| ^^^^^^^^^^^^^^^^ | ||
| | ||
= help: consider using ordering mode `Relaxed` instead | ||
|
||
error: compare_exchange's failure ordering may not be stronger than the success ordering of `Relaxed` | ||
--> $DIR/atomic_ordering_exchange.rs:40:57 | ||
| | ||
LL | let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::Acquire); | ||
| ^^^^^^^^^^^^^^^^^ | ||
| | ||
= help: consider using ordering mode `Relaxed` instead | ||
|
||
error: compare_exchange's failure ordering may not be stronger than the success ordering of `Acquire` | ||
--> $DIR/atomic_ordering_exchange.rs:43:57 | ||
| | ||
LL | let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::SeqCst); | ||
| ^^^^^^^^^^^^^^^^ | ||
| | ||
= help: consider using ordering modes `Acquire` or `Relaxed` instead | ||
|
||
error: compare_exchange's failure ordering may not be stronger than the success ordering of `AcqRel` | ||
--> $DIR/atomic_ordering_exchange.rs:44:56 | ||
| | ||
LL | let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::SeqCst); | ||
| ^^^^^^^^^^^^^^^^ | ||
| | ||
= help: consider using ordering modes `Acquire` or `Relaxed` instead | ||
|
||
error: aborting due to 16 previous errors | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
#![warn(clippy::invalid_atomic_ordering)] | ||
|
||
use std::sync::atomic::{AtomicPtr, Ordering}; | ||
|
||
fn main() { | ||
let ptr = &mut 5; | ||
let ptr2 = &mut 10; | ||
// `compare_exchange_weak` testing | ||
let x = AtomicPtr::new(ptr); | ||
|
||
// Allowed ordering combos | ||
let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::Relaxed); | ||
let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Acquire, Ordering::Acquire); | ||
let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Acquire, Ordering::Relaxed); | ||
let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Release, Ordering::Relaxed); | ||
let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::AcqRel, Ordering::Acquire); | ||
let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::AcqRel, Ordering::Relaxed); | ||
let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::SeqCst, Ordering::Relaxed); | ||
let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::SeqCst, Ordering::Acquire); | ||
let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::SeqCst, Ordering::SeqCst); | ||
|
||
// AcqRel is always forbidden as a failure ordering | ||
let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Relaxed, Ordering::AcqRel); | ||
let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Acquire, Ordering::AcqRel); | ||
let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Release, Ordering::AcqRel); | ||
let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::AcqRel, Ordering::AcqRel); | ||
let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::SeqCst, Ordering::AcqRel); | ||
|
||
// Release is always forbidden as a failure ordering | ||
let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::Release); | ||
let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Acquire, Ordering::Release); | ||
let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Release, Ordering::Release); | ||
let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::AcqRel, Ordering::Release); | ||
let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::SeqCst, Ordering::Release); | ||
|
||
// Release success order forbids failure order of Acquire or SeqCst | ||
let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Release, Ordering::Acquire); | ||
let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Release, Ordering::SeqCst); | ||
|
||
// Relaxed success order also forbids failure order of Acquire or SeqCst | ||
let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::SeqCst); | ||
let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::Acquire); | ||
|
||
// Acquire/AcqRel forbids failure order of SeqCst | ||
let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Acquire, Ordering::SeqCst); | ||
let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::AcqRel, Ordering::SeqCst); | ||
} |
Oops, something went wrong.