mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 07:03:28 -04:00
perf python: Add wrapper for perf_data file abstraction
The perf_data struct is needed for session support. Signed-off-by: Ian Rogers <irogers@google.com> Assisted-by: Gemini:gemini-3.1-pro-preview Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alice Rogers <alice.mei.rogers@gmail.com> Cc: Dapeng Mi <dapeng1.mi@linux.intel.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: James Clark <james.clark@linaro.org> Cc: Leo Yan <leo.yan@linux.dev> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Richter <tmricht@linux.ibm.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <poll.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <internal/lib.h>
|
||||
#include <perf/cpumap.h>
|
||||
@@ -14,6 +15,7 @@
|
||||
|
||||
#include "callchain.h"
|
||||
#include "counts.h"
|
||||
#include "data.h"
|
||||
#include "event.h"
|
||||
#include "evlist.h"
|
||||
#include "evsel.h"
|
||||
@@ -2462,6 +2464,121 @@ static PyObject *pyrf__metrics(PyObject *self, PyObject *args)
|
||||
return list;
|
||||
}
|
||||
|
||||
struct pyrf_data {
|
||||
PyObject_HEAD
|
||||
|
||||
struct perf_data data;
|
||||
};
|
||||
|
||||
static int pyrf_data__init(struct pyrf_data *pdata, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = { "path", "fd", NULL };
|
||||
char *path = NULL;
|
||||
int fd = -1;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|si", kwlist, &path, &fd))
|
||||
return -1;
|
||||
|
||||
if (pdata->data.open)
|
||||
perf_data__close(&pdata->data);
|
||||
free((char *)pdata->data.path);
|
||||
pdata->data.path = NULL;
|
||||
|
||||
if (fd != -1) {
|
||||
struct stat st;
|
||||
|
||||
if (fstat(fd, &st) < 0 || !S_ISFIFO(st.st_mode)) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"fd argument is only supported for pipes");
|
||||
return -1;
|
||||
}
|
||||
if (!path)
|
||||
path = "-";
|
||||
else if (strcmp(path, "-") != 0) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"path must be '-' when fd is provided");
|
||||
return -1;
|
||||
}
|
||||
fd = dup(fd);
|
||||
if (fd < 0) {
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
return -1;
|
||||
}
|
||||
} else if (path && strcmp(path, "-") == 0) {
|
||||
fd = dup(0);
|
||||
if (fd < 0) {
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!path)
|
||||
path = "perf.data";
|
||||
|
||||
pdata->data.path = strdup(path);
|
||||
if (!pdata->data.path) {
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
pdata->data.mode = PERF_DATA_MODE_READ;
|
||||
pdata->data.file.fd = fd;
|
||||
if (perf_data__open(&pdata->data) < 0) {
|
||||
PyErr_Format(PyExc_IOError, "Failed to open perf data: %s",
|
||||
pdata->data.path ? pdata->data.path : "perf.data");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pyrf_data__delete(struct pyrf_data *pdata)
|
||||
{
|
||||
perf_data__close(&pdata->data);
|
||||
free((char *)pdata->data.path);
|
||||
Py_TYPE(pdata)->tp_free((PyObject *)pdata);
|
||||
}
|
||||
|
||||
static PyObject *pyrf_data__str(PyObject *self)
|
||||
{
|
||||
const struct pyrf_data *pdata = (const struct pyrf_data *)self;
|
||||
|
||||
if (!pdata->data.path)
|
||||
return PyUnicode_FromString("[uninitialized]");
|
||||
return PyUnicode_FromString(pdata->data.path);
|
||||
}
|
||||
|
||||
static PyObject *pyrf_data__new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
struct pyrf_data *pdata;
|
||||
|
||||
pdata = (struct pyrf_data *)PyType_GenericNew(type, args, kwargs);
|
||||
if (pdata)
|
||||
memset(&pdata->data, 0, sizeof(pdata->data));
|
||||
return (PyObject *)pdata;
|
||||
}
|
||||
|
||||
static const char pyrf_data__doc[] = PyDoc_STR("perf data file object.");
|
||||
|
||||
static PyTypeObject pyrf_data__type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
.tp_name = "perf.data",
|
||||
.tp_basicsize = sizeof(struct pyrf_data),
|
||||
.tp_dealloc = (destructor)pyrf_data__delete,
|
||||
.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
|
||||
.tp_doc = pyrf_data__doc,
|
||||
.tp_init = (initproc)pyrf_data__init,
|
||||
.tp_repr = pyrf_data__str,
|
||||
.tp_str = pyrf_data__str,
|
||||
};
|
||||
|
||||
static int pyrf_data__setup_types(void)
|
||||
{
|
||||
pyrf_data__type.tp_new = pyrf_data__new;
|
||||
return PyType_Ready(&pyrf_data__type);
|
||||
}
|
||||
|
||||
static PyMethodDef perf__methods[] = {
|
||||
{
|
||||
.ml_name = "metrics",
|
||||
@@ -2524,7 +2641,8 @@ PyMODINIT_FUNC PyInit_perf(void)
|
||||
pyrf_cpu_map__setup_types() < 0 ||
|
||||
pyrf_pmu_iterator__setup_types() < 0 ||
|
||||
pyrf_pmu__setup_types() < 0 ||
|
||||
pyrf_counts_values__setup_types() < 0)
|
||||
pyrf_counts_values__setup_types() < 0 ||
|
||||
pyrf_data__setup_types() < 0)
|
||||
return module;
|
||||
|
||||
/* The page_size is placed in util object. */
|
||||
@@ -2572,6 +2690,9 @@ PyMODINIT_FUNC PyInit_perf(void)
|
||||
Py_INCREF(&pyrf_counts_values__type);
|
||||
PyModule_AddObject(module, "counts_values", (PyObject *)&pyrf_counts_values__type);
|
||||
|
||||
Py_INCREF(&pyrf_data__type);
|
||||
PyModule_AddObject(module, "data", (PyObject *)&pyrf_data__type);
|
||||
|
||||
dict = PyModule_GetDict(module);
|
||||
if (dict == NULL)
|
||||
goto error;
|
||||
|
||||
Reference in New Issue
Block a user