Skip to content

Commit efd2b92

Browse files
committed
perf evsel: Provide a new constructor for tracepoints
The existing constructor receives a perf_event_attr filled with the event type and the config. To reduce the boilerplate for tracepoints, provide a new constructor, perf_evsel__newtp() that receives the tracepoint name and will open the debugfs file, call into libtraceevent new pevent_parse_format file to fill its ->tp_format member, so that users can then just call perf_evsel__field() to access its fields. Cc: David Ahern <[email protected]> Cc: Frederic Weisbecker <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Mike Galbraith <[email protected]> Cc: Namhyung Kim <[email protected]> Cc: Paul Mackerras <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Stephane Eranian <[email protected]> Cc: Steven Rostedt <[email protected]> Link: http://lkml.kernel.org/n/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 2b29175 commit efd2b92

File tree

2 files changed

+87
-6
lines changed

2 files changed

+87
-6
lines changed

tools/perf/util/evsel.c

Lines changed: 82 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <byteswap.h>
1111
#include <linux/bitops.h>
1212
#include "asm/bug.h"
13+
#include "debugfs.h"
1314
#include "event-parse.h"
1415
#include "evsel.h"
1516
#include "evlist.h"
@@ -69,6 +70,72 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
6970
return evsel;
7071
}
7172

73+
static struct event_format *event_format__new(const char *sys, const char *name)
74+
{
75+
int fd, n;
76+
char *filename;
77+
void *bf = NULL, *nbf;
78+
size_t size = 0, alloc_size = 0;
79+
struct event_format *format = NULL;
80+
81+
if (asprintf(&filename, "%s/%s/%s/format", tracing_events_path, sys, name) < 0)
82+
goto out;
83+
84+
fd = open(filename, O_RDONLY);
85+
if (fd < 0)
86+
goto out_free_filename;
87+
88+
do {
89+
if (size == alloc_size) {
90+
alloc_size += BUFSIZ;
91+
nbf = realloc(bf, alloc_size);
92+
if (nbf == NULL)
93+
goto out_free_bf;
94+
bf = nbf;
95+
}
96+
97+
n = read(fd, bf + size, BUFSIZ);
98+
if (n < 0)
99+
goto out_free_bf;
100+
size += n;
101+
} while (n > 0);
102+
103+
pevent_parse_format(&format, bf, size, sys);
104+
105+
out_free_bf:
106+
free(bf);
107+
close(fd);
108+
out_free_filename:
109+
free(filename);
110+
out:
111+
return format;
112+
}
113+
114+
struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx)
115+
{
116+
struct perf_evsel *evsel = zalloc(sizeof(*evsel));
117+
118+
if (evsel != NULL) {
119+
struct perf_event_attr attr = {
120+
.type = PERF_TYPE_TRACEPOINT,
121+
};
122+
123+
evsel->tp_format = event_format__new(sys, name);
124+
if (evsel->tp_format == NULL)
125+
goto out_free;
126+
127+
attr.config = evsel->tp_format->id;
128+
perf_evsel__init(evsel, &attr, idx);
129+
evsel->name = evsel->tp_format->name;
130+
}
131+
132+
return evsel;
133+
134+
out_free:
135+
free(evsel);
136+
return NULL;
137+
}
138+
72139
const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = {
73140
"cycles",
74141
"instructions",
@@ -495,6 +562,10 @@ void perf_evsel__delete(struct perf_evsel *evsel)
495562
perf_evsel__exit(evsel);
496563
close_cgroup(evsel->cgrp);
497564
free(evsel->group_name);
565+
if (evsel->tp_format && evsel->name == evsel->tp_format->name) {
566+
evsel->name = NULL;
567+
pevent_free_format(evsel->tp_format);
568+
}
498569
free(evsel->name);
499570
free(evsel);
500571
}
@@ -1002,14 +1073,19 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
10021073
return 0;
10031074
}
10041075

1076+
struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name)
1077+
{
1078+
return pevent_find_field(evsel->tp_format, name);
1079+
}
1080+
10051081
char *perf_evsel__strval(struct perf_evsel *evsel, struct perf_sample *sample,
10061082
const char *name)
10071083
{
1008-
struct format_field *field = pevent_find_field(evsel->tp_format, name);
1084+
struct format_field *field = perf_evsel__field(evsel, name);
10091085
int offset;
10101086

1011-
if (!field)
1012-
return NULL;
1087+
if (!field)
1088+
return NULL;
10131089

10141090
offset = field->offset;
10151091

@@ -1024,11 +1100,11 @@ char *perf_evsel__strval(struct perf_evsel *evsel, struct perf_sample *sample,
10241100
u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
10251101
const char *name)
10261102
{
1027-
struct format_field *field = pevent_find_field(evsel->tp_format, name);
1103+
struct format_field *field = perf_evsel__field(evsel, name);
10281104
u64 val;
10291105

1030-
if (!field)
1031-
return 0;
1106+
if (!field)
1107+
return 0;
10321108

10331109
val = pevent_read_number(evsel->tp_format->pevent,
10341110
sample->raw_data + field->offset, field->size);

tools/perf/util/evsel.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ struct perf_evlist;
8181
struct perf_record_opts;
8282

8383
struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx);
84+
struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx);
8485
void perf_evsel__init(struct perf_evsel *evsel,
8586
struct perf_event_attr *attr, int idx);
8687
void perf_evsel__exit(struct perf_evsel *evsel);
@@ -128,6 +129,10 @@ char *perf_evsel__strval(struct perf_evsel *evsel, struct perf_sample *sample,
128129
u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
129130
const char *name);
130131

132+
struct format_field;
133+
134+
struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name);
135+
131136
#define perf_evsel__match(evsel, t, c) \
132137
(evsel->attr.type == PERF_TYPE_##t && \
133138
evsel->attr.config == PERF_COUNT_##c)

0 commit comments

Comments
 (0)