perf evlist: Add reference count

This a no-op for most of the perf tool. The reference count is set to
1 at allocation, the put will see the 1, decrement it and perform the
delete.

The purpose for adding the reference count is for the python code. Prior
to this change the python code would clone evlists, but this has issues
if events are opened, etc.

This change adds a reference count for the evlists and a later change
will add it to evsels. The combination is needed for the python code to
operate correctly (not hit asserts in the evsel clone), but the changes
are broken apart for the sake of smaller patches.

Assisted-by: Gemini:gemini-3.1-pro-preview
Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alice Rogers <alice.mei.rogers@gmail.com>
Cc: Dapeng Mi <dapeng1.mi@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Leo Yan <leo.yan@linux.dev>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
This commit is contained in:
Ian Rogers
2026-06-15 18:15:27 -07:00
committed by Namhyung Kim
parent ea43eb1151
commit 3c45ce5ae3
54 changed files with 315 additions and 328 deletions

View File

@@ -268,7 +268,7 @@ static int test_event(const struct evlist_test *e)
ret = e->check(evlist);
}
parse_events_error__exit(&err);
evlist__delete(evlist);
evlist__put(evlist);
return ret;
}

View File

@@ -56,7 +56,7 @@ static int event_cb(void *state, struct pmu_event_info *info)
*ret = TEST_FAIL;
}
}
evlist__delete(evlist);
evlist__put(evlist);
return 0;
}
@@ -174,7 +174,7 @@ static int test_sort(const char *str, int expected_slots_group_size,
CHECK_COND(slots_seen, "slots seen");
ret = TEST_OK;
out_err:
evlist__delete(evlist);
evlist__put(evlist);
parse_events_error__exit(&err);
return ret;
}

View File

@@ -337,7 +337,7 @@ int iostat_prepare(struct evlist *evlist, struct perf_stat_config *config)
if (evlist->core.nr_entries > 0) {
pr_warning("The -e and -M options are not supported."
"All chosen events/metrics will be dropped\n");
evlist__delete(evlist);
evlist__put(evlist);
evlist = evlist__new();
if (!evlist)
return -ENOMEM;

View File

@@ -76,7 +76,7 @@ static struct evlist *bench__create_evlist(char *evstr, const char *uid_str)
parse_events_error__exit(&err);
pr_err("Run 'perf list' for a list of valid events\n");
ret = 1;
goto out_delete_evlist;
goto out_put_evlist;
}
parse_events_error__exit(&err);
if (uid_str) {
@@ -85,24 +85,24 @@ static struct evlist *bench__create_evlist(char *evstr, const char *uid_str)
if (uid == UINT_MAX) {
pr_err("Invalid User: %s", uid_str);
ret = -EINVAL;
goto out_delete_evlist;
goto out_put_evlist;
}
ret = parse_uid_filter(evlist, uid);
if (ret)
goto out_delete_evlist;
goto out_put_evlist;
}
ret = evlist__create_maps(evlist, &opts.target);
if (ret < 0) {
pr_err("Not enough memory to create thread/cpu maps\n");
goto out_delete_evlist;
goto out_put_evlist;
}
evlist__config(evlist, &opts, NULL);
return evlist;
out_delete_evlist:
evlist__delete(evlist);
out_put_evlist:
evlist__put(evlist);
return NULL;
}
@@ -151,7 +151,7 @@ static int bench_evlist_open_close__run(char *evstr, const char *uid_str)
evlist->core.nr_entries, evlist__count_evsel_fds(evlist));
printf(" Number of iterations:\t%d\n", iterations);
evlist__delete(evlist);
evlist__put(evlist);
for (i = 0; i < iterations; i++) {
pr_debug("Started iteration %d\n", i);
@@ -162,7 +162,7 @@ static int bench_evlist_open_close__run(char *evstr, const char *uid_str)
gettimeofday(&start, NULL);
err = bench__do_evlist_open_close(evlist);
if (err) {
evlist__delete(evlist);
evlist__put(evlist);
return err;
}
@@ -171,7 +171,7 @@ static int bench_evlist_open_close__run(char *evstr, const char *uid_str)
runtime_us = timeval2usec(&diff);
update_stats(&time_stats, runtime_us);
evlist__delete(evlist);
evlist__put(evlist);
pr_debug("Iteration %d took:\t%" PRIu64 "us\n", i, runtime_us);
}

View File

@@ -1999,20 +1999,20 @@ int cmd_ftrace(int argc, const char **argv)
ret = evlist__create_maps(ftrace.evlist, &ftrace.target);
if (ret < 0)
goto out_delete_evlist;
goto out_put_evlist;
if (argc) {
ret = evlist__prepare_workload(ftrace.evlist, &ftrace.target,
argv, false,
ftrace__workload_exec_failed_signal);
if (ret < 0)
goto out_delete_evlist;
goto out_put_evlist;
}
ret = cmd_func(&ftrace);
out_delete_evlist:
evlist__delete(ftrace.evlist);
out_put_evlist:
evlist__put(ftrace.evlist);
out_delete_filters:
delete_filter_func(&ftrace.filters);

View File

@@ -1810,7 +1810,7 @@ static struct evlist *kvm_live_event_list(void)
out:
if (err) {
evlist__delete(evlist);
evlist__put(evlist);
evlist = NULL;
}
@@ -1941,7 +1941,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
out:
perf_session__delete(kvm->session);
kvm->session = NULL;
evlist__delete(kvm->evlist);
evlist__put(kvm->evlist);
return err;
}

View File

@@ -2149,7 +2149,7 @@ static int __cmd_contention(int argc, const char **argv)
out_delete:
lock_filter_finish();
evlist__delete(con.evlist);
evlist__put(con.evlist);
lock_contention_finish(&con);
perf_session__delete(session);
perf_env__exit(&host_env);

View File

@@ -4291,7 +4291,7 @@ int cmd_record(int argc, const char **argv)
goto out;
evlist__splice_list_tail(rec->evlist, &def_evlist->core.entries);
evlist__delete(def_evlist);
evlist__put(def_evlist);
}
if (rec->opts.target.tid && !rec->opts.no_inherit_set)
@@ -4401,7 +4401,7 @@ int cmd_record(int argc, const char **argv)
auxtrace_record__free(rec->itr);
out_opts:
evlist__close_control(rec->opts.ctl_fd, rec->opts.ctl_fd_ack, &rec->opts.ctl_fd_close);
evlist__delete(rec->evlist);
evlist__put(rec->evlist);
return err;
}

View File

@@ -3924,7 +3924,7 @@ static int perf_sched__schedstat_record(struct perf_sched *sched,
session = perf_session__new(&data, &sched->tool);
if (IS_ERR(session)) {
pr_err("Perf session creation failed.\n");
evlist__delete(evlist);
evlist__put(evlist);
return PTR_ERR(session);
}
@@ -4023,7 +4023,7 @@ static int perf_sched__schedstat_record(struct perf_sched *sched,
else
fprintf(stderr, "[ perf sched stats: Failed !! ]\n");
evlist__delete(evlist);
evlist__put(evlist);
close(fd);
return err;
}
@@ -4927,7 +4927,7 @@ static int perf_sched__schedstat_live(struct perf_sched *sched,
free_cpu_domain_info(cd_map, sv, nr);
out:
free_schedstat(&cpu_head);
evlist__delete(evlist);
evlist__put(evlist);
return err;
}

View File

@@ -2274,7 +2274,7 @@ static int script_find_metrics(const struct pmu_metric *pm,
}
pr_debug("Found metric '%s' whose evsels match those of in the perf data\n",
pm->metric_name);
evlist__delete(metric_evlist);
evlist__put(metric_evlist);
out:
return 0;
}

View File

@@ -2119,7 +2119,7 @@ static int add_default_events(void)
stat_config.user_requested_cpu_list,
stat_config.system_wide,
stat_config.hardware_aware_grouping) < 0) {
evlist__delete(metric_evlist);
evlist__put(metric_evlist);
ret = -1;
break;
}
@@ -2131,7 +2131,7 @@ static int add_default_events(void)
metricgroup__copy_metric_events(evlist, /*cgrp=*/NULL,
&evlist->metric_events,
&metric_evlist->metric_events);
evlist__delete(metric_evlist);
evlist__put(metric_evlist);
}
list_sort(/*priv=*/NULL, &evlist->core.entries, default_evlist_evsel_cmp);
@@ -2152,7 +2152,7 @@ static int add_default_events(void)
metricgroup__copy_metric_events(evsel_list, /*cgrp=*/NULL,
&evsel_list->metric_events,
&evlist->metric_events);
evlist__delete(evlist);
evlist__put(evlist);
return ret;
}
@@ -2387,7 +2387,7 @@ static int __cmd_report(int argc, const char **argv)
perf_stat.session = session;
stat_config.output = stderr;
evlist__delete(evsel_list);
evlist__put(evsel_list);
evsel_list = session->evlist;
ret = perf_session__process_events(session);
@@ -3066,7 +3066,7 @@ int cmd_stat(int argc, const char **argv)
if (smi_cost && smi_reset)
sysfs__write_int(FREEZE_ON_SMI_PATH, 0);
evlist__delete(evsel_list);
evlist__put(evsel_list);
evlist__close_control(stat_config.ctl_fd, stat_config.ctl_fd_ack, &stat_config.ctl_fd_close);

View File

@@ -1652,14 +1652,14 @@ int cmd_top(int argc, const char **argv)
perf_env__init(&host_env);
status = perf_config(perf_top_config, &top);
if (status)
goto out_delete_evlist;
goto out_put_evlist;
/*
* Since the per arch annotation init routine may need the cpuid, read
* it here, since we are not getting this from the perf.data header.
*/
status = perf_env__set_cmdline(&host_env, argc, argv);
if (status)
goto out_delete_evlist;
goto out_put_evlist;
status = perf_env__read_cpuid(&host_env);
if (status) {
@@ -1680,30 +1680,30 @@ int cmd_top(int argc, const char **argv)
annotate_opts.disassembler_style = strdup(disassembler_style);
if (!annotate_opts.disassembler_style) {
status = -ENOMEM;
goto out_delete_evlist;
goto out_put_evlist;
}
}
if (objdump_path) {
annotate_opts.objdump_path = strdup(objdump_path);
if (!annotate_opts.objdump_path) {
status = -ENOMEM;
goto out_delete_evlist;
goto out_put_evlist;
}
}
if (addr2line_path) {
symbol_conf.addr2line_path = strdup(addr2line_path);
if (!symbol_conf.addr2line_path) {
status = -ENOMEM;
goto out_delete_evlist;
goto out_put_evlist;
}
}
status = symbol__validate_sym_arguments();
if (status)
goto out_delete_evlist;
goto out_put_evlist;
if (annotate_check_args() < 0)
goto out_delete_evlist;
goto out_put_evlist;
status = target__validate(target);
if (status) {
@@ -1718,15 +1718,15 @@ int cmd_top(int argc, const char **argv)
struct evlist *def_evlist = evlist__new_default(target, callchain_param.enabled);
if (!def_evlist)
goto out_delete_evlist;
goto out_put_evlist;
evlist__splice_list_tail(top.evlist, &def_evlist->core.entries);
evlist__delete(def_evlist);
evlist__put(def_evlist);
}
status = evswitch__init(&top.evswitch, top.evlist, stderr);
if (status)
goto out_delete_evlist;
goto out_put_evlist;
if (symbol_conf.report_hierarchy) {
/* disable incompatible options */
@@ -1737,18 +1737,18 @@ int cmd_top(int argc, const char **argv)
pr_err("Error: --hierarchy and --fields options cannot be used together\n");
parse_options_usage(top_usage, options, "fields", 0);
parse_options_usage(NULL, options, "hierarchy", 0);
goto out_delete_evlist;
goto out_put_evlist;
}
}
if (top.stitch_lbr && !(callchain_param.record_mode == CALLCHAIN_LBR)) {
pr_err("Error: --stitch-lbr must be used with --call-graph lbr\n");
goto out_delete_evlist;
goto out_put_evlist;
}
if (nr_cgroups > 0 && opts->record_cgroup) {
pr_err("--cgroup and --all-cgroups cannot be used together\n");
goto out_delete_evlist;
goto out_put_evlist;
}
if (branch_call_mode) {
@@ -1772,7 +1772,7 @@ int cmd_top(int argc, const char **argv)
status = perf_env__read_core_pmu_caps(&host_env);
if (status) {
pr_err("PMU capability data is not available\n");
goto out_delete_evlist;
goto out_put_evlist;
}
}
@@ -1795,7 +1795,7 @@ int cmd_top(int argc, const char **argv)
if (IS_ERR(top.session)) {
status = PTR_ERR(top.session);
top.session = NULL;
goto out_delete_evlist;
goto out_put_evlist;
}
top.evlist->session = top.session;
@@ -1805,7 +1805,7 @@ int cmd_top(int argc, const char **argv)
if (field_order)
parse_options_usage(sort_order ? NULL : top_usage,
options, "fields", 0);
goto out_delete_evlist;
goto out_put_evlist;
}
if (top.uid_str) {
@@ -1814,18 +1814,18 @@ int cmd_top(int argc, const char **argv)
if (uid == UINT_MAX) {
ui__error("Invalid User: %s", top.uid_str);
status = -EINVAL;
goto out_delete_evlist;
goto out_put_evlist;
}
status = parse_uid_filter(top.evlist, uid);
if (status)
goto out_delete_evlist;
goto out_put_evlist;
}
if (evlist__create_maps(top.evlist, target) < 0) {
ui__error("Couldn't create thread/CPU maps: %s\n",
errno == ENOENT ? "No such process" : str_error_r(errno, errbuf, sizeof(errbuf)));
status = -errno;
goto out_delete_evlist;
goto out_put_evlist;
}
if (top.delay_secs < 1)
@@ -1833,7 +1833,7 @@ int cmd_top(int argc, const char **argv)
if (record_opts__config(opts)) {
status = -EINVAL;
goto out_delete_evlist;
goto out_put_evlist;
}
top.sym_evsel = evlist__first(top.evlist);
@@ -1848,14 +1848,14 @@ int cmd_top(int argc, const char **argv)
status = symbol__annotation_init();
if (status < 0)
goto out_delete_evlist;
goto out_put_evlist;
annotation_config__init();
symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
status = symbol__init(NULL);
if (status < 0)
goto out_delete_evlist;
goto out_put_evlist;
sort__setup_elide(stdout);
@@ -1875,13 +1875,13 @@ int cmd_top(int argc, const char **argv)
if (top.sb_evlist == NULL) {
pr_err("Couldn't create side band evlist.\n.");
status = -EINVAL;
goto out_delete_evlist;
goto out_put_evlist;
}
if (evlist__add_bpf_sb_event(top.sb_evlist, &host_env)) {
pr_err("Couldn't ask for PERF_RECORD_BPF_EVENT side band events.\n.");
status = -EINVAL;
goto out_delete_evlist;
goto out_put_evlist;
}
}
#endif
@@ -1896,8 +1896,8 @@ int cmd_top(int argc, const char **argv)
if (!opts->no_bpf_event)
evlist__stop_sb_thread(top.sb_evlist);
out_delete_evlist:
evlist__delete(top.evlist);
out_put_evlist:
evlist__put(top.evlist);
perf_session__delete(top.session);
annotation_options__exit();
perf_env__exit(&host_env);

View File

@@ -4439,7 +4439,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
if (trace->summary_bpf) {
if (trace_prepare_bpf_summary(trace->summary_mode) < 0)
goto out_delete_evlist;
goto out_put_evlist;
if (trace->summary_only)
goto create_maps;
@@ -4507,19 +4507,19 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
err = evlist__create_maps(evlist, &trace->opts.target);
if (err < 0) {
fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
goto out_delete_evlist;
goto out_put_evlist;
}
err = trace__symbols_init(trace, argc, argv, evlist);
if (err < 0) {
fprintf(trace->output, "Problems initializing symbol libraries!\n");
goto out_delete_evlist;
goto out_put_evlist;
}
if (trace->summary_mode == SUMMARY__BY_TOTAL && !trace->summary_bpf) {
trace->syscall_stats = alloc_syscall_stats();
if (!trace->syscall_stats)
goto out_delete_evlist;
goto out_put_evlist;
}
evlist__config(evlist, &trace->opts, &callchain_param);
@@ -4528,7 +4528,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
err = evlist__prepare_workload(evlist, &trace->opts.target, argv, false, NULL);
if (err < 0) {
fprintf(trace->output, "Couldn't run the workload!\n");
goto out_delete_evlist;
goto out_put_evlist;
}
workload_pid = evlist->workload.pid;
}
@@ -4576,7 +4576,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
err = trace__expand_filters(trace, &evsel);
if (err)
goto out_delete_evlist;
goto out_put_evlist;
err = evlist__apply_filters(evlist, &evsel, &trace->opts.target);
if (err < 0)
goto out_error_apply_filters;
@@ -4693,12 +4693,12 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
}
}
out_delete_evlist:
out_put_evlist:
trace_cleanup_bpf_summary();
delete_syscall_stats(trace->syscall_stats);
trace__symbols__exit(trace);
evlist__free_syscall_tp_fields(evlist);
evlist__delete(evlist);
evlist__put(evlist);
cgroup__put(trace->cgroup);
trace->evlist = NULL;
trace->live = false;
@@ -4723,21 +4723,21 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
out_error:
fprintf(trace->output, "%s\n", errbuf);
goto out_delete_evlist;
goto out_put_evlist;
out_error_apply_filters:
fprintf(trace->output,
"Failed to set filter \"%s\" on event %s: %m\n",
evsel->filter, evsel__name(evsel));
goto out_delete_evlist;
goto out_put_evlist;
}
out_error_mem:
fprintf(trace->output, "Not enough memory to run!\n");
goto out_delete_evlist;
goto out_put_evlist;
out_errno:
fprintf(trace->output, "%m\n");
goto out_delete_evlist;
goto out_put_evlist;
}
static int trace__replay(struct trace *trace)
@@ -5417,7 +5417,7 @@ static void trace__exit(struct trace *trace)
zfree(&trace->syscalls.table);
}
zfree(&trace->perfconfig_events);
evlist__delete(trace->evlist);
evlist__put(trace->evlist);
trace->evlist = NULL;
ordered_events__free(&trace->oe.data);
#ifdef HAVE_LIBBPF_SUPPORT

View File

@@ -111,7 +111,7 @@ static int test__backward_ring_buffer(struct test_suite *test __maybe_unused, in
err = evlist__create_maps(evlist, &opts.target);
if (err < 0) {
pr_debug("Not enough memory to create thread/cpu maps\n");
goto out_delete_evlist;
goto out_put_evlist;
}
parse_events_error__init(&parse_error);
@@ -124,7 +124,7 @@ static int test__backward_ring_buffer(struct test_suite *test __maybe_unused, in
if (err) {
pr_debug("Failed to parse tracepoint event, try use root\n");
ret = TEST_SKIP;
goto out_delete_evlist;
goto out_put_evlist;
}
evlist__config(evlist, &opts, NULL);
@@ -133,19 +133,19 @@ static int test__backward_ring_buffer(struct test_suite *test __maybe_unused, in
if (err < 0) {
pr_debug("perf_evlist__open: %s\n",
str_error_r(errno, sbuf, sizeof(sbuf)));
goto out_delete_evlist;
goto out_put_evlist;
}
ret = TEST_FAIL;
err = do_test(evlist, opts.mmap_pages, &sample_count,
&comm_count);
if (err != TEST_OK)
goto out_delete_evlist;
goto out_put_evlist;
if ((sample_count != NR_ITERS) || (comm_count != NR_ITERS)) {
pr_err("Unexpected counter: sample_count=%d, comm_count=%d\n",
sample_count, comm_count);
goto out_delete_evlist;
goto out_put_evlist;
}
evlist__close(evlist);
@@ -154,16 +154,16 @@ static int test__backward_ring_buffer(struct test_suite *test __maybe_unused, in
if (err < 0) {
pr_debug("perf_evlist__open: %s\n",
str_error_r(errno, sbuf, sizeof(sbuf)));
goto out_delete_evlist;
goto out_put_evlist;
}
err = do_test(evlist, 1, &sample_count, &comm_count);
if (err != TEST_OK)
goto out_delete_evlist;
goto out_put_evlist;
ret = TEST_OK;
out_delete_evlist:
evlist__delete(evlist);
out_put_evlist:
evlist__put(evlist);
return ret;
}

View File

@@ -810,7 +810,7 @@ static int do_test_code_reading(bool try_kcore)
}
perf_evlist__set_maps(&evlist->core, NULL, NULL);
evlist__delete(evlist);
evlist__put(evlist);
evlist = NULL;
continue;
}
@@ -847,7 +847,7 @@ static int do_test_code_reading(bool try_kcore)
out_put:
thread__put(thread);
out_err:
evlist__delete(evlist);
evlist__put(evlist);
perf_cpu_map__put(cpus);
perf_thread_map__put(threads);
machine__delete(machine);

View File

@@ -186,7 +186,7 @@ static int test_times(int (attach)(struct evlist *),
err = attach(evlist);
if (err == TEST_SKIP) {
pr_debug(" SKIP : not enough rights\n");
evlist__delete(evlist);
evlist__put(evlist);
return err;
}
@@ -205,7 +205,7 @@ static int test_times(int (attach)(struct evlist *),
count.ena, count.run);
out_err:
evlist__delete(evlist);
evlist__put(evlist);
return !err ? TEST_OK : TEST_FAIL;
}

View File

@@ -117,7 +117,7 @@ static int test__event_update(struct test_suite *test __maybe_unused, int subtes
TEST_ASSERT_VAL("failed to synthesize attr update cpus",
!perf_event__synthesize_event_update_cpus(&tmp.tool, evsel, process_event_cpus));
evlist__delete(evlist);
evlist__put(evlist);
return 0;
}

View File

@@ -33,7 +33,7 @@ static int perf_evsel__roundtrip_cache_name_test(void)
if (err) {
pr_debug("Failure to parse cache event '%s' possibly as PMUs don't support it",
name);
evlist__delete(evlist);
evlist__put(evlist);
continue;
}
evlist__for_each_entry(evlist, evsel) {
@@ -42,7 +42,7 @@ static int perf_evsel__roundtrip_cache_name_test(void)
ret = TEST_FAIL;
}
}
evlist__delete(evlist);
evlist__put(evlist);
}
}
}
@@ -66,7 +66,7 @@ static int perf_evsel__name_array_test(const char *const names[], int nr_names)
if (err) {
pr_debug("failed to parse event '%s', err %d\n",
names[i], err);
evlist__delete(evlist);
evlist__put(evlist);
ret = TEST_FAIL;
continue;
}
@@ -76,7 +76,7 @@ static int perf_evsel__name_array_test(const char *const names[], int nr_names)
ret = TEST_FAIL;
}
}
evlist__delete(evlist);
evlist__put(evlist);
}
return ret;
}

View File

@@ -106,7 +106,7 @@ static int expand_default_events(void)
TEST_ASSERT_VAL("failed to get evlist", evlist);
ret = test_expand_events(evlist);
evlist__delete(evlist);
evlist__put(evlist);
return ret;
}
@@ -133,7 +133,7 @@ static int expand_group_events(void)
ret = test_expand_events(evlist);
out:
parse_events_error__exit(&err);
evlist__delete(evlist);
evlist__put(evlist);
return ret;
}
@@ -164,7 +164,7 @@ static int expand_libpfm_events(void)
ret = test_expand_events(evlist);
out:
evlist__delete(evlist);
evlist__put(evlist);
return ret;
}
@@ -188,7 +188,7 @@ static int expand_metric_events(void)
ret = test_expand_events(evlist);
out:
evlist__delete(evlist);
evlist__put(evlist);
return ret;
}

View File

@@ -744,7 +744,7 @@ static int test__hists_cumulate(struct test_suite *test __maybe_unused, int subt
out:
/* tear down everything */
evlist__delete(evlist);
evlist__put(evlist);
machines__exit(&machines);
put_fake_samples();

View File

@@ -332,7 +332,7 @@ static int test__hists_filter(struct test_suite *test __maybe_unused, int subtes
out:
/* tear down everything */
evlist__delete(evlist);
evlist__put(evlist);
reset_output_field();
machines__exit(&machines);
put_fake_samples();

View File

@@ -353,7 +353,7 @@ static int test__hists_link(struct test_suite *test __maybe_unused, int subtest
out:
/* tear down everything */
evlist__delete(evlist);
evlist__put(evlist);
reset_output_field();
machines__exit(&machines);
put_fake_samples();

View File

@@ -631,7 +631,7 @@ static int test__hists_output(struct test_suite *test __maybe_unused, int subtes
out:
/* tear down everything */
evlist__delete(evlist);
evlist__put(evlist);
machines__exit(&machines);
put_fake_samples();

View File

@@ -215,7 +215,7 @@ static int do_test(size_t i, bool with_pmu, bool with_alias)
out:
parse_events_error__exit(&err);
evlist__delete(evlist);
evlist__put(evlist);
return ret;
}

View File

@@ -153,7 +153,7 @@ static int test__keep_tracking(struct test_suite *test __maybe_unused, int subte
out_err:
if (evlist) {
evlist__disable(evlist);
evlist__delete(evlist);
evlist__put(evlist);
}
perf_cpu_map__put(cpus);
perf_thread_map__put(threads);

View File

@@ -94,7 +94,7 @@ static int test__basic_mmap(struct test_suite *test __maybe_unused, int subtest
/* Permissions failure, flag the failure as a skip. */
err = TEST_SKIP;
}
goto out_delete_evlist;
goto out_put_evlist;
}
evsels[i]->core.attr.wakeup_events = 1;
@@ -106,7 +106,7 @@ static int test__basic_mmap(struct test_suite *test __maybe_unused, int subtest
pr_debug("failed to open counter: %s, "
"tweak /proc/sys/kernel/perf_event_paranoid?\n",
str_error_r(errno, sbuf, sizeof(sbuf)));
goto out_delete_evlist;
goto out_put_evlist;
}
nr_events[i] = 0;
@@ -116,7 +116,7 @@ static int test__basic_mmap(struct test_suite *test __maybe_unused, int subtest
if (evlist__mmap(evlist, 128) < 0) {
pr_debug("failed to mmap events: %d (%s)\n", errno,
str_error_r(errno, sbuf, sizeof(sbuf)));
goto out_delete_evlist;
goto out_put_evlist;
}
for (i = 0; i < nsyscalls; ++i)
@@ -134,7 +134,7 @@ static int test__basic_mmap(struct test_suite *test __maybe_unused, int subtest
if (event->header.type != PERF_RECORD_SAMPLE) {
pr_debug("unexpected %s event\n",
perf_event__name(event->header.type));
goto out_delete_evlist;
goto out_put_evlist;
}
perf_sample__init(&sample, /*all=*/false);
@@ -142,7 +142,7 @@ static int test__basic_mmap(struct test_suite *test __maybe_unused, int subtest
if (err) {
pr_err("Can't parse sample, err = %d\n", err);
perf_sample__exit(&sample);
goto out_delete_evlist;
goto out_put_evlist;
}
err = -1;
@@ -153,7 +153,7 @@ static int test__basic_mmap(struct test_suite *test __maybe_unused, int subtest
if (evsel == NULL) {
pr_debug("event with id %" PRIu64
" doesn't map to an evsel\n", sample.id);
goto out_delete_evlist;
goto out_put_evlist;
}
nr_events[evsel->core.idx]++;
perf_mmap__consume(&md->core);
@@ -168,12 +168,12 @@ static int test__basic_mmap(struct test_suite *test __maybe_unused, int subtest
expected_nr_events[evsel->core.idx],
evsel__name(evsel), nr_events[evsel->core.idx]);
err = -1;
goto out_delete_evlist;
goto out_put_evlist;
}
}
out_delete_evlist:
evlist__delete(evlist);
out_put_evlist:
evlist__put(evlist);
out_free_cpus:
perf_cpu_map__put(cpus);
out_free_threads:

View File

@@ -51,7 +51,7 @@ static int test__syscall_openat_tp_fields(struct test_suite *test __maybe_unused
if (IS_ERR(evsel)) {
pr_debug("%s: evsel__newtp\n", __func__);
ret = PTR_ERR(evsel) == -EACCES ? TEST_SKIP : TEST_FAIL;
goto out_delete_evlist;
goto out_put_evlist;
}
evlist__add(evlist, evsel);
@@ -59,7 +59,7 @@ static int test__syscall_openat_tp_fields(struct test_suite *test __maybe_unused
err = evlist__create_maps(evlist, &opts.target);
if (err < 0) {
pr_debug("%s: evlist__create_maps\n", __func__);
goto out_delete_evlist;
goto out_put_evlist;
}
evsel__config(evsel, &opts, NULL);
@@ -70,14 +70,14 @@ static int test__syscall_openat_tp_fields(struct test_suite *test __maybe_unused
if (err < 0) {
pr_debug("perf_evlist__open: %s\n",
str_error_r(errno, sbuf, sizeof(sbuf)));
goto out_delete_evlist;
goto out_put_evlist;
}
err = evlist__mmap(evlist, UINT_MAX);
if (err < 0) {
pr_debug("evlist__mmap: %s\n",
str_error_r(errno, sbuf, sizeof(sbuf)));
goto out_delete_evlist;
goto out_put_evlist;
}
evlist__enable(evlist);
@@ -115,7 +115,7 @@ static int test__syscall_openat_tp_fields(struct test_suite *test __maybe_unused
if (err) {
pr_debug("Can't parse sample, err = %d\n", err);
perf_sample__exit(&sample);
goto out_delete_evlist;
goto out_put_evlist;
}
tp_flags = perf_sample__intval(&sample, "flags");
@@ -126,7 +126,7 @@ static int test__syscall_openat_tp_fields(struct test_suite *test __maybe_unused
(tp_flags & flags) != flags) {
pr_debug("%s: Expected flags=%#x, got %#x\n",
__func__, flags, tp_flags);
goto out_delete_evlist;
goto out_put_evlist;
}
goto out_ok;
@@ -139,13 +139,13 @@ static int test__syscall_openat_tp_fields(struct test_suite *test __maybe_unused
if (++nr_polls > 5) {
pr_debug("%s: no events!\n", __func__);
goto out_delete_evlist;
goto out_put_evlist;
}
}
out_ok:
ret = TEST_OK;
out_delete_evlist:
evlist__delete(evlist);
out_put_evlist:
evlist__put(evlist);
out:
return ret;
}

View File

@@ -2568,7 +2568,7 @@ static int test_event(const struct evlist_test *e)
ret = e->check(evlist);
}
parse_events_error__exit(&err);
evlist__delete(evlist);
evlist__put(evlist);
return ret;
}
@@ -2594,7 +2594,7 @@ static int test_event_fake_pmu(const char *str)
}
parse_events_error__exit(&err);
evlist__delete(evlist);
evlist__put(evlist);
return ret;
}

View File

@@ -84,7 +84,7 @@ static int __compute_metric(const char *name, struct value *vals,
cpus = perf_cpu_map__new("0");
if (!cpus) {
evlist__delete(evlist);
evlist__put(evlist);
return -ENOMEM;
}
@@ -113,7 +113,7 @@ static int __compute_metric(const char *name, struct value *vals,
/* ... cleanup. */
evlist__free_stats(evlist);
perf_cpu_map__put(cpus);
evlist__delete(evlist);
evlist__put(evlist);
return err;
}

View File

@@ -49,7 +49,7 @@ static int process_events(union perf_event **events, size_t count)
for (i = 0; i < count && !err; i++)
err = process_event(&evlist, events[i]);
evlist__delete(evlist);
evlist__put(evlist);
return err;
}

View File

@@ -105,7 +105,7 @@ static int test__PERF_RECORD(struct test_suite *test __maybe_unused, int subtest
err = evlist__create_maps(evlist, &opts.target);
if (err < 0) {
pr_debug("Not enough memory to create thread/cpu maps\n");
goto out_delete_evlist;
goto out_put_evlist;
}
/*
@@ -117,7 +117,7 @@ static int test__PERF_RECORD(struct test_suite *test __maybe_unused, int subtest
err = evlist__prepare_workload(evlist, &opts.target, argv, false, NULL);
if (err < 0) {
pr_debug("Couldn't run the workload!\n");
goto out_delete_evlist;
goto out_put_evlist;
}
/*
@@ -134,7 +134,7 @@ static int test__PERF_RECORD(struct test_suite *test __maybe_unused, int subtest
pr_debug("sched__get_first_possible_cpu: %s\n",
str_error_r(errno, sbuf, sizeof(sbuf)));
evlist__cancel_workload(evlist);
goto out_delete_evlist;
goto out_put_evlist;
}
cpu = err;
@@ -146,7 +146,7 @@ static int test__PERF_RECORD(struct test_suite *test __maybe_unused, int subtest
pr_debug("sched_setaffinity: %s\n",
str_error_r(errno, sbuf, sizeof(sbuf)));
evlist__cancel_workload(evlist);
goto out_delete_evlist;
goto out_put_evlist;
}
/*
@@ -158,7 +158,7 @@ static int test__PERF_RECORD(struct test_suite *test __maybe_unused, int subtest
pr_debug("perf_evlist__open: %s\n",
str_error_r(errno, sbuf, sizeof(sbuf)));
evlist__cancel_workload(evlist);
goto out_delete_evlist;
goto out_put_evlist;
}
/*
@@ -171,7 +171,7 @@ static int test__PERF_RECORD(struct test_suite *test __maybe_unused, int subtest
pr_debug("evlist__mmap: %s\n",
str_error_r(errno, sbuf, sizeof(sbuf)));
evlist__cancel_workload(evlist);
goto out_delete_evlist;
goto out_put_evlist;
}
/*
@@ -209,7 +209,7 @@ static int test__PERF_RECORD(struct test_suite *test __maybe_unused, int subtest
if (verbose > 0)
perf_event__fprintf(event, NULL, stderr);
pr_debug("Couldn't parse sample\n");
goto out_delete_evlist;
goto out_put_evlist;
}
if (verbose > 0) {
@@ -350,9 +350,9 @@ static int test__PERF_RECORD(struct test_suite *test __maybe_unused, int subtest
pr_debug("PERF_RECORD_MMAP for %s missing!\n", "[vdso]");
++errs;
}
out_delete_evlist:
out_put_evlist:
CPU_FREE(cpu_mask);
evlist__delete(evlist);
evlist__put(evlist);
out:
perf_sample__exit(&sample);
if (err == -EACCES)

View File

@@ -201,7 +201,7 @@ static int test__perf_time_to_tsc(struct test_suite *test __maybe_unused, int su
err = TEST_OK;
out_err:
evlist__delete(evlist);
evlist__put(evlist);
perf_cpu_map__put(cpus);
perf_thread_map__put(threads);
return err;

View File

@@ -80,7 +80,7 @@ static int test__pfm_events(struct test_suite *test __maybe_unused,
evlist__nr_groups(evlist),
0);
evlist__delete(evlist);
evlist__put(evlist);
}
return 0;
}
@@ -165,7 +165,7 @@ static int test__pfm_group(struct test_suite *test __maybe_unused,
evlist__nr_groups(evlist),
table[i].nr_groups);
evlist__delete(evlist);
evlist__put(evlist);
}
return 0;
}

View File

@@ -798,7 +798,7 @@ static int check_parse_id(const char *id, struct parse_events_error *error)
/*warn_if_reordered=*/true, /*fake_tp=*/false);
free(dup);
evlist__delete(evlist);
evlist__put(evlist);
return ret;
}
@@ -865,7 +865,7 @@ static int test__parsing_callback(const struct pmu_metric *pm,
cpus = perf_cpu_map__new("0");
if (!cpus) {
evlist__delete(evlist);
evlist__put(evlist);
return -ENOMEM;
}
@@ -919,7 +919,7 @@ static int test__parsing_callback(const struct pmu_metric *pm,
/* ... cleanup. */
evlist__free_stats(evlist);
perf_cpu_map__put(cpus);
evlist__delete(evlist);
evlist__put(evlist);
return err;
}

View File

@@ -294,7 +294,7 @@ static int test__pmu_config_helpers(struct test_suite *test __maybe_unused,
ret = TEST_OK;
err_out:
parse_events_terms__exit(&terms);
evlist__delete(evlist);
evlist__put(evlist);
test_pmu_put(dir, pmu);
return ret;
}
@@ -346,7 +346,7 @@ static int test__pmu_events(struct test_suite *test __maybe_unused, int subtest
ret = TEST_OK;
err_out:
parse_events_error__exit(&err);
evlist__delete(evlist);
evlist__put(evlist);
test_pmu_put(dir, pmu);
return ret;
}

View File

@@ -59,7 +59,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
evsel = evsel__new(&attr);
if (evsel == NULL) {
pr_debug("evsel__new\n");
goto out_delete_evlist;
goto out_put_evlist;
}
evlist__add(evlist, evsel);
@@ -68,7 +68,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
if (!cpus || !threads) {
err = -ENOMEM;
pr_debug("Not enough memory to create thread/cpu maps\n");
goto out_delete_evlist;
goto out_put_evlist;
}
perf_evlist__set_maps(&evlist->core, cpus, threads);
@@ -80,14 +80,14 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
pr_debug("Couldn't open evlist: %s\nHint: check %s, using %" PRIu64 " in this test.\n",
str_error_r(errno, sbuf, sizeof(sbuf)),
knob, (u64)attr.sample_freq);
goto out_delete_evlist;
goto out_put_evlist;
}
err = evlist__mmap(evlist, 128);
if (err < 0) {
pr_debug("failed to mmap event: %d (%s)\n", errno,
str_error_r(errno, sbuf, sizeof(sbuf)));
goto out_delete_evlist;
goto out_put_evlist;
}
evlist__enable(evlist);
@@ -113,7 +113,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
if (err < 0) {
pr_debug("Error during parse sample\n");
perf_sample__exit(&sample);
goto out_delete_evlist;
goto out_put_evlist;
}
total_periods += sample.period;
@@ -131,10 +131,10 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
err = -1;
}
out_delete_evlist:
out_put_evlist:
perf_cpu_map__put(cpus);
perf_thread_map__put(threads);
evlist__delete(evlist);
evlist__put(evlist);
return err;
}

View File

@@ -582,7 +582,7 @@ static int test__switch_tracking(struct test_suite *test __maybe_unused, int sub
out:
if (evlist) {
evlist__disable(evlist);
evlist__delete(evlist);
evlist__put(evlist);
}
perf_cpu_map__put(cpus);
perf_thread_map__put(threads);

View File

@@ -74,7 +74,7 @@ static int test__task_exit(struct test_suite *test __maybe_unused, int subtest _
if (!cpus || !threads) {
err = -ENOMEM;
pr_debug("Not enough memory to create thread/cpu maps\n");
goto out_delete_evlist;
goto out_put_evlist;
}
perf_evlist__set_maps(&evlist->core, cpus, threads);
@@ -82,7 +82,7 @@ static int test__task_exit(struct test_suite *test __maybe_unused, int subtest _
err = evlist__prepare_workload(evlist, &target, argv, false, workload_exec_failed_signal);
if (err < 0) {
pr_debug("Couldn't run the workload!\n");
goto out_delete_evlist;
goto out_put_evlist;
}
evsel = evlist__first(evlist);
@@ -101,14 +101,14 @@ static int test__task_exit(struct test_suite *test __maybe_unused, int subtest _
if (err < 0) {
pr_debug("Couldn't open the evlist: %s\n",
str_error_r(-err, sbuf, sizeof(sbuf)));
goto out_delete_evlist;
goto out_put_evlist;
}
if (evlist__mmap(evlist, 128) < 0) {
pr_debug("failed to mmap events: %d (%s)\n", errno,
str_error_r(errno, sbuf, sizeof(sbuf)));
err = -1;
goto out_delete_evlist;
goto out_put_evlist;
}
evlist__start_workload(evlist);
@@ -133,7 +133,7 @@ static int test__task_exit(struct test_suite *test __maybe_unused, int subtest _
if (retry_count++ > 1000) {
pr_debug("Failed after retrying 1000 times\n");
err = -1;
goto out_delete_evlist;
goto out_put_evlist;
}
goto retry;
@@ -144,10 +144,10 @@ static int test__task_exit(struct test_suite *test __maybe_unused, int subtest _
err = -1;
}
out_delete_evlist:
out_put_evlist:
perf_cpu_map__put(cpus);
perf_thread_map__put(threads);
evlist__delete(evlist);
evlist__put(evlist);
return err;
}

View File

@@ -67,7 +67,7 @@ static int do_test(enum tool_pmu_event ev, bool with_pmu)
out:
parse_events_error__exit(&err);
evlist__delete(evlist);
evlist__put(evlist);
return ret;
}

View File

@@ -58,7 +58,7 @@ static int session_write_header(char *path)
!perf_session__write_header(session, session->evlist,
perf_data__fd(&data), true));
evlist__delete(session->evlist);
evlist__put(session->evlist);
perf_session__delete(session);
return 0;

View File

@@ -165,7 +165,7 @@ static int test__uncore_event_sorting(struct test_suite *test __maybe_unused,
ret = TEST_OK;
out_err:
evlist__delete(evlist);
evlist__put(evlist);
parse_events_error__exit(&err);
zfree(&pmu_prefix);
zfree(&m.event1);

View File

@@ -520,8 +520,8 @@ int evlist__expand_cgroup(struct evlist *evlist, const char *str, bool open_cgro
cgrp_event_expanded = true;
out_err:
evlist__delete(orig_list);
evlist__delete(tmp_list);
evlist__put(orig_list);
evlist__put(tmp_list);
metricgroup__rblist_exit(&orig_metric_events);
release_cgroup_list();

View File

@@ -1362,7 +1362,7 @@ static void cleanup_events(struct perf_session *session)
zfree(&evsel->priv);
}
evlist__delete(evlist);
evlist__put(evlist);
session->evlist = NULL;
}

View File

@@ -75,7 +75,7 @@ int sigqueue(pid_t pid, int sig, const union sigval value);
#define FD(e, x, y) (*(int *)xyarray__entry(e->core.fd, x, y))
#define SID(e, x, y) xyarray__entry(e->core.sample_id, x, y)
void evlist__init(struct evlist *evlist, struct perf_cpu_map *cpus,
static void evlist__init(struct evlist *evlist, struct perf_cpu_map *cpus,
struct perf_thread_map *threads)
{
perf_evlist__init(&evlist->core);
@@ -88,6 +88,7 @@ void evlist__init(struct evlist *evlist, struct perf_cpu_map *cpus,
evlist->nr_br_cntr = -1;
metricgroup__rblist_init(&evlist->metric_events);
INIT_LIST_HEAD(&evlist->deferred_samples);
refcount_set(&evlist->refcnt, 1);
}
struct evlist *evlist__new(void)
@@ -139,7 +140,7 @@ struct evlist *evlist__new_default(const struct target *target, bool sample_call
return evlist;
out_err:
evlist__delete(evlist);
evlist__put(evlist);
return NULL;
}
@@ -148,13 +149,19 @@ struct evlist *evlist__new_dummy(void)
struct evlist *evlist = evlist__new();
if (evlist && evlist__add_dummy(evlist)) {
evlist__delete(evlist);
evlist__put(evlist);
evlist = NULL;
}
return evlist;
}
struct evlist *evlist__get(struct evlist *evlist)
{
refcount_inc(&evlist->refcnt);
return evlist;
}
/**
* evlist__set_id_pos - set the positions of event ids.
* @evlist: selected event list
@@ -193,7 +200,7 @@ static void evlist__purge(struct evlist *evlist)
evlist->core.nr_entries = 0;
}
void evlist__exit(struct evlist *evlist)
static void evlist__exit(struct evlist *evlist)
{
metricgroup__rblist_exit(&evlist->metric_events);
event_enable_timer__exit(&evlist->eet);
@@ -202,11 +209,14 @@ void evlist__exit(struct evlist *evlist)
perf_evlist__exit(&evlist->core);
}
void evlist__delete(struct evlist *evlist)
void evlist__put(struct evlist *evlist)
{
if (evlist == NULL)
return;
if (!refcount_dec_and_test(&evlist->refcnt))
return;
evlist__free_stats(evlist);
evlist__munmap(evlist);
evlist__close(evlist);

View File

@@ -61,6 +61,7 @@ struct event_enable_timer;
struct evlist {
struct perf_evlist core;
refcount_t refcnt;
bool enabled;
bool no_affinity;
int id_pos;
@@ -109,10 +110,8 @@ struct evsel_str_handler {
struct evlist *evlist__new(void);
struct evlist *evlist__new_default(const struct target *target, bool sample_callchains);
struct evlist *evlist__new_dummy(void);
void evlist__init(struct evlist *evlist, struct perf_cpu_map *cpus,
struct perf_thread_map *threads);
void evlist__exit(struct evlist *evlist);
void evlist__delete(struct evlist *evlist);
struct evlist *evlist__get(struct evlist *evlist);
void evlist__put(struct evlist *evlist);
void evlist__add(struct evlist *evlist, struct evsel *entry);
void evlist__remove(struct evlist *evlist, struct evsel *evsel);

View File

@@ -468,7 +468,7 @@ double expr__has_event(const struct expr_parse_ctx *ctx, bool compute_ids, const
ret = parse_event(tmp, id) ? 0 : 1;
}
out:
evlist__delete(tmp);
evlist__put(tmp);
return ret;
}

View File

@@ -5186,7 +5186,7 @@ int perf_session__read_header(struct perf_session *session)
pr_err("Invalid ids section size %" PRIu64 " for attr %d, not aligned to u64\n",
f_attr.ids.size, i);
err = -EINVAL;
goto out_delete_evlist;
goto out_put_evlist;
}
/*
@@ -5199,7 +5199,7 @@ int perf_session__read_header(struct perf_session *session)
pr_err("Invalid ids section size %" PRIu64 " for attr %d, too many IDs\n",
f_attr.ids.size, i);
err = -EINVAL;
goto out_delete_evlist;
goto out_put_evlist;
}
/*
@@ -5212,19 +5212,19 @@ int perf_session__read_header(struct perf_session *session)
pr_err("Invalid ids section for attr %d: offset=%" PRIu64 " size=%" PRIu64 " exceeds file size %" PRIu64 "\n",
i, f_attr.ids.offset, f_attr.ids.size, (u64)input_stat.st_size);
err = -EINVAL;
goto out_delete_evlist;
goto out_put_evlist;
}
tmp = lseek(fd, 0, SEEK_CUR);
evsel = evsel__new(&f_attr.attr);
if (evsel == NULL)
goto out_delete_evlist;
goto out_put_evlist;
evsel->needs_swap = header->needs_swap;
/*
* Do it before so that if perf_evsel__alloc_id fails, this
* entry gets purged too at evlist__delete().
* entry gets purged too at evlist__put().
*/
evlist__add(session->evlist, evsel);
@@ -5235,7 +5235,7 @@ int perf_session__read_header(struct perf_session *session)
* hattr->ids threads.
*/
if (perf_evsel__alloc_id(&evsel->core, 1, nr_ids))
goto out_delete_evlist;
goto out_put_evlist;
lseek(fd, f_attr.ids.offset, SEEK_SET);
@@ -5265,18 +5265,18 @@ int perf_session__read_header(struct perf_session *session)
err = perf_header__process_sections(header, fd, &session->tevent,
perf_file_section__process);
if (err < 0)
goto out_delete_evlist;
goto out_put_evlist;
if (evlist__prepare_tracepoint_events(session->evlist,
session->tevent.pevent)) {
err = -ENOMEM;
goto out_delete_evlist;
goto out_put_evlist;
}
#else
err = perf_header__process_sections(header, fd, NULL,
perf_file_section__process);
if (err < 0)
goto out_delete_evlist;
goto out_put_evlist;
#endif
}
@@ -5302,8 +5302,8 @@ int perf_session__read_header(struct perf_session *session)
out_errno:
return -errno;
out_delete_evlist:
evlist__delete(session->evlist);
out_put_evlist:
evlist__put(session->evlist);
session->evlist = NULL;
return err;
}

View File

@@ -214,7 +214,7 @@ static void metric__free(struct metric *m)
zfree(&m->metric_refs);
expr__ctx_free(m->pctx);
zfree(&m->modifier);
evlist__delete(m->evlist);
evlist__put(m->evlist);
free(m);
}
@@ -1331,7 +1331,7 @@ static int parse_ids(bool metric_no_merge, bool fake_pmu,
parsed_evlist = NULL;
err_out:
parse_events_error__exit(&parse_error);
evlist__delete(parsed_evlist);
evlist__put(parsed_evlist);
strbuf_release(&events);
return ret;
}
@@ -1542,7 +1542,7 @@ static int parse_groups(struct evlist *perf_evlist,
if (combined_evlist) {
evlist__splice_list_tail(perf_evlist, &combined_evlist->core.entries);
evlist__delete(combined_evlist);
evlist__put(combined_evlist);
}
list_for_each_entry(m, &metric_list, nd) {

View File

@@ -2343,7 +2343,7 @@ int __parse_events(struct evlist *evlist, const char *str, const char *pmu_filte
/*
* There are 2 users - builtin-record and builtin-test objects.
* Both call evlist__delete in case of error, so we dont
* Both call evlist__put in case of error, so we dont
* need to bother.
*/
return ret;
@@ -2546,7 +2546,7 @@ int parse_events_option_new_evlist(const struct option *opt, const char *str, in
}
ret = parse_events_option(opt, str, unset);
if (ret) {
evlist__delete(*args->evlistp);
evlist__put(*args->evlistp);
*args->evlistp = NULL;
}

View File

@@ -57,7 +57,7 @@ static int perf_do_probe_api(setup_probe_fn_t fn, struct perf_cpu cpu, const cha
err = 0;
out_delete:
evlist__delete(evlist);
evlist__put(evlist);
return err;
}

View File

@@ -1292,7 +1292,7 @@ static int pyrf_evsel__setup_types(void)
struct pyrf_evlist {
PyObject_HEAD
struct evlist evlist;
struct evlist *evlist;
};
static int pyrf_evlist__init(struct pyrf_evlist *pevlist,
@@ -1302,18 +1302,27 @@ static int pyrf_evlist__init(struct pyrf_evlist *pevlist,
struct perf_cpu_map *cpus;
struct perf_thread_map *threads;
if (!PyArg_ParseTuple(args, "OO", &pcpus, &pthreads))
if (!PyArg_ParseTuple(args, "O!O!",
&pyrf_cpu_map__type, &pcpus,
&pyrf_thread_map__type, &pthreads))
return -1;
evlist__put(pevlist->evlist);
pevlist->evlist = evlist__new();
if (!pevlist->evlist) {
PyErr_NoMemory();
return -1;
}
threads = ((struct pyrf_thread_map *)pthreads)->threads;
cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
evlist__init(&pevlist->evlist, cpus, threads);
perf_evlist__set_maps(&pevlist->evlist->core, cpus, threads);
return 0;
}
static void pyrf_evlist__delete(struct pyrf_evlist *pevlist)
{
evlist__exit(&pevlist->evlist);
evlist__put(pevlist->evlist);
Py_TYPE(pevlist)->tp_free((PyObject*)pevlist);
}
@@ -1322,7 +1331,7 @@ static PyObject *pyrf_evlist__all_cpus(struct pyrf_evlist *pevlist)
struct pyrf_cpu_map *pcpu_map = PyObject_New(struct pyrf_cpu_map, &pyrf_cpu_map__type);
if (pcpu_map)
pcpu_map->cpus = perf_cpu_map__get(pevlist->evlist.core.all_cpus);
pcpu_map->cpus = perf_cpu_map__get(pevlist->evlist->core.all_cpus);
return (PyObject *)pcpu_map;
}
@@ -1335,7 +1344,7 @@ static PyObject *pyrf_evlist__metrics(struct pyrf_evlist *pevlist)
if (!list)
return NULL;
for (node = rb_first_cached(&pevlist->evlist.metric_events.entries); node;
for (node = rb_first_cached(&pevlist->evlist->metric_events.entries); node;
node = rb_next(node)) {
struct metric_event *me = container_of(node, struct metric_event, nd);
struct list_head *pos;
@@ -1441,7 +1450,7 @@ static PyObject *pyrf_evlist__compute_metric(struct pyrf_evlist *pevlist,
if (!PyArg_ParseTuple(args, "sii", &metric, &cpu, &thread))
return NULL;
for (node = rb_first_cached(&pevlist->evlist.metric_events.entries);
for (node = rb_first_cached(&pevlist->evlist->metric_events.entries);
mexp == NULL && node;
node = rb_next(node)) {
struct metric_event *me = container_of(node, struct metric_event, nd);
@@ -1457,7 +1466,7 @@ static PyObject *pyrf_evlist__compute_metric(struct pyrf_evlist *pevlist,
if (e->metric_events[0] == NULL)
continue;
evlist__for_each_entry(&pevlist->evlist, pos2) {
evlist__for_each_entry(pevlist->evlist, pos2) {
if (pos2->metric_leader != e->metric_events[0])
continue;
cpu_idx = perf_cpu_map__idx(pos2->core.cpus,
@@ -1502,7 +1511,7 @@ static PyObject *pyrf_evlist__compute_metric(struct pyrf_evlist *pevlist,
static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist,
PyObject *args, PyObject *kwargs)
{
struct evlist *evlist = &pevlist->evlist;
struct evlist *evlist = pevlist->evlist;
static char *kwlist[] = { "pages", "overwrite", NULL };
int pages = 128, overwrite = false;
@@ -1522,7 +1531,7 @@ static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist,
static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist,
PyObject *args, PyObject *kwargs)
{
struct evlist *evlist = &pevlist->evlist;
struct evlist *evlist = pevlist->evlist;
static char *kwlist[] = { "timeout", NULL };
int timeout = -1, n;
@@ -1542,7 +1551,7 @@ static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
PyObject *args __maybe_unused,
PyObject *kwargs __maybe_unused)
{
struct evlist *evlist = &pevlist->evlist;
struct evlist *evlist = pevlist->evlist;
PyObject *list = PyList_New(0);
int i;
@@ -1571,7 +1580,7 @@ static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist,
PyObject *args,
PyObject *kwargs __maybe_unused)
{
struct evlist *evlist = &pevlist->evlist;
struct evlist *evlist = pevlist->evlist;
PyObject *pevsel;
struct evsel *evsel;
@@ -1603,7 +1612,7 @@ static struct mmap *get_md(struct evlist *evlist, int cpu)
static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
PyObject *args, PyObject *kwargs)
{
struct evlist *evlist = &pevlist->evlist;
struct evlist *evlist = pevlist->evlist;
union perf_event *event;
int sample_id_all = 1, cpu;
static char *kwlist[] = { "cpu", "sample_id_all", NULL };
@@ -1660,7 +1669,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
static PyObject *pyrf_evlist__open(struct pyrf_evlist *pevlist,
PyObject *args, PyObject *kwargs)
{
struct evlist *evlist = &pevlist->evlist;
struct evlist *evlist = pevlist->evlist;
if (evlist__open(evlist) < 0) {
PyErr_SetFromErrno(PyExc_OSError);
@@ -1673,7 +1682,7 @@ static PyObject *pyrf_evlist__open(struct pyrf_evlist *pevlist,
static PyObject *pyrf_evlist__close(struct pyrf_evlist *pevlist)
{
struct evlist *evlist = &pevlist->evlist;
struct evlist *evlist = pevlist->evlist;
evlist__close(evlist);
@@ -1699,7 +1708,7 @@ static PyObject *pyrf_evlist__config(struct pyrf_evlist *pevlist)
.no_buffering = true,
.no_inherit = true,
};
struct evlist *evlist = &pevlist->evlist;
struct evlist *evlist = pevlist->evlist;
evlist__config(evlist, &opts, &callchain_param);
Py_INCREF(Py_None);
@@ -1708,14 +1717,14 @@ static PyObject *pyrf_evlist__config(struct pyrf_evlist *pevlist)
static PyObject *pyrf_evlist__disable(struct pyrf_evlist *pevlist)
{
evlist__disable(&pevlist->evlist);
evlist__disable(pevlist->evlist);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *pyrf_evlist__enable(struct pyrf_evlist *pevlist)
{
evlist__enable(&pevlist->evlist);
evlist__enable(pevlist->evlist);
Py_INCREF(Py_None);
return Py_None;
}
@@ -1806,7 +1815,26 @@ static Py_ssize_t pyrf_evlist__length(PyObject *obj)
{
struct pyrf_evlist *pevlist = (void *)obj;
return pevlist->evlist.core.nr_entries;
if (!pevlist->evlist)
return 0;
return pevlist->evlist->core.nr_entries;
}
static PyObject *pyrf_evsel__from_evsel(struct evsel *evsel)
{
struct pyrf_evsel *pevsel = PyObject_New(struct pyrf_evsel, &pyrf_evsel__type);
if (!pevsel)
return NULL;
memset(&pevsel->evsel, 0, sizeof(pevsel->evsel));
evsel__init(&pevsel->evsel, &evsel->core.attr, evsel->core.idx);
evsel__clone(&pevsel->evsel, evsel);
if (evsel__is_group_leader(evsel))
evsel__set_leader(&pevsel->evsel, &pevsel->evsel);
return (PyObject *)pevsel;
}
static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i)
@@ -1814,17 +1842,16 @@ static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i)
struct pyrf_evlist *pevlist = (void *)obj;
struct evsel *pos;
if (i >= pevlist->evlist.core.nr_entries) {
if (!pevlist->evlist || i >= pevlist->evlist->core.nr_entries) {
PyErr_SetString(PyExc_IndexError, "Index out of range");
return NULL;
}
evlist__for_each_entry(&pevlist->evlist, pos) {
evlist__for_each_entry(pevlist->evlist, pos) {
if (i-- == 0)
break;
}
return Py_BuildValue("O", container_of(pos, struct pyrf_evsel, evsel));
return pyrf_evsel__from_evsel(pos);
}
static PyObject *pyrf_evlist__str(PyObject *self)
@@ -1835,8 +1862,11 @@ static PyObject *pyrf_evlist__str(PyObject *self)
bool first = true;
PyObject *result;
if (!pevlist->evlist)
return PyUnicode_FromString("evlist(uninitialized)");
strbuf_addstr(&sb, "evlist([");
evlist__for_each_entry(&pevlist->evlist, pos) {
evlist__for_each_entry(pevlist->evlist, pos) {
if (!first)
strbuf_addch(&sb, ',');
if (!pos->pmu)
@@ -1858,6 +1888,24 @@ static PySequenceMethods pyrf_evlist__sequence_methods = {
static const char pyrf_evlist__doc[] = PyDoc_STR("perf event selector list object.");
static PyObject *pyrf_evlist__getattro(struct pyrf_evlist *pevlist, PyObject *attr_name)
{
if (!pevlist->evlist) {
PyErr_SetString(PyExc_ValueError, "evlist not initialized");
return NULL;
}
return PyObject_GenericGetAttr((PyObject *) pevlist, attr_name);
}
static int pyrf_evlist__setattro(struct pyrf_evlist *pevlist, PyObject *attr_name, PyObject *value)
{
if (!pevlist->evlist) {
PyErr_SetString(PyExc_ValueError, "evlist not initialized");
return -1;
}
return PyObject_GenericSetAttr((PyObject *) pevlist, attr_name, value);
}
static PyTypeObject pyrf_evlist__type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "perf.evlist",
@@ -1870,11 +1918,23 @@ static PyTypeObject pyrf_evlist__type = {
.tp_init = (initproc)pyrf_evlist__init,
.tp_repr = pyrf_evlist__str,
.tp_str = pyrf_evlist__str,
.tp_getattro = (getattrofunc) pyrf_evlist__getattro,
.tp_setattro = (setattrofunc) pyrf_evlist__setattro,
};
static PyObject *pyrf_evlist__new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
struct pyrf_evlist *pevlist;
pevlist = (struct pyrf_evlist *)PyType_GenericNew(type, args, kwargs);
if (pevlist)
pevlist->evlist = NULL;
return (PyObject *)pevlist;
}
static int pyrf_evlist__setup_types(void)
{
pyrf_evlist__type.tp_new = PyType_GenericNew;
pyrf_evlist__type.tp_new = pyrf_evlist__new;
return PyType_Ready(&pyrf_evlist__type);
}
@@ -1977,157 +2037,74 @@ static PyObject *pyrf__tracepoint(struct pyrf_evsel *pevsel,
return PyLong_FromLong(tp_pmu__id(sys, name));
}
static PyObject *pyrf_evsel__from_evsel(struct evsel *evsel)
{
struct pyrf_evsel *pevsel = PyObject_New(struct pyrf_evsel, &pyrf_evsel__type);
if (!pevsel)
return NULL;
memset(&pevsel->evsel, 0, sizeof(pevsel->evsel));
evsel__init(&pevsel->evsel, &evsel->core.attr, evsel->core.idx);
evsel__clone(&pevsel->evsel, evsel);
if (evsel__is_group_leader(evsel))
evsel__set_leader(&pevsel->evsel, &pevsel->evsel);
return (PyObject *)pevsel;
}
static int evlist__pos(struct evlist *evlist, struct evsel *evsel)
{
struct evsel *pos;
int idx = 0;
evlist__for_each_entry(evlist, pos) {
if (evsel == pos)
return idx;
idx++;
}
return -1;
}
static struct evsel *evlist__at(struct evlist *evlist, int idx)
{
struct evsel *pos;
int idx2 = 0;
evlist__for_each_entry(evlist, pos) {
if (idx == idx2)
return pos;
idx2++;
}
return NULL;
}
static PyObject *pyrf_evlist__from_evlist(struct evlist *evlist)
{
struct pyrf_evlist *pevlist = PyObject_New(struct pyrf_evlist, &pyrf_evlist__type);
struct evsel *pos;
struct rb_node *node;
if (!pevlist)
return NULL;
memset(&pevlist->evlist, 0, sizeof(pevlist->evlist));
evlist__init(&pevlist->evlist, evlist->core.all_cpus, evlist->core.threads);
evlist__for_each_entry(evlist, pos) {
struct pyrf_evsel *pevsel = (void *)pyrf_evsel__from_evsel(pos);
evlist__add(&pevlist->evlist, &pevsel->evsel);
}
evlist__for_each_entry(&pevlist->evlist, pos) {
struct evsel *leader = evsel__leader(pos);
if (pos != leader) {
int idx = evlist__pos(evlist, leader);
if (idx >= 0)
evsel__set_leader(pos, evlist__at(&pevlist->evlist, idx));
else if (leader == NULL)
evsel__set_leader(pos, pos);
}
leader = pos->metric_leader;
if (pos != leader) {
int idx = evlist__pos(evlist, leader);
if (idx >= 0)
pos->metric_leader = evlist__at(&pevlist->evlist, idx);
else if (leader == NULL)
pos->metric_leader = pos;
}
}
metricgroup__copy_metric_events(&pevlist->evlist, /*cgrp=*/NULL,
&pevlist->evlist.metric_events,
&evlist->metric_events);
for (node = rb_first_cached(&pevlist->evlist.metric_events.entries); node;
node = rb_next(node)) {
struct metric_event *me = container_of(node, struct metric_event, nd);
struct list_head *mpos;
int idx = evlist__pos(evlist, me->evsel);
if (idx >= 0)
me->evsel = evlist__at(&pevlist->evlist, idx);
list_for_each(mpos, &me->head) {
struct metric_expr *e = container_of(mpos, struct metric_expr, nd);
for (int j = 0; e->metric_events[j]; j++) {
idx = evlist__pos(evlist, e->metric_events[j]);
if (idx >= 0)
e->metric_events[j] = evlist__at(&pevlist->evlist, idx);
}
}
}
pevlist->evlist = evlist__get(evlist);
return (PyObject *)pevlist;
}
static PyObject *pyrf__parse_events(PyObject *self, PyObject *args)
{
const char *input;
struct evlist evlist = {};
struct evlist *evlist = evlist__new();
struct parse_events_error err;
PyObject *result;
PyObject *pcpus = NULL, *pthreads = NULL;
struct perf_cpu_map *cpus;
struct perf_thread_map *threads;
if (!PyArg_ParseTuple(args, "s|OO", &input, &pcpus, &pthreads))
if (!evlist)
return PyErr_NoMemory();
if (!PyArg_ParseTuple(args, "s|OO", &input, &pcpus, &pthreads)) {
evlist__put(evlist);
return NULL;
}
threads = pthreads ? ((struct pyrf_thread_map *)pthreads)->threads : NULL;
cpus = pcpus ? ((struct pyrf_cpu_map *)pcpus)->cpus : NULL;
parse_events_error__init(&err);
evlist__init(&evlist, cpus, threads);
if (parse_events(&evlist, input, &err)) {
perf_evlist__set_maps(&evlist->core, cpus, threads);
if (parse_events(evlist, input, &err)) {
parse_events_error__print(&err, input);
PyErr_SetFromErrno(PyExc_OSError);
evlist__put(evlist);
return NULL;
}
result = pyrf_evlist__from_evlist(&evlist);
evlist__exit(&evlist);
result = pyrf_evlist__from_evlist(evlist);
evlist__put(evlist);
return result;
}
static PyObject *pyrf__parse_metrics(PyObject *self, PyObject *args)
{
const char *input, *pmu = NULL;
struct evlist evlist = {};
struct evlist *evlist = evlist__new();
PyObject *result;
PyObject *pcpus = NULL, *pthreads = NULL;
struct perf_cpu_map *cpus;
struct perf_thread_map *threads;
int ret;
if (!PyArg_ParseTuple(args, "s|sOO", &input, &pmu, &pcpus, &pthreads))
if (!evlist)
return PyErr_NoMemory();
if (!PyArg_ParseTuple(args, "s|sOO", &input, &pmu, &pcpus, &pthreads)) {
evlist__put(evlist);
return NULL;
}
threads = pthreads ? ((struct pyrf_thread_map *)pthreads)->threads : NULL;
cpus = pcpus ? ((struct pyrf_cpu_map *)pcpus)->cpus : NULL;
evlist__init(&evlist, cpus, threads);
ret = metricgroup__parse_groups(&evlist, pmu ?: "all", input,
perf_evlist__set_maps(&evlist->core, cpus, threads);
ret = metricgroup__parse_groups(evlist, pmu ?: "all", input,
/*metric_no_group=*/ false,
/*metric_no_merge=*/ false,
/*metric_no_threshold=*/ true,
@@ -2135,12 +2112,13 @@ static PyObject *pyrf__parse_metrics(PyObject *self, PyObject *args)
/*system_wide=*/true,
/*hardware_aware_grouping=*/ false);
if (ret) {
evlist__put(evlist);
errno = -ret;
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
result = pyrf_evlist__from_evlist(&evlist);
evlist__exit(&evlist);
result = pyrf_evlist__from_evlist(evlist);
evlist__put(evlist);
return result;
}

View File

@@ -264,7 +264,7 @@ bool evlist__can_select_event(struct evlist *evlist, const char *str)
ret = true;
out_delete:
evlist__delete(temp_evlist);
evlist__put(temp_evlist);
return ret;
}

View File

@@ -265,7 +265,7 @@ void perf_session__delete(struct perf_session *session)
machines__exit(&session->machines);
if (session->data) {
if (perf_data__is_read(session->data))
evlist__delete(session->evlist);
evlist__put(session->evlist);
perf_data__close(session->data);
}
#ifdef HAVE_LIBTRACEEVENT

View File

@@ -102,7 +102,7 @@ int evlist__start_sb_thread(struct evlist *evlist, struct target *target)
return 0;
if (evlist__create_maps(evlist, target))
goto out_delete_evlist;
goto out_put_evlist;
if (evlist->core.nr_entries > 1) {
bool can_sample_identifier = perf_can_sample_identifier();
@@ -116,25 +116,25 @@ int evlist__start_sb_thread(struct evlist *evlist, struct target *target)
evlist__for_each_entry(evlist, counter) {
if (evsel__open(counter, evlist->core.user_requested_cpus,
evlist->core.threads) < 0)
goto out_delete_evlist;
goto out_put_evlist;
}
if (evlist__mmap(evlist, UINT_MAX))
goto out_delete_evlist;
goto out_put_evlist;
evlist__for_each_entry(evlist, counter) {
if (evsel__enable(counter))
goto out_delete_evlist;
goto out_put_evlist;
}
evlist->thread.done = 0;
if (pthread_create(&evlist->thread.th, NULL, perf_evlist__poll_thread, evlist))
goto out_delete_evlist;
goto out_put_evlist;
return 0;
out_delete_evlist:
evlist__delete(evlist);
out_put_evlist:
evlist__put(evlist);
evlist = NULL;
return -1;
}
@@ -145,5 +145,5 @@ void evlist__stop_sb_thread(struct evlist *evlist)
return;
evlist->thread.done = 1;
pthread_join(evlist->thread.th, NULL);
evlist__delete(evlist);
evlist__put(evlist);
}