xref: /oneTBB/src/tbb/misc.cpp (revision 4523a761)
151c0b2f7Stbbdev /*
2b15aabb3Stbbdev     Copyright (c) 2005-2021 Intel Corporation
351c0b2f7Stbbdev 
451c0b2f7Stbbdev     Licensed under the Apache License, Version 2.0 (the "License");
551c0b2f7Stbbdev     you may not use this file except in compliance with the License.
651c0b2f7Stbbdev     You may obtain a copy of the License at
751c0b2f7Stbbdev 
851c0b2f7Stbbdev         http://www.apache.org/licenses/LICENSE-2.0
951c0b2f7Stbbdev 
1051c0b2f7Stbbdev     Unless required by applicable law or agreed to in writing, software
1151c0b2f7Stbbdev     distributed under the License is distributed on an "AS IS" BASIS,
1251c0b2f7Stbbdev     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1351c0b2f7Stbbdev     See the License for the specific language governing permissions and
1451c0b2f7Stbbdev     limitations under the License.
1551c0b2f7Stbbdev */
1651c0b2f7Stbbdev 
1751c0b2f7Stbbdev // Source file for miscellaneous entities that are infrequently referenced by
1851c0b2f7Stbbdev // an executing program.
1951c0b2f7Stbbdev 
2049e08aacStbbdev #include "oneapi/tbb/detail/_exception.h"
2149e08aacStbbdev #include "oneapi/tbb/detail/_machine.h"
2251c0b2f7Stbbdev 
2349e08aacStbbdev #include "oneapi/tbb/version.h"
2451c0b2f7Stbbdev 
2551c0b2f7Stbbdev #include "misc.h"
2649e08aacStbbdev #include "governor.h"
2751c0b2f7Stbbdev #include "assert_impl.h" // Out-of-line TBB assertion handling routines are instantiated here.
28*4523a761Stbbdev #include "concurrent_monitor_mutex.h"
2951c0b2f7Stbbdev 
3051c0b2f7Stbbdev #include <cstdio>
3151c0b2f7Stbbdev #include <cstdlib>
3251c0b2f7Stbbdev #include <stdexcept>
3351c0b2f7Stbbdev #include <cstring>
3451c0b2f7Stbbdev #include <cstdarg>
3551c0b2f7Stbbdev 
3651c0b2f7Stbbdev #if _WIN32||_WIN64
3751c0b2f7Stbbdev #include <windows.h>
3851c0b2f7Stbbdev #endif
3951c0b2f7Stbbdev 
4051c0b2f7Stbbdev #if !_WIN32
4151c0b2f7Stbbdev #include <unistd.h> // sysconf(_SC_PAGESIZE)
4251c0b2f7Stbbdev #endif
4351c0b2f7Stbbdev 
4451c0b2f7Stbbdev namespace tbb {
4551c0b2f7Stbbdev namespace detail {
4651c0b2f7Stbbdev namespace r1 {
4751c0b2f7Stbbdev 
4849e08aacStbbdev //------------------------------------------------------------------------
4949e08aacStbbdev // governor data
5049e08aacStbbdev //------------------------------------------------------------------------
5149e08aacStbbdev cpu_features_type governor::cpu_features;
5249e08aacStbbdev 
53*4523a761Stbbdev //------------------------------------------------------------------------
54*4523a761Stbbdev // concurrent_monitor_mutex data
55*4523a761Stbbdev //------------------------------------------------------------------------
56*4523a761Stbbdev #if !__TBB_USE_FUTEX
57*4523a761Stbbdev std::mutex concurrent_monitor_mutex::my_init_mutex;
58*4523a761Stbbdev #endif
59*4523a761Stbbdev 
6049e08aacStbbdev 
DefaultSystemPageSize()6151c0b2f7Stbbdev size_t DefaultSystemPageSize() {
6251c0b2f7Stbbdev #if _WIN32
6351c0b2f7Stbbdev     SYSTEM_INFO si;
6451c0b2f7Stbbdev     GetSystemInfo(&si);
6551c0b2f7Stbbdev     return si.dwPageSize;
6651c0b2f7Stbbdev #else
6751c0b2f7Stbbdev     return sysconf(_SC_PAGESIZE);
6851c0b2f7Stbbdev #endif
6951c0b2f7Stbbdev }
7051c0b2f7Stbbdev 
7151c0b2f7Stbbdev /** The leading "\0" is here so that applying "strings" to the binary delivers a clean result. */
7251c0b2f7Stbbdev static const char VersionString[] = "\0" TBB_VERSION_STRINGS;
7351c0b2f7Stbbdev 
7451c0b2f7Stbbdev static bool PrintVersionFlag = false;
7551c0b2f7Stbbdev 
PrintVersion()7651c0b2f7Stbbdev void PrintVersion() {
7751c0b2f7Stbbdev     PrintVersionFlag = true;
7851c0b2f7Stbbdev     std::fputs(VersionString+1,stderr);
7951c0b2f7Stbbdev }
8051c0b2f7Stbbdev 
PrintExtraVersionInfo(const char * category,const char * format,...)8151c0b2f7Stbbdev void PrintExtraVersionInfo( const char* category, const char* format, ... ) {
8251c0b2f7Stbbdev     if( PrintVersionFlag ) {
8351c0b2f7Stbbdev         char str[1024]; std::memset(str, 0, 1024);
8451c0b2f7Stbbdev         va_list args; va_start(args, format);
8551c0b2f7Stbbdev         // Note: correct vsnprintf definition obtained from tbb_assert_impl.h
8651c0b2f7Stbbdev         std::vsnprintf( str, 1024-1, format, args);
8751c0b2f7Stbbdev         va_end(args);
8849e08aacStbbdev         std::fprintf(stderr, "oneTBB: %s\t%s\n", category, str );
8951c0b2f7Stbbdev     }
9051c0b2f7Stbbdev }
9151c0b2f7Stbbdev 
9251c0b2f7Stbbdev //! check for transaction support.
9351c0b2f7Stbbdev #if _MSC_VER
9451c0b2f7Stbbdev #include <intrin.h> // for __cpuid
9551c0b2f7Stbbdev #endif
9651c0b2f7Stbbdev 
9751c0b2f7Stbbdev #if __TBB_x86_32 || __TBB_x86_64
check_cpuid(int leaf,int sub_leaf,int registers[4])9851c0b2f7Stbbdev void check_cpuid(int leaf, int sub_leaf, int registers[4]) {
9951c0b2f7Stbbdev #if _MSC_VER
10051c0b2f7Stbbdev     __cpuidex(registers, leaf, sub_leaf);
10151c0b2f7Stbbdev #else
10251c0b2f7Stbbdev     int reg_eax = 0;
10351c0b2f7Stbbdev     int reg_ebx = 0;
10451c0b2f7Stbbdev     int reg_ecx = 0;
10551c0b2f7Stbbdev     int reg_edx = 0;
10651c0b2f7Stbbdev #if __TBB_x86_32 && __PIC__
10751c0b2f7Stbbdev     // On 32-bit systems with position-independent code GCC fails to work around the stuff in EBX
10851c0b2f7Stbbdev     // register. We help it using backup and restore.
10951c0b2f7Stbbdev     __asm__("mov %%ebx, %%esi\n\t"
11051c0b2f7Stbbdev             "cpuid\n\t"
11151c0b2f7Stbbdev             "xchg %%ebx, %%esi"
11251c0b2f7Stbbdev             : "=a"(reg_eax), "=S"(reg_ebx), "=c"(reg_ecx), "=d"(reg_edx)
11351c0b2f7Stbbdev             : "0"(leaf), "2"(sub_leaf) // read value from eax and ecx
11451c0b2f7Stbbdev     );
11551c0b2f7Stbbdev #else
11651c0b2f7Stbbdev     __asm__("cpuid"
11751c0b2f7Stbbdev             : "=a"(reg_eax), "=b"(reg_ebx), "=c"(reg_ecx), "=d"(reg_edx)
11851c0b2f7Stbbdev             : "0"(leaf), "2"(sub_leaf) // read value from eax and ecx
11951c0b2f7Stbbdev     );
12051c0b2f7Stbbdev #endif
12151c0b2f7Stbbdev     registers[0] = reg_eax;
12251c0b2f7Stbbdev     registers[1] = reg_ebx;
12351c0b2f7Stbbdev     registers[2] = reg_ecx;
12451c0b2f7Stbbdev     registers[3] = reg_edx;
12551c0b2f7Stbbdev #endif
12651c0b2f7Stbbdev }
12751c0b2f7Stbbdev #endif
12851c0b2f7Stbbdev 
detect_cpu_features(cpu_features_type & cpu_features)12951c0b2f7Stbbdev void detect_cpu_features(cpu_features_type& cpu_features) {
13051c0b2f7Stbbdev     suppress_unused_warning(cpu_features);
13151c0b2f7Stbbdev #if __TBB_x86_32 || __TBB_x86_64
13251c0b2f7Stbbdev     const int rtm_ebx_mask = 1 << 11;
13351c0b2f7Stbbdev     const int waitpkg_ecx_mask = 1 << 5;
13451c0b2f7Stbbdev     int registers[4] = {0};
13551c0b2f7Stbbdev 
13651c0b2f7Stbbdev     // Check RTM and WAITPKG
13751c0b2f7Stbbdev     check_cpuid(7, 0, registers);
13851c0b2f7Stbbdev     cpu_features.rtm_enabled = (registers[1] & rtm_ebx_mask) != 0;
13951c0b2f7Stbbdev     cpu_features.waitpkg_enabled = (registers[2] & waitpkg_ecx_mask) != 0;
14051c0b2f7Stbbdev #endif /* (__TBB_x86_32 || __TBB_x86_64) */
14151c0b2f7Stbbdev }
14251c0b2f7Stbbdev 
14351c0b2f7Stbbdev } // namespace r1
14451c0b2f7Stbbdev } // namespace detail
14551c0b2f7Stbbdev } // namespace tbb
146