2016-03-28 13:30:28 +00:00
|
|
|
/*
|
|
|
|
* virperf.c: methods for managing perf events
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library. If not, see
|
|
|
|
* <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
|
2020-02-16 21:59:28 +00:00
|
|
|
#include <unistd.h>
|
2020-01-17 12:17:58 +00:00
|
|
|
#ifndef WIN32
|
|
|
|
# include <sys/ioctl.h>
|
|
|
|
#endif
|
2020-09-01 11:27:44 +00:00
|
|
|
#if defined WITH_SYS_SYSCALL_H
|
2016-03-28 13:30:28 +00:00
|
|
|
# include <sys/syscall.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "virperf.h"
|
|
|
|
#include "virerror.h"
|
|
|
|
#include "virlog.h"
|
|
|
|
#include "virfile.h"
|
|
|
|
#include "virstring.h"
|
|
|
|
#include "virtypedparam.h"
|
2019-04-01 14:28:05 +00:00
|
|
|
#include "viralloc.h"
|
2016-03-28 13:30:28 +00:00
|
|
|
|
|
|
|
VIR_LOG_INIT("util.perf");
|
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_PERF
|
|
|
|
|
2019-03-16 18:20:32 +00:00
|
|
|
VIR_ENUM_IMPL(virPerfEvent,
|
|
|
|
VIR_PERF_EVENT_LAST,
|
2016-07-16 08:15:12 +00:00
|
|
|
"cmt", "mbmt", "mbml",
|
|
|
|
"cpu_cycles", "instructions",
|
2016-12-07 10:57:36 +00:00
|
|
|
"cache_references", "cache_misses",
|
2016-12-13 16:01:38 +00:00
|
|
|
"branch_instructions", "branch_misses",
|
2016-12-13 16:01:40 +00:00
|
|
|
"bus_cycles", "stalled_cycles_frontend",
|
2017-02-23 14:55:30 +00:00
|
|
|
"stalled_cycles_backend", "ref_cpu_cycles",
|
2017-02-23 14:55:33 +00:00
|
|
|
"cpu_clock", "task_clock", "page_faults",
|
2017-02-23 14:55:35 +00:00
|
|
|
"context_switches", "cpu_migrations",
|
2017-02-23 14:55:37 +00:00
|
|
|
"page_faults_min", "page_faults_maj",
|
2019-01-20 16:30:15 +00:00
|
|
|
"alignment_faults", "emulation_faults",
|
|
|
|
);
|
2016-03-28 13:30:28 +00:00
|
|
|
|
|
|
|
struct virPerfEvent {
|
|
|
|
int fd;
|
|
|
|
bool enabled;
|
|
|
|
union {
|
|
|
|
/* cmt */
|
|
|
|
struct {
|
|
|
|
int scale;
|
|
|
|
} cmt;
|
|
|
|
} efields;
|
|
|
|
};
|
|
|
|
typedef struct virPerfEvent *virPerfEventPtr;
|
|
|
|
|
2018-07-28 18:01:41 +00:00
|
|
|
struct _virPerf {
|
2016-03-28 13:30:28 +00:00
|
|
|
struct virPerfEvent events[VIR_PERF_EVENT_LAST];
|
|
|
|
};
|
|
|
|
|
2020-09-01 11:27:44 +00:00
|
|
|
#if defined(__linux__) && defined(WITH_SYS_SYSCALL_H)
|
2016-03-28 13:30:28 +00:00
|
|
|
|
|
|
|
# include <linux/perf_event.h>
|
|
|
|
|
2016-08-03 17:23:31 +00:00
|
|
|
struct virPerfEventAttr {
|
|
|
|
unsigned int attrType;
|
|
|
|
unsigned long long attrConfig;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct virPerfEventAttr attrs[] = {
|
2016-12-16 10:54:38 +00:00
|
|
|
[VIR_PERF_EVENT_CMT] = {
|
|
|
|
.attrType = 0,
|
|
|
|
.attrConfig = 1
|
|
|
|
},
|
|
|
|
[VIR_PERF_EVENT_MBMT] = {
|
|
|
|
.attrType = 0,
|
|
|
|
.attrConfig = 2
|
|
|
|
},
|
2017-04-13 12:02:46 +00:00
|
|
|
[VIR_PERF_EVENT_MBML] = {
|
2016-12-16 10:54:38 +00:00
|
|
|
.attrType = 0,
|
|
|
|
.attrConfig = 3
|
|
|
|
},
|
|
|
|
[VIR_PERF_EVENT_CPU_CYCLES] = {
|
|
|
|
.attrType = PERF_TYPE_HARDWARE,
|
|
|
|
.attrConfig = PERF_COUNT_HW_CPU_CYCLES
|
|
|
|
},
|
|
|
|
[VIR_PERF_EVENT_INSTRUCTIONS] = {
|
|
|
|
.attrType = PERF_TYPE_HARDWARE,
|
|
|
|
.attrConfig = PERF_COUNT_HW_INSTRUCTIONS
|
|
|
|
},
|
|
|
|
[VIR_PERF_EVENT_CACHE_REFERENCES] = {
|
|
|
|
.attrType = PERF_TYPE_HARDWARE,
|
|
|
|
.attrConfig = PERF_COUNT_HW_CACHE_REFERENCES
|
|
|
|
},
|
|
|
|
[VIR_PERF_EVENT_CACHE_MISSES] = {
|
|
|
|
.attrType = PERF_TYPE_HARDWARE,
|
|
|
|
.attrConfig = PERF_COUNT_HW_CACHE_MISSES
|
|
|
|
},
|
|
|
|
[VIR_PERF_EVENT_BRANCH_INSTRUCTIONS] = {
|
|
|
|
.attrType = PERF_TYPE_HARDWARE,
|
|
|
|
.attrConfig = PERF_COUNT_HW_BRANCH_INSTRUCTIONS
|
|
|
|
},
|
|
|
|
[VIR_PERF_EVENT_BRANCH_MISSES] = {
|
|
|
|
.attrType = PERF_TYPE_HARDWARE,
|
|
|
|
.attrConfig = PERF_COUNT_HW_BRANCH_MISSES
|
|
|
|
},
|
|
|
|
[VIR_PERF_EVENT_BUS_CYCLES] = {
|
|
|
|
.attrType = PERF_TYPE_HARDWARE,
|
|
|
|
.attrConfig = PERF_COUNT_HW_BUS_CYCLES
|
|
|
|
},
|
|
|
|
[VIR_PERF_EVENT_STALLED_CYCLES_FRONTEND] = {
|
|
|
|
.attrType = PERF_TYPE_HARDWARE,
|
|
|
|
.attrConfig = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND
|
|
|
|
},
|
|
|
|
[VIR_PERF_EVENT_STALLED_CYCLES_BACKEND] = {
|
|
|
|
.attrType = PERF_TYPE_HARDWARE,
|
|
|
|
.attrConfig = PERF_COUNT_HW_STALLED_CYCLES_BACKEND
|
|
|
|
},
|
|
|
|
[VIR_PERF_EVENT_REF_CPU_CYCLES] = {
|
2016-12-16 10:30:27 +00:00
|
|
|
# ifdef PERF_COUNT_HW_REF_CPU_CYCLES
|
2016-12-16 10:54:38 +00:00
|
|
|
.attrType = PERF_TYPE_HARDWARE,
|
|
|
|
.attrConfig = PERF_COUNT_HW_REF_CPU_CYCLES
|
2016-12-16 10:30:27 +00:00
|
|
|
# else
|
2016-12-16 10:54:38 +00:00
|
|
|
.attrType = 0,
|
|
|
|
.attrConfig = 0,
|
2016-12-16 10:30:27 +00:00
|
|
|
# endif
|
|
|
|
},
|
2016-12-16 10:54:38 +00:00
|
|
|
[VIR_PERF_EVENT_CPU_CLOCK] = {
|
|
|
|
.attrType = PERF_TYPE_SOFTWARE,
|
|
|
|
.attrConfig = PERF_COUNT_SW_CPU_CLOCK
|
|
|
|
},
|
|
|
|
[VIR_PERF_EVENT_TASK_CLOCK] = {
|
|
|
|
.attrType = PERF_TYPE_SOFTWARE,
|
|
|
|
.attrConfig = PERF_COUNT_SW_TASK_CLOCK
|
|
|
|
},
|
|
|
|
[VIR_PERF_EVENT_PAGE_FAULTS] = {
|
|
|
|
.attrType = PERF_TYPE_SOFTWARE,
|
|
|
|
.attrConfig = PERF_COUNT_SW_PAGE_FAULTS
|
|
|
|
},
|
|
|
|
[VIR_PERF_EVENT_CONTEXT_SWITCHES] = {
|
|
|
|
.attrType = PERF_TYPE_SOFTWARE,
|
|
|
|
.attrConfig = PERF_COUNT_SW_CONTEXT_SWITCHES
|
|
|
|
},
|
|
|
|
[VIR_PERF_EVENT_CPU_MIGRATIONS] = {
|
|
|
|
.attrType = PERF_TYPE_SOFTWARE,
|
|
|
|
.attrConfig = PERF_COUNT_SW_CPU_MIGRATIONS
|
|
|
|
},
|
|
|
|
[VIR_PERF_EVENT_PAGE_FAULTS_MIN] = {
|
|
|
|
.attrType = PERF_TYPE_SOFTWARE,
|
|
|
|
.attrConfig = PERF_COUNT_SW_PAGE_FAULTS_MIN
|
|
|
|
},
|
|
|
|
[VIR_PERF_EVENT_PAGE_FAULTS_MAJ] = {
|
|
|
|
.attrType = PERF_TYPE_SOFTWARE,
|
|
|
|
.attrConfig = PERF_COUNT_SW_PAGE_FAULTS_MAJ
|
|
|
|
},
|
|
|
|
[VIR_PERF_EVENT_ALIGNMENT_FAULTS] = {
|
|
|
|
.attrType = PERF_TYPE_SOFTWARE,
|
|
|
|
.attrConfig = PERF_COUNT_SW_ALIGNMENT_FAULTS
|
|
|
|
},
|
|
|
|
[VIR_PERF_EVENT_EMULATION_FAULTS] = {
|
|
|
|
.attrType = PERF_TYPE_SOFTWARE,
|
|
|
|
.attrConfig = PERF_COUNT_SW_EMULATION_FAULTS
|
|
|
|
},
|
2016-08-03 17:23:31 +00:00
|
|
|
};
|
2020-01-09 10:39:55 +00:00
|
|
|
G_STATIC_ASSERT(G_N_ELEMENTS(attrs) == VIR_PERF_EVENT_LAST);
|
2016-08-03 17:23:31 +00:00
|
|
|
typedef struct virPerfEventAttr *virPerfEventAttrPtr;
|
|
|
|
|
virPerfEventIsEnabled: Don't crash on shut off domains
So imagine the following. You connect read only to a daemon and
try to fetch stats for a shut off domain, e.g.:
virsh -r domstats $dom
but all of a sudden, virsh instead of printing the stats throws
the following error at you:
error: Disconnected from qemu:///system due to I/O error
error: End of file while reading data: Input/output error
The daemon crashed. This is its backtrace:
#0 0x00007fa43e3751a8 in virPerfEventIsEnabled (perf=0x0, type=VIR_PERF_EVENT_MBMT) at util/virperf.c:241
#1 0x00007fa424a9f042 in qemuDomainGetStatsPerf (driver=0x7fa3f4022a30, dom=0x7fa3f40e24c0, record=0x7fa41c000e20, maxparams=0x7fa4360b38d0, privflags=1) at qemu/qemu_driver.c:19110
#2 0x00007fa424a9f2e7 in qemuDomainGetStats (conn=0x7fa41c001b20, dom=0x7fa3f40e24c0, stats=127, record=0x7fa4360b3970, flags=1) at qemu/qemu_driver.c:19213
#3 0x00007fa424a9f672 in qemuConnectGetAllDomainStats (conn=0x7fa41c001b20, doms=0x7fa41c0017f0, ndoms=1, stats=127, retStats=0x7fa4360b3a50, flags=0) at qemu/qemu_driver.c:19303
#4 0x00007fa43e4e15f6 in virDomainListGetStats (doms=0x7fa41c0017f0, stats=0, retStats=0x7fa4360b3a50, flags=0) at libvirt-domain.c:11615
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7f28d1a38700 (LWP 16154)]
0x00007f28da4fa1a8 in virPerfEventIsEnabled (perf=0x0, type=VIR_PERF_EVENT_MBMT) at util/virperf.c:241
241 return event->enabled;
Problem is, shut off domains don't have priv->perf allocated.
Therefore if in frame #1 qemuDomainGetStatsPerf() tries to check
if perf events are enabled, NULL is passed to
virPerfEventIsEnabled() which due to some incredible
implementation dereference it. Fix this by checking whether
passed object is not NULL.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
2016-06-03 08:09:17 +00:00
|
|
|
|
2016-03-28 13:30:28 +00:00
|
|
|
static int
|
2016-08-03 17:23:31 +00:00
|
|
|
virPerfRdtAttrInit(void)
|
2016-03-28 13:30:28 +00:00
|
|
|
{
|
|
|
|
char *tmp = NULL;
|
2016-08-03 17:23:31 +00:00
|
|
|
unsigned int attr_type = 0;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *buf = NULL;
|
2016-03-28 13:30:28 +00:00
|
|
|
|
2016-09-06 21:20:30 +00:00
|
|
|
if (virFileReadAllQuiet("/sys/devices/intel_cqm/type", 10, &buf) < 0)
|
2018-07-28 18:01:42 +00:00
|
|
|
return -1;
|
2016-03-28 13:30:28 +00:00
|
|
|
|
|
|
|
if ((tmp = strchr(buf, '\n')))
|
|
|
|
*tmp = '\0';
|
|
|
|
|
2016-08-03 17:23:31 +00:00
|
|
|
if (virStrToLong_ui(buf, NULL, 10, &attr_type) < 0) {
|
2016-03-28 13:30:28 +00:00
|
|
|
virReportSystemError(errno, "%s",
|
2016-05-13 04:26:07 +00:00
|
|
|
_("failed to get rdt event type"));
|
2018-07-28 18:01:42 +00:00
|
|
|
return -1;
|
2016-03-28 13:30:28 +00:00
|
|
|
}
|
|
|
|
|
2016-08-03 17:23:31 +00:00
|
|
|
attrs[VIR_PERF_EVENT_CMT].attrType = attr_type;
|
|
|
|
attrs[VIR_PERF_EVENT_MBMT].attrType = attr_type;
|
|
|
|
attrs[VIR_PERF_EVENT_MBML].attrType = attr_type;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virPerfEventEnable(virPerfPtr perf,
|
|
|
|
virPerfEventType type,
|
|
|
|
pid_t pid)
|
|
|
|
{
|
|
|
|
struct perf_event_attr attr;
|
2016-12-16 10:58:29 +00:00
|
|
|
virPerfEventPtr event = &(perf->events[type]);
|
2016-12-16 10:54:38 +00:00
|
|
|
virPerfEventAttrPtr event_attr = &attrs[type];
|
2016-08-03 17:23:31 +00:00
|
|
|
|
2017-01-24 09:12:03 +00:00
|
|
|
if (event->enabled)
|
|
|
|
return 0;
|
|
|
|
|
2016-08-03 17:23:31 +00:00
|
|
|
if (event_attr->attrType == 0 && (type == VIR_PERF_EVENT_CMT ||
|
2018-09-19 08:38:14 +00:00
|
|
|
type == VIR_PERF_EVENT_MBMT ||
|
|
|
|
type == VIR_PERF_EVENT_MBML)) {
|
2016-09-06 21:20:30 +00:00
|
|
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
|
2016-10-07 12:14:37 +00:00
|
|
|
_("unable to enable host cpu perf event for %s"),
|
2016-12-16 10:54:38 +00:00
|
|
|
virPerfEventTypeToString(type));
|
2016-08-03 17:23:31 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type == VIR_PERF_EVENT_CMT) {
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *buf = NULL;
|
2018-07-28 18:01:42 +00:00
|
|
|
|
2016-05-13 04:26:07 +00:00
|
|
|
if (virFileReadAll("/sys/devices/intel_cqm/events/llc_occupancy.scale",
|
|
|
|
10, &buf) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2016-08-03 17:23:31 +00:00
|
|
|
if (virStrToLong_i(buf, NULL, 10, &event->efields.cmt.scale) < 0) {
|
2016-05-13 04:26:07 +00:00
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("failed to get cmt scaling factor"));
|
|
|
|
goto error;
|
|
|
|
}
|
2016-03-28 13:30:28 +00:00
|
|
|
}
|
|
|
|
|
2016-08-03 17:23:31 +00:00
|
|
|
memset(&attr, 0, sizeof(attr));
|
|
|
|
attr.size = sizeof(attr);
|
|
|
|
attr.inherit = 1;
|
|
|
|
attr.disabled = 1;
|
|
|
|
attr.enable_on_exec = 0;
|
|
|
|
attr.type = event_attr->attrType;
|
|
|
|
attr.config = event_attr->attrConfig;
|
|
|
|
|
|
|
|
event->fd = syscall(__NR_perf_event_open, &attr, pid, -1, -1, 0);
|
2016-03-28 13:30:28 +00:00
|
|
|
if (event->fd < 0) {
|
|
|
|
virReportSystemError(errno,
|
2016-10-07 12:14:37 +00:00
|
|
|
_("unable to open host cpu perf event for %s"),
|
2016-12-16 10:58:29 +00:00
|
|
|
virPerfEventTypeToString(type));
|
2016-04-27 12:55:12 +00:00
|
|
|
goto error;
|
2016-03-28 13:30:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ioctl(event->fd, PERF_EVENT_IOC_ENABLE) < 0) {
|
2016-05-13 04:26:07 +00:00
|
|
|
virReportSystemError(errno,
|
2016-10-07 12:14:37 +00:00
|
|
|
_("unable to enable host cpu perf event for %s"),
|
2016-12-16 10:58:29 +00:00
|
|
|
virPerfEventTypeToString(type));
|
2016-04-27 12:55:12 +00:00
|
|
|
goto error;
|
2016-03-28 13:30:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
event->enabled = true;
|
|
|
|
return 0;
|
|
|
|
|
2016-04-27 12:55:12 +00:00
|
|
|
error:
|
2016-03-28 13:30:28 +00:00
|
|
|
VIR_FORCE_CLOSE(event->fd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
virPerfEventDisable(virPerfPtr perf,
|
|
|
|
virPerfEventType type)
|
|
|
|
{
|
2016-12-16 10:58:29 +00:00
|
|
|
virPerfEventPtr event = &(perf->events[type]);
|
2016-03-28 13:30:28 +00:00
|
|
|
|
2016-10-07 12:28:58 +00:00
|
|
|
if (!event->enabled)
|
|
|
|
return 0;
|
|
|
|
|
2016-03-28 13:30:28 +00:00
|
|
|
if (ioctl(event->fd, PERF_EVENT_IOC_DISABLE) < 0) {
|
|
|
|
virReportSystemError(errno,
|
2016-10-07 12:14:37 +00:00
|
|
|
_("unable to disable host cpu perf event for %s"),
|
2016-12-16 10:58:29 +00:00
|
|
|
virPerfEventTypeToString(type));
|
2016-03-28 13:30:28 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
event->enabled = false;
|
|
|
|
VIR_FORCE_CLOSE(event->fd);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool virPerfEventIsEnabled(virPerfPtr perf,
|
|
|
|
virPerfEventType type)
|
|
|
|
{
|
2017-05-04 14:27:45 +00:00
|
|
|
return perf && perf->events[type].enabled;
|
2016-03-28 13:30:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
virPerfReadEvent(virPerfPtr perf,
|
|
|
|
virPerfEventType type,
|
|
|
|
uint64_t *value)
|
|
|
|
{
|
2016-12-16 10:58:29 +00:00
|
|
|
virPerfEventPtr event = &perf->events[type];
|
|
|
|
if (!event->enabled)
|
2016-03-28 13:30:28 +00:00
|
|
|
return -1;
|
|
|
|
|
2016-03-31 14:43:08 +00:00
|
|
|
if (saferead(event->fd, value, sizeof(uint64_t)) < 0) {
|
2016-03-28 13:30:28 +00:00
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Unable to read cache data"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type == VIR_PERF_EVENT_CMT)
|
|
|
|
*value *= event->efields.cmt.scale;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
2016-08-03 17:23:31 +00:00
|
|
|
static int
|
|
|
|
virPerfRdtAttrInit(void)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-03-28 13:30:28 +00:00
|
|
|
int
|
2019-10-14 12:45:33 +00:00
|
|
|
virPerfEventEnable(virPerfPtr perf G_GNUC_UNUSED,
|
|
|
|
virPerfEventType type G_GNUC_UNUSED,
|
|
|
|
pid_t pid G_GNUC_UNUSED)
|
2016-03-28 13:30:28 +00:00
|
|
|
{
|
|
|
|
virReportSystemError(ENXIO, "%s",
|
|
|
|
_("Perf not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2019-10-14 12:45:33 +00:00
|
|
|
virPerfEventDisable(virPerfPtr perf G_GNUC_UNUSED,
|
|
|
|
virPerfEventType type G_GNUC_UNUSED)
|
2016-03-28 13:30:28 +00:00
|
|
|
{
|
|
|
|
virReportSystemError(ENXIO, "%s",
|
|
|
|
_("Perf not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2019-10-14 12:45:33 +00:00
|
|
|
virPerfEventIsEnabled(virPerfPtr perf G_GNUC_UNUSED,
|
|
|
|
virPerfEventType type G_GNUC_UNUSED)
|
2016-03-28 13:30:28 +00:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2019-10-14 12:45:33 +00:00
|
|
|
virPerfReadEvent(virPerfPtr perf G_GNUC_UNUSED,
|
|
|
|
virPerfEventType type G_GNUC_UNUSED,
|
|
|
|
uint64_t *value G_GNUC_UNUSED)
|
2016-03-28 13:30:28 +00:00
|
|
|
{
|
|
|
|
virReportSystemError(ENXIO, "%s",
|
|
|
|
_("Perf not supported on this platform"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
2016-08-03 16:38:15 +00:00
|
|
|
|
|
|
|
virPerfPtr
|
|
|
|
virPerfNew(void)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
virPerfPtr perf;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(perf) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (i = 0; i < VIR_PERF_EVENT_LAST; i++) {
|
|
|
|
perf->events[i].fd = -1;
|
|
|
|
perf->events[i].enabled = false;
|
|
|
|
}
|
|
|
|
|
2016-08-03 17:23:31 +00:00
|
|
|
if (virPerfRdtAttrInit() < 0)
|
|
|
|
virResetLastError();
|
|
|
|
|
2016-08-03 16:38:15 +00:00
|
|
|
return perf;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
virPerfFree(virPerfPtr perf)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (perf == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = 0; i < VIR_PERF_EVENT_LAST; i++) {
|
|
|
|
if (perf->events[i].enabled)
|
|
|
|
virPerfEventDisable(perf, i);
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(perf);
|
|
|
|
}
|