abseil-cpp/absl/base/internal/sysinfo.cc
Go to the documentation of this file.
1 // Copyright 2017 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "absl/base/internal/sysinfo.h"
16 
17 #include "absl/base/attributes.h"
18 
19 #ifdef _WIN32
20 #include <windows.h>
21 #else
22 #include <fcntl.h>
23 #include <pthread.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27 #endif
28 
29 #ifdef __linux__
30 #include <sys/syscall.h>
31 #endif
32 
33 #if defined(__APPLE__) || defined(__FreeBSD__)
34 #include <sys/sysctl.h>
35 #endif
36 
37 #if defined(__myriad2__)
38 #include <rtems.h>
39 #endif
40 
41 #include <string.h>
42 
43 #include <cassert>
44 #include <cstdint>
45 #include <cstdio>
46 #include <cstdlib>
47 #include <ctime>
48 #include <limits>
49 #include <thread> // NOLINT(build/c++11)
50 #include <utility>
51 #include <vector>
52 
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"
59 
60 namespace absl {
62 namespace base_internal {
63 
64 namespace {
65 
66 #if defined(_WIN32)
67 
68 // Returns number of bits set in `bitMask`
69 DWORD Win32CountSetBits(ULONG_PTR bitMask) {
70  for (DWORD bitSetCount = 0; ; ++bitSetCount) {
71  if (bitMask == 0) return bitSetCount;
72  bitMask &= bitMask - 1;
73  }
74 }
75 
76 // Returns the number of logical CPUs using GetLogicalProcessorInformation(), or
77 // 0 if the number of processors is not available or can not be computed.
78 // https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getlogicalprocessorinformation
79 int Win32NumCPUs() {
80 #pragma comment(lib, "kernel32.lib")
81  using Info = SYSTEM_LOGICAL_PROCESSOR_INFORMATION;
82 
83  DWORD info_size = sizeof(Info);
84  Info* info(static_cast<Info*>(malloc(info_size)));
85  if (info == nullptr) return 0;
86 
87  bool success = GetLogicalProcessorInformation(info, &info_size);
88  if (!success && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
89  free(info);
90  info = static_cast<Info*>(malloc(info_size));
91  if (info == nullptr) return 0;
92  success = GetLogicalProcessorInformation(info, &info_size);
93  }
94 
95  DWORD logicalProcessorCount = 0;
96  if (success) {
97  Info* ptr = info;
98  DWORD byteOffset = 0;
99  while (byteOffset + sizeof(Info) <= info_size) {
100  switch (ptr->Relationship) {
101  case RelationProcessorCore:
102  logicalProcessorCount += Win32CountSetBits(ptr->ProcessorMask);
103  break;
104 
105  case RelationNumaNode:
106  case RelationCache:
107  case RelationProcessorPackage:
108  // Ignore other entries
109  break;
110 
111  default:
112  // Ignore unknown entries
113  break;
114  }
115  byteOffset += sizeof(Info);
116  ptr++;
117  }
118  }
119  free(info);
120  return logicalProcessorCount;
121 }
122 
123 #endif
124 
125 } // namespace
126 
127 static int GetNumCPUs() {
128 #if defined(__myriad2__)
129  return 1;
130 #elif defined(_WIN32)
131  const unsigned hardware_concurrency = Win32NumCPUs();
132  return hardware_concurrency ? hardware_concurrency : 1;
133 #elif defined(_AIX)
134  return sysconf(_SC_NPROCESSORS_ONLN);
135 #else
136  // Other possibilities:
137  // - Read /sys/devices/system/cpu/online and use cpumask_parse()
138  // - sysconf(_SC_NPROCESSORS_ONLN)
139  return std::thread::hardware_concurrency();
140 #endif
141 }
142 
143 #if defined(_WIN32)
144 
145 static double GetNominalCPUFrequency() {
146 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
147  !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
148  // UWP apps don't have access to the registry and currently don't provide an
149  // API informing about CPU nominal frequency.
150  return 1.0;
151 #else
152 #pragma comment(lib, "advapi32.lib") // For Reg* functions.
153  HKEY key;
154  // Use the Reg* functions rather than the SH functions because shlwapi.dll
155  // pulls in gdi32.dll which makes process destruction much more costly.
156  if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
157  "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0,
158  KEY_READ, &key) == ERROR_SUCCESS) {
159  DWORD type = 0;
160  DWORD data = 0;
161  DWORD data_size = sizeof(data);
162  auto result = RegQueryValueExA(key, "~MHz", 0, &type,
163  reinterpret_cast<LPBYTE>(&data), &data_size);
164  RegCloseKey(key);
165  if (result == ERROR_SUCCESS && type == REG_DWORD &&
166  data_size == sizeof(data)) {
167  return data * 1e6; // Value is MHz.
168  }
169  }
170  return 1.0;
171 #endif // WINAPI_PARTITION_APP && !WINAPI_PARTITION_DESKTOP
172 }
173 
174 #elif defined(CTL_HW) && defined(HW_CPU_FREQ)
175 
176 static double GetNominalCPUFrequency() {
177  unsigned 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);
182  }
183  return 1.0;
184 }
185 
186 #else
187 
188 // Helper function for reading a long from a file. Returns true if successful
189 // and the memory location pointed to by value is set to the value read.
190 static bool ReadLongFromFile(const char *file, long *value) {
191  bool ret = false;
192  int fd = open(file, O_RDONLY);
193  if (fd != -1) {
194  char line[1024];
195  char *err;
196  memset(line, '\0', sizeof(line));
197  int len = read(fd, line, sizeof(line) - 1);
198  if (len <= 0) {
199  ret = false;
200  } else {
201  const long temp_value = strtol(line, &err, 10);
202  if (line[0] != '\0' && (*err == '\n' || *err == '\0')) {
203  *value = temp_value;
204  ret = true;
205  }
206  }
207  close(fd);
208  }
209  return ret;
210 }
211 
212 #if defined(ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY)
213 
214 // Reads a monotonic time source and returns a value in
215 // nanoseconds. The returned value uses an arbitrary epoch, not the
216 // Unix epoch.
217 static int64_t ReadMonotonicClockNanos() {
218  struct timespec t;
219 #ifdef CLOCK_MONOTONIC_RAW
220  int rc = clock_gettime(CLOCK_MONOTONIC_RAW, &t);
221 #else
222  int rc = clock_gettime(CLOCK_MONOTONIC, &t);
223 #endif
224  if (rc != 0) {
225  perror("clock_gettime() failed");
226  abort();
227  }
228  return int64_t{t.tv_sec} * 1000000000 + t.tv_nsec;
229 }
230 
231 class UnscaledCycleClockWrapperForInitializeFrequency {
232  public:
233  static int64_t Now() { return base_internal::UnscaledCycleClock::Now(); }
234 };
235 
236 struct TimeTscPair {
237  int64_t time; // From ReadMonotonicClockNanos().
238  int64_t tsc; // From UnscaledCycleClock::Now().
239 };
240 
241 // Returns a pair of values (monotonic kernel time, TSC ticks) that
242 // approximately correspond to each other. This is accomplished by
243 // doing several reads and picking the reading with the lowest
244 // latency. This approach is used to minimize the probability that
245 // our thread was preempted between clock reads.
246 static TimeTscPair GetTimeTscPair() {
248  TimeTscPair best;
249  for (int i = 0; i < 10; ++i) {
250  int64_t t0 = ReadMonotonicClockNanos();
252  int64_t t1 = ReadMonotonicClockNanos();
253  int64_t latency = t1 - t0;
254  if (latency < best_latency) {
255  best_latency = latency;
256  best.time = t0;
257  best.tsc = tsc;
258  }
259  }
260  return best;
261 }
262 
263 // Measures and returns the TSC frequency by taking a pair of
264 // measurements approximately `sleep_nanoseconds` apart.
265 static double MeasureTscFrequencyWithSleep(int sleep_nanoseconds) {
266  auto t0 = GetTimeTscPair();
267  struct timespec ts;
268  ts.tv_sec = 0;
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;
275 }
276 
277 // Measures and returns the TSC frequency by calling
278 // MeasureTscFrequencyWithSleep(), doubling the sleep interval until the
279 // frequency measurement stabilizes.
280 static double MeasureTscFrequency() {
281  double last_measurement = -1.0;
282  int sleep_nanoseconds = 1000000; // 1 millisecond.
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) {
287  // Use the current measurement if it is within 1% of the
288  // previous measurement.
289  return measurement;
290  }
291  last_measurement = measurement;
292  sleep_nanoseconds *= 2;
293  }
294  return last_measurement;
295 }
296 
297 #endif // ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
298 
299 static double GetNominalCPUFrequency() {
300  long freq = 0;
301 
302  // Google's production kernel has a patch to export the TSC
303  // frequency through sysfs. If the kernel is exporting the TSC
304  // frequency use that. There are issues where cpuinfo_max_freq
305  // cannot be relied on because the BIOS may be exporting an invalid
306  // p-state (on x86) or p-states may be used to put the processor in
307  // a new mode (turbo mode). Essentially, those frequencies cannot
308  // always be relied upon. The same reasons apply to /proc/cpuinfo as
309  // well.
310  if (ReadLongFromFile("/sys/devices/system/cpu/cpu0/tsc_freq_khz", &freq)) {
311  return freq * 1e3; // Value is kHz.
312  }
313 
314 #if defined(ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY)
315  // On these platforms, the TSC frequency is the nominal CPU
316  // frequency. But without having the kernel export it directly
317  // though /sys/devices/system/cpu/cpu0/tsc_freq_khz, there is no
318  // other way to reliably get the TSC frequency, so we have to
319  // measure it ourselves. Some CPUs abuse cpuinfo_max_freq by
320  // exporting "fake" frequencies for implementing new features. For
321  // example, Intel's turbo mode is enabled by exposing a p-state
322  // value with a higher frequency than that of the real TSC
323  // rate. Because of this, we prefer to measure the TSC rate
324  // ourselves on i386 and x86-64.
325  return MeasureTscFrequency();
326 #else
327 
328  // If CPU scaling is in effect, we want to use the *maximum*
329  // frequency, not whatever CPU speed some random processor happens
330  // to be using now.
331  if (ReadLongFromFile("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq",
332  &freq)) {
333  return freq * 1e3; // Value is kHz.
334  }
335 
336  return 1.0;
337 #endif // !ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
338 }
339 
340 #endif
341 
343 ABSL_CONST_INIT static int num_cpus = 0;
344 
345 // NumCPUs() may be called before main() and before malloc is properly
346 // initialized, therefore this must not allocate memory.
347 int NumCPUs() {
349  &init_num_cpus_once, []() { num_cpus = GetNumCPUs(); });
350  return num_cpus;
351 }
352 
353 // A default frequency of 0.0 might be dangerous if it is used in division.
356 
357 // NominalCPUFrequency() may be called before main() and before malloc is
358 // properly initialized, therefore this must not allocate memory.
363  return nominal_cpu_frequency;
364 }
365 
366 #if defined(_WIN32)
367 
368 pid_t GetTID() {
369  return pid_t{GetCurrentThreadId()};
370 }
371 
372 #elif defined(__linux__)
373 
374 #ifndef SYS_gettid
375 #define SYS_gettid __NR_gettid
376 #endif
377 
378 pid_t GetTID() {
379  return syscall(SYS_gettid);
380 }
381 
382 #elif defined(__akaros__)
383 
384 pid_t GetTID() {
385  // Akaros has a concept of "vcore context", which is the state the program
386  // is forced into when we need to make a user-level scheduling decision, or
387  // run a signal handler. This is analogous to the interrupt context that a
388  // CPU might enter if it encounters some kind of exception.
389  //
390  // There is no current thread context in vcore context, but we need to give
391  // a reasonable answer if asked for a thread ID (e.g., in a signal handler).
392  // Thread 0 always exists, so if we are in vcore context, we return that.
393  //
394  // Otherwise, we know (since we are using pthreads) that the uthread struct
395  // current_uthread is pointing to is the first element of a
396  // struct pthread_tcb, so we extract and return the thread ID from that.
397  //
398  // TODO(dcross): Akaros anticipates moving the thread ID to the uthread
399  // structure at some point. We should modify this code to remove the cast
400  // when that happens.
401  if (in_vcore_context())
402  return 0;
403  return reinterpret_cast<struct pthread_tcb *>(current_uthread)->id;
404 }
405 
406 #elif defined(__myriad2__)
407 
408 pid_t GetTID() {
409  uint32_t tid;
410  rtems_task_ident(RTEMS_SELF, 0, &tid);
411  return tid;
412 }
413 
414 #else
415 
416 // Fallback implementation of GetTID using pthread_getspecific.
418 ABSL_CONST_INIT static pthread_key_t tid_key;
421 
422 // We set a bit per thread in this array to indicate that an ID is in
423 // use. ID 0 is unused because it is the default value returned by
424 // pthread_getspecific().
425 ABSL_CONST_INIT static std::vector<uint32_t> *tid_array
426  ABSL_GUARDED_BY(tid_lock) = nullptr;
427 static constexpr int kBitsPerWord = 32; // tid_array is uint32_t.
428 
429 // Returns the TID to tid_array.
430 static void FreeTID(void *v) {
431  intptr_t tid = reinterpret_cast<intptr_t>(v);
432  int word = tid / kBitsPerWord;
433  uint32_t mask = ~(1u << (tid % kBitsPerWord));
435  assert(0 <= word && static_cast<size_t>(word) < tid_array->size());
436  (*tid_array)[word] &= mask;
437 }
438 
439 static void InitGetTID() {
440  if (pthread_key_create(&tid_key, FreeTID) != 0) {
441  // The logging system calls GetTID() so it can't be used here.
442  perror("pthread_key_create failed");
443  abort();
444  }
445 
446  // Initialize tid_array.
448  tid_array = new std::vector<uint32_t>(1);
449  (*tid_array)[0] = 1; // ID 0 is never-allocated.
450 }
451 
452 // Return a per-thread small integer ID from pthread's thread-specific data.
453 pid_t GetTID() {
455 
456  intptr_t tid = reinterpret_cast<intptr_t>(pthread_getspecific(tid_key));
457  if (tid != 0) {
458  return tid;
459  }
460 
461  int bit; // tid_array[word] = 1u << bit;
462  size_t word;
463  {
464  // Search for the first unused ID.
466  // First search for a word in the array that is not all ones.
467  word = 0;
468  while (word < tid_array->size() && ~(*tid_array)[word] == 0) {
469  ++word;
470  }
471  if (word == tid_array->size()) {
472  tid_array->push_back(0); // No space left, add kBitsPerWord more IDs.
473  }
474  // Search for a zero bit in the word.
475  bit = 0;
476  while (bit < kBitsPerWord && (((*tid_array)[word] >> bit) & 1) != 0) {
477  ++bit;
478  }
479  tid = (word * kBitsPerWord) + bit;
480  (*tid_array)[word] |= 1u << bit; // Mark the TID as allocated.
481  }
482 
483  if (pthread_setspecific(tid_key, reinterpret_cast<void *>(tid)) != 0) {
484  perror("pthread_setspecific failed");
485  abort();
486  }
487 
488  return static_cast<pid_t>(tid);
489 }
490 
491 #endif
492 
493 // GetCachedTID() caches the thread ID in thread-local storage (which is a
494 // userspace construct) to avoid unnecessary system calls. Without this caching,
495 // it can take roughly 98ns, while it takes roughly 1ns with this caching.
496 pid_t GetCachedTID() {
497 #ifdef ABSL_HAVE_THREAD_LOCAL
498  static thread_local pid_t thread_id = GetTID();
499  return thread_id;
500 #else
501  return GetTID();
502 #endif // ABSL_HAVE_THREAD_LOCAL
503 }
504 
505 } // namespace base_internal
507 } // namespace absl
ptr
char * ptr
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:45
_gevent_test_main.result
result
Definition: _gevent_test_main.py:96
absl::base_internal::kBitsPerWord
static constexpr int kBitsPerWord
Definition: abseil-cpp/absl/base/internal/sysinfo.cc:427
absl::base_internal::SpinLockHolder
Definition: third_party/abseil-cpp/absl/base/internal/spinlock.h:196
ABSL_CONST_INIT
#define ABSL_CONST_INIT
Definition: abseil-cpp/absl/base/attributes.h:716
memset
return memset(p, 0, total)
absl::base_internal::nominal_cpu_frequency
static ABSL_CONST_INIT double nominal_cpu_frequency
Definition: abseil-cpp/absl/base/internal/sysinfo.cc:355
string.h
error_ref_leak.err
err
Definition: error_ref_leak.py:35
file
Definition: bloaty/third_party/zlib/examples/gzappend.c:170
u
OPENSSL_EXPORT pem_password_cb void * u
Definition: pem.h:351
absl::base_internal::SpinLock
Definition: third_party/abseil-cpp/absl/base/internal/spinlock.h:52
absl::base_internal::NumCPUs
int NumCPUs()
Definition: abseil-cpp/absl/base/internal/sysinfo.cc:347
nanosleep
int nanosleep(const struct timespec *req, struct timespec *rem)
Definition: os390-syscalls.c:385
absl::kConstInit
@ kConstInit
Definition: abseil-cpp/absl/base/const_init.h:70
ABSL_NAMESPACE_END
#define ABSL_NAMESPACE_END
Definition: third_party/abseil-cpp/absl/base/config.h:171
gen_build_yaml.struct
def struct(**kwargs)
Definition: test/core/end2end/gen_build_yaml.py:30
absl::base_internal::NominalCPUFrequency
double NominalCPUFrequency()
Definition: abseil-cpp/absl/base/internal/sysinfo.cc:359
absl::base_internal::GetCachedTID
pid_t GetCachedTID()
Definition: abseil-cpp/absl/base/internal/sysinfo.cc:496
tid
int tid
Definition: fake_binder_test.cc:236
absl::base_internal::tid_once
static ABSL_CONST_INIT once_flag tid_once
Definition: abseil-cpp/absl/base/internal/sysinfo.cc:417
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
absl::call_once
void call_once(absl::once_flag &flag, Callable &&fn, Args &&... args)
Definition: abseil-cpp/absl/base/call_once.h:206
ABSL_NAMESPACE_BEGIN
#define ABSL_NAMESPACE_BEGIN
Definition: third_party/abseil-cpp/absl/base/config.h:170
absl::base_internal::InitGetTID
static void InitGetTID()
Definition: abseil-cpp/absl/base/internal/sysinfo.cc:439
int64_t
signed __int64 int64_t
Definition: stdint-msvc2008.h:89
absl::base_internal::num_cpus
static ABSL_CONST_INIT int num_cpus
Definition: abseil-cpp/absl/base/internal/sysinfo.cc:343
max
int max
Definition: bloaty/third_party/zlib/examples/enough.c:170
t0
static int64_t t0
Definition: bloaty/third_party/re2/util/benchmark.cc:44
absl::base_internal::GetTID
pid_t GetTID()
Definition: abseil-cpp/absl/base/internal/sysinfo.cc:453
absl::base_internal::GetNominalCPUFrequency
static double GetNominalCPUFrequency()
Definition: abseil-cpp/absl/base/internal/sysinfo.cc:299
setup.v
v
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:42
syscall
const char * syscall
Definition: third_party/libuv/src/win/internal.h:270
close
#define close
Definition: test-fs.c:48
absl::base_internal::tid_lock
static ABSL_CONST_INIT absl::base_internal::SpinLock tid_lock(absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY)
intptr_t
_W64 signed int intptr_t
Definition: stdint-msvc2008.h:118
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
absl::base_internal::ABSL_GUARDED_BY
static ABSL_CONST_INIT std::vector< uint32_t > *tid_array ABSL_GUARDED_BY(tid_lock)
absl::base_internal::tid_key
static ABSL_CONST_INIT pthread_key_t tid_key
Definition: abseil-cpp/absl/base/internal/sysinfo.cc:418
absl::base_internal::init_nominal_cpu_frequency_once
static ABSL_CONST_INIT once_flag init_nominal_cpu_frequency_once
Definition: abseil-cpp/absl/base/internal/sysinfo.cc:354
absl::base_internal::LowLevelCallOnce
void LowLevelCallOnce(absl::once_flag *flag, Callable &&fn, Args &&... args)
Definition: abseil-cpp/absl/base/call_once.h:193
value
const char * value
Definition: hpack_parser_table.cc:165
absl::Now
ABSL_NAMESPACE_BEGIN Time Now()
Definition: abseil-cpp/absl/time/clock.cc:39
absl::base_internal::SCHEDULE_KERNEL_ONLY
@ SCHEDULE_KERNEL_ONLY
Definition: abseil-cpp/absl/base/internal/scheduling_mode.h:50
read
int read(izstream &zs, T *x, Items items)
Definition: bloaty/third_party/zlib/contrib/iostream2/zstream.h:115
key
const char * key
Definition: hpack_parser_table.cc:164
absl::base_internal::init_num_cpus_once
static ABSL_CONST_INIT once_flag init_num_cpus_once
Definition: abseil-cpp/absl/base/internal/sysinfo.cc:342
thread_id
static uv_thread_t thread_id
Definition: benchmark-million-async.c:32
absl::str_format_internal::LengthMod::t
@ t
ret
UniquePtr< SSL_SESSION > ret
Definition: ssl_x509.cc:1029
regen-readme.line
line
Definition: regen-readme.py:30
open
#define open
Definition: test-fs.c:46
absl::base_internal::ReadLongFromFile
static bool ReadLongFromFile(const char *file, long *value)
Definition: abseil-cpp/absl/base/internal/sysinfo.cc:190
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
asyncio_get_stats.type
type
Definition: asyncio_get_stats.py:37
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
absl::once_flag
Definition: abseil-cpp/absl/base/call_once.h:85
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
t1
Table t1
Definition: abseil-cpp/absl/container/internal/raw_hash_set_allocator_test.cc:185
absl::base_internal::GetNumCPUs
static int GetNumCPUs()
Definition: abseil-cpp/absl/base/internal/sysinfo.cc:127
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
absl::base_internal::FreeTID
static void FreeTID(void *v)
Definition: abseil-cpp/absl/base/internal/sysinfo.cc:430


grpc
Author(s):
autogenerated on Fri May 16 2025 03:00:24