summaryrefslogtreecommitdiff
path: root/tools/perf/util/evlist.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/evlist.c')
-rw-r--r--tools/perf/util/evlist.c288
1 files changed, 73 insertions, 215 deletions
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index bbc746a..e584cd3 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -18,7 +18,6 @@
#include <unistd.h>
#include "parse-events.h"
-#include "parse-options.h"
#include <sys/mman.h>
@@ -50,18 +49,6 @@ struct perf_evlist *perf_evlist__new(void)
return evlist;
}
-struct perf_evlist *perf_evlist__new_default(void)
-{
- struct perf_evlist *evlist = perf_evlist__new();
-
- if (evlist && perf_evlist__add_default(evlist)) {
- perf_evlist__delete(evlist);
- evlist = NULL;
- }
-
- return evlist;
-}
-
/**
* perf_evlist__set_id_pos - set the positions of event ids.
* @evlist: selected event list
@@ -117,8 +104,6 @@ void perf_evlist__delete(struct perf_evlist *evlist)
void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
{
list_add_tail(&entry->node, &evlist->entries);
- entry->idx = evlist->nr_entries;
-
if (!evlist->nr_entries++)
perf_evlist__set_id_pos(evlist);
}
@@ -167,7 +152,7 @@ int perf_evlist__add_default(struct perf_evlist *evlist)
event_attr_init(&attr);
- evsel = perf_evsel__new(&attr);
+ evsel = perf_evsel__new(&attr, 0);
if (evsel == NULL)
goto error;
@@ -192,7 +177,7 @@ static int perf_evlist__add_attrs(struct perf_evlist *evlist,
size_t i;
for (i = 0; i < nr_attrs; i++) {
- evsel = perf_evsel__new_idx(attrs + i, evlist->nr_entries + i);
+ evsel = perf_evsel__new(attrs + i, evlist->nr_entries + i);
if (evsel == NULL)
goto out_delete_partial_list;
list_add_tail(&evsel->node, &head);
@@ -251,12 +236,13 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist,
int perf_evlist__add_newtp(struct perf_evlist *evlist,
const char *sys, const char *name, void *handler)
{
- struct perf_evsel *evsel = perf_evsel__newtp(sys, name);
+ struct perf_evsel *evsel;
+ evsel = perf_evsel__newtp(sys, name, evlist->nr_entries);
if (evsel == NULL)
return -1;
- evsel->handler = handler;
+ evsel->handler.func = handler;
perf_evlist__add(evlist, evsel);
return 0;
}
@@ -541,7 +527,7 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
if ((old & md->mask) + size != ((old + size) & md->mask)) {
unsigned int offset = old;
unsigned int len = min(sizeof(*event), size), cpy;
- void *dst = md->event_copy;
+ void *dst = &md->event_copy;
do {
cpy = min(md->mask + 1 - (offset & md->mask), len);
@@ -551,7 +537,7 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
len -= cpy;
} while (len);
- event = (union perf_event *) md->event_copy;
+ event = &md->event_copy;
}
old += size;
@@ -608,8 +594,6 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist,
evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot,
MAP_SHARED, fd, 0);
if (evlist->mmap[idx].base == MAP_FAILED) {
- pr_debug2("failed to mmap perf event ring buffer, error %d\n",
- errno);
evlist->mmap[idx].base = NULL;
return -1;
}
@@ -618,36 +602,9 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist,
return 0;
}
-static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
- int prot, int mask, int cpu, int thread,
- int *output)
+static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int mask)
{
struct perf_evsel *evsel;
-
- list_for_each_entry(evsel, &evlist->entries, node) {
- int fd = FD(evsel, cpu, thread);
-
- if (*output == -1) {
- *output = fd;
- if (__perf_evlist__mmap(evlist, idx, prot, mask,
- *output) < 0)
- return -1;
- } else {
- if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
- return -1;
- }
-
- if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
- perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0)
- return -1;
- }
-
- return 0;
-}
-
-static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot,
- int mask)
-{
int cpu, thread;
int nr_cpus = cpu_map__nr(evlist->cpus);
int nr_threads = thread_map__nr(evlist->threads);
@@ -657,9 +614,23 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot,
int output = -1;
for (thread = 0; thread < nr_threads; thread++) {
- if (perf_evlist__mmap_per_evsel(evlist, cpu, prot, mask,
- cpu, thread, &output))
- goto out_unmap;
+ list_for_each_entry(evsel, &evlist->entries, node) {
+ int fd = FD(evsel, cpu, thread);
+
+ if (output == -1) {
+ output = fd;
+ if (__perf_evlist__mmap(evlist, cpu,
+ prot, mask, output) < 0)
+ goto out_unmap;
+ } else {
+ if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, output) != 0)
+ goto out_unmap;
+ }
+
+ if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
+ perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0)
+ goto out_unmap;
+ }
}
}
@@ -671,9 +642,9 @@ out_unmap:
return -1;
}
-static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot,
- int mask)
+static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, int mask)
{
+ struct perf_evsel *evsel;
int thread;
int nr_threads = thread_map__nr(evlist->threads);
@@ -681,9 +652,23 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot,
for (thread = 0; thread < nr_threads; thread++) {
int output = -1;
- if (perf_evlist__mmap_per_evsel(evlist, thread, prot, mask, 0,
- thread, &output))
- goto out_unmap;
+ list_for_each_entry(evsel, &evlist->entries, node) {
+ int fd = FD(evsel, 0, thread);
+
+ if (output == -1) {
+ output = fd;
+ if (__perf_evlist__mmap(evlist, thread,
+ prot, mask, output) < 0)
+ goto out_unmap;
+ } else {
+ if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, output) != 0)
+ goto out_unmap;
+ }
+
+ if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
+ perf_evlist__id_add_fd(evlist, evsel, 0, thread, fd) < 0)
+ goto out_unmap;
+ }
}
return 0;
@@ -694,90 +679,20 @@ out_unmap:
return -1;
}
-static size_t perf_evlist__mmap_size(unsigned long pages)
-{
- /* 512 kiB: default amount of unprivileged mlocked memory */
- if (pages == UINT_MAX)
- pages = (512 * 1024) / page_size;
- else if (!is_power_of_2(pages))
- return 0;
-
- return (pages + 1) * page_size;
-}
-
-static long parse_pages_arg(const char *str, unsigned long min,
- unsigned long max)
-{
- unsigned long pages, val;
- static struct parse_tag tags[] = {
- { .tag = 'B', .mult = 1 },
- { .tag = 'K', .mult = 1 << 10 },
- { .tag = 'M', .mult = 1 << 20 },
- { .tag = 'G', .mult = 1 << 30 },
- { .tag = 0 },
- };
-
- if (str == NULL)
- return -EINVAL;
-
- val = parse_tag_value(str, tags);
- if (val != (unsigned long) -1) {
- /* we got file size value */
- pages = PERF_ALIGN(val, page_size) / page_size;
- } else {
- /* we got pages count value */
- char *eptr;
- pages = strtoul(str, &eptr, 10);
- if (*eptr != '\0')
- return -EINVAL;
- }
-
- if ((pages == 0) && (min == 0)) {
- /* leave number of pages at 0 */
- } else if (pages < (1UL << 31) && !is_power_of_2(pages)) {
- /* round pages up to next power of 2 */
- pages = next_pow2(pages);
- pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n",
- pages * page_size, pages);
- }
-
- if (pages > max)
- return -EINVAL;
-
- return pages;
-}
-
-int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,
- int unset __maybe_unused)
-{
- unsigned int *mmap_pages = opt->value;
- unsigned long max = UINT_MAX;
- long pages;
-
- if (max < SIZE_MAX / page_size)
- max = SIZE_MAX / page_size;
-
- pages = parse_pages_arg(str, 1, max);
- if (pages < 0) {
- pr_err("Invalid argument for --mmap_pages/-m\n");
- return -1;
- }
-
- *mmap_pages = pages;
- return 0;
-}
-
-/**
- * perf_evlist__mmap - Create mmaps to receive events.
- * @evlist: list of events
- * @pages: map length in pages
- * @overwrite: overwrite older events?
+/** perf_evlist__mmap - Create per cpu maps to receive events
+ *
+ * @evlist - list of events
+ * @pages - map length in pages
+ * @overwrite - overwrite older events?
*
- * If @overwrite is %false the user needs to signal event consumption using
- * perf_mmap__write_tail(). Using perf_evlist__mmap_read() does this
- * automatically.
+ * If overwrite is false the user needs to signal event consuption using:
*
- * Return: %0 on success, negative error code otherwise.
+ * struct perf_mmap *m = &evlist->mmap[cpu];
+ * unsigned int head = perf_mmap__read_head(m);
+ *
+ * perf_mmap__write_tail(m, head)
+ *
+ * Using perf_evlist__read_on_cpu does this automatically.
*/
int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
bool overwrite)
@@ -787,6 +702,14 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
const struct thread_map *threads = evlist->threads;
int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), mask;
+ /* 512 kiB: default amount of unprivileged mlocked memory */
+ if (pages == UINT_MAX)
+ pages = (512 * 1024) / page_size;
+ else if (!is_power_of_2(pages))
+ return -EINVAL;
+
+ mask = pages * page_size - 1;
+
if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0)
return -ENOMEM;
@@ -794,9 +717,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
return -ENOMEM;
evlist->overwrite = overwrite;
- evlist->mmap_len = perf_evlist__mmap_size(pages);
- pr_debug("mmap size %zuB\n", evlist->mmap_len);
- mask = evlist->mmap_len - page_size - 1;
+ evlist->mmap_len = (pages + 1) * page_size;
list_for_each_entry(evsel, &evlist->entries, node) {
if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
@@ -811,7 +732,8 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
return perf_evlist__mmap_per_cpu(evlist, prot, mask);
}
-int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
+int perf_evlist__create_maps(struct perf_evlist *evlist,
+ struct perf_target *target)
{
evlist->threads = thread_map__new_str(target->pid, target->tid,
target->uid);
@@ -819,11 +741,9 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
if (evlist->threads == NULL)
return -1;
- if (target->force_per_cpu)
- evlist->cpus = cpu_map__new(target->cpu_list);
- else if (target__has_task(target))
+ if (perf_target__has_task(target))
evlist->cpus = cpu_map__dummy_new();
- else if (!target__has_cpu(target) && !target->uses_mmap)
+ else if (!perf_target__has_cpu(target) && !target->uses_mmap)
evlist->cpus = cpu_map__dummy_new();
else
evlist->cpus = cpu_map__new(target->cpu_list);
@@ -1032,7 +952,8 @@ out_err:
return err;
}
-int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target,
+int perf_evlist__prepare_workload(struct perf_evlist *evlist,
+ struct perf_target *target,
const char *argv[], bool pipe_output,
bool want_signal)
{
@@ -1084,7 +1005,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
exit(-1);
}
- if (target__none(target))
+ if (perf_target__none(target))
evlist->threads->map[0] = evlist->workload.pid;
close(child_ready_pipe[1]);
@@ -1150,68 +1071,5 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)
perf_evsel__name(evsel));
}
- return printed + fprintf(fp, "\n");
-}
-
-int perf_evlist__strerror_tp(struct perf_evlist *evlist __maybe_unused,
- int err, char *buf, size_t size)
-{
- char sbuf[128];
-
- switch (err) {
- case ENOENT:
- scnprintf(buf, size, "%s",
- "Error:\tUnable to find debugfs\n"
- "Hint:\tWas your kernel was compiled with debugfs support?\n"
- "Hint:\tIs the debugfs filesystem mounted?\n"
- "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'");
- break;
- case EACCES:
- scnprintf(buf, size,
- "Error:\tNo permissions to read %s/tracing/events/raw_syscalls\n"
- "Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n",
- debugfs_mountpoint, debugfs_mountpoint);
- break;
- default:
- scnprintf(buf, size, "%s", strerror_r(err, sbuf, sizeof(sbuf)));
- break;
- }
-
- return 0;
-}
-
-int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
- int err, char *buf, size_t size)
-{
- int printed, value;
- char sbuf[128], *emsg = strerror_r(err, sbuf, sizeof(sbuf));
-
- switch (err) {
- case EACCES:
- case EPERM:
- printed = scnprintf(buf, size,
- "Error:\t%s.\n"
- "Hint:\tCheck /proc/sys/kernel/perf_event_paranoid setting.", emsg);
-
- if (filename__read_int("/proc/sys/kernel/perf_event_paranoid", &value))
- break;
-
- printed += scnprintf(buf + printed, size - printed, "\nHint:\t");
-
- if (value >= 2) {
- printed += scnprintf(buf + printed, size - printed,
- "For your workloads it needs to be <= 1\nHint:\t");
- }
- printed += scnprintf(buf + printed, size - printed,
- "For system wide tracing it needs to be set to -1");
-
- printed += scnprintf(buf + printed, size - printed,
- ".\nHint:\tThe current value is %d.", value);
- break;
- default:
- scnprintf(buf, size, "%s", emsg);
- break;
- }
-
- return 0;
+ return printed + fprintf(fp, "\n");;
}