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;
129 #if defined(__myriad2__)
131 #elif defined(_WIN32)
132 const unsigned hardware_concurrency = Win32NumCPUs();
133 return hardware_concurrency ? hardware_concurrency : 1;
138 return std::thread::hardware_concurrency();
145 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
146 !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
151 #pragma comment(lib, "advapi32.lib") // For Reg* functions.
155 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
156 "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0,
157 KEY_READ, &
key) == ERROR_SUCCESS) {
160 DWORD data_size =
sizeof(
data);
162 reinterpret_cast<LPBYTE
>(&
data), &data_size);
164 if (
result == ERROR_SUCCESS &&
type == REG_DWORD &&
165 data_size ==
sizeof(
data)) {
170 #endif // WINAPI_PARTITION_APP && !WINAPI_PARTITION_DESKTOP
173 #elif defined(CTL_HW) && defined(HW_CPU_FREQ)
177 size_t size =
sizeof(freq);
178 int mib[2] = {CTL_HW, HW_CPU_FREQ};
179 if (sysctl(mib, 2, &freq, &
size,
nullptr, 0) == 0) {
180 return static_cast<double>(freq);
200 const long temp_value = strtol(
line, &
err, 10);
201 if (
line[0] !=
'\0' && (*
err ==
'\n' || *
err ==
'\0')) {
211 #if defined(ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY)
216 static int64_t ReadMonotonicClockNanos() {
218 #ifdef CLOCK_MONOTONIC_RAW
219 int rc = clock_gettime(CLOCK_MONOTONIC_RAW, &t);
221 int rc = clock_gettime(CLOCK_MONOTONIC, &t);
224 perror(
"clock_gettime() failed");
227 return int64_t{t.tv_sec} * 1000000000 +
t.tv_nsec;
230 class UnscaledCycleClockWrapperForInitializeFrequency {
245 static TimeTscPair GetTimeTscPair() {
248 for (
int i = 0;
i < 10; ++
i) {
253 if (latency < best_latency) {
254 best_latency = latency;
264 static double MeasureTscFrequencyWithSleep(
int sleep_nanoseconds) {
265 auto t0 = GetTimeTscPair();
268 ts.tv_nsec = sleep_nanoseconds;
269 while (
nanosleep(&ts, &ts) != 0 && errno == EINTR) {}
270 auto t1 = GetTimeTscPair();
271 double elapsed_ticks =
t1.tsc -
t0.tsc;
272 double elapsed_time = (
t1.time -
t0.time) * 1e-9;
273 return elapsed_ticks / elapsed_time;
279 static double MeasureTscFrequency() {
280 double last_measurement = -1.0;
281 int sleep_nanoseconds = 1000000;
282 for (
int i = 0;
i < 8; ++
i) {
283 double measurement = MeasureTscFrequencyWithSleep(sleep_nanoseconds);
284 if (measurement * 0.99 < last_measurement &&
285 last_measurement < measurement * 1.01) {
290 last_measurement = measurement;
291 sleep_nanoseconds *= 2;
293 return last_measurement;
296 #endif // ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
313 #if defined(ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY)
324 return MeasureTscFrequency();
330 if (
ReadLongFromFile(
"/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq",
336 #endif // !ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
368 return pid_t{GetCurrentThreadId()};
371 #elif defined(__linux__)
374 #define SYS_gettid __NR_gettid
381 #elif defined(__akaros__)
400 if (in_vcore_context())
402 return reinterpret_cast<struct pthread_tcb *
>(current_uthread)->
id;
405 #elif defined(__myriad2__)
409 rtems_task_ident(RTEMS_SELF, 0, &
tid);
434 assert(0 <= word &&
static_cast<size_t>(word) < tid_array->size());
435 (*tid_array)[word] &= mask;
441 perror(
"pthread_key_create failed");
447 tid_array =
new std::vector<uint32_t>(1);
467 while (word < tid_array->
size() && ~(*tid_array)[word] == 0) {
470 if (word == tid_array->size()) {
471 tid_array->push_back(0);
475 while (bit <
kBitsPerWord && (((*tid_array)[word] >> bit) & 1) != 0) {
479 (*tid_array)[word] |= 1
u << bit;
482 if (pthread_setspecific(
tid_key,
reinterpret_cast<void *
>(
tid)) != 0) {
483 perror(
"pthread_setspecific failed");
487 return static_cast<pid_t
>(
tid);
496 #ifdef ABSL_HAVE_THREAD_LOCAL
501 #endif // ABSL_HAVE_THREAD_LOCAL