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;
@@ -40,16 +40,16 @@ pub const _TMFAILURE_RTRY: u32 = 1 << 15;
4040/// Transaction cancelled.
4141pub const _TMFAILURE_CNCL: u32 = 1 << 16 ;
4242
43- /// Transaction cancelled due to high memory usage.
43+ /// Transaction cancelled due to a memory fault
4444pub const _TMFAILURE_MEM: u32 = 1 << 17 ;
4545
46- ///
46+ /// Transaction error caused by implementation defined feature
4747pub const _TMFAILURE_IMP: u32 = 1 << 18 ;
4848
49- ///
49+ /// Transaction aborted because of non-recovera
5050pub const _TMFAILURE_ERR: u32 = 1 << 19 ;
5151
52- ///
52+ /// Transaction cancelled due to size doesn't fit
5353pub const _TMFAILURE_SIZE: u32 = 1 << 20 ;
5454
5555/// Transaction abort in a inner nested transaction.
@@ -58,10 +58,10 @@ pub const _TMFAILURE_NEST: u32 = 1 << 21;
5858/// Transaction abort 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+ /// Transaction aborted in trivial TM implementation
6565pub const _TMFAILURE_TRIVIAL: u32 = 1 << 24 ;
6666
6767
@@ -116,9 +116,72 @@ pub unsafe fn __ttest() -> u32 {
116116 aarch64_ttest ( ) as _
117117}
118118
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)
119+
120+ #[ cfg( test) ]
121+ mod tests {
122+ use stdarch_test:: simd_test;
123+
124+ use crate :: core_arch:: aarch64:: * ;
125+
126+ #[ simd_test( enable = "tme" ) ]
127+ unsafe fn test_tstart ( ) {
128+ let mut x = 0 ;
129+ for i in 0 ..10 {
130+ let code = tme:: __tstart ( ) ;
131+ if code == _TMSTART_SUCCESS {
132+ x += 1 ;
133+ assert_eq ! ( x, i+1 ) ;
134+ break ;
135+ }
136+ assert_eq ! ( x, 0 ) ;
137+ }
138+ }
139+
140+ #[ simd_test( enable = "tme" ) ]
141+ unsafe fn test_tcommit ( ) {
142+ let mut x = 0 ;
143+ for i in 0 ..10 {
144+ let code = tme:: __tstart ( ) ;
145+ if code == _TMSTART_SUCCESS {
146+ x += 1 ;
147+ assert_eq ! ( x, i+1 ) ;
148+ tme:: __tcommit ( ) ;
149+ }
150+ assert_eq ! ( x, i+1 ) ;
151+ }
152+ }
153+
154+ #[ simd_test( enable = "tme" ) ]
155+ unsafe fn test_tcancel ( ) {
156+ let reason = 0x123 ;
157+ let cancel_code = ( 0 | ( reason & _TMFAILURE_REASON) as i32 ) as u32 ;
158+ let mut x = 0 ;
159+
160+ for i in 0 ..10 {
161+ let code = tme:: __tstart ( ) ;
162+ if code == _TMSTART_SUCCESS {
163+ x += 1 ;
164+ assert_eq ! ( x, i+1 ) ;
165+ tme:: __tcancel ( cancel_code) ;
166+ break ;
167+ }
168+ }
169+
170+ assert_eq ! ( x, 0 ) ;
171+ }
172+
173+ #[ simd_test( enable = "tme" ) ]
174+ unsafe fn test_ttest ( ) {
175+ let reason = 0x123 ;
176+ let cancel_code = ( 0 | ( reason & _TMFAILURE_REASON) as i32 ) as u32 ;
177+ for _ in 0 ..10 {
178+ let code = tme:: __tstart ( ) ;
179+ if code == _TMSTART_SUCCESS {
180+ if tme:: __ttest ( ) == 2 {
181+ tme:: __tcancel ( cancel_code) ;
182+ break ;
183+ }
184+ }
185+ }
186+ }
124187}
0 commit comments