diff options
Diffstat (limited to 'src/elision.rs')
-rw-r--r-- | src/elision.rs | 86 |
1 files changed, 41 insertions, 45 deletions
diff --git a/src/elision.rs b/src/elision.rs index 68cfa63..8fa229e 100644 --- a/src/elision.rs +++ b/src/elision.rs @@ -5,6 +5,8 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. +#[cfg(all(feature = "hardware-lock-elision", any(target_arch = "x86", target_arch = "x86_64")))] +use std::arch::asm; use std::sync::atomic::AtomicUsize; // Extension trait to add lock elision primitives to atomic types @@ -26,14 +28,14 @@ pub trait AtomicElisionExt { #[inline] pub fn have_elision() -> bool { cfg!(all( - feature = "nightly", + feature = "hardware-lock-elision", any(target_arch = "x86", target_arch = "x86_64"), )) } // This implementation is never actually called because it is guarded by // have_elision(). -#[cfg(not(all(feature = "nightly", any(target_arch = "x86", target_arch = "x86_64"))))] +#[cfg(not(all(feature = "hardware-lock-elision", any(target_arch = "x86", target_arch = "x86_64"))))] impl AtomicElisionExt for AtomicUsize { type IntType = usize; @@ -48,37 +50,33 @@ impl AtomicElisionExt for AtomicUsize { } } -#[cfg(all(feature = "nightly", any(target_arch = "x86", target_arch = "x86_64")))] +#[cfg(all(feature = "hardware-lock-elision", any(target_arch = "x86", target_arch = "x86_64")))] impl AtomicElisionExt for AtomicUsize { type IntType = usize; - #[cfg(target_pointer_width = "32")] #[inline] fn elision_compare_exchange_acquire(&self, current: usize, new: usize) -> Result<usize, usize> { unsafe { + use core::arch::asm; let prev: usize; - llvm_asm!("xacquire; lock; cmpxchgl $2, $1" - : "={eax}" (prev), "+*m" (self) - : "r" (new), "{eax}" (current) - : "memory" - : "volatile"); - if prev == current { - Ok(prev) - } else { - Err(prev) - } - } - } - #[cfg(target_pointer_width = "64")] - #[inline] - fn elision_compare_exchange_acquire(&self, current: usize, new: usize) -> Result<usize, usize> { - unsafe { - let prev: usize; - llvm_asm!("xacquire; lock; cmpxchgq $2, $1" - : "={rax}" (prev), "+*m" (self) - : "r" (new), "{rax}" (current) - : "memory" - : "volatile"); + #[cfg(target_pointer_width = "32")] + asm!( + "xacquire", + "lock", + "cmpxchg [{:e}], {:e}", + in(reg) self, + in(reg) new, + inout("eax") current => prev, + ); + #[cfg(target_pointer_width = "64")] + asm!( + "xacquire", + "lock", + "cmpxchg [{}], {}", + in(reg) self, + in(reg) new, + inout("rax") current => prev, + ); if prev == current { Ok(prev) } else { @@ -87,29 +85,27 @@ impl AtomicElisionExt for AtomicUsize { } } - #[cfg(target_pointer_width = "32")] - #[inline] - fn elision_fetch_sub_release(&self, val: usize) -> usize { - unsafe { - let prev: usize; - llvm_asm!("xrelease; lock; xaddl $2, $1" - : "=r" (prev), "+*m" (self) - : "0" (val.wrapping_neg()) - : "memory" - : "volatile"); - prev - } - } - #[cfg(target_pointer_width = "64")] #[inline] fn elision_fetch_sub_release(&self, val: usize) -> usize { unsafe { + use core::arch::asm; let prev: usize; - llvm_asm!("xrelease; lock; xaddq $2, $1" - : "=r" (prev), "+*m" (self) - : "0" (val.wrapping_neg()) - : "memory" - : "volatile"); + #[cfg(target_pointer_width = "32")] + asm!( + "xrelease", + "lock", + "xadd [{:e}], {:e}", + in(reg) self, + inout(reg) val.wrapping_neg() => prev, + ); + #[cfg(target_pointer_width = "64")] + asm!( + "xrelease", + "lock", + "xadd [{}], {}", + in(reg) self, + inout(reg) val.wrapping_neg() => prev, + ); prev } } |