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