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

[libvirt] [PATCH] BSD: implement nodeGetCPUStats



Implementation obtains CPU usage information using
kern.cp_time and kern.cp_times sysctl(8)s and reports
CPU utilization.
---
 src/nodeinfo.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 85 insertions(+)

diff --git a/src/nodeinfo.c b/src/nodeinfo.c
index 05bc038..b837500 100644
--- a/src/nodeinfo.c
+++ b/src/nodeinfo.c
@@ -36,6 +36,7 @@
 #if defined(__FreeBSD__) || defined(__APPLE__)
 # include <sys/types.h>
 # include <sys/sysctl.h>
+# include <sys/resource.h>
 #endif
 
 #include "c-ctype.h"
@@ -99,9 +100,91 @@ appleFreebsdNodeGetMemorySize(unsigned long *memory)
 #endif /* defined(__FreeBSD__) || defined(__APPLE__) */
 
 #ifdef __FreeBSD__
+# define BSD_CPU_STATS_ALL 1
 # define BSD_MEMORY_STATS_ALL 4
 
 static int
+freebsdNodeGetCPUStats(int cpuNum,
+                       virNodeCPUStatsPtr params,
+                       int *nparams)
+{
+    char *sysctl_name = NULL;
+    long *cpu_times, total = 0;
+    size_t i, cpu_times_size;
+    int cpu_times_num, offset;
+    int ret = -1;
+    double utilization = 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;
+    }
+
+    if (cpuNum == VIR_NODE_CPU_STATS_ALL_CPUS) {
+        if (VIR_STRDUP(sysctl_name, "kern.cp_time") < 0)
+            return -1;
+        cpu_times_num = 1;
+        offset = 0;
+    } else {
+        cpu_times_num = appleFreebsdNodeGetCPUCount();
+
+        if (cpuNum >= cpu_times_num) {
+            virReportInvalidArg(cpuNum,
+                                _("Invalid cpuNum in %s"),
+                                __FUNCTION__);
+            return -1;
+        }
+
+        offset = cpu_times_num * CPUSTATES;
+
+        if (VIR_STRDUP(sysctl_name, "kern.cp_times") < 0)
+            return -1;
+    }
+
+    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; i < CPUSTATES; ++i)
+        total += cpu_times[offset + i];
+
+    utilization = 100 * (1.0 - (double)cpu_times[offset + CP_IDLE] / total);
+
+    virNodeCPUStatsPtr param = &params[0];
+
+    if (virStrcpyStatic(param->field, VIR_NODE_CPU_STATS_UTILIZATION) == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Field '%s' too long for destination"),
+                       VIR_NODE_CPU_STATS_UTILIZATION);
+        goto cleanup;
+    }
+
+    param->value = utilization;
+    ret = 0;
+
+cleanup:
+    VIR_FREE(sysctl_name);
+    VIR_FREE(cpu_times);
+
+    return ret;
+}
+
+static int
 freebsdNodeGetMemoryStats(virNodeMemoryStatsPtr params,
                                int *nparams)
 {
@@ -1066,6 +1149,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"));
-- 
1.8.4.3


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