Skip to content

Commit 45b6e28

Browse files
captain5050namhyung
authored andcommitted
perf tp_pmu: Add event APIs
Add event APIs for the tracepoint PMU allowing things like perf list to function using it. For perf list add the tracepoint format in the long description (shown with -v). $ sudo perf list -v tracepoint List of pre-defined events (to be used in -e or -M): alarmtimer:alarmtimer_cancel [Tracepoint event] [name: alarmtimer_cancel ID: 416 format: field:unsigned short common_type; offset:0; size:2; signed:0; field:unsigned char common_flags; offset:2; size:1; signed:0; field:unsigned char common_preempt_count; offset:3; size:1; signed:0; field:int common_pid; offset:4; size:4; signed:1; field:void * alarm; offset:8; size:8; signed:0; field:unsigned char alarm_type; offset:16; size:1; signed:0; field:s64 expires; offset:24; size:8; signed:1; field:s64 now; offset:32; size:8; signed:1; print fmt: "alarmtimer:%p type:%s expires:%llu now:%llu",REC->alarm,__print_flags((1 << REC->alarm_type)," | ",{ 1 << 0, "REALTIME" },{ 1 << 1,"BOOTTIME" },{ 1 << 3,"REALTIME Freezer" },{ 1 << 4,"BOOTTIME Freezer" }),REC->expires,REC->now . Unit: tracepoint] alarmtimer:alarmtimer_fired [Tracepoint event] [name: alarmtimer_fired ID: 418 ... Signed-off-by: Ian Rogers <[email protected]> Tested-by: Arnaldo Carvalho de Melo <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Namhyung Kim <[email protected]>
1 parent d002aab commit 45b6e28

File tree

3 files changed

+129
-0
lines changed

3 files changed

+129
-0
lines changed

tools/perf/util/pmu.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "hwmon_pmu.h"
2525
#include "pmus.h"
2626
#include "tool_pmu.h"
27+
#include "tp_pmu.h"
2728
#include <util/pmu-bison.h>
2829
#include <util/pmu-flex.h>
2930
#include "parse-events.h"
@@ -1983,6 +1984,8 @@ bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name)
19831984
return false;
19841985
if (perf_pmu__is_tool(pmu) && tool_pmu__skip_event(name))
19851986
return false;
1987+
if (perf_pmu__is_tracepoint(pmu))
1988+
return tp_pmu__have_event(pmu, name);
19861989
if (perf_pmu__is_hwmon(pmu))
19871990
return hwmon_pmu__have_event(pmu, name);
19881991
if (perf_pmu__is_drm(pmu))
@@ -1998,6 +2001,8 @@ size_t perf_pmu__num_events(struct perf_pmu *pmu)
19982001
{
19992002
size_t nr;
20002003

2004+
if (perf_pmu__is_tracepoint(pmu))
2005+
return tp_pmu__num_events(pmu);
20012006
if (perf_pmu__is_hwmon(pmu))
20022007
return hwmon_pmu__num_events(pmu);
20032008
if (perf_pmu__is_drm(pmu))
@@ -2068,6 +2073,8 @@ int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus,
20682073
struct hashmap_entry *entry;
20692074
size_t bkt;
20702075

2076+
if (perf_pmu__is_tracepoint(pmu))
2077+
return tp_pmu__for_each_event(pmu, state, cb);
20712078
if (perf_pmu__is_hwmon(pmu))
20722079
return hwmon_pmu__for_each_event(pmu, state, cb);
20732080
if (perf_pmu__is_drm(pmu))

tools/perf/util/tp_pmu.c

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
22
#include "tp_pmu.h"
3+
#include "pmus.h"
34
#include <api/fs/fs.h>
45
#include <api/fs/tracing_path.h>
56
#include <api/io_dir.h>
@@ -93,3 +94,117 @@ int tp_pmu__for_each_tp_sys(void *state, tp_sys_callback cb)
9394
close(events_dir.dirfd);
9495
return ret;
9596
}
97+
98+
bool perf_pmu__is_tracepoint(const struct perf_pmu *pmu)
99+
{
100+
return pmu->type == PERF_TYPE_TRACEPOINT;
101+
}
102+
103+
struct for_each_event_args {
104+
void *state;
105+
pmu_event_callback cb;
106+
const struct perf_pmu *pmu;
107+
};
108+
109+
static int for_each_event_cb(void *state, const char *sys_name, const char *evt_name)
110+
{
111+
struct for_each_event_args *args = state;
112+
char name[2 * FILENAME_MAX + 2];
113+
/* 16 possible hex digits and 22 other characters and \0. */
114+
char encoding[16 + 22];
115+
char *format = NULL;
116+
size_t format_size;
117+
struct pmu_event_info info = {
118+
.pmu = args->pmu,
119+
.pmu_name = args->pmu->name,
120+
.event_type_desc = "Tracepoint event",
121+
};
122+
char *tp_dir = get_events_file(sys_name);
123+
char path[PATH_MAX];
124+
int id, err;
125+
126+
if (!tp_dir)
127+
return -1;
128+
129+
scnprintf(path, sizeof(path), "%s/%s/id", tp_dir, evt_name);
130+
err = filename__read_int(path, &id);
131+
if (err == 0) {
132+
snprintf(encoding, sizeof(encoding), "tracepoint/config=0x%x/", id);
133+
info.encoding_desc = encoding;
134+
}
135+
136+
scnprintf(path, sizeof(path), "%s/%s/format", tp_dir, evt_name);
137+
put_events_file(tp_dir);
138+
err = filename__read_str(path, &format, &format_size);
139+
if (err == 0) {
140+
info.long_desc = format;
141+
for (size_t i = 0 ; i < format_size; i++) {
142+
/* Swap tabs to spaces due to some rendering issues. */
143+
if (format[i] == '\t')
144+
format[i] = ' ';
145+
}
146+
}
147+
snprintf(name, sizeof(name), "%s:%s", sys_name, evt_name);
148+
info.name = name;
149+
err = args->cb(args->state, &info);
150+
free(format);
151+
return err;
152+
}
153+
154+
static int for_each_event_sys_cb(void *state, const char *sys_name)
155+
{
156+
return tp_pmu__for_each_tp_event(sys_name, state, for_each_event_cb);
157+
}
158+
159+
int tp_pmu__for_each_event(struct perf_pmu *pmu, void *state, pmu_event_callback cb)
160+
{
161+
struct for_each_event_args args = {
162+
.state = state,
163+
.cb = cb,
164+
.pmu = pmu,
165+
};
166+
167+
return tp_pmu__for_each_tp_sys(&args, for_each_event_sys_cb);
168+
}
169+
170+
static int num_events_cb(void *state, const char *sys_name __maybe_unused,
171+
const char *evt_name __maybe_unused)
172+
{
173+
size_t *count = state;
174+
175+
(*count)++;
176+
return 0;
177+
}
178+
179+
static int num_events_sys_cb(void *state, const char *sys_name)
180+
{
181+
return tp_pmu__for_each_tp_event(sys_name, state, num_events_cb);
182+
}
183+
184+
size_t tp_pmu__num_events(struct perf_pmu *pmu __maybe_unused)
185+
{
186+
size_t count = 0;
187+
188+
tp_pmu__for_each_tp_sys(&count, num_events_sys_cb);
189+
return count;
190+
}
191+
192+
bool tp_pmu__have_event(struct perf_pmu *pmu __maybe_unused, const char *name)
193+
{
194+
char *dup_name, *colon;
195+
int id;
196+
197+
colon = strchr(name, ':');
198+
if (colon == NULL)
199+
return false;
200+
201+
dup_name = strdup(name);
202+
if (!dup_name)
203+
return false;
204+
205+
colon = dup_name + (colon - name);
206+
*colon = '\0';
207+
id = tp_pmu__id(dup_name, colon + 1);
208+
free(dup_name);
209+
return id >= 0;
210+
}

tools/perf/util/tp_pmu.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,18 @@
22
#ifndef __TP_PMU_H
33
#define __TP_PMU_H
44

5+
#include "pmu.h"
6+
57
typedef int (*tp_sys_callback)(void *state, const char *sys_name);
68
typedef int (*tp_event_callback)(void *state, const char *sys_name, const char *evt_name);
79

810
int tp_pmu__id(const char *sys, const char *name);
911
int tp_pmu__for_each_tp_event(const char *sys, void *state, tp_event_callback cb);
1012
int tp_pmu__for_each_tp_sys(void *state, tp_sys_callback cb);
1113

14+
bool perf_pmu__is_tracepoint(const struct perf_pmu *pmu);
15+
int tp_pmu__for_each_event(struct perf_pmu *pmu, void *state, pmu_event_callback cb);
16+
size_t tp_pmu__num_events(struct perf_pmu *pmu);
17+
bool tp_pmu__have_event(struct perf_pmu *pmu, const char *name);
18+
1219
#endif /* __TP_PMU_H */

0 commit comments

Comments
 (0)