]>
git.proxmox.com Git - rustc.git/blob - vendor/parking_lot-0.9.0/src/elision.rs
1 // Copyright 2016 Amanieu d'Antras
3 // Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4 // http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5 // http://opensource.org/licenses/MIT>, at your option. This file may not be
6 // copied, modified, or distributed except according to those terms.
8 use std
::sync
::atomic
::AtomicUsize
;
10 // Extension trait to add lock elision primitives to atomic types
11 pub trait AtomicElisionExt
{
14 // Perform a compare_exchange and start a transaction
15 fn elision_compare_exchange_acquire(
17 current
: Self::IntType
,
19 ) -> Result
<Self::IntType
, Self::IntType
>;
21 // Perform a fetch_sub and end a transaction
22 fn elision_fetch_sub_release(&self, val
: Self::IntType
) -> Self::IntType
;
25 // Indicates whether the target architecture supports lock elision
27 pub fn have_elision() -> bool
{
28 cfg
!(all(feature
= "nightly", any(target_arch
= "x86", target_arch
= "x86_64"),))
31 // This implementation is never actually called because it is guarded by
33 #[cfg(not(all(feature = "nightly", any(target_arch = "x86", target_arch = "x86_64"))))]
34 impl AtomicElisionExt
for AtomicUsize
{
38 fn elision_compare_exchange_acquire(&self, _
: usize, _
: usize) -> Result
<usize, usize> {
43 fn elision_fetch_sub_release(&self, _
: usize) -> usize {
48 #[cfg(all(feature = "nightly", any(target_arch = "x86", target_arch = "x86_64")))]
49 impl AtomicElisionExt
for AtomicUsize
{
52 #[cfg(target_pointer_width = "32")]
54 fn elision_compare_exchange_acquire(&self, current
: usize, new
: usize) -> Result
<usize, usize> {
57 asm
!("xacquire; lock; cmpxchgl $2, $1"
58 : "={eax}" (prev
), "+*m" (self)
59 : "r" (new
), "{eax}" (current
)
62 if prev
== current { Ok(prev) }
else { Err(prev) }
65 #[cfg(target_pointer_width = "64")]
67 fn elision_compare_exchange_acquire(&self, current
: usize, new
: usize) -> Result
<usize, usize> {
70 asm
!("xacquire; lock; cmpxchgq $2, $1"
71 : "={rax}" (prev
), "+*m" (self)
72 : "r" (new
), "{rax}" (current
)
75 if prev
== current { Ok(prev) }
else { Err(prev) }
79 #[cfg(target_pointer_width = "32")]
81 fn elision_fetch_sub_release(&self, val
: usize) -> usize {
84 asm
!("xrelease; lock; xaddl $2, $1"
85 : "=r" (prev
), "+*m" (self)
86 : "0" (val
.wrapping_neg())
92 #[cfg(target_pointer_width = "64")]
94 fn elision_fetch_sub_release(&self, val
: usize) -> usize {
97 asm
!("xrelease; lock; xaddq $2, $1"
98 : "=r" (prev
), "+*m" (self)
99 : "0" (val
.wrapping_neg())