1 /*
2     Copyright (c) 2005-2020 Intel Corporation
3 
4     Licensed under the Apache License, Version 2.0 (the "License");
5     you may not use this file except in compliance with the License.
6     You may obtain a copy of the License at
7 
8         http://www.apache.org/licenses/LICENSE-2.0
9 
10     Unless required by applicable law or agreed to in writing, software
11     distributed under the License is distributed on an "AS IS" BASIS,
12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     See the License for the specific language governing permissions and
14     limitations under the License.
15 */
16 
17 // Header that includes Intel(R) Transactional Synchronization Extensions (Intel(R) TSX) specific test functions
18 
19 #if __TBB_TSX_AVAILABLE
20 #define __TBB_TSX_TESTING_ENABLED_FOR_THIS_COMPILER (__INTEL_COMPILER || __GNUC__ || _MSC_VER || __SUNPRO_CC)
21 #if __TBB_TSX_TESTING_ENABLED_FOR_THIS_COMPILER
22 
23 #include "harness_defs.h"
24 
IsInsideTx()25 inline static bool IsInsideTx()
26 {
27     return __TBB_machine_is_in_transaction() != 0;
28 }
29 
30 #if _MSC_VER
31 #include <intrin.h> // for __cpuid
32 #endif
33 // TODO: consider reusing tbb_misc.cpp:cpu_has_speculation() instead of code duplication.
have_TSX()34 bool have_TSX() {
35     bool result = false;
36     const int hle_ebx_mask = 1<<4;
37     const int rtm_ebx_mask = 1<<11;
38 #if _MSC_VER
39     int info[4] = {0,0,0,0};
40     const int reg_ebx = 1;
41     int old_ecx = 0;
42     __cpuidex(info, 7, old_ecx);
43     result = (info[reg_ebx] & rtm_ebx_mask)!=0;
44     if( result ) ASSERT( (info[reg_ebx] & hle_ebx_mask)!=0, NULL );
45 #elif __GNUC__ || __SUNPRO_CC
46     int32_t reg_ebx = 0;
47     int32_t reg_eax = 7;
48     int32_t reg_ecx = 0;
49     __asm__ __volatile__ ( "movl %%ebx, %%esi\n"
50                            "cpuid\n"
51                            "movl %%ebx, %0\n"
52                            "movl %%esi, %%ebx\n"
53                            : "=a"(reg_ebx) : "0" (reg_eax), "c" (reg_ecx) : "esi",
54 #if __TBB_x86_64
55                            "ebx",
56 #endif
57                            "edx"
58                            );
59     result = (reg_ebx & rtm_ebx_mask)!=0 ;
60     if( result ) ASSERT( (reg_ebx & hle_ebx_mask)!=0, NULL );
61 #endif
62     return result;
63 }
64 
65 #endif /* __TBB_TSX_TESTING_ENABLED_FOR_THIS_COMPILER */
66 #endif /* __TBB_TSX_AVAILABLE */
67