virNodeGetCpuTime: Implement linux support
---
src/libvirt_private.syms | 1 +
src/nodeinfo.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++
src/nodeinfo.h | 2 +-
3 files changed, 62 insertions(+), 1 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 65a86d3..b879454 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -651,6 +651,7 @@ virNodeDeviceObjUnlock;
# nodeinfo.h
nodeCapsInitNUMA;
+nodeGetCpuTime;
nodeGetCellsFreeMemory;
nodeGetFreeMemory;
nodeGetInfo;
diff --git a/src/nodeinfo.c b/src/nodeinfo.c
index 5d40aca..81222ec 100644
--- a/src/nodeinfo.c
+++ b/src/nodeinfo.c
@@ -57,12 +57,15 @@
#ifdef __linux__
# define CPUINFO_PATH "/proc/cpuinfo"
# define CPU_SYS_PATH "/sys/devices/system/cpu"
+# define PROCSTAT_PATH "/proc/stat"
/* NB, this is not static as we need to call it from the testsuite */
int linuxNodeInfoCPUPopulate(FILE *cpuinfo,
virNodeInfoPtr nodeinfo,
bool need_hyperthreads);
+int linuxNodeCpuTime(FILE *procstat, virNodeCpuTimePtr cpu_time);
+
/* Return the positive decimal contents of the given
* CPU_SYS_PATH/cpu%u/FILE, or -1 on error. If MISSING_OK and the
* file could not be found, return 1 instead of an error; this is
@@ -322,6 +325,38 @@ int linuxNodeInfoCPUPopulate(FILE *cpuinfo,
return 0;
}
+#define TICK_TO_NSEC (1000ull * 1000ull * 1000ull / sysconf(_SC_CLK_TCK))
+
+int linuxNodeCpuTime(FILE *procstat, virNodeCpuTimePtr cpu_time)
+{
+ char line[1024];
+ unsigned long long usr, ni, sys, idle, iowait;
+ unsigned long long irq, softirq, steal, guest, guest_nice;;
+
+ memset(cpu_time, 0, sizeof(*cpu_time));
+ while (fgets(line, sizeof(line), procstat) != NULL) {
+ char *buf = line;
+
+ if (STRPREFIX(buf, "cpu ")) { /* aka total logical CPU time */
+ if (sscanf(buf,
+ "%*s %llu %llu %llu %llu %llu" // user ~ iowait
+ "%llu %llu %llu %llu %llu", // irq ~ guest_nice
+ &usr, &ni, &sys, &idle, &iowait,
+ &irq, &softirq, &steal, &guest, &guest_nice)
< 4) {
+ return -1;
+ }
+ cpu_time->user = (usr + ni) * TICK_TO_NSEC;
+ cpu_time->system = (sys + irq + softirq) * TICK_TO_NSEC;
+ cpu_time->idle = idle * TICK_TO_NSEC;
+ cpu_time->iowait = iowait * TICK_TO_NSEC;
+
+ return 0;
+ }
+ }
+
+ nodeReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no \'cpu\'
line found"));
+ return -1;
+}
#endif
int nodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, virNodeInfoPtr nodeinfo) {
@@ -360,6 +395,31 @@ int nodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, virNodeInfoPtr
nodeinfo) {
#endif
}
+int nodeGetCpuTime(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virNodeCpuTimePtr cpu_time)
+{
+
+#ifdef __linux__
+ {
+ int ret;
+ FILE *procstat = fopen(PROCSTAT_PATH, "r");
+ if (!procstat) {
+ virReportSystemError(errno,
+ _("cannot open %s"), PROCSTAT_PATH);
+ return -1;
+ }
+ ret = linuxNodeCpuTime(procstat, cpu_time);
+ VIR_FORCE_FCLOSE(procstat);
+
+ return ret;
+ }
+#else
+ nodeReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("node CPU time not implemented on this platform"));
+ return -1;
+#endif
+}
+
#if HAVE_NUMACTL
# if LIBNUMA_API_VERSION <= 1
# define NUMA_MAX_N_CPUS 4096
diff --git a/src/nodeinfo.h b/src/nodeinfo.h
index 88bac6c..106e9c1 100644
--- a/src/nodeinfo.h
+++ b/src/nodeinfo.h
@@ -30,7 +30,7 @@
int nodeGetInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo);
int nodeCapsInitNUMA(virCapsPtr caps);
-
+int nodeGetCpuTime(virConnectPtr conn, virNodeCpuTimePtr cpu_time);
int nodeGetCellsFreeMemory(virConnectPtr conn,
unsigned long long *freeMems,
int startCell,
--
1.7.1
--
Minoru Usui <usui(a)mxm.nes.nec.co.jp>