15 #include "absl/base/internal/sysinfo.h"
17 #include "absl/base/attributes.h"
25 #include <sys/types.h>
30 #include <sys/syscall.h>
33 #if defined(__APPLE__) || defined(__FreeBSD__)
34 #include <sys/sysctl.h>
37 #if defined(__myriad2__)
53 #include "absl/base/call_once.h"
54 #include "absl/base/config.h"
55 #include "absl/base/internal/raw_logging.h"
56 #include "absl/base/internal/spinlock.h"
57 #include "absl/base/internal/unscaledcycleclock.h"
58 #include "absl/base/thread_annotations.h"
62 namespace base_internal {
69 DWORD Win32CountSetBits(ULONG_PTR bitMask) {
70 for (DWORD bitSetCount = 0; ; ++bitSetCount) {
71 if (bitMask == 0)
return bitSetCount;
72 bitMask &= bitMask - 1;
80 #pragma comment(lib, "kernel32.lib")
81 using Info = SYSTEM_LOGICAL_PROCESSOR_INFORMATION;
83 DWORD info_size =
sizeof(Info);
84 Info* info(
static_cast<Info*
>(malloc(info_size)));
85 if (info ==
nullptr)
return 0;
87 bool success = GetLogicalProcessorInformation(info, &info_size);
88 if (!success && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
90 info =
static_cast<Info*
>(malloc(info_size));
91 if (info ==
nullptr)
return 0;
92 success = GetLogicalProcessorInformation(info, &info_size);
95 DWORD logicalProcessorCount = 0;
99 while (byteOffset +
sizeof(Info) <= info_size) {
100 switch (
ptr->Relationship) {
101 case RelationProcessorCore:
102 logicalProcessorCount += Win32CountSetBits(
ptr->ProcessorMask);
105 case RelationNumaNode:
107 case RelationProcessorPackage:
115 byteOffset +=
sizeof(Info);
120 return logicalProcessorCount;
128 #if defined(__myriad2__)
130 #elif defined(_WIN32)
131 const unsigned hardware_concurrency = Win32NumCPUs();
132 return hardware_concurrency ? hardware_concurrency : 1;
134 return sysconf(_SC_NPROCESSORS_ONLN);
139 return std::thread::hardware_concurrency();
146 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
147 !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
152 #pragma comment(lib, "advapi32.lib") // For Reg* functions.
156 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
157 "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0,
158 KEY_READ, &
key) == ERROR_SUCCESS) {
161 DWORD data_size =
sizeof(
data);
163 reinterpret_cast<LPBYTE
>(&
data), &data_size);
165 if (
result == ERROR_SUCCESS &&
type == REG_DWORD &&
166 data_size ==
sizeof(
data)) {
171 #endif // WINAPI_PARTITION_APP && !WINAPI_PARTITION_DESKTOP
174 #elif defined(CTL_HW) && defined(HW_CPU_FREQ)
178 size_t size =
sizeof(freq);
179 int mib[2] = {CTL_HW, HW_CPU_FREQ};
180 if (sysctl(mib, 2, &freq, &
size,
nullptr, 0) == 0) {
181 return static_cast<double>(freq);
201 const long temp_value = strtol(
line, &
err, 10);
202 if (
line[0] !=
'\0' && (*
err ==
'\n' || *
err ==
'\0')) {
212 #if defined(ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY)
217 static int64_t ReadMonotonicClockNanos() {
219 #ifdef CLOCK_MONOTONIC_RAW
220 int rc = clock_gettime(CLOCK_MONOTONIC_RAW, &t);
222 int rc = clock_gettime(CLOCK_MONOTONIC, &t);
225 perror(
"clock_gettime() failed");
228 return int64_t{t.tv_sec} * 1000000000 +
t.tv_nsec;
231 class UnscaledCycleClockWrapperForInitializeFrequency {
246 static TimeTscPair GetTimeTscPair() {
249 for (
int i = 0;
i < 10; ++
i) {
254 if (latency < best_latency) {
255 best_latency = latency;
265 static double MeasureTscFrequencyWithSleep(
int sleep_nanoseconds) {
266 auto t0 = GetTimeTscPair();
269 ts.tv_nsec = sleep_nanoseconds;
270 while (
nanosleep(&ts, &ts) != 0 && errno == EINTR) {}
271 auto t1 = GetTimeTscPair();
272 double elapsed_ticks =
t1.tsc -
t0.tsc;
273 double elapsed_time = (
t1.time -
t0.time) * 1e-9;
274 return elapsed_ticks / elapsed_time;
280 static double MeasureTscFrequency() {
281 double last_measurement = -1.0;
282 int sleep_nanoseconds = 1000000;
283 for (
int i = 0;
i < 8; ++
i) {
284 double measurement = MeasureTscFrequencyWithSleep(sleep_nanoseconds);
285 if (measurement * 0.99 < last_measurement &&
286 last_measurement < measurement * 1.01) {
291 last_measurement = measurement;
292 sleep_nanoseconds *= 2;
294 return last_measurement;
297 #endif // ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
314 #if defined(ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY)
325 return MeasureTscFrequency();
331 if (
ReadLongFromFile(
"/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq",
337 #endif // !ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
369 return pid_t{GetCurrentThreadId()};
372 #elif defined(__linux__)
375 #define SYS_gettid __NR_gettid
382 #elif defined(__akaros__)
401 if (in_vcore_context())
403 return reinterpret_cast<struct pthread_tcb *
>(current_uthread)->
id;
406 #elif defined(__myriad2__)
410 rtems_task_ident(RTEMS_SELF, 0, &
tid);
435 assert(0 <= word &&
static_cast<size_t>(word) < tid_array->size());
436 (*tid_array)[word] &= mask;
442 perror(
"pthread_key_create failed");
448 tid_array =
new std::vector<uint32_t>(1);
468 while (word < tid_array->
size() && ~(*tid_array)[word] == 0) {
471 if (word == tid_array->size()) {
472 tid_array->push_back(0);
476 while (bit <
kBitsPerWord && (((*tid_array)[word] >> bit) & 1) != 0) {
480 (*tid_array)[word] |= 1
u << bit;
483 if (pthread_setspecific(
tid_key,
reinterpret_cast<void *
>(
tid)) != 0) {
484 perror(
"pthread_setspecific failed");
488 return static_cast<pid_t
>(
tid);
497 #ifdef ABSL_HAVE_THREAD_LOCAL
502 #endif // ABSL_HAVE_THREAD_LOCAL