Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Up-to-date FreeBSD support #230

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ MACH_SRCS = [
"src/mach/topology.c",
]

FREEBSD_SRCS = [
"src/freebsd/topology.c",
]

EMSCRIPTEN_SRCS = [
"src/emscripten/init.c",
]
Expand Down Expand Up @@ -112,6 +116,10 @@ MACH_ARM_SRCS = [
"src/arm/mach/init.c",
]

FREEBSD_X86_SRCS = [
"src/x86/freebsd/init.c",
]

EMSCRIPTEN_SRCS = [
"src/emscripten/init.c",
]
Expand All @@ -132,6 +140,7 @@ cc_library(
":macos_x86_64": COMMON_SRCS + X86_SRCS + MACH_SRCS + MACH_X86_SRCS,
":macos_x86_64_legacy": COMMON_SRCS + X86_SRCS + MACH_SRCS + MACH_X86_SRCS,
":macos_arm64": COMMON_SRCS + MACH_SRCS + MACH_ARM_SRCS,
":freebsd_x86_64": COMMON_SRCS + X86_SRCS + FREEBSD_SRCS + FREEBSD_X86_SRCS,
":windows_x86_64": COMMON_SRCS + X86_SRCS + WINDOWS_X86_SRCS,
":windows_arm64": COMMON_SRCS + ARM_SRCS + WINDOWS_ARM_SRCS,
":android_armv7": COMMON_SRCS + ARM_SRCS + LINUX_SRCS + LINUX_ARM32_SRCS + ANDROID_ARM_SRCS,
Expand Down Expand Up @@ -175,6 +184,7 @@ cc_library(
# Headers must be in textual_hdrs to allow us to set the standard to C99
textual_hdrs = [
"include/cpuinfo.h",
"src/freebsd/api.h",
"src/linux/api.h",
"src/mach/api.h",
"src/cpuinfo/common.h",
Expand Down Expand Up @@ -463,3 +473,10 @@ config_setting(
"cpu": "asmjs",
},
)

config_setting(
name = "freebsd_x86_64",
values = {
"cpu": "freebsd",
},
)
14 changes: 12 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ ENDIF()

# -- [ Determine target processor
SET(CPUINFO_TARGET_PROCESSOR "${CMAKE_SYSTEM_PROCESSOR}")
IF(CPUINFO_TARGET_PROCESSOR STREQUAL "amd64")
SET(CPUINFO_TARGET_PROCESSOR "AMD64")
ENDIF()
IF(IS_APPLE_OS AND CMAKE_OSX_ARCHITECTURES MATCHES "^(x86_64|arm64.*)$")
SET(CPUINFO_TARGET_PROCESSOR "${CMAKE_OSX_ARCHITECTURES}")
ELSEIF(CMAKE_GENERATOR MATCHES "^Visual Studio " AND CMAKE_VS_PLATFORM_NAME)
Expand Down Expand Up @@ -105,7 +108,7 @@ IF(NOT CMAKE_SYSTEM_NAME)
"Target operating system is not specified. "
"cpuinfo will compile, but cpuinfo_initialize() will always fail.")
SET(CPUINFO_SUPPORTED_PLATFORM FALSE)
ELSEIF(NOT CMAKE_SYSTEM_NAME MATCHES "^(Windows|WindowsStore|CYGWIN|MSYS|Darwin|Linux|Android)$")
ELSEIF(NOT CMAKE_SYSTEM_NAME MATCHES "^(Windows|WindowsStore|CYGWIN|MSYS|Darwin|Linux|Android|FreeBSD)$")
IF(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.14" AND NOT IS_APPLE_OS)
MESSAGE(WARNING
"Target operating system \"${CMAKE_SYSTEM_NAME}\" is not supported in cpuinfo. "
Expand Down Expand Up @@ -178,6 +181,8 @@ IF(CPUINFO_SUPPORTED_PLATFORM)
LIST(APPEND CPUINFO_SRCS src/x86/mach/init.c)
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "^(Windows|WindowsStore|CYGWIN|MSYS)$")
LIST(APPEND CPUINFO_SRCS src/x86/windows/init.c)
ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
LIST(APPEND CPUINFO_SRCS src/x86/freebsd/init.c)
ENDIF()
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "^Windows" AND CPUINFO_TARGET_PROCESSOR MATCHES "^(ARM64|arm64)$")
LIST(APPEND CPUINFO_SRCS
Expand Down Expand Up @@ -234,9 +239,11 @@ IF(CPUINFO_SUPPORTED_PLATFORM)
src/linux/processors.c)
ELSEIF(IS_APPLE_OS)
LIST(APPEND CPUINFO_SRCS src/mach/topology.c)
ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
LIST(APPEND CPUINFO_SRCS src/freebsd/topology.c)
ENDIF()

IF(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "Android")
IF(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "Android" OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
SET(CMAKE_THREAD_PREFER_PTHREAD TRUE)
SET(THREADS_PREFER_PTHREAD_FLAG TRUE)
FIND_PACKAGE(Threads REQUIRED)
Expand Down Expand Up @@ -301,6 +308,9 @@ IF(CPUINFO_SUPPORTED_PLATFORM)
TARGET_LINK_LIBRARIES(cpuinfo_internals PUBLIC ${CMAKE_THREAD_LIBS_INIT})
TARGET_COMPILE_DEFINITIONS(cpuinfo PRIVATE _GNU_SOURCE=1)
TARGET_COMPILE_DEFINITIONS(cpuinfo_internals PRIVATE _GNU_SOURCE=1)
ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
TARGET_LINK_LIBRARIES(cpuinfo PUBLIC ${CMAKE_THREAD_LIBS_INIT})
TARGET_LINK_LIBRARIES(cpuinfo_internals PUBLIC ${CMAKE_THREAD_LIBS_INIT})
ENDIF()
ELSE()
TARGET_COMPILE_DEFINITIONS(cpuinfo INTERFACE CPUINFO_SUPPORTED_PLATFORM=0)
Expand Down
1 change: 1 addition & 0 deletions src/cpuinfo/internal-api.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ extern CPUINFO_INTERNAL const struct cpuinfo_core** cpuinfo_linux_cpu_to_core_ma

CPUINFO_PRIVATE void cpuinfo_x86_mach_init(void);
CPUINFO_PRIVATE void cpuinfo_x86_linux_init(void);
CPUINFO_PRIVATE void cpuinfo_x86_freebsd_init(void);
#if defined(_WIN32) || defined(__CYGWIN__)
#if CPUINFO_ARCH_ARM64
CPUINFO_PRIVATE BOOL CALLBACK cpuinfo_arm_windows_init(PINIT_ONCE init_once, PVOID parameter, PVOID* context);
Expand Down
12 changes: 12 additions & 0 deletions src/freebsd/api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once

#include <stdint.h>

struct cpuinfo_freebsd_topology {
uint32_t packages;
uint32_t cores;
uint32_t threads;
uint32_t threads_per_core;
};

struct cpuinfo_freebsd_topology cpuinfo_freebsd_detect_topology(void);
110 changes: 110 additions & 0 deletions src/freebsd/topology.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>

#include <sys/sysctl.h>
#include <sys/types.h>

#include <cpuinfo/log.h>
#include <freebsd/api.h>

static int sysctl_int(const char *name) {
int value = 0;
size_t value_size = sizeof(value);
if (sysctlbyname(name, &value, &value_size, NULL, 0) != 0) {
cpuinfo_log_error("sysctlbyname(\"%s\") failed: %s", name,
strerror(errno));
} else if (value <= 0) {
cpuinfo_log_error(
"sysctlbyname(\"%s\") returned invalid value %d %zu", name,
value, value_size);
value = 0;
}
return value;
}

static char *sysctl_str(const char *name) {
size_t value_size = 0;
if (sysctlbyname(name, NULL, &value_size, NULL, 0) != 0) {
cpuinfo_log_error("sysctlbyname(\"%s\") failed: %s", name,
strerror(errno));
} else if (value_size <= 0) {
cpuinfo_log_error(
"sysctlbyname(\"%s\") returned invalid value size %zu",
name, value_size);
}
value_size += 1;
char *value = calloc(value_size, 1);
if (!value) {
cpuinfo_log_error("calloc %zu bytes failed", value_size);
return NULL;
}
if (sysctlbyname(name, value, &value_size, NULL, 0) != 0) {
cpuinfo_log_error("sysctlbyname(\"%s\") failed: %s", name,
strerror(errno));
free(value);
return NULL;
}
return value;
}

struct cpuinfo_freebsd_topology cpuinfo_freebsd_detect_topology(void) {
struct cpuinfo_freebsd_topology topology = {
.packages = 0,
.cores = 0,
.threads_per_core = 0,
.threads = 0,
};
char *topology_spec = sysctl_str("kern.sched.topology_spec");
if (!topology_spec) {
return topology;
}
const char *group_tag = "<group level=\"1\" cache-level=\"0\">";
char *p = strstr(topology_spec, group_tag);
while (p) {
const char *cpu_tag = "cpu count=\"";
char *q = strstr(p, cpu_tag);
if (q) {
p = q + strlen(cpu_tag);
topology.packages += atoi(p);
} else {
break;
}
}
if (topology.packages == 0) {
const char *group_tag = "<group level=\"1\"";
char *p = strstr(topology_spec, group_tag);
while (p) {
topology.packages += 1;
p++;
p = strstr(p, group_tag);
}
}
if (topology.packages == 0) {
cpuinfo_log_error("failed to parse topology_spec:%s",
topology_spec);
free(topology_spec);
goto fail;
}
free(topology_spec);
topology.cores = sysctl_int("kern.smp.cores");
if (topology.cores == 0) {
goto fail;
}
if (topology.cores < topology.packages) {
goto fail;
}
topology.threads_per_core = sysctl_int("kern.smp.threads_per_core");
if (topology.threads_per_core == 0) {
goto fail;
}
cpuinfo_log_debug("freebsd topology: packages = %d, cores = %d, "
"threads_per_core = %d",
topology.packages, topology.cores,
topology.threads_per_core);
topology.threads = topology.threads_per_core * topology.cores;
return topology;
fail:
topology.packages = 0;
return topology;
}
2 changes: 2 additions & 0 deletions src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ bool CPUINFO_ABI cpuinfo_initialize(void) {
#if CPUINFO_ARCH_X86 || CPUINFO_ARCH_X86_64
#if defined(__MACH__) && defined(__APPLE__)
pthread_once(&init_guard, &cpuinfo_x86_mach_init);
#elif defined(__FreeBSD__)
pthread_once(&init_guard, &cpuinfo_x86_freebsd_init);
#elif defined(__linux__)
pthread_once(&init_guard, &cpuinfo_x86_linux_init);
#elif defined(_WIN32) || defined(__CYGWIN__)
Expand Down
Loading