-
Notifications
You must be signed in to change notification settings - Fork 59
Expand file tree
/
Copy pathmisc.cpp
More file actions
156 lines (132 loc) · 4.54 KB
/
misc.cpp
File metadata and controls
156 lines (132 loc) · 4.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/*
Copyright (c) 2005-2024 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Source file for miscellaneous entities that are infrequently referenced by
// an executing program.
#include "oneapi/tbb/detail/_exception.h"
#include "oneapi/tbb/detail/_machine.h"
#include "oneapi/tbb/version.h"
#include "misc.h"
#include "governor.h"
#include "assert_impl.h" // Out-of-line TBB assertion handling routines are instantiated here.
#include "concurrent_monitor_mutex.h"
#include <cstdio>
#include <cstdlib>
#include <stdexcept>
#include <cstring>
#include <cstdarg>
#if _WIN32||_WIN64
#include <windows.h>
#endif
#if !_WIN32
#include <unistd.h> // sysconf(_SC_PAGESIZE)
#endif
namespace tbb {
namespace detail {
namespace r1 {
//------------------------------------------------------------------------
// governor data
//------------------------------------------------------------------------
cpu_features_type governor::cpu_features;
//------------------------------------------------------------------------
// concurrent_monitor_mutex data
//------------------------------------------------------------------------
#if !__TBB_USE_FUTEX
std::mutex concurrent_monitor_mutex::my_init_mutex;
#endif
size_t DefaultSystemPageSize() {
#if _WIN32
SYSTEM_INFO si;
GetSystemInfo(&si);
return si.dwPageSize;
#else
return sysconf(_SC_PAGESIZE);
#endif
}
/** The leading "\0" is here so that applying "strings" to the binary delivers a clean result. */
static const char VersionString[] = "\0" TBB_VERSION_STRINGS;
static bool PrintVersionFlag = false;
void PrintVersion() {
PrintVersionFlag = true;
std::fputs(VersionString+1,stderr);
}
void PrintExtraVersionInfo( const char* category, const char* format, ... ) {
if( PrintVersionFlag ) {
char str[1024]; std::memset(str, 0, 1024);
va_list args; va_start(args, format);
// Note: correct vsnprintf definition obtained from tbb_assert_impl.h
std::vsnprintf( str, 1024-1, format, args);
va_end(args);
std::fprintf(stderr, "oneTBB: %s\t%s\n", category, str );
}
}
//! check for transaction support.
#if _MSC_VER
#include <intrin.h> // for __cpuid
#elif __APPLE__
#include <sys/sysctl.h>
#endif
#if __TBB_x86_32 || __TBB_x86_64
void check_cpuid(int leaf, int sub_leaf, int registers[4]) {
#if _MSC_VER
__cpuidex(registers, leaf, sub_leaf);
#else
int reg_eax = 0;
int reg_ebx = 0;
int reg_ecx = 0;
int reg_edx = 0;
#if __TBB_x86_32 && __PIC__
// On 32-bit systems with position-independent code GCC fails to work around the stuff in EBX
// register. We help it using backup and restore.
__asm__("mov %%ebx, %%esi\n\t"
"cpuid\n\t"
"xchg %%ebx, %%esi"
: "=a"(reg_eax), "=S"(reg_ebx), "=c"(reg_ecx), "=d"(reg_edx)
: "0"(leaf), "2"(sub_leaf) // read value from eax and ecx
);
#else
__asm__("cpuid"
: "=a"(reg_eax), "=b"(reg_ebx), "=c"(reg_ecx), "=d"(reg_edx)
: "0"(leaf), "2"(sub_leaf) // read value from eax and ecx
);
#endif
registers[0] = reg_eax;
registers[1] = reg_ebx;
registers[2] = reg_ecx;
registers[3] = reg_edx;
#endif
}
#endif
void detect_cpu_features(cpu_features_type& cpu_features) {
suppress_unused_warning(cpu_features);
#if __TBB_x86_32 || __TBB_x86_64
const int rtm_ebx_mask = 1 << 11;
const int waitpkg_ecx_mask = 1 << 5;
const int hybrid_edx_mask = 1 << 15;
int registers[4] = {0};
// Check RTM, WAITPKG, HYBRID
check_cpuid(7, 0, registers);
cpu_features.rtm_enabled = (registers[1] & rtm_ebx_mask) != 0;
cpu_features.waitpkg_enabled = (registers[2] & waitpkg_ecx_mask) != 0;
cpu_features.hybrid = (registers[3] & hybrid_edx_mask) != 0;
#elif __APPLE__
// Check HYBRID (hw.nperflevels > 1)
uint64_t nperflevels = 0;
size_t nperflevels_size = sizeof(nperflevels);
if (!sysctlbyname("hw.nperflevels", &nperflevels, &nperflevels_size, nullptr, 0)) {
cpu_features.hybrid = (nperflevels > 1);
}
#endif
}
} // namespace r1
} // namespace detail
} // namespace tbb