From ea88133475e09ed4de3e46bb6a0362ba603923a9 Mon Sep 17 00:00:00 2001 From: Evan Wilde Date: Tue, 26 Aug 2025 15:08:30 -0700 Subject: [PATCH] FreeBSD: Improve CPU core count handling This improves the CPU core count handling for FreeBSD. This uses sysconf to grab the number of configured processors when logical and physical CPU counts are requested, and then pthread_getaffinity_np and the number of active processors. This takes into account the number of available cores when the process is restricted to a subset of the processors. This also fixes the `dispatch_workqueye` test, which has its own implementation to extract the core count. FreeBSD does not have an `hw.activecpu` syscall, so the syscallbyname was failing and the activecpu count was garbage from the stack. I've updated the test to initialize the value with `0xa1a1a1` to make the garbage clearer. Also update the test for FreeBSD to take advantage of sysconf and pthread_getaffinity_np in the test. Fixes: #897 --- src/shims.h | 6 +++--- src/shims/hw_config.h | 4 ++-- tests/dispatch_workqueue.c | 10 +++++++--- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/shims.h b/src/shims.h index e14697a9f..a65052dd0 100644 --- a/src/shims.h +++ b/src/shims.h @@ -58,9 +58,6 @@ #define DISPATCH_WORKQ_MAX_PTHREAD_COUNT 255 #endif -#include "shims/hw_config.h" -#include "shims/priority.h" - #if HAVE_PTHREAD_NP_H #include #endif @@ -69,6 +66,9 @@ #include #endif +#include "shims/hw_config.h" +#include "shims/priority.h" + #if !HAVE_DECL_FD_COPY #define FD_COPY(f, t) (void)(*(t) = *(f)) #endif diff --git a/src/shims/hw_config.h b/src/shims/hw_config.h index 06b8921d9..4e6f7c3c9 100644 --- a/src/shims/hw_config.h +++ b/src/shims/hw_config.h @@ -102,14 +102,14 @@ static inline uint32_t _dispatch_hw_get_config(_dispatch_hw_config_t c) { uint32_t val = 1; -#if defined(__linux__) && HAVE_SYSCONF +#if defined(__FreeBSD__) || (defined(__linux__) && HAVE_SYSCONF) switch (c) { case _dispatch_hw_config_logical_cpus: case _dispatch_hw_config_physical_cpus: return (uint32_t)sysconf(_SC_NPROCESSORS_CONF); case _dispatch_hw_config_active_cpus: { -#ifdef __USE_GNU +#if defined(__FreeBSD__) || __USE_GNU // Prefer pthread_getaffinity_np because it considers // scheduler cpu affinity. This matters if the program // is restricted to a subset of the online cpus (eg via numactl). diff --git a/tests/dispatch_workqueue.c b/tests/dispatch_workqueue.c index c12598b69..3f3328736 100644 --- a/tests/dispatch_workqueue.c +++ b/tests/dispatch_workqueue.c @@ -4,6 +4,10 @@ #if defined(__linux__) // For pthread_getaffinity_np() #include +#elif defined(__FreeBSD__) +// for pthread_getaffinity_np / cpu_set_t +#include +#include #endif struct test_context { @@ -37,11 +41,11 @@ spin(void *context) static uint32_t activecpu(void) { - uint32_t activecpu; -#if defined(__linux__) || defined(__OpenBSD__) + uint32_t activecpu = 0xa1a1a1; +#if defined(__linux__) || defined(__OpenBSD__) || defined(__FreeBSD__) activecpu = (uint32_t)sysconf(_SC_NPROCESSORS_ONLN); -#if defined(__linux__) && __USE_GNU +#if defined(__FreeBSD__) || (defined(__linux__) && __USE_GNU) cpu_set_t cpuset; if (pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t),