]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
perf python: Add parse_events function
authorIan Rogers <irogers@google.com>
Tue, 19 Nov 2024 01:16:41 +0000 (17:16 -0800)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 18 Dec 2024 19:24:33 +0000 (16:24 -0300)
Add basic parse_events function that takes a string and returns an
evlist. As the python evlist is embedded in a pyrf_evlist, and the
evsels are embedded in pyrf_evsels, copy the parsed data into those
structs and update evsel__clone to enable this.

Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
Cc: Colin Ian King <colin.i.king@gmail.com>
Cc: Dapeng Mi <dapeng1.mi@linux.intel.com>
Cc: Howard Chu <howardchu95@gmail.com>
Cc: Ilya Leoshkevich <iii@linux.ibm.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Michael Petlan <mpetlan@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Richter <tmricht@linux.ibm.com>
Cc: Veronika Molnarova <vmolnaro@redhat.com>
Cc: Weilin Wang <weilin.wang@intel.com>
Link: https://lore.kernel.org/r/20241119011644.971342-20-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/cgroup.c
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/python.c

index 0f759dd96db710fd7ad37ad97fbaef1741e669ee..fbcc0626f9ce280bfe791f2cf68eb828feeb7c2c 100644 (file)
@@ -473,7 +473,7 @@ int evlist__expand_cgroup(struct evlist *evlist, const char *str,
 
                leader = NULL;
                evlist__for_each_entry(orig_list, pos) {
-                       evsel = evsel__clone(pos);
+                       evsel = evsel__clone(/*dest=*/NULL, pos);
                        if (evsel == NULL)
                                goto out_err;
 
index f6bf845808d6ec80d5bd411e2eb7d13ccd906b58..6ae5d110994a0322312e65721f987798832aa002 100644 (file)
@@ -454,7 +454,7 @@ static int evsel__copy_config_terms(struct evsel *dst, struct evsel *src)
  * The assumption is that @orig is not configured nor opened yet.
  * So we only care about the attributes that can be set while it's parsed.
  */
-struct evsel *evsel__clone(struct evsel *orig)
+struct evsel *evsel__clone(struct evsel *dest, struct evsel *orig)
 {
        struct evsel *evsel;
 
@@ -467,7 +467,11 @@ struct evsel *evsel__clone(struct evsel *orig)
        if (orig->bpf_obj)
                return NULL;
 
-       evsel = evsel__new(&orig->core.attr);
+       if (dest)
+               evsel = dest;
+       else
+               evsel = evsel__new(&orig->core.attr);
+
        if (evsel == NULL)
                return NULL;
 
@@ -512,11 +516,12 @@ struct evsel *evsel__clone(struct evsel *orig)
        evsel->core.leader = orig->core.leader;
 
        evsel->max_events = orig->max_events;
-       free((char *)evsel->unit);
-       evsel->unit = strdup(orig->unit);
-       if (evsel->unit == NULL)
-               goto out_err;
-
+       zfree(&evsel->unit);
+       if (orig->unit) {
+               evsel->unit = strdup(orig->unit);
+               if (evsel->unit == NULL)
+                       goto out_err;
+       }
        evsel->scale = orig->scale;
        evsel->snapshot = orig->snapshot;
        evsel->per_pkg = orig->per_pkg;
index 76749bb0e1a54209a98911143e06c29be61e7a09..5ad352c94d00f7b2c2dea19a56b7abf4220c4211 100644 (file)
@@ -244,7 +244,7 @@ static inline struct evsel *evsel__new(struct perf_event_attr *attr)
        return evsel__new_idx(attr, 0);
 }
 
-struct evsel *evsel__clone(struct evsel *orig);
+struct evsel *evsel__clone(struct evsel *dest, struct evsel *orig);
 
 int copy_config_terms(struct list_head *dst, struct list_head *src);
 void free_config_terms(struct list_head *config_terms);
index 3e32a502a41c0d8cc348308b4395ba4781ce67a9..c84c912874b7151b104b22e26fb553dcaf3271ec 100644 (file)
@@ -13,6 +13,7 @@
 #include "evsel.h"
 #include "event.h"
 #include "print_binary.h"
+#include "strbuf.h"
 #include "thread_map.h"
 #include "trace-event.h"
 #include "mmap.h"
@@ -1201,6 +1202,60 @@ static PyObject *pyrf__tracepoint(struct pyrf_evsel *pevsel,
 #endif // HAVE_LIBTRACEEVENT
 }
 
+static PyObject *pyrf_evsel__from_evsel(struct evsel *evsel)
+{
+       struct pyrf_evsel *pevsel = PyObject_New(struct pyrf_evsel, &pyrf_evsel__type);
+
+       if (!pevsel)
+               return NULL;
+
+       memset(&pevsel->evsel, 0, sizeof(pevsel->evsel));
+       evsel__init(&pevsel->evsel, &evsel->core.attr, evsel->core.idx);
+
+       evsel__clone(&pevsel->evsel, evsel);
+       return (PyObject *)pevsel;
+}
+
+static PyObject *pyrf_evlist__from_evlist(struct evlist *evlist)
+{
+       struct pyrf_evlist *pevlist = PyObject_New(struct pyrf_evlist, &pyrf_evlist__type);
+       struct evsel *pos;
+
+       if (!pevlist)
+               return NULL;
+
+       memset(&pevlist->evlist, 0, sizeof(pevlist->evlist));
+       evlist__init(&pevlist->evlist, evlist->core.all_cpus, evlist->core.threads);
+       evlist__for_each_entry(evlist, pos) {
+               struct pyrf_evsel *pevsel = (void *)pyrf_evsel__from_evsel(pos);
+
+               evlist__add(&pevlist->evlist, &pevsel->evsel);
+       }
+       return (PyObject *)pevlist;
+}
+
+static PyObject *pyrf__parse_events(PyObject *self, PyObject *args)
+{
+       const char *input;
+       struct evlist evlist = {};
+       struct parse_events_error err;
+       PyObject *result;
+
+       if (!PyArg_ParseTuple(args, "s", &input))
+               return NULL;
+
+       parse_events_error__init(&err);
+       evlist__init(&evlist, NULL, NULL);
+       if (parse_events(&evlist, input, &err)) {
+               parse_events_error__print(&err, input);
+               PyErr_SetFromErrno(PyExc_OSError);
+               return NULL;
+       }
+       result = pyrf_evlist__from_evlist(&evlist);
+       evlist__exit(&evlist);
+       return result;
+}
+
 static PyMethodDef perf__methods[] = {
        {
                .ml_name  = "tracepoint",
@@ -1208,6 +1263,12 @@ static PyMethodDef perf__methods[] = {
                .ml_flags = METH_VARARGS | METH_KEYWORDS,
                .ml_doc   = PyDoc_STR("Get tracepoint config.")
        },
+       {
+               .ml_name  = "parse_events",
+               .ml_meth  = (PyCFunction) pyrf__parse_events,
+               .ml_flags = METH_VARARGS,
+               .ml_doc   = PyDoc_STR("Parse a string of events and return an evlist.")
+       },
        { .ml_name = NULL, }
 };