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