Skip to content

Commit 2abca5a

Browse files
committed
x86_64: Merge _cmpxchg16b and __cmpxchg16b
1 parent 18b6cb0 commit 2abca5a

File tree

1 file changed

+40
-42
lines changed

1 file changed

+40
-42
lines changed

src/imp/atomic128/x86_64.rs

Lines changed: 40 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,35 @@ struct Pair {
4545
hi: u64,
4646
}
4747

48-
#[inline(always)]
49-
unsafe fn __cmpxchg16b(dst: *mut u128, old: u128, new: u128) -> (u128, bool) {
48+
#[cfg_attr(
49+
not(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b")),
50+
target_feature(enable = "cmpxchg16b")
51+
)]
52+
#[cfg_attr(
53+
any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"),
54+
inline
55+
)]
56+
#[cfg_attr(
57+
not(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b")),
58+
inline(never)
59+
)]
60+
unsafe fn _cmpxchg16b(
61+
dst: *mut u128,
62+
old: u128,
63+
new: u128,
64+
success: Ordering,
65+
failure: Ordering,
66+
) -> (u128, bool) {
5067
debug_assert!(dst as usize % 16 == 0);
5168

69+
// Miri and Sanitizer do not support inline assembly.
70+
#[cfg(any(miri, portable_atomic_sanitize_thread))]
71+
// SAFETY: the caller must uphold the safety contract for `_cmpxchg16b`.
72+
unsafe {
73+
let res = core::arch::x86_64::cmpxchg16b(dst, old, new, success, failure);
74+
(res, res == old)
75+
}
76+
#[cfg(not(any(miri, portable_atomic_sanitize_thread)))]
5277
// SAFETY: the caller must guarantee that `dst` is valid for both writes and
5378
// reads, 16-byte aligned (required by CMPXCHG16B), that there are no
5479
// concurrent non-atomic operations, and that the CPU supports CMPXCHG16B.
@@ -62,6 +87,8 @@ unsafe fn __cmpxchg16b(dst: *mut u128, old: u128, new: u128) -> (u128, bool) {
6287
//
6388
// Refs: https://www.felixcloutier.com/x86/cmpxchg8b:cmpxchg16b
6489
unsafe {
90+
// cmpxchg16b is always SeqCst.
91+
let _ = (success, failure);
6592
let r: u8;
6693
let old = U128 { whole: old };
6794
let new = U128 { whole: new };
@@ -101,40 +128,6 @@ unsafe fn cmpxchg16b(
101128
success: Ordering,
102129
failure: Ordering,
103130
) -> (u128, bool) {
104-
#[cfg_attr(
105-
not(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b")),
106-
target_feature(enable = "cmpxchg16b")
107-
)]
108-
#[cfg_attr(
109-
any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"),
110-
inline
111-
)]
112-
#[cfg_attr(
113-
not(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b")),
114-
inline(never)
115-
)]
116-
unsafe fn _cmpxchg16b(
117-
dst: *mut u128,
118-
old: u128,
119-
new: u128,
120-
success: Ordering,
121-
failure: Ordering,
122-
) -> (u128, bool) {
123-
// Miri and Sanitizer do not support inline assembly.
124-
#[cfg(any(miri, portable_atomic_sanitize_thread))]
125-
// SAFETY: the caller must uphold the safety contract for `_cmpxchg16b`.
126-
unsafe {
127-
let res = core::arch::x86_64::cmpxchg16b(dst, old, new, success, failure);
128-
(res, res == old)
129-
}
130-
#[cfg(not(any(miri, portable_atomic_sanitize_thread)))]
131-
// SAFETY: the caller must uphold the safety contract for `_cmpxchg16b`.
132-
unsafe {
133-
let _ = (success, failure);
134-
__cmpxchg16b(dst, old, new)
135-
}
136-
}
137-
138131
#[cfg(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"))]
139132
// SAFETY: the caller must guarantee that `dst` is valid for both writes and
140133
// reads, 16-byte aligned, that there are no concurrent non-atomic operations,
@@ -434,9 +427,12 @@ mod tests {
434427
test_atomic_int!(u128);
435428

436429
#[test]
437-
#[cfg_attr(miri, ignore)] // Miri doesn't support inline assembly
438430
fn test() {
439-
assert!(std::is_x86_feature_detected!("cmpxchg16b"));
431+
// Miri doesn't support inline assembly used in is_x86_feature_detected
432+
#[cfg(not(miri))]
433+
{
434+
assert!(std::is_x86_feature_detected!("cmpxchg16b"));
435+
}
440436
assert!(AtomicI128::is_lock_free());
441437
assert!(AtomicU128::is_lock_free());
442438
}
@@ -450,13 +446,15 @@ mod tests {
450446
use super::super::*;
451447

452448
::quickcheck::quickcheck! {
453-
#[cfg_attr(miri, ignore)] // Miri doesn't support inline assembly
454-
#[cfg_attr(portable_atomic_sanitize_thread, ignore)] // TSan doesn't know the semantics of the asm synchronization instructions.
455449
fn test(x: u128, y: u128, z: u128) -> bool {
456-
assert!(std::is_x86_feature_detected!("cmpxchg16b"));
450+
// Miri doesn't support inline assembly used in is_x86_feature_detected
451+
#[cfg(not(miri))]
452+
{
453+
assert!(std::is_x86_feature_detected!("cmpxchg16b"));
454+
}
457455
unsafe {
458456
let a = Align16(UnsafeCell::new(x));
459-
let (res, ok) = __cmpxchg16b(a.get(), y, z);
457+
let (res, ok) = _cmpxchg16b(a.get(), y, z, Ordering::SeqCst, Ordering::SeqCst);
460458
if x == y {
461459
assert!(ok);
462460
assert_eq!(res, x);

0 commit comments

Comments
 (0)