11//! ARM's Transactional Memory Extensions (TME).
22//!
3- //! This CPU feature is available on Aarch64 – ARMv8-A arch. onwards .
3+ //! This CPU feature is available on Aarch64 - A architecture profile .
44//! This feature is in the non-neon feature set. TME specific vendor documentation can
55//! be found [TME Intrinsics Introduction][tme_intrinsics_intro].
66//!
77//! The reference is [ACLE Q4 2019][acle_q4_2019_ref].
88//!
99//! 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.
1211//!
1312//! [acle_q4_2019_ref]: https://static.docs.arm.com/101028/0010/ACLE_2019Q4_release-0010.pdf
1413//! [tme_intrinsics_intro]: https://developer.arm.com/docs/101028/0010/transactional-memory-extension-tme-intrinsics
1514//! [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
1616
1717#[ cfg( test) ]
1818use stdarch_test:: assert_instr;
@@ -37,34 +37,33 @@ pub const _TMFAILURE_REASON: u32 = 0x00007FFF_u32;
3737/// Transaction retry is possible.
3838pub const _TMFAILURE_RTRY: u32 = 1 << 15 ;
3939
40- /// Transaction cancelled.
40+ /// Transaction executed a TCANCEL instruction
4141pub const _TMFAILURE_CNCL: u32 = 1 << 16 ;
4242
43- /// Transaction cancelled due to high memory usage.
43+ /// Transaction aborted because a conflict occurred
4444pub const _TMFAILURE_MEM: u32 = 1 << 17 ;
4545
46- ///
46+ /// Fallback error type for any other reason
4747pub const _TMFAILURE_IMP: u32 = 1 << 18 ;
4848
49- ///
49+ /// Transaction aborted because a non-permissible operation was attempted
5050pub const _TMFAILURE_ERR: u32 = 1 << 19 ;
5151
52- ///
52+ /// Transaction aborted due to read or write set limit was exceeded
5353pub const _TMFAILURE_SIZE: u32 = 1 << 20 ;
5454
55- /// Transaction abort in a inner nested transaction.
55+ /// Transaction aborted due to transactional nesting level was exceeded
5656pub const _TMFAILURE_NEST: u32 = 1 << 21 ;
5757
58- /// Transaction abort due to a debug trap.
58+ /// Transaction aborted due to a debug trap.
5959pub const _TMFAILURE_DBG: u32 = 1 << 22 ;
6060
61- ///
61+ /// Transaction failed from interrupt
6262pub const _TMFAILURE_INT: u32 = 1 << 23 ;
6363
64- ///
64+ /// Indicates a TRIVIAL version of TM is available
6565pub const _TMFAILURE_TRIVIAL: u32 = 1 << 24 ;
6666
67-
6867/// Starts a new transaction. When the transaction starts successfully the return value is 0.
6968/// If the transaction fails, all state modifications are discarded and a cause of the failure
7069/// is encoded in the return value.
@@ -116,9 +115,71 @@ pub unsafe fn __ttest() -> u32 {
116115 aarch64_ttest ( ) as _
117116}
118117
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+ }
124185}
0 commit comments