1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct HardwareMemoryTransactionManager
{
#[cfg(target_arch = "x86_64")] cpu_supports_hardware_transactions: bool,
}
impl HardwareMemoryTransactionManager
{
#[cfg(target_arch = "x86_64")]
#[inline(always)]
pub fn new() -> Self
{
Self
{
cpu_supports_hardware_transactions:
{
let cpu_id = CpuId::new();
if let Some(extended_features) = cpu_id.get_extended_feature_info()
{
extended_features.has_rtm()
}
else
{
false
}
}
}
}
#[cfg(not(target_arch = "x86_64"))]
#[inline(always)]
pub fn new() -> Self
{
Self
{
}
}
#[cfg(not(target_arch = "x86_64"))]
#[inline(always)]
pub fn execute_transaction_once_gracefully<TransactionCallback: FnMut() -> Result<(), u8>>(&self, mut transaction_callback: TransactionCallback) -> Result<(), Option<HardwareMemoryTransactionResult>>
{
Err(None)
}
#[inline(always)]
#[cfg(target_arch = "x86_64")]
pub fn execute_transaction_once_gracefully<TransactionCallback: FnMut() -> Result<(), u8>>(&self, transaction_callback: TransactionCallback) -> Result<(), Option<HardwareMemoryTransactionResult>>
{
if self.cpu_supports_hardware_transactions()
{
self.execute_transaction_once(transaction_callback).map_err(|error| Some(error))
}
else
{
Err(None)
}
}
#[cfg(target_arch = "x86_64")]
#[inline(always)]
pub fn execute_transaction_once<TransactionCallback: FnMut() -> Result<(), u8>>(&self, mut transaction_callback: TransactionCallback) -> Result<(), HardwareMemoryTransactionResult>
{
debug_assert!(self.cpu_supports_hardware_transactions(), "This x86_64 CPU does not have hardware transactions that we can use");
let xbegin_result_code = unsafe { _xbegin() };
if xbegin_result_code == _XBEGIN_STARTED
{
match transaction_callback()
{
Ok(()) =>
{
unsafe { _xend() };
Ok(())
},
Err(result_status_code) => unsafe { _xabort(result_status_code as u32) },
}
}
else
{
Err(HardwareMemoryTransactionResult::new(xbegin_result_code))
}
}
#[cfg(not(target_arch = "x86_64"))]
#[inline(always)]
pub fn execute_transaction_once<TransactionCallback: FnMut() -> u8>(mut transaction_callback: TransactionCallback) -> Result<(), HardwareMemoryTransactionResult>
{
panic!("TSX hardware transactions are not supported on non x86_64 platforms")
}
#[cfg(target_arch = "x86_64")]
#[inline(always)]
pub fn cpu_supports_hardware_transactions(&self) -> bool
{
self.cpu_supports_hardware_transactions
}
#[inline(always)]
#[cfg(target_arch = "x86_64")]
pub fn is_inside_a_running_transaction(&self) -> bool
{
if self.cpu_supports_hardware_transactions()
{
unsafe { _xtest() }
}
else
{
false
}
}
#[cfg(not(target_arch = "x86_64"))]
#[inline(always)]
pub fn cpu_supports_hardware_transactions(&self) -> bool
{
false
}
}