Hi,
I was bothered long enough by the
"OS_MON (cpu_sup), util/1 unavailable for this OS"
message when testing erlang builds on OpenBSD and decided to have a shot
at an implementation.
I tried to keep it structurally very similar to the already available
FreeBSD implementation (which looks to me like it's leaking memory,
though), and filled the gaps with what I understood from OpenBSD's
top(1) implementation.
Tests pass, and interactive use of cpu_sup:util/0 and cpu_sup:util/1
produces reasonable results here, both with and without SMP enabled.
It would be great if some of you could have a look if what I came up
with makes sense.
cheers,
Volker
Index: Makefile
===================================================================
RCS file: /cvs/ports/lang/erlang/25/Makefile,v
retrieving revision 1.15
diff -u -p -r1.15 Makefile
--- Makefile 8 Mar 2023 07:54:04 -0000 1.15
+++ Makefile 27 Mar 2023 20:36:55 -0000
@@ -10,6 +10,7 @@ PKGNAME= erlang-$V
PKGNAME-main= erlang-$V
PKGNAME-wx= erlang-wx-$V
EPOCH= 0
+REVISION= 0
VERSION_SPEC= >=25v0,<26v0
PKGSPEC-main= erlang-${VERSION_SPEC}
Index: patches/patch-lib_os_mon_c_src_cpu_sup_c
===================================================================
RCS file: patches/patch-lib_os_mon_c_src_cpu_sup_c
diff -N patches/patch-lib_os_mon_c_src_cpu_sup_c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-lib_os_mon_c_src_cpu_sup_c 27 Mar 2023 20:36:55 -0000
@@ -0,0 +1,131 @@
+Index: lib/os_mon/c_src/cpu_sup.c
+--- lib/os_mon/c_src/cpu_sup.c.orig
++++ lib/os_mon/c_src/cpu_sup.c
+@@ -87,6 +87,11 @@ typedef struct {
+ #define CU_BSD_VALUES (6)
+ #endif
+
++#if defined(__OpenBSD__)
++#include <sys/types.h>
++#include <sys/sched.h>
++#define CU_OPENBSD_VALUES (6)
++#endif
+
+ #define FD_IN (0)
+ #define FD_OUT (1)
+@@ -178,12 +183,17 @@ static int processors_online() {
+ void getsysctl(const char *, void *, size_t);
+ #endif
+
++#if defined(__OpenBSD__)
++static int getncpu(void);
++static int getncpuonline(void);
++#endif
++
+ int main(int argc, char** argv) {
+ char cmd;
+ int rc;
+ int sz;
+ unsigned int *rv;
+-#if defined(__linux__) || (defined(__APPLE__) && defined(__MACH__)) ||defined(__FreeBSD__)
++#if defined(__linux__) || (defined(__APPLE__) && defined(__MACH__)) ||defined(__FreeBSD__) ||defined(__OpenBSD__)
+ unsigned int no_of_cpus = 0;
+ #endif
+
+@@ -207,6 +217,15 @@ int main(int argc, char** argv) {
+ }
+ #endif
+
++#if defined(__OpenBSD__)
++ no_of_cpus = getncpu();
++ if ( no_of_cpus == -1 )
++ error("cpu_sup: sysctl error");
++
++ if ( (rv = (unsigned int*)malloc(sizeof(unsigned int)*(2 + 2*no_of_cpus*CU_OPENBSD_VALUES))) == NULL)
++ error("cpu_sup: malloc error");
++#endif
++
+ #if defined(__FreeBSD__)
+ getsysctl("hw.ncpu", &no_of_cpus, sizeof(int));
+ if ( (rv = (unsigned int*)malloc(sizeof(unsigned int)*(2 + 2*no_of_cpus*CU_BSD_VALUES))) == NULL) {
+@@ -244,7 +263,7 @@ int main(int argc, char** argv) {
+ case AVG5: bsd_loadavg(1); break;
+ case AVG15: bsd_loadavg(2); break;
+ #endif
+-#if defined(__sun__) || defined(__linux__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__)
++#if defined(__sun__) || defined(__linux__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__) || defined(__OpenBSD__)
+ case UTIL: util_measure(&rv,&sz); sendv(rv, sz); break;
+ #endif
+ case QUIT: free((void*)rv); return 0;
+@@ -709,6 +728,71 @@ static void util_measure(unsigned int **result_vec, in
+ }
+
+ *result_sz = 2 + 2*CU_BSD_VALUES * no_of_cpus;
++}
++#endif
++
++/* ---------------------------- *
++ * OpenBSD stat functions *
++ * ---------------------------- */
++
++#if defined(__OpenBSD__)
++static int getncpu(void) {
++ const int mib[] = { CTL_HW, HW_NCPU };
++ int numcpu;
++ size_t size = sizeof(numcpu);
++
++ if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &numcpu, &size, NULL, 0) == -1)
++ error("cpu_sup: sysctl error");
++
++ return(numcpu);
++}
++
++static int getncpuonline(void) {
++ const int mib[] = { CTL_HW, HW_NCPUONLINE };
++ int numcpu;
++ size_t size = sizeof(numcpu);
++
++ if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &numcpu, &size, NULL, 0) == -1)
++ error("cpu_sup: sysctl error");
++
++ return(numcpu);
++}
++
++static void util_measure(unsigned int **result_vec, int *result_sz) {
++ static int mib[] = { CTL_KERN, KERN_CPTIME2, 0 };
++ size_t size_cpu_times;
++ int64_t *cpu_times;
++ unsigned int *rv = NULL;
++ int i;
++ int ncpuonline = getncpuonline();
++
++ size_cpu_times = sizeof(int64_t) * CPUSTATES;
++ cpu_times = malloc(size_cpu_times);
++ if (!cpu_times)
++ error("cpu_sup: malloc error");
++
++ rv = *result_vec;
++ rv[0] = ncpuonline;
++ rv[1] = CU_OPENBSD_VALUES;
++ ++rv; /* first value is number of cpus */
++ ++rv; /* second value is number of entries */
++
++ for (i = 0; i < ncpuonline; ++i) {
++ mib[2] = i;
++ if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), cpu_times, &size_cpu_times, NULL, 0) == -1)
++ error("cpu_sup: sysctl error");
++
++ rv[ 0] = CU_CPU_ID; rv[ 1] = i;
++ rv[ 2] = CU_USER; rv[ 3] = (unsigned int)cpu_times[CP_USER];
++ rv[ 4] = CU_NICE_USER; rv[ 5] = (unsigned int)cpu_times[CP_NICE];
++ rv[ 6] = CU_KERNEL; rv[ 7] = (unsigned int)cpu_times[CP_SYS];
++ rv[ 8] = CU_IDLE; rv[ 9] = (unsigned int)cpu_times[CP_IDLE];
++ rv[10] = CU_HARD_IRQ; rv[11] = (unsigned int)cpu_times[CP_INTR];
++ rv += CU_OPENBSD_VALUES*2;
++ }
++ free((void*) cpu_times);
++
++ *result_sz = 2 + 2*CU_OPENBSD_VALUES * ncpuonline;
+ }
+ #endif
+
Index: patches/patch-lib_os_mon_src_cpu_sup_erl
===================================================================
RCS file: patches/patch-lib_os_mon_src_cpu_sup_erl
diff -N patches/patch-lib_os_mon_src_cpu_sup_erl
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-lib_os_mon_src_cpu_sup_erl 27 Mar 2023 20:36:55 -0000
@@ -0,0 +1,11 @@
+Index: lib/os_mon/src/cpu_sup.erl
+--- lib/os_mon/src/cpu_sup.erl.orig
++++ lib/os_mon/src/cpu_sup.erl
+@@ -163,6 +163,7 @@ handle_call({?util, D, PC}, {Client, _Tag},
+ when Flavor == sunos;
+ Flavor == linux;
+ Flavor == freebsd;
++ Flavor == openbsd;
+ Flavor == darwin ->
+ case measurement_server_call(State#state.server, {?util, D, PC, Client}) of
+ {error, Reason} ->
Index: patches/patch-lib_os_mon_test_cpu_sup_SUITE_erl
===================================================================
RCS file: patches/patch-lib_os_mon_test_cpu_sup_SUITE_erl
diff -N patches/patch-lib_os_mon_test_cpu_sup_SUITE_erl
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-lib_os_mon_test_cpu_sup_SUITE_erl 27 Mar 2023 20:36:55 -0000
@@ -0,0 +1,12 @@
+Index: lib/os_mon/test/cpu_sup_SUITE.erl
+--- lib/os_mon/test/cpu_sup_SUITE.erl.orig
++++ lib/os_mon/test/cpu_sup_SUITE.erl
+@@ -61,6 +61,8 @@ all() ->
+ [load_api, util_api, util_values, port, unavailable];
+ {unix, linux} ->
+ [load_api, util_api, util_values, port, unavailable];
++ {unix, openbsd} ->
++ [load_api, util_api, util_values, port, unavailable];
+ {unix, freebsd} ->
+ [load_api, util_api, util_values, port, unavailable];
+ {unix, darwin} ->