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