xref: /oneTBB/src/tbb/misc.cpp (revision 51c0b2f7)
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 // Source file for miscellaneous entities that are infrequently referenced by
18 // an executing program.
19 
20 #include "tbb/detail/_exception.h"
21 #include "tbb/detail/_machine.h"
22 
23 #include "tbb/version.h"
24 
25 #include "misc.h"
26 #include "assert_impl.h" // Out-of-line TBB assertion handling routines are instantiated here.
27 
28 #include <cstdio>
29 #include <cstdlib>
30 #include <stdexcept>
31 #include <cstring>
32 #include <cstdarg>
33 
34 #if _WIN32||_WIN64
35 #include <windows.h>
36 #endif
37 
38 #if !_WIN32
39 #include <unistd.h> // sysconf(_SC_PAGESIZE)
40 #endif
41 
42 namespace tbb {
43 namespace detail {
44 namespace r1 {
45 
46 size_t DefaultSystemPageSize() {
47 #if _WIN32
48     SYSTEM_INFO si;
49     GetSystemInfo(&si);
50     return si.dwPageSize;
51 #else
52     return sysconf(_SC_PAGESIZE);
53 #endif
54 }
55 
56 /** The leading "\0" is here so that applying "strings" to the binary delivers a clean result. */
57 static const char VersionString[] = "\0" TBB_VERSION_STRINGS;
58 
59 static bool PrintVersionFlag = false;
60 
61 void PrintVersion() {
62     PrintVersionFlag = true;
63     std::fputs(VersionString+1,stderr);
64 }
65 
66 void PrintExtraVersionInfo( const char* category, const char* format, ... ) {
67     if( PrintVersionFlag ) {
68         char str[1024]; std::memset(str, 0, 1024);
69         va_list args; va_start(args, format);
70         // Note: correct vsnprintf definition obtained from tbb_assert_impl.h
71         std::vsnprintf( str, 1024-1, format, args);
72         va_end(args);
73         std::fprintf(stderr, "TBB: %s\t%s\n", category, str );
74     }
75 }
76 
77 //! check for transaction support.
78 #if _MSC_VER
79 #include <intrin.h> // for __cpuid
80 #endif
81 
82 #if __TBB_x86_32 || __TBB_x86_64
83 void check_cpuid(int leaf, int sub_leaf, int registers[4]) {
84 #if _MSC_VER
85     __cpuidex(registers, leaf, sub_leaf);
86 #else
87     int reg_eax = 0;
88     int reg_ebx = 0;
89     int reg_ecx = 0;
90     int reg_edx = 0;
91 #if __TBB_x86_32 && __PIC__
92     // On 32-bit systems with position-independent code GCC fails to work around the stuff in EBX
93     // register. We help it using backup and restore.
94     __asm__("mov %%ebx, %%esi\n\t"
95             "cpuid\n\t"
96             "xchg %%ebx, %%esi"
97             : "=a"(reg_eax), "=S"(reg_ebx), "=c"(reg_ecx), "=d"(reg_edx)
98             : "0"(leaf), "2"(sub_leaf) // read value from eax and ecx
99     );
100 #else
101     __asm__("cpuid"
102             : "=a"(reg_eax), "=b"(reg_ebx), "=c"(reg_ecx), "=d"(reg_edx)
103             : "0"(leaf), "2"(sub_leaf) // read value from eax and ecx
104     );
105 #endif
106     registers[0] = reg_eax;
107     registers[1] = reg_ebx;
108     registers[2] = reg_ecx;
109     registers[3] = reg_edx;
110 #endif
111 }
112 #endif
113 
114 void detect_cpu_features(cpu_features_type& cpu_features) {
115     suppress_unused_warning(cpu_features);
116 #if __TBB_x86_32 || __TBB_x86_64
117     const int rtm_ebx_mask = 1 << 11;
118     const int waitpkg_ecx_mask = 1 << 5;
119     int registers[4] = {0};
120 
121     // Check RTM and WAITPKG
122     check_cpuid(7, 0, registers);
123     cpu_features.rtm_enabled = (registers[1] & rtm_ebx_mask) != 0;
124     cpu_features.waitpkg_enabled = (registers[2] & waitpkg_ecx_mask) != 0;
125 #endif /* (__TBB_x86_32 || __TBB_x86_64) */
126 }
127 
128 } // namespace r1
129 } // namespace detail
130 } // namespace tbb
131