1use crate::sync::atomic::Ordering;
2
3#[cfg(test)]
4use stdarch_test::assert_instr;
5
6/// Compares and exchange 16 bytes (128 bits) of data atomically.
7///
8/// This intrinsic corresponds to the `cmpxchg16b` instruction on `x86_64`
9/// processors. It performs an atomic compare-and-swap, updating the `ptr`
10/// memory location to `val` if the current value in memory equals `old`.
11///
12/// # Return value
13///
14/// This function returns the previous value at the memory location. If it is
15/// equal to `old` then the memory was updated to `new`.
16///
17/// # Memory Orderings
18///
19/// This atomic operation has the same semantics of memory orderings as
20/// `AtomicUsize::compare_exchange` does, only operating on 16 bytes of memory
21/// instead of just a pointer.
22///
23/// The failure ordering must be [`Ordering::SeqCst`], [`Ordering::Acquire`] or
24/// [`Ordering::Relaxed`].
25///
26/// For more information on memory orderings here see the `compare_exchange`
27/// documentation for other `Atomic*` types in the standard library.
28///
29/// # Unsafety
30///
31/// This method is unsafe because it takes a raw pointer and will attempt to
32/// read and possibly write the memory at the pointer. The pointer must also be
33/// aligned on a 16-byte boundary.
34///
35/// This method also requires the `cmpxchg16b` CPU feature to be available at
36/// runtime to work correctly. If the CPU running the binary does not actually
37/// support `cmpxchg16b` and the program enters an execution path that
38/// eventually would reach this function the behavior is undefined.
39#[inline]
40#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
41#[cfg_attr(test, assert_instr(cmpxchg16b, success = Ordering::SeqCst, failure = Ordering::SeqCst))]
42#[target_feature(enable = "cmpxchg16b")]
43#[stable(feature = "cmpxchg16b_intrinsic", since = "1.67.0")]
44pub unsafe fn cmpxchg16b(
45 dst: *mut u128,
46 old: u128,
47 new: u128,
48 success: Ordering,
49 failure: Ordering,
50) -> u128 {
51 debug_assert!(dst as usize % 16 == 0);
52
53 let res: Result = crate::sync::atomic::atomic_compare_exchange(dst, old, new, success, failure);
54 res.unwrap_or_else(|x: u128| x)
55}
56