diff options
Diffstat (limited to 'tools/perf/util/evlist.c')
-rw-r--r-- | tools/perf/util/evlist.c | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 3cebc9a8d52e..b4b54d84e9b0 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1175,11 +1175,51 @@ void perf_evlist__close(struct perf_evlist *evlist) } } +static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist) +{ + int err = -ENOMEM; + + /* + * Try reading /sys/devices/system/cpu/online to get + * an all cpus map. + * + * FIXME: -ENOMEM is the best we can do here, the cpu_map + * code needs an overhaul to properly forward the + * error, and we may not want to do that fallback to a + * default cpu identity map :-\ + */ + evlist->cpus = cpu_map__new(NULL); + if (evlist->cpus == NULL) + goto out; + + evlist->threads = thread_map__new_dummy(); + if (evlist->threads == NULL) + goto out_free_cpus; + + err = 0; +out: + return err; +out_free_cpus: + cpu_map__delete(evlist->cpus); + evlist->cpus = NULL; + goto out; +} + int perf_evlist__open(struct perf_evlist *evlist) { struct perf_evsel *evsel; int err; + /* + * Default: one fd per CPU, all threads, aka systemwide + * as sys_perf_event_open(cpu = -1, thread = -1) is EINVAL + */ + if (evlist->threads == NULL && evlist->cpus == NULL) { + err = perf_evlist__create_syswide_maps(evlist); + if (err < 0) + goto out_err; + } + perf_evlist__update_id_pos(evlist); evlist__for_each(evlist, evsel) { @@ -1276,8 +1316,14 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar sigaction(SIGUSR1, &act, NULL); } - if (target__none(target)) + if (target__none(target)) { + if (evlist->threads == NULL) { + fprintf(stderr, "FATAL: evlist->threads need to be set at this point (%s:%d).\n", + __func__, __LINE__); + goto out_close_pipes; + } evlist->threads->map[0] = evlist->workload.pid; + } close(child_ready_pipe[1]); close(go_pipe[0]); |