diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7e4be4183..5dce67822 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -174,7 +174,7 @@ if(OS_SOLARIS)
endif(OS_SOLARIS)
if(OS_NETBSD)
- set(netbsd netbsd.cc netbsd.h)
+ set(netbsd netbsd.cc netbsd.h bsdcommon.cc bsdcommon.h)
set(optional_sources ${optional_sources} ${netbsd})
endif(OS_NETBSD)
diff --git a/src/bsdcommon.cc b/src/bsdcommon.cc
new file mode 100644
index 000000000..9b9f92bd3
--- /dev/null
+++ b/src/bsdcommon.cc
@@ -0,0 +1,163 @@
+/*
+ *
+ * Conky, a system monitor, based on torsmo
+ *
+ * Please see COPYING for details
+ *
+ * Copyright (c) 2005-2024 Brenden Matthews, Philip Kovacs, et. al.
+ * (see AUTHORS)
+ * All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#include "bsdcommon.h"
+#include "logging.h"
+
+#include
+
+#include
+
+static kvm_t *kd = nullptr;
+static bool kvm_initialised = false;
+static bool cpu_initialised = false;
+
+static struct bsdcommon::cpu_load *cpu_loads = nullptr;
+
+bool bsdcommon::init_kvm() {
+ if (kvm_initialised) {
+ return true;
+ }
+
+ kd = kvm_open(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr);
+ if (kd == nullptr) {
+ NORM_ERR("opening kvm");
+ return false;
+ }
+
+ kvm_initialised = true;
+ return false;
+}
+
+void bsdcommon::deinit_kvm() {
+ if (!kvm_initialised || kd == nullptr) {
+ return;
+ }
+
+ kvm_close(kd);
+}
+
+void bsdcommon::get_cpu_count(float **cpu_usage, unsigned int *cpu_count) {
+ int ncpu = 1;
+ int mib[2] = {CTL_HW, HW_NCPU};
+ size_t len = sizeof(ncpu);
+
+ if (sysctl(mib, 2, &ncpu, &len, nullptr, 0) != 0) {
+ NORM_ERR("error getting kern.ncpu, defaulting to 1");
+ ncpu = 1;
+ }
+
+ if (*cpu_count != ncpu) {
+ *cpu_count = ncpu;
+
+ if (*cpu_usage != nullptr) {
+ free(*cpu_usage);
+ *cpu_usage = nullptr;
+ }
+
+ if (cpu_loads != nullptr) {
+ free(cpu_loads);
+ cpu_loads = nullptr;
+ }
+ }
+
+ if (*cpu_usage == nullptr) {
+ // [0] - Total CPU
+ // [1, 2, ... ] - CPU1, CPU2, ...
+ *cpu_usage = (float*)calloc(ncpu + 1, sizeof(float));
+ if (*cpu_usage == nullptr) {
+ CRIT_ERR("calloc of cpu_usage");
+ }
+ }
+
+ if (cpu_loads == nullptr) {
+ cpu_loads = (struct cpu_load*)calloc(ncpu + 1, sizeof(struct cpu_load));
+ if (cpu_loads == nullptr) {
+ CRIT_ERR("calloc of cpu_loads");
+ }
+ }
+}
+
+void bsdcommon::update_cpu_usage(float **cpu_usage, unsigned int *cpu_count) {
+ uint64_t cp_time0[CPUSTATES];
+ int mib_cpu0[2] = {CTL_KERN, KERN_CP_TIME};
+ uint64_t cp_timen[CPUSTATES];
+ int mib_cpun[3] = {CTL_KERN, KERN_CP_TIME, 0};
+ size_t size = 0;
+ u_int64_t used = 0, total = 0;
+
+ if (!cpu_initialised) {
+ get_cpu_count(cpu_usage, cpu_count);
+ cpu_initialised = true;
+ }
+
+ size = sizeof(cp_time0);
+ if (sysctl(mib_cpu0, 2, &cp_time0, &size, nullptr, 0) != 0) {
+ NORM_ERR("unable to get kern.cp_time for cpu0");
+ return;
+ }
+
+ for (int j = 0; j < CPUSTATES; ++j) {
+ total += cp_time0[j];
+ }
+ used = total - cp_time0[CP_IDLE];
+
+ if ((total - cpu_loads[0].old_total) != 0) {
+ const float diff_used = (float)(used - cpu_loads[0].old_used);
+ const float diff_total = (float)(total - cpu_loads[0].old_total);
+ (*cpu_usage)[0] = diff_used / diff_total;
+ } else {
+ (*cpu_usage)[0] = 0;
+ }
+ cpu_loads[0].old_used = used;
+ cpu_loads[0].old_total = total;
+
+ for (int i = 0; i < *cpu_count; ++i) {
+ mib_cpun[2] = i;
+ size = sizeof(cp_timen);
+ if (sysctl(mib_cpun, 3, &cp_timen, &size, nullptr, 0) != 0) {
+ NORM_ERR("unable to get kern.cp_time for cpu%d", i);
+ return;
+ }
+
+ total = 0;
+ used = 0;
+ for (int j = 0; j < CPUSTATES; ++j) {
+ total += cp_timen[j];
+ }
+ used = total - cp_timen[CP_IDLE];
+
+ const int n = i + 1; // [0] is the total CPU, must shift by 1
+ if ((total - cpu_loads[n].old_total) != 0) {
+ const float diff_used = (float)(used - cpu_loads[n].old_used);
+ const float diff_total = (float)(total - cpu_loads[n].old_total);
+ (*cpu_usage)[n] = diff_used / diff_total;
+ } else {
+ (*cpu_usage)[n] = 0;
+ }
+
+ cpu_loads[n].old_used = used;
+ cpu_loads[n].old_total = total;
+ }
+}
diff --git a/src/bsdcommon.h b/src/bsdcommon.h
new file mode 100644
index 000000000..9b8ee824c
--- /dev/null
+++ b/src/bsdcommon.h
@@ -0,0 +1,49 @@
+/*
+ *
+ * Conky, a system monitor, based on torsmo
+ *
+ * Please see COPYING for details
+ *
+ * Copyright (c) 2005-2024 Brenden Matthews, Philip Kovacs, et. al.
+ * (see AUTHORS)
+ * All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+/*
+ * Shared or very similar code across BSDs.
+ */
+
+#ifndef BSDCOMMON_H_
+#define BSDCOMMON_H_
+
+#define BSD_COMMON
+
+#include
+
+namespace bsdcommon {
+ struct cpu_load {
+ uint64_t old_used;
+ uint64_t old_total;
+ };
+
+ bool init_kvm();
+ void deinit_kvm();
+
+ void get_cpu_count(float **cpu_usage, unsigned int *cpu_count);
+ void update_cpu_usage(float **cpu_usage, unsigned int *cpu_count);
+};
+
+#endif /*BSDCOMMON_H_*/
diff --git a/src/main.cc b/src/main.cc
index 2b0bf4e6e..c83ab8c60 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -52,6 +52,10 @@
#include "freebsd.h"
#endif /* FreeBSD */
+#if defined(__NetBSD__)
+#include "netbsd.h"
+#endif /* NetBSD */
+
#if defined(__HAIKU__)
#include "haiku.h"
#endif /* Haiku */
@@ -411,6 +415,11 @@ int main(int argc, char **argv) {
conky::shutdown_display_outputs();
+#ifdef BSD_COMMON
+ bsdcommon::deinit_kvm();
+#endif
+
+//TODO(gmb): Move this to bsdcommon and remove external kd.
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
kvm_close(kd);
#endif
diff --git a/src/netbsd.cc b/src/netbsd.cc
index 793c9d633..618ea8c2b 100644
--- a/src/netbsd.cc
+++ b/src/netbsd.cc
@@ -29,6 +29,7 @@
#include "netbsd.h"
#include "net_stat.h"
+#include "bsdcommon.h"
#include
#include
@@ -53,23 +54,10 @@
#include
#include
-static kvm_t *kd = nullptr;
-static int kd_init = 0, nkd_init = 0, cpu_setup = 0;
+static int nkd_init = 0;
static u_int32_t sensvalue;
static char errbuf[_POSIX2_LINE_MAX];
-static int init_kvm(void) {
- if (kd_init) { return 0; }
-
- kd = kvm_openfiles(nullptr, NULL, NULL, KVM_NO_FILES, errbuf);
- if (kd == nullptr) {
- NORM_ERR("cannot kvm_openfiles: %s", errbuf);
- return -1;
- }
- kd_init = 1;
- return 0;
-}
-
static int swapmode(int *retavail, int *retfree) {
int n;
struct swapent *sep;
@@ -243,6 +231,8 @@ int update_net_stats() {
int update_total_processes() {
/* It's easier to use kvm here than sysctl */
+// TODO(gmb): Use bsdcommon.
+/*
int n_processes;
info.procs = 0;
@@ -255,10 +245,14 @@ int update_total_processes() {
}
info.procs = n_processes;
+*/
return 1;
}
int update_running_processes() {
+
+// TODO(gmb): Use bsdcommon.
+/*
struct kinfo_proc2 *p;
int n_processes;
int i, cnt = 0;
@@ -279,56 +273,16 @@ int update_running_processes() {
}
info.run_procs = cnt;
-
+*/
return 1;
}
-struct cpu_load_struct {
- unsigned long load[5];
-};
-
-struct cpu_load_struct fresh = {{0, 0, 0, 0, 0}};
-
-long cpu_used, oldtotal, oldused;
-
-// TODO(gmb): Implement support for multiple processors.
void get_cpu_count(void) {
- int cpu_count = 1;
- info.cpu_count = cpu_count;
- info.cpu_usage = (float *)malloc((info.cpu_count + 1) * sizeof(float));
- if (info.cpu_usage == nullptr) { CRIT_ERR("malloc"); }
+ bsdcommon::get_cpu_count(&info.cpu_usage, &info.cpu_count);
}
-// TODO(gmb): Implement support for multiple processors.
int update_cpu_usage() {
- long used, total;
- static u_int64_t cp_time[CPUSTATES];
- size_t len = sizeof(cp_time);
-
- info.cpu_usage[0] = 0;
-
- if (sysctlbyname("kern.cp_time", &cp_time, &len, nullptr, 0) < 0) {
- NORM_ERR("cannot get kern.cp_time");
- return 1;
- }
-
- fresh.load[0] = cp_time[CP_USER];
- fresh.load[1] = cp_time[CP_NICE];
- fresh.load[2] = cp_time[CP_SYS];
- fresh.load[3] = cp_time[CP_IDLE];
- fresh.load[4] = cp_time[CP_IDLE];
-
- used = fresh.load[0] + fresh.load[1] + fresh.load[2];
- total = fresh.load[0] + fresh.load[1] + fresh.load[2] + fresh.load[3];
-
- if ((total - oldtotal) != 0) {
- info.cpu_usage[0] = ((float)(used - oldused)) / (float)(total - oldtotal);
- } else {
- info.cpu_usage[0] = 0;
- }
-
- oldused = used;
- oldtotal = total;
+ bsdcommon::update_cpu_usage(&info.cpu_usage, &info.cpu_count);
return 1;
}
diff --git a/src/netbsd.h b/src/netbsd.h
index 40177e131..62be0fc40 100644
--- a/src/netbsd.h
+++ b/src/netbsd.h
@@ -15,6 +15,8 @@
#include "common.h"
#include "conky.h"
+#include "bsdcommon.h"
+
int get_entropy_avail(unsigned int *);
int get_entropy_poolsize(unsigned int *);