diff options
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/config.c | 2 | ||||
-rw-r--r-- | tools/perf/util/evsel.c | 90 | ||||
-rw-r--r-- | tools/perf/util/evsel.h | 3 | ||||
-rw-r--r-- | tools/perf/util/parse-events.c | 27 | ||||
-rw-r--r-- | tools/perf/util/thread_map.c | 21 |
5 files changed, 115 insertions, 28 deletions
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index 0deac6a14b65..6faa3a18bfbd 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c @@ -120,7 +120,7 @@ static char *parse_value(void) static inline int iskeychar(int c) { - return isalnum(c) || c == '-'; + return isalnum(c) || c == '-' || c == '_'; } static int get_value(config_fn_t fn, void *data, char *name, unsigned int len) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 57e4ce57bbcc..91d19138f3ec 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -15,6 +15,7 @@ #include "cpumap.h" #include "thread_map.h" #include "target.h" +#include "../../include/linux/perf_event.h" #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) #define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0)) @@ -64,6 +65,95 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx) return evsel; } +static const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = { + "cycles", + "instructions", + "cache-references", + "cache-misses", + "branches", + "branch-misses", + "bus-cycles", + "stalled-cycles-frontend", + "stalled-cycles-backend", + "ref-cycles", +}; + +const char *__perf_evsel__hw_name(u64 config) +{ + if (config < PERF_COUNT_HW_MAX && perf_evsel__hw_names[config]) + return perf_evsel__hw_names[config]; + + return "unknown-hardware"; +} + +static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size) +{ + int colon = 0; + struct perf_event_attr *attr = &evsel->attr; + int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(attr->config)); + bool exclude_guest_default = false; + +#define MOD_PRINT(context, mod) do { \ + if (!attr->exclude_##context) { \ + if (!colon) colon = r++; \ + r += scnprintf(bf + r, size - r, "%c", mod); \ + } } while(0) + + if (attr->exclude_kernel || attr->exclude_user || attr->exclude_hv) { + MOD_PRINT(kernel, 'k'); + MOD_PRINT(user, 'u'); + MOD_PRINT(hv, 'h'); + exclude_guest_default = true; + } + + if (attr->precise_ip) { + if (!colon) + colon = r++; + r += scnprintf(bf + r, size - r, "%.*s", attr->precise_ip, "ppp"); + exclude_guest_default = true; + } + + if (attr->exclude_host || attr->exclude_guest == exclude_guest_default) { + MOD_PRINT(host, 'H'); + MOD_PRINT(guest, 'G'); + } +#undef MOD_PRINT + if (colon) + bf[colon] = ':'; + return r; +} + +int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size) +{ + int ret; + + switch (evsel->attr.type) { + case PERF_TYPE_RAW: + ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config); + break; + + case PERF_TYPE_HARDWARE: + ret = perf_evsel__hw_name(evsel, bf, size); + break; + default: + /* + * FIXME + * + * This is the minimal perf_evsel__name so that we can + * reconstruct event names taking into account event modifiers. + * + * The old event_name uses it now for raw anr hw events, so that + * we don't drag all the parsing stuff into the python binding. + * + * On the next devel cycle the rest of the event naming will be + * brought here. + */ + return 0; + } + + return ret; +} + void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts, struct perf_evsel *first) { diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 3d6b3e4cb66b..4ba8b564e6f4 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -83,6 +83,9 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts, struct perf_evsel *first); +const char* __perf_evsel__hw_name(u64 config); +int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size); + int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads); int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus); diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index fac7d59309b8..05dbc8b3c767 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -62,19 +62,6 @@ static struct event_symbol event_symbols[] = { #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[PERF_COUNT_HW_MAX] = { - "cycles", - "instructions", - "cache-references", - "cache-misses", - "branches", - "branch-misses", - "bus-cycles", - "stalled-cycles-frontend", - "stalled-cycles-backend", - "ref-cycles", -}; - static const char *sw_event_names[PERF_COUNT_SW_MAX] = { "cpu-clock", "task-clock", @@ -300,6 +287,16 @@ const char *event_name(struct perf_evsel *evsel) u64 config = evsel->attr.config; int type = evsel->attr.type; + if (type == PERF_TYPE_RAW || type == PERF_TYPE_HARDWARE) { + /* + * XXX minimal fix, see comment on perf_evsen__name, this static buffer + * will go away together with event_name in the next devel cycle. + */ + static char bf[128]; + perf_evsel__name(evsel, bf, sizeof(bf)); + return bf; + } + if (evsel->name) return evsel->name; @@ -317,9 +314,7 @@ const char *__event_name(int type, u64 config) switch (type) { case PERF_TYPE_HARDWARE: - if (config < PERF_COUNT_HW_MAX && hw_event_names[config]) - return hw_event_names[config]; - return "unknown-hardware"; + return __perf_evsel__hw_name(config); case PERF_TYPE_HW_CACHE: { u8 cache_type, cache_op, cache_result; diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c index 84d9bd782004..9b5f856cc280 100644 --- a/tools/perf/util/thread_map.c +++ b/tools/perf/util/thread_map.c @@ -188,28 +188,27 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str) nt = realloc(threads, (sizeof(*threads) + sizeof(pid_t) * total_tasks)); if (nt == NULL) - goto out_free_threads; + goto out_free_namelist; threads = nt; - if (threads) { - for (i = 0; i < items; i++) - threads->map[j++] = atoi(namelist[i]->d_name); - threads->nr = total_tasks; - } - - for (i = 0; i < items; i++) + for (i = 0; i < items; i++) { + threads->map[j++] = atoi(namelist[i]->d_name); free(namelist[i]); + } + threads->nr = total_tasks; free(namelist); - - if (!threads) - break; } out: strlist__delete(slist); return threads; +out_free_namelist: + for (i = 0; i < items; i++) + free(namelist[i]); + free(namelist); + out_free_threads: free(threads); threads = NULL; |