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 *);