| 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 | |