1 | use crate::sync::atomic::Ordering; |
2 | |
3 | #[cfg (test)] |
4 | use 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" )] |
44 | pub 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 | |