-
Notifications
You must be signed in to change notification settings - Fork 276
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This intrinsic isn't actually specified by Intel, but it's something gated with CPUID and can otherwise be a useful thing to have when building primitives! There exists an `AtomicU128` type in the standard library but it's only exposed currently (and it's unstable) when a platform fully supports 128-bit atomics. The x86_64 architecture does not support it *unless* the `cmpxchg16b` instruction is available, and it isn't always available! This commit is also a proposal for how we can include support for 128-bit atomics in the standard library on relevant platforms. I'm thinking that we'll expose this one low-level intrinsic in `std::arch::x86_64`, and then if desired a crate on crates.io can build `AtomicU128` from this API. In any case this is all unstable regardless!
- Loading branch information
1 parent
abcdfe3
commit 98c489f
Showing
8 changed files
with
105 additions
and
1 deletion.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
use sync::atomic::Ordering; | ||
|
||
#[cfg(test)] | ||
use stdsimd_test::assert_instr; | ||
|
||
/// Compare and exchange 16 bytes (128 bits) of data atomically. | ||
/// | ||
/// This intrinsic corresponds to the `cmpxchg16b` instruction on x86_64 | ||
/// processors. It performs an atomic compare-and-swap, updating the `ptr` | ||
/// memory location to `val` if the current value in memory equals `old`. | ||
/// | ||
/// # Return value | ||
/// | ||
/// This function returns the previous value at the memory location. If it is | ||
/// equal to `old` then the memory was updated to `new`. | ||
/// | ||
/// # Memory Orderings | ||
/// | ||
/// This atomic operations has the same semantics of memory orderings as | ||
/// `AtomicUsize::compare_exchange` does, only operating on 16 bytes of memory | ||
/// instead of just a pointer. | ||
/// | ||
/// For more information on memory orderings here see the `compare_exchange` | ||
/// documentation for other `Atomic*` types in the standard library. | ||
/// | ||
/// # Unsafety | ||
/// | ||
/// This method is unsafe because it takes a raw pointer and will attempt to | ||
/// read and possibly write the memory at the pointer. The pointer must also be | ||
/// aligned on a 16-byte boundary. | ||
/// | ||
/// This method also requires the `cmpxchg16b` CPU feature to be available at | ||
/// runtime to work correctly. If the CPU running the binary does not actually | ||
/// support `cmpxchg16b` and the program enters an execution path that | ||
/// eventually would reach this function the behavior is undefined. | ||
/// | ||
/// The `success` ordering must also be stronger or equal to `failure`, or this | ||
/// function call is undefined. See the `Atomic*` documentation's | ||
/// `compare_exchange` function for more information. When `compare_exchange` | ||
/// panics, this is undefined behavior. Currently this function aborts the | ||
/// process with an undefined instruction. | ||
#[inline] | ||
#[cfg_attr(test, assert_instr(cmpxchg16b, success = Ordering::SeqCst, failure = Ordering::SeqCst))] | ||
#[target_feature(enable = "cmpxchg16b")] | ||
pub unsafe fn cmpxchg16b( | ||
dst: *mut u128, | ||
old: u128, | ||
new: u128, | ||
success: Ordering, | ||
failure: Ordering, | ||
) -> u128 { | ||
use intrinsics; | ||
use sync::atomic::Ordering::*; | ||
|
||
debug_assert!(dst as usize % 16 == 0); | ||
|
||
let (val, _ok) = match (success, failure) { | ||
(Acquire, Acquire) => intrinsics::atomic_cxchg_acq(dst, old, new), | ||
(Release, Relaxed) => intrinsics::atomic_cxchg_rel(dst, old, new), | ||
(AcqRel, Acquire) => intrinsics::atomic_cxchg_acqrel(dst, old, new), | ||
(Relaxed, Relaxed) => intrinsics::atomic_cxchg_relaxed(dst, old, new), | ||
(SeqCst, SeqCst) => intrinsics::atomic_cxchg(dst, old, new), | ||
(Acquire, Relaxed) => intrinsics::atomic_cxchg_acq_failrelaxed(dst, old, new), | ||
(AcqRel, Relaxed) => intrinsics::atomic_cxchg_acqrel_failrelaxed(dst, old, new), | ||
(SeqCst, Relaxed) => intrinsics::atomic_cxchg_failrelaxed(dst, old, new), | ||
(SeqCst, Acquire) => intrinsics::atomic_cxchg_failacq(dst, old, new), | ||
|
||
// The above block is all copied from libcore, and this statement is | ||
// also copied from libcore except that it's a panic in libcore and we | ||
// have a little bit more of a lightweight panic here. | ||
_ => ::coresimd::x86::ud2(), | ||
}; | ||
val | ||
} |
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 |
---|---|---|
|
@@ -38,3 +38,6 @@ pub use self::bswap::*; | |
|
||
mod rdrand; | ||
pub use self::rdrand::*; | ||
|
||
mod cmpxchg16b; | ||
pub use self::cmpxchg16b::*; |
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
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