1
0
mirror of https://github.com/Llewellynvdm/conky.git synced 2025-01-29 01:58:26 +00:00

NetBSD: Fix CPU Usage.

Report the correct number of CPUs and calculate the per-CPU load.

Start implementing a common BSD interface, as all BSD implementations use
*slightly* different functions to achieve the same goal,
and maintaining them in one place would be easier.

Fixes #2097.
This commit is contained in:
Toth Janos 2024-12-05 13:16:04 +01:00 committed by Tóth János
parent d0247218a8
commit e9f343ffee
6 changed files with 235 additions and 58 deletions

View File

@ -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)

163
src/bsdcommon.cc Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*
*/
#include "bsdcommon.h"
#include "logging.h"
#include <kvm.h>
#include <sys/sysctl.h>
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;
}
}

49
src/bsdcommon.h Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*
*/
/*
* Shared or very similar code across BSDs.
*/
#ifndef BSDCOMMON_H_
#define BSDCOMMON_H_
#define BSD_COMMON
#include <stdint.h>
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_*/

View File

@ -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

View File

@ -29,6 +29,7 @@
#include "netbsd.h"
#include "net_stat.h"
#include "bsdcommon.h"
#include <err.h>
#include <fcntl.h>
@ -53,23 +54,10 @@
#include <net/if.h>
#include <net/if_types.h>
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;
}

View File

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