@@ -45,10 +45,35 @@ struct Pair {
45
45
hi : u64 ,
46
46
}
47
47
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 ) {
50
67
debug_assert ! ( dst as usize % 16 == 0 ) ;
51
68
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) ) ) ]
52
77
// SAFETY: the caller must guarantee that `dst` is valid for both writes and
53
78
// reads, 16-byte aligned (required by CMPXCHG16B), that there are no
54
79
// 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) {
62
87
//
63
88
// Refs: https://www.felixcloutier.com/x86/cmpxchg8b:cmpxchg16b
64
89
unsafe {
90
+ // cmpxchg16b is always SeqCst.
91
+ let _ = ( success, failure) ;
65
92
let r: u8 ;
66
93
let old = U128 { whole : old } ;
67
94
let new = U128 { whole : new } ;
@@ -101,40 +128,6 @@ unsafe fn cmpxchg16b(
101
128
success : Ordering ,
102
129
failure : Ordering ,
103
130
) -> ( 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
-
138
131
#[ cfg( any( target_feature = "cmpxchg16b" , portable_atomic_target_feature = "cmpxchg16b" ) ) ]
139
132
// SAFETY: the caller must guarantee that `dst` is valid for both writes and
140
133
// reads, 16-byte aligned, that there are no concurrent non-atomic operations,
@@ -434,9 +427,12 @@ mod tests {
434
427
test_atomic_int ! ( u128 ) ;
435
428
436
429
#[ test]
437
- #[ cfg_attr( miri, ignore) ] // Miri doesn't support inline assembly
438
430
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
+ }
440
436
assert ! ( AtomicI128 :: is_lock_free( ) ) ;
441
437
assert ! ( AtomicU128 :: is_lock_free( ) ) ;
442
438
}
@@ -450,13 +446,15 @@ mod tests {
450
446
use super :: super :: * ;
451
447
452
448
:: 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.
455
449
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
+ }
457
455
unsafe {
458
456
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 ) ;
460
458
if x == y {
461
459
assert!( ok) ;
462
460
assert_eq!( res, x) ;
0 commit comments