1
1
//! ARM's Transactional Memory Extensions (TME).
2
2
//!
3
- //! This CPU feature is available on Aarch64 – ARMv8-A arch. onwards .
3
+ //! This CPU feature is available on Aarch64 - A architecture profile .
4
4
//! This feature is in the non-neon feature set. TME specific vendor documentation can
5
5
//! be found [TME Intrinsics Introduction][tme_intrinsics_intro].
6
6
//!
7
7
//! The reference is [ACLE Q4 2019][acle_q4_2019_ref].
8
8
//!
9
9
//! ACLE has a section for TME extensions and state masks for aborts and failure codes.
10
- //! In addition to that [LLVM Aarch64 Intrinsics][llvm_aarch64_int] are
11
- //! self explanatory for what needs to be exported.
10
+ //! [ARM A64 Architecture Register Datasheet][a_profile_future] also describes possible failure code scenarios.
12
11
//!
13
12
//! [acle_q4_2019_ref]: https://static.docs.arm.com/101028/0010/ACLE_2019Q4_release-0010.pdf
14
13
//! [tme_intrinsics_intro]: https://developer.arm.com/docs/101028/0010/transactional-memory-extension-tme-intrinsics
15
14
//! [llvm_aarch64_int]: https://github.com/llvm/llvm-project/commit/a36d31478c182903523e04eb271bbf102bfab2cc#diff-ff24e1c35f4d54f1110ce5d90c709319R626-R646
15
+ //! [a_profile_future]: https://static.docs.arm.com/ddi0601/a/SysReg_xml_futureA-2019-04.pdf?_ga=2.116560387.441514988.1590524918-1110153136.1588469296
16
16
17
17
#[ cfg( test) ]
18
18
use stdarch_test:: assert_instr;
@@ -37,34 +37,33 @@ pub const _TMFAILURE_REASON: u32 = 0x00007FFF_u32;
37
37
/// Transaction retry is possible.
38
38
pub const _TMFAILURE_RTRY: u32 = 1 << 15 ;
39
39
40
- /// Transaction cancelled.
40
+ /// Transaction executed a TCANCEL instruction
41
41
pub const _TMFAILURE_CNCL: u32 = 1 << 16 ;
42
42
43
- /// Transaction cancelled due to high memory usage.
43
+ /// Transaction aborted because a conflict occurred
44
44
pub const _TMFAILURE_MEM: u32 = 1 << 17 ;
45
45
46
- ///
46
+ /// Fallback error type for any other reason
47
47
pub const _TMFAILURE_IMP: u32 = 1 << 18 ;
48
48
49
- ///
49
+ /// Transaction aborted because a non-permissible operation was attempted
50
50
pub const _TMFAILURE_ERR: u32 = 1 << 19 ;
51
51
52
- ///
52
+ /// Transaction aborted due to read or write set limit was exceeded
53
53
pub const _TMFAILURE_SIZE: u32 = 1 << 20 ;
54
54
55
- /// Transaction abort in a inner nested transaction.
55
+ /// Transaction aborted due to transactional nesting level was exceeded
56
56
pub const _TMFAILURE_NEST: u32 = 1 << 21 ;
57
57
58
- /// Transaction abort due to a debug trap.
58
+ /// Transaction aborted due to a debug trap.
59
59
pub const _TMFAILURE_DBG: u32 = 1 << 22 ;
60
60
61
- ///
61
+ /// Transaction failed from interrupt
62
62
pub const _TMFAILURE_INT: u32 = 1 << 23 ;
63
63
64
- ///
64
+ /// Indicates a TRIVIAL version of TM is available
65
65
pub const _TMFAILURE_TRIVIAL: u32 = 1 << 24 ;
66
66
67
-
68
67
/// Starts a new transaction. When the transaction starts successfully the return value is 0.
69
68
/// If the transaction fails, all state modifications are discarded and a cause of the failure
70
69
/// is encoded in the return value.
@@ -116,9 +115,71 @@ pub unsafe fn __ttest() -> u32 {
116
115
aarch64_ttest ( ) as _
117
116
}
118
117
119
- /// Encodes cancellation reason, which is the parameter passed to [`__tcancel`]
120
- /// Takes cancellation reason flags and retry-ability.
121
- #[ inline]
122
- pub const fn _tcancel_code ( reason : u32 , retryable : bool ) -> u32 {
123
- ( retryable as i32 ) << 15 | ( reason & _TMFAILURE_REASON)
118
+ #[ cfg( test) ]
119
+ mod tests {
120
+ use stdarch_test:: simd_test;
121
+
122
+ use crate :: core_arch:: aarch64:: * ;
123
+
124
+ #[ simd_test( enable = "tme" ) ]
125
+ unsafe fn test_tstart ( ) {
126
+ let mut x = 0 ;
127
+ for i in 0 ..10 {
128
+ let code = tme:: __tstart ( ) ;
129
+ if code == _TMSTART_SUCCESS {
130
+ x += 1 ;
131
+ assert_eq ! ( x, i+1 ) ;
132
+ break ;
133
+ }
134
+ assert_eq ! ( x, 0 ) ;
135
+ }
136
+ }
137
+
138
+ #[ simd_test( enable = "tme" ) ]
139
+ unsafe fn test_tcommit ( ) {
140
+ let mut x = 0 ;
141
+ for i in 0 ..10 {
142
+ let code = tme:: __tstart ( ) ;
143
+ if code == _TMSTART_SUCCESS {
144
+ x += 1 ;
145
+ assert_eq ! ( x, i+1 ) ;
146
+ tme:: __tcommit ( ) ;
147
+ }
148
+ assert_eq ! ( x, i+1 ) ;
149
+ }
150
+ }
151
+
152
+ #[ simd_test( enable = "tme" ) ]
153
+ unsafe fn test_tcancel ( ) {
154
+ let reason = 0x123 ;
155
+ let cancel_code = ( 0 | ( reason & _TMFAILURE_REASON) as i32 ) as u32 ;
156
+ let mut x = 0 ;
157
+
158
+ for i in 0 ..10 {
159
+ let code = tme:: __tstart ( ) ;
160
+ if code == _TMSTART_SUCCESS {
161
+ x += 1 ;
162
+ assert_eq ! ( x, i+1 ) ;
163
+ tme:: __tcancel ( cancel_code) ;
164
+ break ;
165
+ }
166
+ }
167
+
168
+ assert_eq ! ( x, 0 ) ;
169
+ }
170
+
171
+ #[ simd_test( enable = "tme" ) ]
172
+ unsafe fn test_ttest ( ) {
173
+ let reason = 0x123 ;
174
+ let cancel_code = ( 0 | ( reason & _TMFAILURE_REASON) as i32 ) as u32 ;
175
+ for _ in 0 ..10 {
176
+ let code = tme:: __tstart ( ) ;
177
+ if code == _TMSTART_SUCCESS {
178
+ if tme:: __ttest ( ) == 2 {
179
+ tme:: __tcancel ( cancel_code) ;
180
+ break ;
181
+ }
182
+ }
183
+ }
184
+ }
124
185
}
0 commit comments