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