Coverage Report

Created: 2024-05-04 12:45

/proc/self/cwd/external/cpuinfo/src/api.c
Line
Count
Source (jump to first uncovered line)
1
#include <stdbool.h>
2
#include <stddef.h>
3
4
#include <cpuinfo.h>
5
#include <cpuinfo/internal-api.h>
6
#include <cpuinfo/log.h>
7
8
#ifdef __linux__
9
  #include <linux/api.h>
10
11
  #include <unistd.h>
12
  #include <sys/syscall.h>
13
  #if !defined(__NR_getcpu)
14
    #include <asm-generic/unistd.h>
15
  #endif
16
#endif
17
18
bool cpuinfo_is_initialized = false;
19
20
struct cpuinfo_processor* cpuinfo_processors = NULL;
21
struct cpuinfo_core* cpuinfo_cores = NULL;
22
struct cpuinfo_cluster* cpuinfo_clusters = NULL;
23
struct cpuinfo_package* cpuinfo_packages = NULL;
24
struct cpuinfo_cache* cpuinfo_cache[cpuinfo_cache_level_max] = { NULL };
25
26
uint32_t cpuinfo_processors_count = 0;
27
uint32_t cpuinfo_cores_count = 0;
28
uint32_t cpuinfo_clusters_count = 0;
29
uint32_t cpuinfo_packages_count = 0;
30
uint32_t cpuinfo_cache_count[cpuinfo_cache_level_max] = { 0 };
31
uint32_t cpuinfo_max_cache_size = 0;
32
33
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 \
34
    || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
35
  struct cpuinfo_uarch_info* cpuinfo_uarchs = NULL;
36
  uint32_t cpuinfo_uarchs_count = 0;
37
#else
38
  struct cpuinfo_uarch_info cpuinfo_global_uarch = { cpuinfo_uarch_unknown };
39
#endif
40
41
#ifdef __linux__
42
  uint32_t cpuinfo_linux_cpu_max = 0;
43
  const struct cpuinfo_processor** cpuinfo_linux_cpu_to_processor_map = NULL;
44
  const struct cpuinfo_core** cpuinfo_linux_cpu_to_core_map = NULL;
45
  #if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 \
46
            || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
47
    const uint32_t* cpuinfo_linux_cpu_to_uarch_index_map = NULL;
48
  #endif
49
#endif
50
51
52
0
const struct cpuinfo_processor* cpuinfo_get_processors(void) {
53
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
54
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "processors");
55
0
  }
56
0
  return cpuinfo_processors;
57
0
}
58
59
0
const struct cpuinfo_core* cpuinfo_get_cores(void) {
60
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
61
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "core");
62
0
  }
63
0
  return cpuinfo_cores;
64
0
}
65
66
0
const struct cpuinfo_cluster* cpuinfo_get_clusters(void) {
67
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
68
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "clusters");
69
0
  }
70
0
  return cpuinfo_clusters;
71
0
}
72
73
0
const struct cpuinfo_package* cpuinfo_get_packages(void) {
74
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
75
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "packages");
76
0
  }
77
0
  return cpuinfo_packages;
78
0
}
79
80
0
const struct cpuinfo_uarch_info* cpuinfo_get_uarchs() {
81
0
  if (!cpuinfo_is_initialized) {
82
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "uarchs");
83
0
  }
84
  #if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 \
85
    || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
86
    return cpuinfo_uarchs;
87
  #else
88
0
    return &cpuinfo_global_uarch;
89
0
  #endif
90
0
}
91
92
0
const struct cpuinfo_processor* cpuinfo_get_processor(uint32_t index) {
93
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
94
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "processor");
95
0
  }
96
0
  if CPUINFO_UNLIKELY(index >= cpuinfo_processors_count) {
97
0
    return NULL;
98
0
  }
99
0
  return &cpuinfo_processors[index];
100
0
}
101
102
0
const struct cpuinfo_core* cpuinfo_get_core(uint32_t index) {
103
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
104
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "core");
105
0
  }
106
0
  if CPUINFO_UNLIKELY(index >= cpuinfo_cores_count) {
107
0
    return NULL;
108
0
  }
109
0
  return &cpuinfo_cores[index];
110
0
}
111
112
0
const struct cpuinfo_cluster* cpuinfo_get_cluster(uint32_t index) {
113
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
114
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "cluster");
115
0
  }
116
0
  if CPUINFO_UNLIKELY(index >= cpuinfo_clusters_count) {
117
0
    return NULL;
118
0
  }
119
0
  return &cpuinfo_clusters[index];
120
0
}
121
122
0
const struct cpuinfo_package* cpuinfo_get_package(uint32_t index) {
123
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
124
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "package");
125
0
  }
126
0
  if CPUINFO_UNLIKELY(index >= cpuinfo_packages_count) {
127
0
    return NULL;
128
0
  }
129
0
  return &cpuinfo_packages[index];
130
0
}
131
132
0
const struct cpuinfo_uarch_info* cpuinfo_get_uarch(uint32_t index) {
133
0
  if (!cpuinfo_is_initialized) {
134
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "uarch");
135
0
  }
136
  #if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 \
137
    || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
138
    if CPUINFO_UNLIKELY(index >= cpuinfo_uarchs_count) {
139
      return NULL;
140
    }
141
    return &cpuinfo_uarchs[index];
142
  #else
143
0
    if CPUINFO_UNLIKELY(index != 0) {
144
0
      return NULL;
145
0
    }
146
0
    return &cpuinfo_global_uarch;
147
0
  #endif
148
0
}
149
150
0
uint32_t cpuinfo_get_processors_count(void) {
151
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
152
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "processors_count");
153
0
  }
154
0
  return cpuinfo_processors_count;
155
0
}
156
157
0
uint32_t cpuinfo_get_cores_count(void) {
158
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
159
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "cores_count");
160
0
  }
161
0
  return cpuinfo_cores_count;
162
0
}
163
164
0
uint32_t cpuinfo_get_clusters_count(void) {
165
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
166
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "clusters_count");
167
0
  }
168
0
  return cpuinfo_clusters_count;
169
0
}
170
171
0
uint32_t cpuinfo_get_packages_count(void) {
172
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
173
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "packages_count");
174
0
  }
175
0
  return cpuinfo_packages_count;
176
0
}
177
178
0
uint32_t cpuinfo_get_uarchs_count(void) {
179
0
  if (!cpuinfo_is_initialized) {
180
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "uarchs_count");
181
0
  }
182
  #if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 \
183
    || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
184
    return cpuinfo_uarchs_count;
185
  #else
186
0
    return 1;
187
0
  #endif
188
0
}
189
190
0
const struct cpuinfo_cache* CPUINFO_ABI cpuinfo_get_l1i_caches(void) {
191
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
192
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l1i_caches");
193
0
  }
194
0
  return cpuinfo_cache[cpuinfo_cache_level_1i];
195
0
}
196
197
0
const struct cpuinfo_cache* CPUINFO_ABI cpuinfo_get_l1d_caches(void) {
198
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
199
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l1d_caches");
200
0
  }
201
0
  return cpuinfo_cache[cpuinfo_cache_level_1d];
202
0
}
203
204
0
const struct cpuinfo_cache* CPUINFO_ABI cpuinfo_get_l2_caches(void) {
205
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
206
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l2_caches");
207
0
  }
208
0
  return cpuinfo_cache[cpuinfo_cache_level_2];
209
0
}
210
211
0
const struct cpuinfo_cache* CPUINFO_ABI cpuinfo_get_l3_caches(void) {
212
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
213
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l3_caches");
214
0
  }
215
0
  return cpuinfo_cache[cpuinfo_cache_level_3];
216
0
}
217
218
0
const struct cpuinfo_cache* CPUINFO_ABI cpuinfo_get_l4_caches(void) {
219
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
220
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l4_caches");
221
0
  }
222
0
  return cpuinfo_cache[cpuinfo_cache_level_4];
223
0
}
224
225
0
const struct cpuinfo_cache* CPUINFO_ABI cpuinfo_get_l1i_cache(uint32_t index) {
226
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
227
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l1i_cache");
228
0
  }
229
0
  if CPUINFO_UNLIKELY(index >= cpuinfo_cache_count[cpuinfo_cache_level_1i]) {
230
0
    return NULL;
231
0
  }
232
0
  return &cpuinfo_cache[cpuinfo_cache_level_1i][index];
233
0
}
234
235
0
const struct cpuinfo_cache* CPUINFO_ABI cpuinfo_get_l1d_cache(uint32_t index) {
236
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
237
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l1d_cache");
238
0
  }
239
0
  if CPUINFO_UNLIKELY(index >= cpuinfo_cache_count[cpuinfo_cache_level_1d]) {
240
0
    return NULL;
241
0
  }
242
0
  return &cpuinfo_cache[cpuinfo_cache_level_1d][index];
243
0
}
244
245
0
const struct cpuinfo_cache* CPUINFO_ABI cpuinfo_get_l2_cache(uint32_t index) {
246
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
247
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l2_cache");
248
0
  }
249
0
  if CPUINFO_UNLIKELY(index >= cpuinfo_cache_count[cpuinfo_cache_level_2]) {
250
0
    return NULL;
251
0
  }
252
0
  return &cpuinfo_cache[cpuinfo_cache_level_2][index];
253
0
}
254
255
0
const struct cpuinfo_cache* CPUINFO_ABI cpuinfo_get_l3_cache(uint32_t index) {
256
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
257
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l3_cache");
258
0
  }
259
0
  if CPUINFO_UNLIKELY(index >= cpuinfo_cache_count[cpuinfo_cache_level_3]) {
260
0
    return NULL;
261
0
  }
262
0
  return &cpuinfo_cache[cpuinfo_cache_level_3][index];
263
0
}
264
265
0
const struct cpuinfo_cache* CPUINFO_ABI cpuinfo_get_l4_cache(uint32_t index) {
266
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
267
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l4_cache");
268
0
  }
269
0
  if CPUINFO_UNLIKELY(index >= cpuinfo_cache_count[cpuinfo_cache_level_4]) {
270
0
    return NULL;
271
0
  }
272
0
  return &cpuinfo_cache[cpuinfo_cache_level_4][index];
273
0
}
274
275
0
uint32_t CPUINFO_ABI cpuinfo_get_l1i_caches_count(void) {
276
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
277
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l1i_caches_count");
278
0
  }
279
0
  return cpuinfo_cache_count[cpuinfo_cache_level_1i];
280
0
}
281
282
0
uint32_t CPUINFO_ABI cpuinfo_get_l1d_caches_count(void) {
283
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
284
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l1d_caches_count");
285
0
  }
286
0
  return cpuinfo_cache_count[cpuinfo_cache_level_1d];
287
0
}
288
289
0
uint32_t CPUINFO_ABI cpuinfo_get_l2_caches_count(void) {
290
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
291
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l2_caches_count");
292
0
  }
293
0
  return cpuinfo_cache_count[cpuinfo_cache_level_2];
294
0
}
295
296
0
uint32_t CPUINFO_ABI cpuinfo_get_l3_caches_count(void) {
297
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
298
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l3_caches_count");
299
0
  }
300
0
  return cpuinfo_cache_count[cpuinfo_cache_level_3];
301
0
}
302
303
0
uint32_t CPUINFO_ABI cpuinfo_get_l4_caches_count(void) {
304
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
305
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l4_caches_count");
306
0
  }
307
0
  return cpuinfo_cache_count[cpuinfo_cache_level_4];
308
0
}
309
310
0
uint32_t CPUINFO_ABI cpuinfo_get_max_cache_size(void) {
311
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
312
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "max_cache_size");
313
0
  }
314
0
  return cpuinfo_max_cache_size;
315
0
}
316
317
0
const struct cpuinfo_processor* CPUINFO_ABI cpuinfo_get_current_processor(void) {
318
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
319
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "current_processor");
320
0
  }
321
0
  #ifdef __linux__
322
    /* Initializing this variable silences a MemorySanitizer error. */
323
0
    unsigned cpu = 0;
324
0
    if CPUINFO_UNLIKELY(syscall(__NR_getcpu, &cpu, NULL, NULL) != 0) {
325
0
      return 0;
326
0
    }
327
0
    if CPUINFO_UNLIKELY((uint32_t) cpu >= cpuinfo_linux_cpu_max) {
328
0
      return 0;
329
0
    }
330
0
    return cpuinfo_linux_cpu_to_processor_map[cpu];
331
  #else
332
    return NULL;
333
  #endif
334
0
}
335
336
0
const struct cpuinfo_core* CPUINFO_ABI cpuinfo_get_current_core(void) {
337
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
338
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "current_core");
339
0
  }
340
0
  #ifdef __linux__
341
    /* Initializing this variable silences a MemorySanitizer error. */
342
0
    unsigned cpu = 0;
343
0
    if CPUINFO_UNLIKELY(syscall(__NR_getcpu, &cpu, NULL, NULL) != 0) {
344
0
      return 0;
345
0
    }
346
0
    if CPUINFO_UNLIKELY((uint32_t) cpu >= cpuinfo_linux_cpu_max) {
347
0
      return 0;
348
0
    }
349
0
    return cpuinfo_linux_cpu_to_core_map[cpu];
350
  #else
351
    return NULL;
352
  #endif
353
0
}
354
355
0
uint32_t CPUINFO_ABI cpuinfo_get_current_uarch_index(void) {
356
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
357
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "current_uarch_index");
358
0
  }
359
  #if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 \
360
    || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
361
    #ifdef __linux__
362
      if (cpuinfo_linux_cpu_to_uarch_index_map == NULL) {
363
        /* Special case: avoid syscall on systems with only a single type of cores */
364
        return 0;
365
      }
366
367
      /* General case */
368
      /* Initializing this variable silences a MemorySanitizer error. */
369
      unsigned cpu = 0;
370
      if CPUINFO_UNLIKELY(syscall(__NR_getcpu, &cpu, NULL, NULL) != 0) {
371
        return 0;
372
      }
373
      if CPUINFO_UNLIKELY((uint32_t) cpu >= cpuinfo_linux_cpu_max) {
374
        return 0;
375
      }
376
      return cpuinfo_linux_cpu_to_uarch_index_map[cpu];
377
    #else
378
      /* Fallback: pretend to be on the big core. */
379
      return 0;
380
    #endif
381
  #else
382
    /* Only ARM/ARM64/RISCV processors may include cores of different types in the same package. */
383
0
    return 0;
384
0
  #endif
385
0
}
386
387
0
uint32_t CPUINFO_ABI cpuinfo_get_current_uarch_index_with_default(uint32_t default_uarch_index) {
388
0
  if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
389
0
    cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "current_uarch_index_with_default");
390
0
  }
391
  #if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 \
392
    || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
393
    #ifdef __linux__
394
      if (cpuinfo_linux_cpu_to_uarch_index_map == NULL) {
395
        /* Special case: avoid syscall on systems with only a single type of cores */
396
        return 0;
397
      }
398
399
      /* General case */
400
      /* Initializing this variable silences a MemorySanitizer error. */
401
      unsigned cpu = 0;
402
      if CPUINFO_UNLIKELY(syscall(__NR_getcpu, &cpu, NULL, NULL) != 0) {
403
        return default_uarch_index;
404
      }
405
      if CPUINFO_UNLIKELY((uint32_t) cpu >= cpuinfo_linux_cpu_max) {
406
        return default_uarch_index;
407
      }
408
      return cpuinfo_linux_cpu_to_uarch_index_map[cpu];
409
    #else
410
      /* Fallback: no API to query current core, use default uarch index. */
411
      return default_uarch_index;
412
    #endif
413
  #else
414
    /* Only ARM/ARM64/RISCV processors may include cores of different types in the same package. */
415
0
    return 0;
416
0
  #endif
417
0
}