[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCHv3 6/6] virNodeGetCPUTime: Implement linux support



virNodeGetCPUTime: Implement linux support

Signed-off-by: Minoru Usui <usui mxm nes nec co jp>
---
 src/libvirt_private.syms |    1 +
 src/nodeinfo.c           |   78 ++++++++++++++++++++++++++++++++++++++++++++++
 src/nodeinfo.h           |    5 ++-
 3 files changed, 83 insertions(+), 1 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 54e4482..70d4a61 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..06bb4f9 100644
--- a/src/nodeinfo.c
+++ b/src/nodeinfo.c
@@ -57,12 +57,16 @@
 #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, unsigned long long *stats,
+                     unsigned int nr_stats ATTRIBUTE_UNUSED, unsigned int flags);
+
 /* 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 +326,53 @@ int linuxNodeInfoCPUPopulate(FILE *cpuinfo,
     return 0;
 }
 
+#define TICK_TO_NSEC (1000ull * 1000ull * 1000ull / sysconf(_SC_CLK_TCK))
+
+int linuxNodeCpuTime(FILE *procstat, unsigned long long *stats,
+                     unsigned int nr_stats ATTRIBUTE_UNUSED, unsigned int flags)
+{
+    char line[1024];
+    unsigned long long usr, ni, sys, idle, iowait;
+    unsigned long long irq, softirq, steal, guest, guest_nice;
+
+    if (flags & VIR_NODE_CPU_TIME_UTILIZATION) {
+        nodeReportError(VIR_ERR_INVALID_ARG, "%s",
+                        _("VIR_NODE_CPU_TIME_UTILIZATOIN not supported on this platform."));
+        return -1;
+    }
+
+    while (fgets(line, sizeof(line), procstat) != NULL) {
+        char *buf = line;
+        int idx = 0;
+
+        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) {
+                continue;
+            }
+
+            if (VIR_NODE_CPU_TIME_KERNEL)
+                stats[idx++] = (sys + irq + softirq) * TICK_TO_NSEC;
+
+            if (VIR_NODE_CPU_TIME_USER)
+                stats[idx++] = (usr + ni)            * TICK_TO_NSEC;
+
+            if (VIR_NODE_CPU_TIME_IDLE)
+                stats[idx++] = idle                  * TICK_TO_NSEC;
+
+            if (VIR_NODE_CPU_TIME_IOWAIT)
+                stats[idx++] = iowait                * TICK_TO_NSEC;
+
+            return idx;
+        }
+    }
+
+    nodeReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no \'cpu \' line found"));
+    return -1;
+}
 #endif
 
 int nodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, virNodeInfoPtr nodeinfo) {
@@ -360,6 +411,33 @@ int nodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, virNodeInfoPtr nodeinfo) {
 #endif
 }
 
+int nodeGetCpuTime(virConnectPtr conn ATTRIBUTE_UNUSED,
+                   unsigned long long *stats,
+                   unsigned int nr_stats,
+                   unsigned int flags)
+{
+
+#ifdef __linux__
+    {
+    int ret;
+    FILE *procstat = fopen(PROCSTAT_PATH, "r");
+    if (!procstat) {
+        virReportSystemError(errno,
+                             _("cannot open %s"), PROCSTAT_PATH);
+        return -1;
+    }
+    ret = linuxNodeCpuTime(procstat, stats, nr_stats, flags);
+    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..6489cca 100644
--- a/src/nodeinfo.h
+++ b/src/nodeinfo.h
@@ -30,7 +30,10 @@
 int nodeGetInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo);
 int nodeCapsInitNUMA(virCapsPtr caps);
 
-
+int nodeGetCpuTime(virConnectPtr conn ATTRIBUTE_UNUSED,
+                   unsigned long long *stats,
+                   unsigned int nr_stats,
+                   unsigned int flags);
 int nodeGetCellsFreeMemory(virConnectPtr conn,
                            unsigned long long *freeMems,
                            int startCell,
-- 
1.7.1

-- 
Minoru Usui <usui mxm nes nec co jp>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]