mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 17:34:18 +03:00
BSD: implement nodeGetCPUStats
Implementation obtains CPU usage information using kern.cp_time and kern.cp_times sysctl(8)s and reports CPU utilization.
This commit is contained in:
parent
05bf937572
commit
3b00df01fb
@ -691,6 +691,14 @@ typedef enum {
|
||||
*/
|
||||
#define VIR_NODE_CPU_STATS_IOWAIT "iowait"
|
||||
|
||||
/**
|
||||
* VIR_NODE_CPU_STATS_INTR:
|
||||
*
|
||||
* The cumulative interrupt CPU time,
|
||||
* since the node booting up (in nanoseconds).
|
||||
*/
|
||||
#define VIR_NODE_CPU_STATS_INTR "intr"
|
||||
|
||||
/**
|
||||
* VIR_NODE_CPU_STATS_UTILIZATION:
|
||||
*
|
||||
|
104
src/nodeinfo.c
104
src/nodeinfo.c
@ -34,8 +34,10 @@
|
||||
#include "conf/domain_conf.h"
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__APPLE__)
|
||||
# include <sys/time.h>
|
||||
# include <sys/types.h>
|
||||
# include <sys/sysctl.h>
|
||||
# include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
#include "c-ctype.h"
|
||||
@ -99,8 +101,108 @@ appleFreebsdNodeGetMemorySize(unsigned long *memory)
|
||||
#endif /* defined(__FreeBSD__) || defined(__APPLE__) */
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
# define BSD_CPU_STATS_ALL 4
|
||||
# define BSD_MEMORY_STATS_ALL 4
|
||||
|
||||
# define TICK_TO_NSEC (1000ull * 1000ull * 1000ull / (stathz ? stathz : hz))
|
||||
|
||||
static int
|
||||
freebsdNodeGetCPUStats(int cpuNum,
|
||||
virNodeCPUStatsPtr params,
|
||||
int *nparams)
|
||||
{
|
||||
const char *sysctl_name;
|
||||
long *cpu_times;
|
||||
struct clockinfo clkinfo;
|
||||
size_t i, j, cpu_times_size, clkinfo_size;
|
||||
int cpu_times_num, offset, hz, stathz, ret = -1;
|
||||
struct field_cpu_map {
|
||||
const char *field;
|
||||
int idx[CPUSTATES];
|
||||
} cpu_map[] = {
|
||||
{VIR_NODE_CPU_STATS_KERNEL, {CP_SYS}},
|
||||
{VIR_NODE_CPU_STATS_USER, {CP_USER, CP_NICE}},
|
||||
{VIR_NODE_CPU_STATS_IDLE, {CP_IDLE}},
|
||||
{VIR_NODE_CPU_STATS_INTR, {CP_INTR}},
|
||||
{NULL, {0}}
|
||||
};
|
||||
|
||||
if ((*nparams) == 0) {
|
||||
*nparams = BSD_CPU_STATS_ALL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((*nparams) != BSD_CPU_STATS_ALL) {
|
||||
virReportInvalidArg(*nparams,
|
||||
_("nparams in %s must be equal to %d"),
|
||||
__FUNCTION__, BSD_CPU_STATS_ALL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
clkinfo_size = sizeof(clkinfo);
|
||||
if (sysctlbyname("kern.clockrate", &clkinfo, &clkinfo_size, NULL, 0) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("sysctl failed for '%s'"),
|
||||
"kern.clockrate");
|
||||
return -1;
|
||||
}
|
||||
|
||||
stathz = clkinfo.stathz;
|
||||
hz = clkinfo.hz;
|
||||
|
||||
if (cpuNum == VIR_NODE_CPU_STATS_ALL_CPUS) {
|
||||
sysctl_name = "kern.cp_time";
|
||||
cpu_times_num = 1;
|
||||
offset = 0;
|
||||
} else {
|
||||
sysctl_name = "kern.cp_times";
|
||||
cpu_times_num = appleFreebsdNodeGetCPUCount();
|
||||
|
||||
if (cpuNum >= cpu_times_num) {
|
||||
virReportInvalidArg(cpuNum,
|
||||
_("Invalid cpuNum in %s"),
|
||||
__FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset = cpu_times_num * CPUSTATES;
|
||||
}
|
||||
|
||||
cpu_times_size = sizeof(long) * cpu_times_num * CPUSTATES;
|
||||
|
||||
if (VIR_ALLOC_N(cpu_times, cpu_times_num * CPUSTATES) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (sysctlbyname(sysctl_name, cpu_times, &cpu_times_size, NULL, 0) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("sysctl failed for '%s'"),
|
||||
sysctl_name);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (i = 0; cpu_map[i].field != NULL; i++) {
|
||||
virNodeCPUStatsPtr param = ¶ms[i];
|
||||
|
||||
if (virStrcpyStatic(param->field, cpu_map[i].field) == NULL) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Field '%s' too long for destination"),
|
||||
cpu_map[i].field);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
param->value = 0;
|
||||
for (j = 0; j < ARRAY_CARDINALITY(cpu_map[i].idx); j++)
|
||||
param->value += cpu_times[offset + cpu_map[i].idx[j]] * TICK_TO_NSEC;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(cpu_times);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
freebsdNodeGetMemoryStats(virNodeMemoryStatsPtr params,
|
||||
int *nparams)
|
||||
@ -1045,6 +1147,8 @@ int nodeGetCPUStats(int cpuNum ATTRIBUTE_UNUSED,
|
||||
|
||||
return ret;
|
||||
}
|
||||
#elif defined(__FreeBSD__)
|
||||
return freebsdNodeGetCPUStats(cpuNum, params, nparams);
|
||||
#else
|
||||
virReportError(VIR_ERR_NO_SUPPORT, "%s",
|
||||
_("node CPU stats not implemented on this platform"));
|
||||
|
@ -347,9 +347,10 @@ cmdNodeCpuStats(vshControl *ctl, const vshCmd *cmd)
|
||||
unsigned long long sys;
|
||||
unsigned long long idle;
|
||||
unsigned long long iowait;
|
||||
unsigned long long intr;
|
||||
unsigned long long util;
|
||||
} cpu_stats[2];
|
||||
double user_time, sys_time, idle_time, iowait_time, total_time;
|
||||
double user_time, sys_time, idle_time, iowait_time, intr_time, total_time;
|
||||
double usage;
|
||||
|
||||
if (vshCommandOptInt(cmd, "cpu", &cpuNum) < 0) {
|
||||
@ -390,6 +391,8 @@ cmdNodeCpuStats(vshControl *ctl, const vshCmd *cmd)
|
||||
cpu_stats[i].idle = value;
|
||||
} else if (STREQ(params[j].field, VIR_NODE_CPU_STATS_IOWAIT)) {
|
||||
cpu_stats[i].iowait = value;
|
||||
} else if (STREQ(params[j].field, VIR_NODE_CPU_STATS_INTR)) {
|
||||
cpu_stats[i].intr = value;
|
||||
} else if (STREQ(params[j].field, VIR_NODE_CPU_STATS_UTILIZATION)) {
|
||||
cpu_stats[i].util = value;
|
||||
flag_utilization = true;
|
||||
@ -406,6 +409,7 @@ cmdNodeCpuStats(vshControl *ctl, const vshCmd *cmd)
|
||||
vshPrint(ctl, "%-15s %20llu\n", _("system:"), cpu_stats[0].sys);
|
||||
vshPrint(ctl, "%-15s %20llu\n", _("idle:"), cpu_stats[0].idle);
|
||||
vshPrint(ctl, "%-15s %20llu\n", _("iowait:"), cpu_stats[0].iowait);
|
||||
vshPrint(ctl, "%-15s %20llu\n", _("intr:"), cpu_stats[0].intr);
|
||||
}
|
||||
} else {
|
||||
if (flag_utilization) {
|
||||
@ -418,7 +422,8 @@ cmdNodeCpuStats(vshControl *ctl, const vshCmd *cmd)
|
||||
sys_time = cpu_stats[1].sys - cpu_stats[0].sys;
|
||||
idle_time = cpu_stats[1].idle - cpu_stats[0].idle;
|
||||
iowait_time = cpu_stats[1].iowait - cpu_stats[0].iowait;
|
||||
total_time = user_time + sys_time + idle_time + iowait_time;
|
||||
intr_time = cpu_stats[1].intr - cpu_stats[0].intr;
|
||||
total_time = user_time + sys_time + idle_time + iowait_time + intr_time;
|
||||
|
||||
usage = (user_time + sys_time) / total_time * 100;
|
||||
|
||||
@ -432,6 +437,8 @@ cmdNodeCpuStats(vshControl *ctl, const vshCmd *cmd)
|
||||
_("idle:"), idle_time / total_time * 100);
|
||||
vshPrint(ctl, "%-15s %5.1lf%%\n",
|
||||
_("iowait:"), iowait_time / total_time * 100);
|
||||
vshPrint(ctl, "%-15s %5.1lf%%\n",
|
||||
_("intr:"), intr_time / total_time * 100);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user