Coverage Report

Created: 2025-11-16 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/parking_lot-0.12.5/src/elision.rs
Line
Count
Source
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
0
pub fn have_elision() -> bool {
28
0
    cfg!(all(
29
        feature = "hardware-lock-elision",
30
        not(miri),
31
        any(target_arch = "x86", target_arch = "x86_64"),
32
    ))
33
0
}
Unexecuted instantiation: parking_lot::elision::have_elision
Unexecuted instantiation: parking_lot::elision::have_elision
34
35
// This implementation is never actually called because it is guarded by
36
// have_elision().
37
#[cfg(not(all(
38
    feature = "hardware-lock-elision",
39
    not(miri),
40
    any(target_arch = "x86", target_arch = "x86_64")
41
)))]
42
impl AtomicElisionExt for AtomicUsize {
43
    type IntType = usize;
44
45
    #[inline]
46
0
    fn elision_compare_exchange_acquire(&self, _: usize, _: usize) -> Result<usize, usize> {
47
0
        unreachable!();
Unexecuted instantiation: <core::sync::atomic::AtomicUsize as parking_lot::elision::AtomicElisionExt>::elision_compare_exchange_acquire
Unexecuted instantiation: <core::sync::atomic::AtomicUsize as parking_lot::elision::AtomicElisionExt>::elision_compare_exchange_acquire
48
    }
49
50
    #[inline]
51
0
    fn elision_fetch_sub_release(&self, _: usize) -> usize {
52
0
        unreachable!();
Unexecuted instantiation: <core::sync::atomic::AtomicUsize as parking_lot::elision::AtomicElisionExt>::elision_fetch_sub_release
Unexecuted instantiation: <core::sync::atomic::AtomicUsize as parking_lot::elision::AtomicElisionExt>::elision_fetch_sub_release
53
    }
54
}
55
56
#[cfg(all(
57
    feature = "hardware-lock-elision",
58
    not(miri),
59
    any(target_arch = "x86", target_arch = "x86_64")
60
))]
61
impl AtomicElisionExt for AtomicUsize {
62
    type IntType = usize;
63
64
    #[inline]
65
    fn elision_compare_exchange_acquire(&self, current: usize, new: usize) -> Result<usize, usize> {
66
        unsafe {
67
            use core::arch::asm;
68
            let prev: usize;
69
            #[cfg(target_pointer_width = "32")]
70
            asm!(
71
                "xacquire",
72
                "lock",
73
                "cmpxchg [{:e}], {:e}",
74
                in(reg) self,
75
                in(reg) new,
76
                inout("eax") current => prev,
77
            );
78
            #[cfg(target_pointer_width = "64")]
79
            asm!(
80
                "xacquire",
81
                "lock",
82
                "cmpxchg [{}], {}",
83
                in(reg) self,
84
                in(reg) new,
85
                inout("rax") current => prev,
86
            );
87
            if prev == current {
88
                Ok(prev)
89
            } else {
90
                Err(prev)
91
            }
92
        }
93
    }
94
95
    #[inline]
96
    fn elision_fetch_sub_release(&self, val: usize) -> usize {
97
        unsafe {
98
            use core::arch::asm;
99
            let prev: usize;
100
            #[cfg(target_pointer_width = "32")]
101
            asm!(
102
                "xrelease",
103
                "lock",
104
                "xadd [{:e}], {:e}",
105
                in(reg) self,
106
                inout(reg) val.wrapping_neg() => prev,
107
            );
108
            #[cfg(target_pointer_width = "64")]
109
            asm!(
110
                "xrelease",
111
                "lock",
112
                "xadd [{}], {}",
113
                in(reg) self,
114
                inout(reg) val.wrapping_neg() => prev,
115
            );
116
            prev
117
        }
118
    }
119
}