Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 979c842

Browse files
authoredJul 2, 2024··
Merge branch 'pytorch:main' into main
2 parents d85ee4a + 05332fd commit 979c842

File tree

7 files changed

+530
-2
lines changed

7 files changed

+530
-2
lines changed
 

‎BUILD.bazel

+17
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ MACH_SRCS = [
6363
"src/mach/topology.c",
6464
]
6565

66+
FREEBSD_SRCS = [
67+
"src/freebsd/topology.c",
68+
]
69+
6670
EMSCRIPTEN_SRCS = [
6771
"src/emscripten/init.c",
6872
]
@@ -112,6 +116,10 @@ MACH_ARM_SRCS = [
112116
"src/arm/mach/init.c",
113117
]
114118

119+
FREEBSD_X86_SRCS = [
120+
"src/x86/freebsd/init.c",
121+
]
122+
115123
EMSCRIPTEN_SRCS = [
116124
"src/emscripten/init.c",
117125
]
@@ -132,6 +140,7 @@ cc_library(
132140
":macos_x86_64": COMMON_SRCS + X86_SRCS + MACH_SRCS + MACH_X86_SRCS,
133141
":macos_x86_64_legacy": COMMON_SRCS + X86_SRCS + MACH_SRCS + MACH_X86_SRCS,
134142
":macos_arm64": COMMON_SRCS + MACH_SRCS + MACH_ARM_SRCS,
143+
":freebsd_x86_64": COMMON_SRCS + X86_SRCS + FREEBSD_SRCS + FREEBSD_X86_SRCS,
135144
":windows_x86_64": COMMON_SRCS + X86_SRCS + WINDOWS_X86_SRCS,
136145
":windows_arm64": COMMON_SRCS + ARM_SRCS + WINDOWS_ARM_SRCS,
137146
":android_armv7": COMMON_SRCS + ARM_SRCS + LINUX_SRCS + LINUX_ARM32_SRCS + ANDROID_ARM_SRCS,
@@ -175,6 +184,7 @@ cc_library(
175184
# Headers must be in textual_hdrs to allow us to set the standard to C99
176185
textual_hdrs = [
177186
"include/cpuinfo.h",
187+
"src/freebsd/api.h",
178188
"src/linux/api.h",
179189
"src/mach/api.h",
180190
"src/cpuinfo/common.h",
@@ -463,3 +473,10 @@ config_setting(
463473
"cpu": "asmjs",
464474
},
465475
)
476+
477+
config_setting(
478+
name = "freebsd_x86_64",
479+
values = {
480+
"cpu": "freebsd",
481+
},
482+
)

‎CMakeLists.txt

+12-2
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ ENDIF()
6767

6868
# -- [ Determine target processor
6969
SET(CPUINFO_TARGET_PROCESSOR "${CMAKE_SYSTEM_PROCESSOR}")
70+
IF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD" AND CPUINFO_TARGET_PROCESSOR STREQUAL "amd64")
71+
SET(CPUINFO_TARGET_PROCESSOR "AMD64")
72+
ENDIF()
7073
IF(IS_APPLE_OS AND CMAKE_OSX_ARCHITECTURES MATCHES "^(x86_64|arm64.*)$")
7174
SET(CPUINFO_TARGET_PROCESSOR "${CMAKE_OSX_ARCHITECTURES}")
7275
ELSEIF(CMAKE_GENERATOR MATCHES "^Visual Studio " AND CMAKE_VS_PLATFORM_NAME)
@@ -105,7 +108,7 @@ IF(NOT CMAKE_SYSTEM_NAME)
105108
"Target operating system is not specified. "
106109
"cpuinfo will compile, but cpuinfo_initialize() will always fail.")
107110
SET(CPUINFO_SUPPORTED_PLATFORM FALSE)
108-
ELSEIF(NOT CMAKE_SYSTEM_NAME MATCHES "^(Windows|WindowsStore|CYGWIN|MSYS|Darwin|Linux|Android)$")
111+
ELSEIF(NOT CMAKE_SYSTEM_NAME MATCHES "^(Windows|WindowsStore|CYGWIN|MSYS|Darwin|Linux|Android|FreeBSD)$")
109112
IF(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.14" AND NOT IS_APPLE_OS)
110113
MESSAGE(WARNING
111114
"Target operating system \"${CMAKE_SYSTEM_NAME}\" is not supported in cpuinfo. "
@@ -178,6 +181,8 @@ IF(CPUINFO_SUPPORTED_PLATFORM)
178181
LIST(APPEND CPUINFO_SRCS src/x86/mach/init.c)
179182
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "^(Windows|WindowsStore|CYGWIN|MSYS)$")
180183
LIST(APPEND CPUINFO_SRCS src/x86/windows/init.c)
184+
ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
185+
LIST(APPEND CPUINFO_SRCS src/x86/freebsd/init.c)
181186
ENDIF()
182187
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "^Windows" AND CPUINFO_TARGET_PROCESSOR MATCHES "^(ARM64|arm64)$")
183188
LIST(APPEND CPUINFO_SRCS
@@ -234,9 +239,11 @@ IF(CPUINFO_SUPPORTED_PLATFORM)
234239
src/linux/processors.c)
235240
ELSEIF(IS_APPLE_OS)
236241
LIST(APPEND CPUINFO_SRCS src/mach/topology.c)
242+
ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
243+
LIST(APPEND CPUINFO_SRCS src/freebsd/topology.c)
237244
ENDIF()
238245

239-
IF(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "Android")
246+
IF(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "Android" OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
240247
SET(CMAKE_THREAD_PREFER_PTHREAD TRUE)
241248
SET(THREADS_PREFER_PTHREAD_FLAG TRUE)
242249
FIND_PACKAGE(Threads REQUIRED)
@@ -301,6 +308,9 @@ IF(CPUINFO_SUPPORTED_PLATFORM)
301308
TARGET_LINK_LIBRARIES(cpuinfo_internals PUBLIC ${CMAKE_THREAD_LIBS_INIT})
302309
TARGET_COMPILE_DEFINITIONS(cpuinfo PRIVATE _GNU_SOURCE=1)
303310
TARGET_COMPILE_DEFINITIONS(cpuinfo_internals PRIVATE _GNU_SOURCE=1)
311+
ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
312+
TARGET_LINK_LIBRARIES(cpuinfo PUBLIC ${CMAKE_THREAD_LIBS_INIT})
313+
TARGET_LINK_LIBRARIES(cpuinfo_internals PUBLIC ${CMAKE_THREAD_LIBS_INIT})
304314
ENDIF()
305315
ELSE()
306316
TARGET_COMPILE_DEFINITIONS(cpuinfo INTERFACE CPUINFO_SUPPORTED_PLATFORM=0)

‎src/cpuinfo/internal-api.h

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ extern CPUINFO_INTERNAL const struct cpuinfo_core** cpuinfo_linux_cpu_to_core_ma
4949

5050
CPUINFO_PRIVATE void cpuinfo_x86_mach_init(void);
5151
CPUINFO_PRIVATE void cpuinfo_x86_linux_init(void);
52+
CPUINFO_PRIVATE void cpuinfo_x86_freebsd_init(void);
5253
#if defined(_WIN32) || defined(__CYGWIN__)
5354
#if CPUINFO_ARCH_ARM64
5455
CPUINFO_PRIVATE BOOL CALLBACK cpuinfo_arm_windows_init(PINIT_ONCE init_once, PVOID parameter, PVOID* context);

‎src/freebsd/api.h

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#pragma once
2+
3+
#include <stdint.h>
4+
5+
struct cpuinfo_freebsd_topology {
6+
uint32_t packages;
7+
uint32_t cores;
8+
uint32_t threads;
9+
uint32_t threads_per_core;
10+
};
11+
12+
struct cpuinfo_freebsd_topology cpuinfo_freebsd_detect_topology(void);

‎src/freebsd/topology.c

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#include <errno.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
5+
#include <sys/sysctl.h>
6+
#include <sys/types.h>
7+
8+
#include <cpuinfo/log.h>
9+
#include <freebsd/api.h>
10+
11+
static int sysctl_int(const char* name) {
12+
int value = 0;
13+
size_t value_size = sizeof(value);
14+
if (sysctlbyname(name, &value, &value_size, NULL, 0) != 0) {
15+
cpuinfo_log_error("sysctlbyname(\"%s\") failed: %s", name, strerror(errno));
16+
} else if (value <= 0) {
17+
cpuinfo_log_error("sysctlbyname(\"%s\") returned invalid value %d %zu", name, value, value_size);
18+
value = 0;
19+
}
20+
return value;
21+
}
22+
23+
static char* sysctl_str(const char* name) {
24+
size_t value_size = 0;
25+
if (sysctlbyname(name, NULL, &value_size, NULL, 0) != 0) {
26+
cpuinfo_log_error("sysctlbyname(\"%s\") failed: %s", name, strerror(errno));
27+
} else if (value_size <= 0) {
28+
cpuinfo_log_error("sysctlbyname(\"%s\") returned invalid value size %zu", name, value_size);
29+
}
30+
value_size += 1;
31+
char* value = calloc(value_size, 1);
32+
if (!value) {
33+
cpuinfo_log_error("calloc %zu bytes failed", value_size);
34+
return NULL;
35+
}
36+
if (sysctlbyname(name, value, &value_size, NULL, 0) != 0) {
37+
cpuinfo_log_error("sysctlbyname(\"%s\") failed: %s", name, strerror(errno));
38+
free(value);
39+
return NULL;
40+
}
41+
return value;
42+
}
43+
44+
struct cpuinfo_freebsd_topology cpuinfo_freebsd_detect_topology(void) {
45+
struct cpuinfo_freebsd_topology topology = {
46+
.packages = 0,
47+
.cores = 0,
48+
.threads_per_core = 0,
49+
.threads = 0,
50+
};
51+
char* topology_spec = sysctl_str("kern.sched.topology_spec");
52+
if (!topology_spec) {
53+
return topology;
54+
}
55+
const char* group_tag = "<group level=\"1\" cache-level=\"0\">";
56+
char* p = strstr(topology_spec, group_tag);
57+
while (p) {
58+
const char* cpu_tag = "cpu count=\"";
59+
char* q = strstr(p, cpu_tag);
60+
if (q) {
61+
p = q + strlen(cpu_tag);
62+
topology.packages += atoi(p);
63+
} else {
64+
break;
65+
}
66+
}
67+
if (topology.packages == 0) {
68+
const char* group_tag = "<group level=\"1\"";
69+
char* p = strstr(topology_spec, group_tag);
70+
while (p) {
71+
topology.packages += 1;
72+
p++;
73+
p = strstr(p, group_tag);
74+
}
75+
}
76+
if (topology.packages == 0) {
77+
cpuinfo_log_error("failed to parse topology_spec:%s", topology_spec);
78+
free(topology_spec);
79+
goto fail;
80+
}
81+
free(topology_spec);
82+
topology.cores = sysctl_int("kern.smp.cores");
83+
if (topology.cores == 0) {
84+
goto fail;
85+
}
86+
if (topology.cores < topology.packages) {
87+
goto fail;
88+
}
89+
topology.threads_per_core = sysctl_int("kern.smp.threads_per_core");
90+
if (topology.threads_per_core == 0) {
91+
goto fail;
92+
}
93+
cpuinfo_log_debug(
94+
"freebsd topology: packages = %d, cores = %d, "
95+
"threads_per_core = %d",
96+
topology.packages,
97+
topology.cores,
98+
topology.threads_per_core);
99+
topology.threads = topology.threads_per_core * topology.cores;
100+
return topology;
101+
fail:
102+
topology.packages = 0;
103+
return topology;
104+
}

‎src/init.c

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ bool CPUINFO_ABI cpuinfo_initialize(void) {
2424
#if CPUINFO_ARCH_X86 || CPUINFO_ARCH_X86_64
2525
#if defined(__MACH__) && defined(__APPLE__)
2626
pthread_once(&init_guard, &cpuinfo_x86_mach_init);
27+
#elif defined(__FreeBSD__)
28+
pthread_once(&init_guard, &cpuinfo_x86_freebsd_init);
2729
#elif defined(__linux__)
2830
pthread_once(&init_guard, &cpuinfo_x86_linux_init);
2931
#elif defined(_WIN32) || defined(__CYGWIN__)

‎src/x86/freebsd/init.c

+382
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,382 @@
1+
#include <stdint.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
5+
#include <cpuinfo.h>
6+
#include <cpuinfo/internal-api.h>
7+
#include <cpuinfo/log.h>
8+
#include <freebsd/api.h>
9+
#include <x86/api.h>
10+
11+
static inline uint32_t max(uint32_t a, uint32_t b) {
12+
return a > b ? a : b;
13+
}
14+
15+
static inline uint32_t bit_mask(uint32_t bits) {
16+
return (UINT32_C(1) << bits) - UINT32_C(1);
17+
}
18+
19+
void cpuinfo_x86_freebsd_init(void) {
20+
struct cpuinfo_processor* processors = NULL;
21+
struct cpuinfo_core* cores = NULL;
22+
struct cpuinfo_cluster* clusters = NULL;
23+
struct cpuinfo_package* packages = NULL;
24+
struct cpuinfo_cache* l1i = NULL;
25+
struct cpuinfo_cache* l1d = NULL;
26+
struct cpuinfo_cache* l2 = NULL;
27+
struct cpuinfo_cache* l3 = NULL;
28+
struct cpuinfo_cache* l4 = NULL;
29+
30+
struct cpuinfo_freebsd_topology freebsd_topology = cpuinfo_freebsd_detect_topology();
31+
if (freebsd_topology.packages == 0) {
32+
cpuinfo_log_error("failed to detect topology");
33+
goto cleanup;
34+
}
35+
processors = calloc(freebsd_topology.threads, sizeof(struct cpuinfo_processor));
36+
if (processors == NULL) {
37+
cpuinfo_log_error(
38+
"failed to allocate %zu bytes for descriptions of %" PRIu32 " logical processors",
39+
freebsd_topology.threads * sizeof(struct cpuinfo_processor),
40+
freebsd_topology.threads);
41+
goto cleanup;
42+
}
43+
cores = calloc(freebsd_topology.cores, sizeof(struct cpuinfo_core));
44+
if (cores == NULL) {
45+
cpuinfo_log_error(
46+
"failed to allocate %zu bytes for descriptions of %" PRIu32 " cores",
47+
freebsd_topology.cores * sizeof(struct cpuinfo_core),
48+
freebsd_topology.cores);
49+
goto cleanup;
50+
}
51+
/* On x86 a cluster of cores is the biggest group of cores that shares a
52+
* cache. */
53+
clusters = calloc(freebsd_topology.packages, sizeof(struct cpuinfo_cluster));
54+
if (clusters == NULL) {
55+
cpuinfo_log_error(
56+
"failed to allocate %zu bytes for descriptions of %" PRIu32 " core clusters",
57+
freebsd_topology.packages * sizeof(struct cpuinfo_cluster),
58+
freebsd_topology.packages);
59+
goto cleanup;
60+
}
61+
packages = calloc(freebsd_topology.packages, sizeof(struct cpuinfo_package));
62+
if (packages == NULL) {
63+
cpuinfo_log_error(
64+
"failed to allocate %zu bytes for descriptions of %" PRIu32 " physical packages",
65+
freebsd_topology.packages * sizeof(struct cpuinfo_package),
66+
freebsd_topology.packages);
67+
goto cleanup;
68+
}
69+
70+
struct cpuinfo_x86_processor x86_processor;
71+
memset(&x86_processor, 0, sizeof(x86_processor));
72+
cpuinfo_x86_init_processor(&x86_processor);
73+
char brand_string[48];
74+
cpuinfo_x86_normalize_brand_string(x86_processor.brand_string, brand_string);
75+
76+
const uint32_t threads_per_core = freebsd_topology.threads_per_core;
77+
const uint32_t threads_per_package = freebsd_topology.threads / freebsd_topology.packages;
78+
const uint32_t cores_per_package = freebsd_topology.cores / freebsd_topology.packages;
79+
for (uint32_t i = 0; i < freebsd_topology.packages; i++) {
80+
clusters[i] = (struct cpuinfo_cluster){
81+
.processor_start = i * threads_per_package,
82+
.processor_count = threads_per_package,
83+
.core_start = i * cores_per_package,
84+
.core_count = cores_per_package,
85+
.cluster_id = 0,
86+
.package = packages + i,
87+
.vendor = x86_processor.vendor,
88+
.uarch = x86_processor.uarch,
89+
.cpuid = x86_processor.cpuid,
90+
};
91+
packages[i].processor_start = i * threads_per_package;
92+
packages[i].processor_count = threads_per_package;
93+
packages[i].core_start = i * cores_per_package;
94+
packages[i].core_count = cores_per_package;
95+
packages[i].cluster_start = i;
96+
packages[i].cluster_count = 1;
97+
cpuinfo_x86_format_package_name(x86_processor.vendor, brand_string, packages[i].name);
98+
}
99+
for (uint32_t i = 0; i < freebsd_topology.cores; i++) {
100+
cores[i] = (struct cpuinfo_core){
101+
.processor_start = i * threads_per_core,
102+
.processor_count = threads_per_core,
103+
.core_id = i % cores_per_package,
104+
.cluster = clusters + i / cores_per_package,
105+
.package = packages + i / cores_per_package,
106+
.vendor = x86_processor.vendor,
107+
.uarch = x86_processor.uarch,
108+
.cpuid = x86_processor.cpuid,
109+
};
110+
}
111+
for (uint32_t i = 0; i < freebsd_topology.threads; i++) {
112+
const uint32_t smt_id = i % threads_per_core;
113+
const uint32_t core_id = i / threads_per_core;
114+
const uint32_t package_id = i / threads_per_package;
115+
116+
/* Reconstruct APIC IDs from topology components */
117+
const uint32_t thread_bits_mask = bit_mask(x86_processor.topology.thread_bits_length);
118+
const uint32_t core_bits_mask = bit_mask(x86_processor.topology.core_bits_length);
119+
const uint32_t package_bits_offset =
120+
max(x86_processor.topology.thread_bits_offset + x86_processor.topology.thread_bits_length,
121+
x86_processor.topology.core_bits_offset + x86_processor.topology.core_bits_length);
122+
const uint32_t apic_id = ((smt_id & thread_bits_mask) << x86_processor.topology.thread_bits_offset) |
123+
((core_id & core_bits_mask) << x86_processor.topology.core_bits_offset) |
124+
(package_id << package_bits_offset);
125+
cpuinfo_log_debug("reconstructed APIC ID 0x%08" PRIx32 " for thread %" PRIu32, apic_id, i);
126+
127+
processors[i].smt_id = smt_id;
128+
processors[i].core = cores + i / threads_per_core;
129+
processors[i].cluster = clusters + i / threads_per_package;
130+
processors[i].package = packages + i / threads_per_package;
131+
processors[i].apic_id = apic_id;
132+
}
133+
134+
uint32_t threads_per_l1 = 0, l1_count = 0;
135+
if (x86_processor.cache.l1i.size != 0 || x86_processor.cache.l1d.size != 0) {
136+
/* Assume that threads on the same core share L1 */
137+
threads_per_l1 = freebsd_topology.threads / freebsd_topology.cores;
138+
cpuinfo_log_warning(
139+
"freebsd kernel did not report number of "
140+
"threads sharing L1 cache; assume %" PRIu32,
141+
threads_per_l1);
142+
l1_count = freebsd_topology.threads / threads_per_l1;
143+
cpuinfo_log_debug("detected %" PRIu32 " L1 caches", l1_count);
144+
}
145+
146+
uint32_t threads_per_l2 = 0, l2_count = 0;
147+
if (x86_processor.cache.l2.size != 0) {
148+
if (x86_processor.cache.l3.size != 0) {
149+
/* This is not a last-level cache; assume that threads
150+
* on the same core share L2 */
151+
threads_per_l2 = freebsd_topology.threads / freebsd_topology.cores;
152+
} else {
153+
/* This is a last-level cache; assume that threads on
154+
* the same package share L2 */
155+
threads_per_l2 = freebsd_topology.threads / freebsd_topology.packages;
156+
}
157+
cpuinfo_log_warning(
158+
"freebsd kernel did not report number of "
159+
"threads sharing L2 cache; assume %" PRIu32,
160+
threads_per_l2);
161+
l2_count = freebsd_topology.threads / threads_per_l2;
162+
cpuinfo_log_debug("detected %" PRIu32 " L2 caches", l2_count);
163+
}
164+
165+
uint32_t threads_per_l3 = 0, l3_count = 0;
166+
if (x86_processor.cache.l3.size != 0) {
167+
/*
168+
* Assume that threads on the same package share L3.
169+
* However, is it not necessarily the last-level cache (there
170+
* may be L4 cache as well)
171+
*/
172+
threads_per_l3 = freebsd_topology.threads / freebsd_topology.packages;
173+
cpuinfo_log_warning(
174+
"freebsd kernel did not report number of "
175+
"threads sharing L3 cache; assume %" PRIu32,
176+
threads_per_l3);
177+
l3_count = freebsd_topology.threads / threads_per_l3;
178+
cpuinfo_log_debug("detected %" PRIu32 " L3 caches", l3_count);
179+
}
180+
181+
uint32_t threads_per_l4 = 0, l4_count = 0;
182+
if (x86_processor.cache.l4.size != 0) {
183+
/*
184+
* Assume that all threads share this L4.
185+
* As of now, L4 cache exists only on notebook x86 CPUs, which
186+
* are single-package, but multi-socket systems could have
187+
* shared L4 (like on IBM POWER8).
188+
*/
189+
threads_per_l4 = freebsd_topology.threads;
190+
cpuinfo_log_warning(
191+
"freebsd kernel did not report number of "
192+
"threads sharing L4 cache; assume %" PRIu32,
193+
threads_per_l4);
194+
l4_count = freebsd_topology.threads / threads_per_l4;
195+
cpuinfo_log_debug("detected %" PRIu32 " L4 caches", l4_count);
196+
}
197+
198+
if (x86_processor.cache.l1i.size != 0) {
199+
l1i = calloc(l1_count, sizeof(struct cpuinfo_cache));
200+
if (l1i == NULL) {
201+
cpuinfo_log_error(
202+
"failed to allocate %zu bytes for descriptions of "
203+
"%" PRIu32 " L1I caches",
204+
l1_count * sizeof(struct cpuinfo_cache),
205+
l1_count);
206+
return;
207+
}
208+
for (uint32_t c = 0; c < l1_count; c++) {
209+
l1i[c] = (struct cpuinfo_cache){
210+
.size = x86_processor.cache.l1i.size,
211+
.associativity = x86_processor.cache.l1i.associativity,
212+
.sets = x86_processor.cache.l1i.sets,
213+
.partitions = x86_processor.cache.l1i.partitions,
214+
.line_size = x86_processor.cache.l1i.line_size,
215+
.flags = x86_processor.cache.l1i.flags,
216+
.processor_start = c * threads_per_l1,
217+
.processor_count = threads_per_l1,
218+
};
219+
}
220+
for (uint32_t t = 0; t < freebsd_topology.threads; t++) {
221+
processors[t].cache.l1i = &l1i[t / threads_per_l1];
222+
}
223+
}
224+
225+
if (x86_processor.cache.l1d.size != 0) {
226+
l1d = calloc(l1_count, sizeof(struct cpuinfo_cache));
227+
if (l1d == NULL) {
228+
cpuinfo_log_error(
229+
"failed to allocate %zu bytes for descriptions of "
230+
"%" PRIu32 " L1D caches",
231+
l1_count * sizeof(struct cpuinfo_cache),
232+
l1_count);
233+
return;
234+
}
235+
for (uint32_t c = 0; c < l1_count; c++) {
236+
l1d[c] = (struct cpuinfo_cache){
237+
.size = x86_processor.cache.l1d.size,
238+
.associativity = x86_processor.cache.l1d.associativity,
239+
.sets = x86_processor.cache.l1d.sets,
240+
.partitions = x86_processor.cache.l1d.partitions,
241+
.line_size = x86_processor.cache.l1d.line_size,
242+
.flags = x86_processor.cache.l1d.flags,
243+
.processor_start = c * threads_per_l1,
244+
.processor_count = threads_per_l1,
245+
};
246+
}
247+
for (uint32_t t = 0; t < freebsd_topology.threads; t++) {
248+
processors[t].cache.l1d = &l1d[t / threads_per_l1];
249+
}
250+
}
251+
252+
if (l2_count != 0) {
253+
l2 = calloc(l2_count, sizeof(struct cpuinfo_cache));
254+
if (l2 == NULL) {
255+
cpuinfo_log_error(
256+
"failed to allocate %zu bytes for descriptions of "
257+
"%" PRIu32 " L2 caches",
258+
l2_count * sizeof(struct cpuinfo_cache),
259+
l2_count);
260+
return;
261+
}
262+
for (uint32_t c = 0; c < l2_count; c++) {
263+
l2[c] = (struct cpuinfo_cache){
264+
.size = x86_processor.cache.l2.size,
265+
.associativity = x86_processor.cache.l2.associativity,
266+
.sets = x86_processor.cache.l2.sets,
267+
.partitions = x86_processor.cache.l2.partitions,
268+
.line_size = x86_processor.cache.l2.line_size,
269+
.flags = x86_processor.cache.l2.flags,
270+
.processor_start = c * threads_per_l2,
271+
.processor_count = threads_per_l2,
272+
};
273+
}
274+
for (uint32_t t = 0; t < freebsd_topology.threads; t++) {
275+
processors[t].cache.l2 = &l2[t / threads_per_l2];
276+
}
277+
}
278+
279+
if (l3_count != 0) {
280+
l3 = calloc(l3_count, sizeof(struct cpuinfo_cache));
281+
if (l3 == NULL) {
282+
cpuinfo_log_error(
283+
"failed to allocate %zu bytes for descriptions of "
284+
"%" PRIu32 " L3 caches",
285+
l3_count * sizeof(struct cpuinfo_cache),
286+
l3_count);
287+
return;
288+
}
289+
for (uint32_t c = 0; c < l3_count; c++) {
290+
l3[c] = (struct cpuinfo_cache){
291+
.size = x86_processor.cache.l3.size,
292+
.associativity = x86_processor.cache.l3.associativity,
293+
.sets = x86_processor.cache.l3.sets,
294+
.partitions = x86_processor.cache.l3.partitions,
295+
.line_size = x86_processor.cache.l3.line_size,
296+
.flags = x86_processor.cache.l3.flags,
297+
.processor_start = c * threads_per_l3,
298+
.processor_count = threads_per_l3,
299+
};
300+
}
301+
for (uint32_t t = 0; t < freebsd_topology.threads; t++) {
302+
processors[t].cache.l3 = &l3[t / threads_per_l3];
303+
}
304+
}
305+
306+
if (l4_count != 0) {
307+
l4 = calloc(l4_count, sizeof(struct cpuinfo_cache));
308+
if (l4 == NULL) {
309+
cpuinfo_log_error(
310+
"failed to allocate %zu bytes for descriptions of "
311+
"%" PRIu32 " L4 caches",
312+
l4_count * sizeof(struct cpuinfo_cache),
313+
l4_count);
314+
return;
315+
}
316+
for (uint32_t c = 0; c < l4_count; c++) {
317+
l4[c] = (struct cpuinfo_cache){
318+
.size = x86_processor.cache.l4.size,
319+
.associativity = x86_processor.cache.l4.associativity,
320+
.sets = x86_processor.cache.l4.sets,
321+
.partitions = x86_processor.cache.l4.partitions,
322+
.line_size = x86_processor.cache.l4.line_size,
323+
.flags = x86_processor.cache.l4.flags,
324+
.processor_start = c * threads_per_l4,
325+
.processor_count = threads_per_l4,
326+
};
327+
}
328+
for (uint32_t t = 0; t < freebsd_topology.threads; t++) {
329+
processors[t].cache.l4 = &l4[t / threads_per_l4];
330+
}
331+
}
332+
333+
/* Commit changes */
334+
cpuinfo_processors = processors;
335+
cpuinfo_cores = cores;
336+
cpuinfo_clusters = clusters;
337+
cpuinfo_packages = packages;
338+
cpuinfo_cache[cpuinfo_cache_level_1i] = l1i;
339+
cpuinfo_cache[cpuinfo_cache_level_1d] = l1d;
340+
cpuinfo_cache[cpuinfo_cache_level_2] = l2;
341+
cpuinfo_cache[cpuinfo_cache_level_3] = l3;
342+
cpuinfo_cache[cpuinfo_cache_level_4] = l4;
343+
344+
cpuinfo_processors_count = freebsd_topology.threads;
345+
cpuinfo_cores_count = freebsd_topology.cores;
346+
cpuinfo_clusters_count = freebsd_topology.packages;
347+
cpuinfo_packages_count = freebsd_topology.packages;
348+
cpuinfo_cache_count[cpuinfo_cache_level_1i] = l1_count;
349+
cpuinfo_cache_count[cpuinfo_cache_level_1d] = l1_count;
350+
cpuinfo_cache_count[cpuinfo_cache_level_2] = l2_count;
351+
cpuinfo_cache_count[cpuinfo_cache_level_3] = l3_count;
352+
cpuinfo_cache_count[cpuinfo_cache_level_4] = l4_count;
353+
cpuinfo_max_cache_size = cpuinfo_compute_max_cache_size(&processors[0]);
354+
355+
cpuinfo_global_uarch = (struct cpuinfo_uarch_info){
356+
.uarch = x86_processor.uarch,
357+
.cpuid = x86_processor.cpuid,
358+
.processor_count = freebsd_topology.threads,
359+
.core_count = freebsd_topology.cores,
360+
};
361+
362+
__sync_synchronize();
363+
364+
cpuinfo_is_initialized = true;
365+
366+
processors = NULL;
367+
cores = NULL;
368+
clusters = NULL;
369+
packages = NULL;
370+
l1i = l1d = l2 = l3 = l4 = NULL;
371+
372+
cleanup:
373+
free(processors);
374+
free(cores);
375+
free(clusters);
376+
free(packages);
377+
free(l1i);
378+
free(l1d);
379+
free(l2);
380+
free(l3);
381+
free(l4);
382+
}

0 commit comments

Comments
 (0)
Please sign in to comment.