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 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 76 void PrintVersion() { 77 PrintVersionFlag = true; 78 std::fputs(VersionString+1,stderr); 79 } 80 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 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 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