#include "exec_cmd.h"
#include "string.h"
#include "cache.h"
+#include "header.h"
int nr_counters;
-struct perf_counter_attr attrs[MAX_COUNTERS];
+struct perf_event_attr attrs[MAX_COUNTERS];
struct event_symbol {
u8 type;
{ CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" },
};
-#define __PERF_COUNTER_FIELD(config, name) \
- ((config & PERF_COUNTER_##name##_MASK) >> PERF_COUNTER_##name##_SHIFT)
+#define __PERF_EVENT_FIELD(config, name) \
+ ((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT)
-#define PERF_COUNTER_RAW(config) __PERF_COUNTER_FIELD(config, RAW)
-#define PERF_COUNTER_CONFIG(config) __PERF_COUNTER_FIELD(config, CONFIG)
-#define PERF_COUNTER_TYPE(config) __PERF_COUNTER_FIELD(config, TYPE)
-#define PERF_COUNTER_ID(config) __PERF_COUNTER_FIELD(config, EVENT)
+#define PERF_EVENT_RAW(config) __PERF_EVENT_FIELD(config, RAW)
+#define PERF_EVENT_CONFIG(config) __PERF_EVENT_FIELD(config, CONFIG)
+#define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE)
+#define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT)
static const char *hw_event_names[] = {
"cycles",
(strcmp(evt_dirent.d_name, "..")) && \
(!tp_event_has_id(&sys_dirent, &evt_dirent)))
-#define MAX_EVENT_LENGTH 30
+#define MAX_EVENT_LENGTH 512
int valid_debugfs_mount(const char *debugfs)
{
DIR *sys_dir, *evt_dir;
struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
char id_buf[4];
- int sys_dir_fd, fd;
+ int fd;
u64 id;
char evt_path[MAXPATHLEN];
+ char dir_path[MAXPATHLEN];
if (valid_debugfs_mount(debugfs_path))
return NULL;
sys_dir = opendir(debugfs_path);
if (!sys_dir)
- goto cleanup;
- sys_dir_fd = dirfd(sys_dir);
+ return NULL;
for_each_subsystem(sys_dir, sys_dirent, sys_next) {
- int dfd = openat(sys_dir_fd, sys_dirent.d_name,
- O_RDONLY|O_DIRECTORY), evt_dir_fd;
- if (dfd == -1)
- continue;
- evt_dir = fdopendir(dfd);
- if (!evt_dir) {
- close(dfd);
+
+ snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
+ sys_dirent.d_name);
+ evt_dir = opendir(dir_path);
+ if (!evt_dir)
continue;
- }
- evt_dir_fd = dirfd(evt_dir);
+
for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
- snprintf(evt_path, MAXPATHLEN, "%s/id",
+
+ snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
evt_dirent.d_name);
- fd = openat(evt_dir_fd, evt_path, O_RDONLY);
+ fd = open(evt_path, O_RDONLY);
if (fd < 0)
continue;
if (read(fd, id_buf, sizeof(id_buf)) < 0) {
closedir(evt_dir);
}
-cleanup:
closedir(sys_dir);
return NULL;
}
}
static enum event_result
-parse_generic_hw_event(const char **str, struct perf_counter_attr *attr)
+parse_generic_hw_event(const char **str, struct perf_event_attr *attr)
{
const char *s = *str;
int cache_type = -1, cache_op = -1, cache_result = -1;
const char *evt_name,
unsigned int evt_length,
char *flags,
- struct perf_counter_attr *attr,
+ struct perf_event_attr *attr,
const char **strp)
{
char evt_path[MAXPATHLEN];
int fd;
if (flags) {
- if (!strncmp(flags, "record", strlen(flags)))
+ if (!strncmp(flags, "record", strlen(flags))) {
attr->sample_type |= PERF_SAMPLE_RAW;
+ attr->sample_type |= PERF_SAMPLE_TIME;
+ attr->sample_type |= PERF_SAMPLE_CPU;
+ }
}
snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
static enum event_result parse_tracepoint_event(const char **strp,
- struct perf_counter_attr *attr)
+ struct perf_event_attr *attr)
{
const char *evt_name;
char *flags;
}
static enum event_result
-parse_symbolic_event(const char **strp, struct perf_counter_attr *attr)
+parse_symbolic_event(const char **strp, struct perf_event_attr *attr)
{
const char *str = *strp;
unsigned int i;
}
static enum event_result
-parse_raw_event(const char **strp, struct perf_counter_attr *attr)
+parse_raw_event(const char **strp, struct perf_event_attr *attr)
{
const char *str = *strp;
u64 config;
}
static enum event_result
-parse_numeric_event(const char **strp, struct perf_counter_attr *attr)
+parse_numeric_event(const char **strp, struct perf_event_attr *attr)
{
const char *str = *strp;
char *endp;
}
static enum event_result
-parse_event_modifier(const char **strp, struct perf_counter_attr *attr)
+parse_event_modifier(const char **strp, struct perf_event_attr *attr)
{
const char *str = *strp;
int eu = 1, ek = 1, eh = 1;
* Symbolic names are (almost) exactly matched.
*/
static enum event_result
-parse_event_symbols(const char **str, struct perf_counter_attr *attr)
+parse_event_symbols(const char **str, struct perf_event_attr *attr)
{
enum event_result ret;
return ret;
}
+static void store_event_type(const char *orgname)
+{
+ char filename[PATH_MAX], *c;
+ FILE *file;
+ int id;
+
+ sprintf(filename, "/sys/kernel/debug/tracing/events/%s/id", orgname);
+ c = strchr(filename, ':');
+ if (c)
+ *c = '/';
+
+ file = fopen(filename, "r");
+ if (!file)
+ return;
+ if (fscanf(file, "%i", &id) < 1)
+ die("cannot store event ID");
+ fclose(file);
+ perf_header__push_event(id, orgname);
+}
+
+
int parse_events(const struct option *opt __used, const char *str, int unset __used)
{
- struct perf_counter_attr attr;
+ struct perf_event_attr attr;
enum event_result ret;
+ if (strchr(str, ':'))
+ store_event_type(str);
+
for (;;) {
if (nr_counters == MAX_COUNTERS)
return -1;
{
DIR *sys_dir, *evt_dir;
struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
- int sys_dir_fd;
char evt_path[MAXPATHLEN];
+ char dir_path[MAXPATHLEN];
if (valid_debugfs_mount(debugfs_path))
return;
sys_dir = opendir(debugfs_path);
if (!sys_dir)
- goto cleanup;
- sys_dir_fd = dirfd(sys_dir);
+ return;
for_each_subsystem(sys_dir, sys_dirent, sys_next) {
- int dfd = openat(sys_dir_fd, sys_dirent.d_name,
- O_RDONLY|O_DIRECTORY), evt_dir_fd;
- if (dfd == -1)
- continue;
- evt_dir = fdopendir(dfd);
- if (!evt_dir) {
- close(dfd);
+
+ snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
+ sys_dirent.d_name);
+ evt_dir = opendir(dir_path);
+ if (!evt_dir)
continue;
- }
- evt_dir_fd = dirfd(evt_dir);
+
for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
snprintf(evt_path, MAXPATHLEN, "%s:%s",
sys_dirent.d_name, evt_dirent.d_name);
}
closedir(evt_dir);
}
-
-cleanup:
closedir(sys_dir);
}