aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Baron <jbaron@redhat.com>2009-07-21 12:20:22 -0400
committerPeter Zijlstra <a.p.zijlstra@chello.nl>2009-07-22 12:05:57 -0400
commitf6bdafef2ab911f03321fa83d8da1df99878009e (patch)
treea948428dcda80abccbe6071036662b7cf07db268
parent28ac909b49a155856c957d080f8a796b3c1d1f3e (diff)
perf_counter: Add tracepoint support to perf list, perf stat
Add support to 'perf list' and 'perf stat' for kernel tracepoints. The implementation creates a 'for_each_subsystem' and 'for_each_event' for easy iteration over the tracepoints. Signed-off-by: Jason Baron <jbaron@redhat.com> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <426129bf9fcc8ee63bb094cf736e7316a7dcd77a.1248190728.git.jbaron@redhat.com>
-rw-r--r--tools/perf/util/parse-events.c175
-rw-r--r--tools/perf/util/util.h2
2 files changed, 176 insertions, 1 deletions
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index d18c98edd00d..5a3cd3a34af1 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -12,6 +12,8 @@ int nr_counters;
12 12
13struct perf_counter_attr attrs[MAX_COUNTERS]; 13struct perf_counter_attr attrs[MAX_COUNTERS];
14 14
15static char default_debugfs_path[] = "/sys/kernel/debug/tracing/events";
16
15struct event_symbol { 17struct event_symbol {
16 u8 type; 18 u8 type;
17 u64 config; 19 u64 config;
@@ -110,6 +112,88 @@ static unsigned long hw_cache_stat[C(MAX)] = {
110 [C(BPU)] = (CACHE_READ), 112 [C(BPU)] = (CACHE_READ),
111}; 113};
112 114
115#define for_each_subsystem(sys_dir, sys_dirent, sys_next, file, st) \
116 while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \
117 if (snprintf(file, MAXPATHLEN, "%s/%s", default_debugfs_path, \
118 sys_dirent.d_name) && \
119 (!stat(file, &st)) && (S_ISDIR(st.st_mode)) && \
120 (strcmp(sys_dirent.d_name, ".")) && \
121 (strcmp(sys_dirent.d_name, "..")))
122
123#define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next, file, st) \
124 while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next) \
125 if (snprintf(file, MAXPATHLEN, "%s/%s/%s", default_debugfs_path, \
126 sys_dirent.d_name, evt_dirent.d_name) && \
127 (!stat(file, &st)) && (S_ISDIR(st.st_mode)) && \
128 (strcmp(evt_dirent.d_name, ".")) && \
129 (strcmp(evt_dirent.d_name, "..")))
130
131#define MAX_EVENT_LENGTH 30
132
133static int valid_debugfs_mount(void)
134{
135 struct statfs st_fs;
136
137 if (statfs(default_debugfs_path, &st_fs) < 0)
138 return -ENOENT;
139 else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
140 return -ENOENT;
141 return 0;
142}
143
144static char *tracepoint_id_to_name(u64 config)
145{
146 static char tracepoint_name[2 * MAX_EVENT_LENGTH];
147 DIR *sys_dir, *evt_dir;
148 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
149 struct stat st;
150 char id_buf[4];
151 int fd;
152 u64 id;
153 char evt_path[MAXPATHLEN];
154
155 if (valid_debugfs_mount())
156 return "unkown";
157
158 sys_dir = opendir(default_debugfs_path);
159 if (!sys_dir)
160 goto cleanup;
161
162 for_each_subsystem(sys_dir, sys_dirent, sys_next, evt_path, st) {
163 evt_dir = opendir(evt_path);
164 if (!evt_dir)
165 goto cleanup;
166 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next,
167 evt_path, st) {
168 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id",
169 default_debugfs_path, sys_dirent.d_name,
170 evt_dirent.d_name);
171 fd = open(evt_path, O_RDONLY);
172 if (fd < 0)
173 continue;
174 if (read(fd, id_buf, sizeof(id_buf)) < 0) {
175 close(fd);
176 continue;
177 }
178 close(fd);
179 id = atoll(id_buf);
180 if (id == config) {
181 closedir(evt_dir);
182 closedir(sys_dir);
183 snprintf(tracepoint_name, 2 * MAX_EVENT_LENGTH,
184 "%s:%s", sys_dirent.d_name,
185 evt_dirent.d_name);
186 return tracepoint_name;
187 }
188 }
189 closedir(evt_dir);
190 }
191
192cleanup:
193 closedir(sys_dir);
194 return "unkown";
195}
196
113static int is_cache_op_valid(u8 cache_type, u8 cache_op) 197static int is_cache_op_valid(u8 cache_type, u8 cache_op)
114{ 198{
115 if (hw_cache_stat[cache_type] & COP(cache_op)) 199 if (hw_cache_stat[cache_type] & COP(cache_op))
@@ -177,6 +261,9 @@ char *event_name(int counter)
177 return sw_event_names[config]; 261 return sw_event_names[config];
178 return "unknown-software"; 262 return "unknown-software";
179 263
264 case PERF_TYPE_TRACEPOINT:
265 return tracepoint_id_to_name(config);
266
180 default: 267 default:
181 break; 268 break;
182 } 269 }
@@ -265,6 +352,53 @@ parse_generic_hw_event(const char **str, struct perf_counter_attr *attr)
265 return 1; 352 return 1;
266} 353}
267 354
355static int parse_tracepoint_event(const char **strp,
356 struct perf_counter_attr *attr)
357{
358 const char *evt_name;
359 char sys_name[MAX_EVENT_LENGTH];
360 char id_buf[4];
361 int fd;
362 unsigned int sys_length, evt_length;
363 u64 id;
364 char evt_path[MAXPATHLEN];
365
366 if (valid_debugfs_mount())
367 return 0;
368
369 evt_name = strchr(*strp, ':');
370 if (!evt_name)
371 return 0;
372
373 sys_length = evt_name - *strp;
374 if (sys_length >= MAX_EVENT_LENGTH)
375 return 0;
376
377 strncpy(sys_name, *strp, sys_length);
378 sys_name[sys_length] = '\0';
379 evt_name = evt_name + 1;
380 evt_length = strlen(evt_name);
381 if (evt_length >= MAX_EVENT_LENGTH)
382 return 0;
383
384 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", default_debugfs_path,
385 sys_name, evt_name);
386 fd = open(evt_path, O_RDONLY);
387 if (fd < 0)
388 return 0;
389
390 if (read(fd, id_buf, sizeof(id_buf)) < 0) {
391 close(fd);
392 return 0;
393 }
394 close(fd);
395 id = atoll(id_buf);
396 attr->config = id;
397 attr->type = PERF_TYPE_TRACEPOINT;
398 *strp = evt_name + evt_length;
399 return 1;
400}
401
268static int check_events(const char *str, unsigned int i) 402static int check_events(const char *str, unsigned int i)
269{ 403{
270 int n; 404 int n;
@@ -374,7 +508,8 @@ parse_event_modifier(const char **strp, struct perf_counter_attr *attr)
374 */ 508 */
375static int parse_event_symbols(const char **str, struct perf_counter_attr *attr) 509static int parse_event_symbols(const char **str, struct perf_counter_attr *attr)
376{ 510{
377 if (!(parse_raw_event(str, attr) || 511 if (!(parse_tracepoint_event(str, attr) ||
512 parse_raw_event(str, attr) ||
378 parse_numeric_event(str, attr) || 513 parse_numeric_event(str, attr) ||
379 parse_symbolic_event(str, attr) || 514 parse_symbolic_event(str, attr) ||
380 parse_generic_hw_event(str, attr))) 515 parse_generic_hw_event(str, attr)))
@@ -423,6 +558,42 @@ static const char * const event_type_descriptors[] = {
423}; 558};
424 559
425/* 560/*
561 * Print the events from <debugfs_mount_point>/tracing/events
562 */
563
564static void print_tracepoint_events(void)
565{
566 DIR *sys_dir, *evt_dir;
567 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
568 struct stat st;
569 char evt_path[MAXPATHLEN];
570
571 if (valid_debugfs_mount())
572 return;
573
574 sys_dir = opendir(default_debugfs_path);
575 if (!sys_dir)
576 goto cleanup;
577
578 for_each_subsystem(sys_dir, sys_dirent, sys_next, evt_path, st) {
579 evt_dir = opendir(evt_path);
580 if (!evt_dir)
581 goto cleanup;
582 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next,
583 evt_path, st) {
584 snprintf(evt_path, MAXPATHLEN, "%s:%s",
585 sys_dirent.d_name, evt_dirent.d_name);
586 fprintf(stderr, " %-40s [%s]\n", evt_path,
587 event_type_descriptors[PERF_TYPE_TRACEPOINT+1]);
588 }
589 closedir(evt_dir);
590 }
591
592cleanup:
593 closedir(sys_dir);
594}
595
596/*
426 * Print the help text for the event symbols: 597 * Print the help text for the event symbols:
427 */ 598 */
428void print_events(void) 599void print_events(void)
@@ -472,5 +643,7 @@ void print_events(void)
472 "rNNN"); 643 "rNNN");
473 fprintf(stderr, "\n"); 644 fprintf(stderr, "\n");
474 645
646 print_tracepoint_events();
647
475 exit(129); 648 exit(129);
476} 649}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index b4be6071c105..68fe157d72fb 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -50,6 +50,7 @@
50#include <unistd.h> 50#include <unistd.h>
51#include <stdio.h> 51#include <stdio.h>
52#include <sys/stat.h> 52#include <sys/stat.h>
53#include <sys/statfs.h>
53#include <fcntl.h> 54#include <fcntl.h>
54#include <stddef.h> 55#include <stddef.h>
55#include <stdlib.h> 56#include <stdlib.h>
@@ -80,6 +81,7 @@
80#include <netdb.h> 81#include <netdb.h>
81#include <pwd.h> 82#include <pwd.h>
82#include <inttypes.h> 83#include <inttypes.h>
84#include "../../../include/linux/magic.h"
83 85
84#ifndef NO_ICONV 86#ifndef NO_ICONV
85#include <iconv.h> 87#include <iconv.h>