Skip to content

Commit 7b05123

Browse files
committed
Add FreeBSD support
1 parent 959002f commit 7b05123

File tree

7 files changed

+556
-2
lines changed

7 files changed

+556
-2
lines changed

BUILD.bazel

+17
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ MACH_SRCS = [
5959
"src/mach/topology.c",
6060
]
6161

62+
FREEBSD_SRCS = [
63+
"src/freebsd/topology.c",
64+
]
65+
6266
EMSCRIPTEN_SRCS = [
6367
"src/emscripten/init.c",
6468
]
@@ -97,6 +101,10 @@ MACH_ARM_SRCS = [
97101
"src/arm/mach/init.c",
98102
]
99103

104+
FREEBSD_X86_SRCS = [
105+
"src/x86/freebsd/init.c",
106+
]
107+
100108
EMSCRIPTEN_SRCS = [
101109
"src/emscripten/init.c",
102110
]
@@ -116,6 +124,7 @@ cc_library(
116124
":macos_x86_64": COMMON_SRCS + X86_SRCS + MACH_SRCS + MACH_X86_SRCS,
117125
":macos_x86_64_legacy": COMMON_SRCS + X86_SRCS + MACH_SRCS + MACH_X86_SRCS,
118126
":macos_arm64": COMMON_SRCS + MACH_SRCS + MACH_ARM_SRCS,
127+
":freebsd_x86_64": COMMON_SRCS + X86_SRCS + FREEBSD_SRCS + FREEBSD_X86_SRCS,
119128
":windows_x86_64": COMMON_SRCS + X86_SRCS + WINDOWS_X86_SRCS,
120129
":android_armv7": COMMON_SRCS + ARM_SRCS + LINUX_SRCS + LINUX_ARM32_SRCS + ANDROID_ARM_SRCS,
121130
":android_arm64": COMMON_SRCS + ARM_SRCS + LINUX_SRCS + LINUX_ARM64_SRCS + ANDROID_ARM_SRCS,
@@ -156,6 +165,7 @@ cc_library(
156165
# Headers must be in textual_hdrs to allow us to set the standard to C99
157166
textual_hdrs = [
158167
"include/cpuinfo.h",
168+
"src/freebsd/api.h",
159169
"src/linux/api.h",
160170
"src/mach/api.h",
161171
"src/cpuinfo/common.h",
@@ -423,3 +433,10 @@ config_setting(
423433
"cpu": "asmjs",
424434
},
425435
)
436+
437+
config_setting(
438+
name = "freebsd_x86_64",
439+
values = {
440+
"cpu": "freebsd",
441+
},
442+
)

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(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
@@ -225,9 +230,11 @@ IF(CPUINFO_SUPPORTED_PLATFORM)
225230
src/linux/processors.c)
226231
ELSEIF(IS_APPLE_OS)
227232
LIST(APPEND CPUINFO_SRCS src/mach/topology.c)
233+
ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
234+
LIST(APPEND CPUINFO_SRCS src/freebsd/topology.c)
228235
ENDIF()
229236

230-
IF(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "Android")
237+
IF(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "Android" OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
231238
SET(CMAKE_THREAD_PREFER_PTHREAD TRUE)
232239
SET(THREADS_PREFER_PTHREAD_FLAG TRUE)
233240
FIND_PACKAGE(Threads REQUIRED)
@@ -292,6 +299,9 @@ IF(CPUINFO_SUPPORTED_PLATFORM)
292299
TARGET_LINK_LIBRARIES(cpuinfo_internals PUBLIC ${CMAKE_THREAD_LIBS_INIT})
293300
TARGET_COMPILE_DEFINITIONS(cpuinfo PRIVATE _GNU_SOURCE=1)
294301
TARGET_COMPILE_DEFINITIONS(cpuinfo_internals PRIVATE _GNU_SOURCE=1)
302+
ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
303+
TARGET_LINK_LIBRARIES(cpuinfo PUBLIC ${CMAKE_THREAD_LIBS_INIT})
304+
TARGET_LINK_LIBRARIES(cpuinfo_internals PUBLIC ${CMAKE_THREAD_LIBS_INIT})
295305
ENDIF()
296306
ELSE()
297307
TARGET_COMPILE_DEFINITIONS(cpuinfo INTERFACE CPUINFO_SUPPORTED_PLATFORM=0)

src/cpuinfo/internal-api.h

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ extern CPUINFO_INTERNAL uint32_t cpuinfo_max_cache_size;
5050

5151
CPUINFO_PRIVATE void cpuinfo_x86_mach_init(void);
5252
CPUINFO_PRIVATE void cpuinfo_x86_linux_init(void);
53+
CPUINFO_PRIVATE void cpuinfo_x86_freebsd_init(void);
5354
#if defined(_WIN32) || defined(__CYGWIN__)
5455
#if CPUINFO_ARCH_ARM64
5556
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

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

src/init.c

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

0 commit comments

Comments
 (0)