/rust/registry/src/index.crates.io-6f17d22bba15001f/parking_lot-0.12.3/src/elision.rs
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2016 Amanieu d'Antras |
2 | | // |
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. |
7 | | |
8 | | use std::sync::atomic::AtomicUsize; |
9 | | |
10 | | // Extension trait to add lock elision primitives to atomic types |
11 | | pub trait AtomicElisionExt { |
12 | | type IntType; |
13 | | |
14 | | // Perform a compare_exchange and start a transaction |
15 | | fn elision_compare_exchange_acquire( |
16 | | &self, |
17 | | current: Self::IntType, |
18 | | new: Self::IntType, |
19 | | ) -> Result<Self::IntType, Self::IntType>; |
20 | | |
21 | | // Perform a fetch_sub and end a transaction |
22 | | fn elision_fetch_sub_release(&self, val: Self::IntType) -> Self::IntType; |
23 | | } |
24 | | |
25 | | // Indicates whether the target architecture supports lock elision |
26 | | #[inline] |
27 | 408k | pub fn have_elision() -> bool { |
28 | 408k | cfg!(all( |
29 | 408k | feature = "hardware-lock-elision", |
30 | 408k | any(target_arch = "x86", target_arch = "x86_64"), |
31 | 408k | )) |
32 | 408k | } parking_lot::elision::have_elision Line | Count | Source | 27 | 319k | pub fn have_elision() -> bool { | 28 | 319k | cfg!(all( | 29 | 319k | feature = "hardware-lock-elision", | 30 | 319k | any(target_arch = "x86", target_arch = "x86_64"), | 31 | 319k | )) | 32 | 319k | } |
parking_lot::elision::have_elision Line | Count | Source | 27 | 89.3k | pub fn have_elision() -> bool { | 28 | 89.3k | cfg!(all( | 29 | 89.3k | feature = "hardware-lock-elision", | 30 | 89.3k | any(target_arch = "x86", target_arch = "x86_64"), | 31 | 89.3k | )) | 32 | 89.3k | } |
|
33 | | |
34 | | // This implementation is never actually called because it is guarded by |
35 | | // have_elision(). |
36 | | #[cfg(not(all( |
37 | | feature = "hardware-lock-elision", |
38 | | any(target_arch = "x86", target_arch = "x86_64") |
39 | | )))] |
40 | | impl AtomicElisionExt for AtomicUsize { |
41 | | type IntType = usize; |
42 | | |
43 | | #[inline] |
44 | 0 | fn elision_compare_exchange_acquire(&self, _: usize, _: usize) -> Result<usize, usize> { |
45 | 0 | unreachable!(); |
46 | | } |
47 | | |
48 | | #[inline] |
49 | 0 | fn elision_fetch_sub_release(&self, _: usize) -> usize { |
50 | 0 | unreachable!(); |
51 | | } |
52 | | } |
53 | | |
54 | | #[cfg(all( |
55 | | feature = "hardware-lock-elision", |
56 | | any(target_arch = "x86", target_arch = "x86_64") |
57 | | ))] |
58 | | impl AtomicElisionExt for AtomicUsize { |
59 | | type IntType = usize; |
60 | | |
61 | | #[inline] |
62 | | fn elision_compare_exchange_acquire(&self, current: usize, new: usize) -> Result<usize, usize> { |
63 | | unsafe { |
64 | | use core::arch::asm; |
65 | | let prev: usize; |
66 | | #[cfg(target_pointer_width = "32")] |
67 | | asm!( |
68 | | "xacquire", |
69 | | "lock", |
70 | | "cmpxchg [{:e}], {:e}", |
71 | | in(reg) self, |
72 | | in(reg) new, |
73 | | inout("eax") current => prev, |
74 | | ); |
75 | | #[cfg(target_pointer_width = "64")] |
76 | | asm!( |
77 | | "xacquire", |
78 | | "lock", |
79 | | "cmpxchg [{}], {}", |
80 | | in(reg) self, |
81 | | in(reg) new, |
82 | | inout("rax") current => prev, |
83 | | ); |
84 | | if prev == current { |
85 | | Ok(prev) |
86 | | } else { |
87 | | Err(prev) |
88 | | } |
89 | | } |
90 | | } |
91 | | |
92 | | #[inline] |
93 | | fn elision_fetch_sub_release(&self, val: usize) -> usize { |
94 | | unsafe { |
95 | | use core::arch::asm; |
96 | | let prev: usize; |
97 | | #[cfg(target_pointer_width = "32")] |
98 | | asm!( |
99 | | "xrelease", |
100 | | "lock", |
101 | | "xadd [{:e}], {:e}", |
102 | | in(reg) self, |
103 | | inout(reg) val.wrapping_neg() => prev, |
104 | | ); |
105 | | #[cfg(target_pointer_width = "64")] |
106 | | asm!( |
107 | | "xrelease", |
108 | | "lock", |
109 | | "xadd [{}], {}", |
110 | | in(reg) self, |
111 | | inout(reg) val.wrapping_neg() => prev, |
112 | | ); |
113 | | prev |
114 | | } |
115 | | } |
116 | | } |