*/
#define VIR_DOMAIN_CPU_STATS_CPUTIME "cpu_time"
+/**
+ * VIR_DOMAIN_CPU_STATS_USERTIME:
+ * cpu time charged to user instructions in nanoseconds, as a ullong
+ */
+#define VIR_DOMAIN_CPU_STATS_USERTIME "user_time"
+
+/**
+ * VIR_DOMAIN_CPU_STATS_SYSTEMTIME:
+ * cpu time charged to system instructions in nanoseconds, as a ullong
+ */
+#define VIR_DOMAIN_CPU_STATS_SYSTEMTIME "system_time"
+
int virDomainGetCPUStats(virDomainPtr domain,
virTypedParameterPtr params,
unsigned int nparams,
#define QEMU_NB_NUMA_PARAM 2
+#define QEMU_NB_TOTAL_CPU_STAT_PARAM 3
+#define QEMU_NB_PER_CPU_STAT_PARAM 1
+
#if HAVE_LINUX_KVM_H
# include <linux/kvm.h>
#endif
int nparams)
{
unsigned long long cpu_time;
- int param_idx = 0;
int ret;
if (nparams == 0) /* return supported number of params */
- return 1;
+ return QEMU_NB_TOTAL_CPU_STAT_PARAM;
/* entry 0 is cputime */
ret = virCgroupGetCpuacctUsage(group, &cpu_time);
if (ret < 0) {
return -1;
}
- virTypedParameterAssign(¶ms[param_idx], VIR_DOMAIN_CPU_STATS_CPUTIME,
- VIR_TYPED_PARAM_ULLONG, cpu_time);
- return 1;
+ if (virTypedParameterAssign(¶ms[0], VIR_DOMAIN_CPU_STATS_CPUTIME,
+ VIR_TYPED_PARAM_ULLONG, cpu_time) < 0)
+ return -1;
+
+ if (nparams > 1) {
+ unsigned long long user;
+ unsigned long long sys;
+
+ ret = virCgroupGetCpuacctStat(group, &user, &sys);
+ if (ret < 0) {
+ virReportSystemError(-ret, "%s", _("unable to get cpu account"));
+ return -1;
+ }
+
+ if (virTypedParameterAssign(¶ms[1],
+ VIR_DOMAIN_CPU_STATS_USERTIME,
+ VIR_TYPED_PARAM_ULLONG, user) < 0)
+ return -1;
+ if (nparams > 2 &&
+ virTypedParameterAssign(¶ms[2],
+ VIR_DOMAIN_CPU_STATS_SYSTEMTIME,
+ VIR_TYPED_PARAM_ULLONG, sys) < 0)
+ return -1;
+
+ if (nparams > QEMU_NB_TOTAL_CPU_STAT_PARAM)
+ nparams = QEMU_NB_TOTAL_CPU_STAT_PARAM;
+ }
+
+ return nparams;
}
static int
/* return the number of supported params */
if (nparams == 0 && ncpus != 0)
- return 1; /* only cpu_time is supported */
+ return QEMU_NB_PER_CPU_STAT_PARAM; /* only cpu_time is supported */
/* return percpu cputime in index 0 */
param_idx = 0;
if (i < start_cpu)
continue;
ent = ¶ms[ (i - start_cpu) * nparams + param_idx];
- virTypedParameterAssign(ent, VIR_DOMAIN_CPU_STATS_CPUTIME,
- VIR_TYPED_PARAM_ULLONG, cpu_time);
+ if (virTypedParameterAssign(ent, VIR_DOMAIN_CPU_STATS_CPUTIME,
+ VIR_TYPED_PARAM_ULLONG, cpu_time) < 0)
+ goto cleanup;
}
rv = param_idx + 1;
cleanup:
int virTypedParameterArrayValidate(virTypedParameterPtr params, int nparams,
/* const char *name, int type ... */ ...)
- ATTRIBUTE_SENTINEL;
+ ATTRIBUTE_SENTINEL ATTRIBUTE_RETURN_CHECK;
int virTypedParameterAssign(virTypedParameterPtr param, const char *name,
- int type, /* TYPE arg */ ...);
+ int type, /* TYPE arg */ ...)
+ ATTRIBUTE_RETURN_CHECK;
#endif /* __VIR_TYPED_PARAM_H */
for (j = 0; j < nparams; j++) {
pos = i * nparams + j;
- vshPrint(ctl, "\t%-10s ", params[pos].field);
+ vshPrint(ctl, "\t%-12s ", params[pos].field);
if (STREQ(params[pos].field, VIR_DOMAIN_CPU_STATS_CPUTIME) &&
params[j].type == VIR_TYPED_PARAM_ULLONG) {
- vshPrint(ctl, "%lld.%09lld seconds\n",
+ vshPrint(ctl, "%9lld.%09lld seconds\n",
params[pos].value.ul / 1000000000,
params[pos].value.ul % 1000000000);
} else {
vshPrint(ctl, _("Total:\n"));
for (i = 0; i < nparams; i++) {
- vshPrint(ctl, "\t%-10s ", params[i].field);
- if (STREQ(params[i].field, VIR_DOMAIN_CPU_STATS_CPUTIME) &&
+ vshPrint(ctl, "\t%-12s ", params[i].field);
+ if ((STREQ(params[i].field, VIR_DOMAIN_CPU_STATS_CPUTIME) ||
+ STREQ(params[i].field, VIR_DOMAIN_CPU_STATS_USERTIME) ||
+ STREQ(params[i].field, VIR_DOMAIN_CPU_STATS_SYSTEMTIME)) &&
params[i].type == VIR_TYPED_PARAM_ULLONG) {
- vshPrint(ctl, "%llu.%09llu seconds\n",
+ vshPrint(ctl, "%9lld.%09lld seconds\n",
params[i].value.ul / 1000000000,
params[i].value.ul % 1000000000);
} else {