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