Linux Perf Users
 help / color / mirror / Atom feed
From: Ian Rogers <irogers@google.com>
To: linux-perf-users@vger.kernel.org,
	 Arnaldo Carvalho de Melo <acme@kernel.org>,
	Namhyung Kim <namhyung@kernel.org>
Cc: linux-kernel@vger.kernel.org,
	Peter Zijlstra <peterz@infradead.org>,
	 Ingo Molnar <mingo@redhat.com>, Jiri Olsa <jolsa@kernel.org>,
	 Adrian Hunter <adrian.hunter@intel.com>,
	James Clark <james.clark@linaro.org>,
	 Kan Liang <kan.liang@linux.intel.com>,
	Dapeng Mi <dapeng1.mi@linux.intel.com>,
	 Thomas Falcon <thomas.falcon@intel.com>,
	John Garry <john.garry@linux.dev>,  Will Deacon <will@kernel.org>,
	Leo Yan <leo.yan@arm.com>,
	 Athira Rajeev <atrajeev@linux.ibm.com>,
	Thomas Richter <tmricht@linux.ibm.com>,
	 Ravi Bangoria <ravi.bangoria@amd.com>,
	Sandipan Das <sandipan.das@amd.com>,
	 Ian Rogers <irogers@google.com>
Subject: [PATCH v1 02/41] perf env: Add host_env() singleton
Date: Tue,  3 Nov 2026 15:44:18 -0800	[thread overview]
Message-ID: <20261103234502.1008382-3-irogers@google.com> (raw)
In-Reply-To: <20261103234502.1008382-1-irogers@google.com>

Add host_env() to provide a statically initialized singleton
struct perf_env representing the live host environment, replacing
ad-hoc stack and static host_env instances across subcommands,
utilities, benchmarks, and tests.

Drop the redundant struct perf_env * parameter from
machine__new_host(), machine__new_kallsyms(), machine__new_live(),
and __perf_session__new().

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/bench/synthesize.c         | 13 ++------
 tools/perf/builtin-buildid-list.c     |  5 +--
 tools/perf/builtin-inject.c           |  3 +-
 tools/perf/builtin-kallsyms.c         | 12 ++-----
 tools/perf/builtin-lock.c             |  6 +---
 tools/perf/builtin-top.c              | 17 +++-------
 tools/perf/builtin-trace.c            | 18 +++--------
 tools/perf/perf.c                     |  3 ++
 tools/perf/tests/code-reading.c       |  5 +--
 tools/perf/tests/dlfilter-test.c      |  5 +--
 tools/perf/tests/dwarf-unwind.c       |  5 +--
 tools/perf/tests/mmap-thread-lookup.c |  5 +--
 tools/perf/tests/symbols.c            |  7 +----
 tools/perf/util/debug.c               |  6 +---
 tools/perf/util/env.c                 | 45 +++++++++++++++++----------
 tools/perf/util/env.h                 | 10 ++++++
 tools/perf/util/header.c              |  3 ++
 tools/perf/util/machine.c             | 16 +++++-----
 tools/perf/util/machine.h             | 28 +++++++++++++++--
 tools/perf/util/parse-events.c        |  9 ++----
 tools/perf/util/probe-event.c         |  5 +--
 tools/perf/util/rwsem.h               |  6 ++++
 tools/perf/util/session.c             |  6 ++--
 tools/perf/util/session.h             | 22 +++++++++++--
 24 files changed, 129 insertions(+), 131 deletions(-)

diff --git a/tools/perf/bench/synthesize.c b/tools/perf/bench/synthesize.c
index 265d49a913d9..6aac1ccc7f4b 100644
--- a/tools/perf/bench/synthesize.c
+++ b/tools/perf/bench/synthesize.c
@@ -115,16 +115,12 @@ static int run_single_threaded(void)
 		.pid = "self",
 	};
 	struct perf_thread_map *threads;
-	struct perf_env host_env;
 	int err;
 
 	perf_set_singlethreaded();
-	perf_env__init(&host_env);
-	session = __perf_session__new(/*data=*/NULL, /*tool=*/NULL,
-				      /*trace_event_repipe=*/false, &host_env);
+	session = perf_session__new(/*data=*/NULL, /*tool=*/NULL);
 	if (IS_ERR(session)) {
 		pr_err("Session creation failed.\n");
-		perf_env__exit(&host_env);
 		return PTR_ERR(session);
 	}
 	threads = thread_map__new_by_pid(getpid());
@@ -149,7 +145,6 @@ static int run_single_threaded(void)
 		perf_thread_map__put(threads);
 
 	perf_session__delete(session);
-	perf_env__exit(&host_env);
 	return err;
 }
 
@@ -163,14 +158,11 @@ static int do_run_multi_threaded(struct target *target,
 	int err = 0;
 	struct stats time_stats, event_stats;
 	struct perf_session *session;
-	struct perf_env host_env;
 
-	perf_env__init(&host_env);
 	init_stats(&time_stats);
 	init_stats(&event_stats);
 	for (i = 0; i < multi_iterations; i++) {
-		session = __perf_session__new(/*data=*/NULL, /*tool=*/NULL,
-					      /*trace_event_repipe=*/false, &host_env);
+		session = perf_session__new(/*data=*/NULL, /*tool=*/NULL);
 		if (IS_ERR(session)) {
 			err = PTR_ERR(session);
 			goto err_out;
@@ -209,7 +201,6 @@ static int do_run_multi_threaded(struct target *target,
 	printf("    Average time per event %.3f usec\n",
 		time_average / event_average);
 err_out:
-	perf_env__exit(&host_env);
 	return err;
 }
 
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 5555f5dcefe4..f6159300ee63 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -45,14 +45,11 @@ static int buildid__map_cb(struct map *map, void *arg __maybe_unused)
 
 static void buildid__show_kernel_maps(void)
 {
-	struct perf_env host_env;
 	struct machine *machine;
 
-	perf_env__init(&host_env);
-	machine = machine__new_host(&host_env);
+	machine = machine__new_host();
 	machine__for_each_kernel_map(machine, buildid__map_cb, NULL);
 	machine__delete(machine);
-	perf_env__exit(&host_env);
 }
 
 static int sysfs__fprintf_build_id(FILE *fp)
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index ce7562fc788c..d115dc5ab6d6 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -2871,8 +2871,7 @@ int cmd_inject(int argc, const char **argv)
 		}
 	}
 	inject.session = __perf_session__new(&data, tool,
-					     /*trace_event_repipe=*/inject.output.is_pipe,
-					     /*host_env=*/NULL);
+					     /*trace_event_repipe=*/inject.output.is_pipe);
 
 	if (IS_ERR(inject.session)) {
 		ret = PTR_ERR(inject.session);
diff --git a/tools/perf/builtin-kallsyms.c b/tools/perf/builtin-kallsyms.c
index 3c4339982b16..e85beb380d9d 100644
--- a/tools/perf/builtin-kallsyms.c
+++ b/tools/perf/builtin-kallsyms.c
@@ -19,17 +19,10 @@
 
 static int __cmd_kallsyms(int argc, const char **argv)
 {
-	int i, err;
-	struct perf_env host_env;
+	int i, err = 0;
 	struct machine *machine = NULL;
 
-
-	perf_env__init(&host_env);
-	err = perf_env__set_cmdline(&host_env, argc, argv);
-	if (err)
-		goto out;
-
-	machine = machine__new_kallsyms(&host_env);
+	machine = machine__new_kallsyms();
 	if (machine == NULL) {
 		pr_err("Couldn't read /proc/kallsyms\n");
 		err = -1;
@@ -54,7 +47,6 @@ static int __cmd_kallsyms(int argc, const char **argv)
 	}
 out:
 	machine__delete(machine);
-	perf_env__exit(&host_env);
 	return err;
 }
 
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 778923c92f42..6d557c552f36 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -2015,7 +2015,6 @@ static int __cmd_contention(int argc, const char **argv)
 		.owner = show_lock_owner,
 		.cgroups = RB_ROOT,
 	};
-	struct perf_env host_env;
 
 	lockhash_table = calloc(LOCKHASH_SIZE, sizeof(*lockhash_table));
 	if (!lockhash_table)
@@ -2032,9 +2031,7 @@ static int __cmd_contention(int argc, const char **argv)
 	eops.mmap2		 = perf_event__process_mmap2;
 	eops.tracing_data	 = perf_event__process_tracing_data;
 
-	perf_env__init(&host_env);
-	session = __perf_session__new(use_bpf ? NULL : &data, &eops,
-				/*trace_event_repipe=*/false, &host_env);
+	session = perf_session__new(use_bpf ? NULL : &data, &eops);
 
 	if (IS_ERR(session)) {
 		pr_err("Initializing perf session failed\n");
@@ -2157,7 +2154,6 @@ static int __cmd_contention(int argc, const char **argv)
 	evlist__put(con.evlist);
 	lock_contention_finish(&con);
 	perf_session__delete(session);
-	perf_env__exit(&host_env);
 	zfree(&lockhash_table);
 	return err;
 }
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index a3442d2d6edf..e52ee42d7e0f 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1658,7 +1658,6 @@ int cmd_top(int argc, const char **argv)
 		NULL
 	};
 	int status = hists__init();
-	struct perf_env host_env;
 
 	if (status < 0)
 		return status;
@@ -1672,7 +1671,6 @@ int cmd_top(int argc, const char **argv)
 	if (top.evlist == NULL)
 		return -ENOMEM;
 
-	perf_env__init(&host_env);
 	status = perf_config(perf_top_config, &top);
 	if (status)
 		goto out_put_evlist;
@@ -1680,11 +1678,7 @@ int cmd_top(int argc, const char **argv)
 	 * 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_put_evlist;
-
-	status = perf_env__read_cpuid(&host_env);
+	status = perf_env__read_cpuid(host_env());
 	if (status) {
 		/*
 		 * Some arches do not provide a get_cpuid(), so just use pr_debug, otherwise
@@ -1803,7 +1797,7 @@ int cmd_top(int argc, const char **argv)
 		symbol_conf.show_branchflag_count = true;
 
 	if (opts->branch_stack) {
-		status = perf_env__read_core_pmu_caps(&host_env);
+		status = perf_env__read_core_pmu_caps(host_env());
 		if (status) {
 			pr_err("PMU capability data is not available\n");
 			goto out_put_evlist;
@@ -1823,9 +1817,7 @@ int cmd_top(int argc, const char **argv)
 
 	setup_browser(false);
 
-	top.session = __perf_session__new(/*data=*/NULL, /*tool=*/NULL,
-					  /*trace_event_repipe=*/false,
-					  &host_env);
+	top.session = perf_session__new(/*data=*/NULL, /*tool=*/NULL);
 	if (IS_ERR(top.session)) {
 		status = PTR_ERR(top.session);
 		top.session = NULL;
@@ -1912,7 +1904,7 @@ int cmd_top(int argc, const char **argv)
 			goto out_put_evlist;
 		}
 
-		if (evlist__add_bpf_sb_event(top.sb_evlist, &host_env)) {
+		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;
 			evlist__put(top.sb_evlist);
@@ -1936,7 +1928,6 @@ int cmd_top(int argc, const char **argv)
 	evlist__put(top.evlist);
 	perf_session__delete(top.session);
 	annotation_options__exit();
-	perf_env__exit(&host_env);
 
 	return status;
 }
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 4094141461f9..fb02fa6dd437 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -142,7 +142,6 @@ struct syscall_fmt {
 };
 
 struct trace {
-	struct perf_env		host_env;
 	struct perf_tool	tool;
 	struct {
 		/** Sorted sycall numbers used by the trace. */
@@ -2121,20 +2120,14 @@ static char *trace__machine__resolve_kernel_addr(void *vmachine, unsigned long l
 	return machine__resolve_kernel_addr(vmachine, addrp, modp);
 }
 
-static int trace__symbols_init(struct trace *trace, int argc, const char **argv,
-			       struct evlist *evlist)
+static int trace__symbols_init(struct trace *trace, struct evlist *evlist)
 {
 	int err = symbol__init(NULL);
 
 	if (err)
 		return err;
 
-	perf_env__init(&trace->host_env);
-	err = perf_env__set_cmdline(&trace->host_env, argc, argv);
-	if (err)
-		goto out;
-
-	trace->host = machine__new_host(&trace->host_env);
+	trace->host = machine__new_host();
 	if (trace->host == NULL) {
 		err = -ENOMEM;
 		goto out;
@@ -2155,10 +2148,8 @@ static int trace__symbols_init(struct trace *trace, int argc, const char **argv,
 					    /*mmap_data=*/false,
 					    /*nr_threads_synthesize=*/1);
 out:
-	if (err) {
-		perf_env__exit(&trace->host_env);
+	if (err)
 		symbol__exit();
-	}
 	return err;
 }
 
@@ -2167,7 +2158,6 @@ static void trace__symbols__exit(struct trace *trace)
 	machine__delete(trace->host);
 	trace->host = NULL;
 
-	perf_env__exit(&trace->host_env);
 	symbol__exit();
 }
 
@@ -4833,7 +4823,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
 		goto out_put_evlist;
 	}
 
-	err = trace__symbols_init(trace, argc, argv, evlist);
+	err = trace__symbols_init(trace, evlist);
 	if (err < 0) {
 		fprintf(trace->output, "Problems initializing symbol libraries!\n");
 		goto out_put_evlist;
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index d60bc929c257..bcbc12295a38 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -32,6 +32,7 @@
 #include "util/build-id.h"
 #include "util/config.h"
 #include "util/debug.h"
+#include "util/env.h"
 #ifdef HAVE_LIBTRACEEVENT
 #include "util/trace-event.h"
 #endif
@@ -380,12 +381,14 @@ static int run_builtin(const struct cmd_struct *p, int argc, const char **argv)
 		use_pager = 1;
 	commit_pager_choice();
 
+	perf_env__set_cmdline(host_env(), argc, argv);
 	status = p->fn(argc, argv);
 	perf_config__exit();
 #ifdef HAVE_LIBTRACEEVENT
 	trace_event__exit();
 #endif
 	exit_browser(status);
+	perf_env__exit(host_env());
 
 	if (status)
 		return status & 0xff;
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 130cd6021f93..ac21b083eadc 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -710,12 +710,10 @@ static int do_test_code_reading(bool try_kcore)
 	struct dso *dso;
 	const char *events[] = { "cpu-cycles", "cpu-cycles:u", "cpu-clock", "cpu-clock:u", NULL };
 	int evidx = 0;
-	struct perf_env host_env;
 
 	pid = getpid();
 
-	perf_env__init(&host_env);
-	machine = machine__new_host(&host_env);
+	machine = machine__new_host();
 	if (!machine) {
 		pr_debug("machine__new_host failed\n");
 		goto out_err;
@@ -851,7 +849,6 @@ static int do_test_code_reading(bool try_kcore)
 	perf_cpu_map__put(cpus);
 	perf_thread_map__put(threads);
 	machine__delete(machine);
-	perf_env__exit(&host_env);
 	tested_sections__free(&tested_sections);
 
 	return err;
diff --git a/tools/perf/tests/dlfilter-test.c b/tools/perf/tests/dlfilter-test.c
index 204663571943..312fc7e8c49a 100644
--- a/tools/perf/tests/dlfilter-test.c
+++ b/tools/perf/tests/dlfilter-test.c
@@ -322,7 +322,6 @@ static int run_perf_script(struct test_data *td)
 
 static int test__dlfilter_test(struct test_data *td)
 {
-	struct perf_env host_env;
 	u64 sample_type = TEST_SAMPLE_TYPE;
 	pid_t pid = 12345;
 	pid_t tid = 12346;
@@ -356,8 +355,7 @@ static int test__dlfilter_test(struct test_data *td)
 		return test_result("Failed to find program symbols", TEST_FAIL);
 
 	pr_debug("Creating new host machine structure\n");
-	perf_env__init(&host_env);
-	td->machine = machine__new_host(&host_env);
+	td->machine = machine__new_host();
 
 	td->fd = creat(td->perf_data_file_name, 0644);
 	if (td->fd < 0)
@@ -390,7 +388,6 @@ static int test__dlfilter_test(struct test_data *td)
 
 	err = run_perf_script(td) ? TEST_FAIL : TEST_OK;
 out:
-	perf_env__exit(&host_env);
 	return err;
 }
 
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index 9ed78d00fb87..d324c9c09b0b 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -181,7 +181,6 @@ NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__krava_1(struct thread *th
 noinline int test__dwarf_unwind(struct test_suite *test __maybe_unused,
 				int subtest __maybe_unused)
 {
-	struct perf_env host_env;
 	struct machine *machine;
 	struct thread *thread;
 	int err = -1;
@@ -190,8 +189,7 @@ noinline int test__dwarf_unwind(struct test_suite *test __maybe_unused,
 	callchain_param.record_mode = CALLCHAIN_DWARF;
 	dwarf_callchain_users = true;
 
-	perf_env__init(&host_env);
-	machine = machine__new_live(&host_env, /*kernel_maps=*/true, pid);
+	machine = machine__new_live(/*kernel_maps=*/true, pid);
 	if (!machine) {
 		pr_err("Could not get machine\n");
 		goto out;
@@ -216,7 +214,6 @@ noinline int test__dwarf_unwind(struct test_suite *test __maybe_unused,
 
  out:
 	machine__delete(machine);
-	perf_env__exit(&host_env);
 	return err;
 }
 
diff --git a/tools/perf/tests/mmap-thread-lookup.c b/tools/perf/tests/mmap-thread-lookup.c
index 0c5619c6e6e9..7559123983c5 100644
--- a/tools/perf/tests/mmap-thread-lookup.c
+++ b/tools/perf/tests/mmap-thread-lookup.c
@@ -156,7 +156,6 @@ static int synth_process(struct machine *machine)
 
 static int mmap_events(synth_cb synth)
 {
-	struct perf_env host_env;
 	struct machine *machine;
 	int err, i;
 
@@ -169,8 +168,7 @@ static int mmap_events(synth_cb synth)
 	 */
 	TEST_ASSERT_VAL("failed to create threads", !threads_create());
 
-	perf_env__init(&host_env);
-	machine = machine__new_host(&host_env);
+	machine = machine__new_host();
 
 	dump_trace = verbose > 1 ? 1 : 0;
 
@@ -212,7 +210,6 @@ static int mmap_events(synth_cb synth)
 	}
 
 	machine__delete(machine);
-	perf_env__exit(&host_env);
 	return err;
 }
 
diff --git a/tools/perf/tests/symbols.c b/tools/perf/tests/symbols.c
index b644d95c6be9..ca7550aa124a 100644
--- a/tools/perf/tests/symbols.c
+++ b/tools/perf/tests/symbols.c
@@ -15,18 +15,15 @@
 #include "tests.h"
 
 struct test_info {
-	struct perf_env host_env;
 	struct machine *machine;
 	struct thread *thread;
 };
 
 static int init_test_info(struct test_info *ti)
 {
-	perf_env__init(&ti->host_env);
-	ti->machine = machine__new_host(&ti->host_env);
+	ti->machine = machine__new_host();
 	if (!ti->machine) {
 		pr_debug("machine__new_host() failed!\n");
-		perf_env__exit(&ti->host_env);
 		return TEST_FAIL;
 	}
 
@@ -34,7 +31,6 @@ static int init_test_info(struct test_info *ti)
 	ti->thread = machine__findnew_thread(ti->machine, 100, 100);
 	if (!ti->thread) {
 		pr_debug("machine__findnew_thread() failed!\n");
-		perf_env__exit(&ti->host_env);
 		return TEST_FAIL;
 	}
 
@@ -45,7 +41,6 @@ static void exit_test_info(struct test_info *ti)
 {
 	thread__put(ti->thread);
 	machine__delete(ti->machine);
-	perf_env__exit(&ti->host_env);
 }
 
 struct dso_map {
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index b7095519419e..dfba9ddeacb7 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -312,10 +312,8 @@ void __dump_stack(FILE *file, void **stackdump, size_t stackdump_size)
 	pid_t pid = getpid();
 	struct machine *machine;
 	struct thread *thread = NULL;
-	struct perf_env host_env;
 
-	perf_env__init(&host_env);
-	machine = machine__new_live(&host_env, /*kernel_maps=*/false, pid);
+	machine = machine__new_live(/*kernel_maps=*/false, pid);
 
 	if (machine)
 		thread = machine__find_thread(machine, pid, pid);
@@ -328,7 +326,6 @@ void __dump_stack(FILE *file, void **stackdump, size_t stackdump_size)
 		 */
 		backtrace_symbols_fd(stackdump, stackdump_size, fileno(file));
 		machine__delete(machine);
-		perf_env__exit(&host_env);
 		return;
 	}
 #endif
@@ -355,7 +352,6 @@ void __dump_stack(FILE *file, void **stackdump, size_t stackdump_size)
 	}
 	thread__put(thread);
 	machine__delete(machine);
-	perf_env__exit(&host_env);
 }
 
 /* Obtain a backtrace and print it to stdout. */
diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c
index 4ab46ca6b4ef..1fe6ce84e607 100644
--- a/tools/perf/util/env.c
+++ b/tools/perf/util/env.c
@@ -13,6 +13,7 @@
 #include <linux/zalloc.h>
 #include "cgroup.h"
 #include <errno.h>
+#include <pthread.h>
 #include <sys/utsname.h>
 #include <stdlib.h>
 #include <string.h>
@@ -246,6 +247,22 @@ void free_cpu_domain_info(struct cpu_domain_map **cd_map, u32 schedstat_version,
 	zfree(&cd_map);
 }
 
+static struct perf_env __host_env = {
+#ifdef HAVE_LIBBPF_SUPPORT
+	.bpf_progs = {
+		.lock = __PERF_RWSEM_INITIALIZER,
+		.infos = RB_ROOT,
+		.btfs = RB_ROOT,
+	},
+#endif
+	.cgroups = {
+		.lock = __PERF_RWSEM_INITIALIZER,
+		.tree = RB_ROOT,
+	},
+	.kernel_is_64_bit = -1,
+	.lock = { .lock = __PERF_MUTEX_INITIALIZER },
+};
+
 void perf_env__exit(struct perf_env *env)
 {
 	int i, j;
@@ -313,6 +330,11 @@ void perf_env__init(struct perf_env *env)
 	mutex_init(&env->lock);
 }
 
+struct perf_env *host_env(void)
+{
+	return &__host_env;
+}
+
 static const char *uts_machine(void)
 {
 	static struct utsname uts;
@@ -409,6 +431,7 @@ int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[])
 	int i;
 
 	/* do not include NULL termination */
+	zfree(&env->cmdline_argv);
 	env->cmdline_argv = calloc(argc, sizeof(char *));
 	if (env->cmdline_argv == NULL)
 		goto out_enomem;
@@ -1110,15 +1133,10 @@ bool perf_env__is_x86_amd_cpu(struct perf_env *env)
 
 bool x86__is_amd_cpu(void)
 {
-	struct perf_env env = { .total_mem = 0, };
-	bool is_amd;
+	struct perf_env *env = host_env();
 
-	perf_env__init(&env);
-	perf_env__cpuid(&env);
-	is_amd = perf_env__is_x86_amd_cpu(&env);
-	perf_env__exit(&env);
-
-	return is_amd;
+	perf_env__cpuid(env);
+	return perf_env__is_x86_amd_cpu(env);
 }
 
 bool perf_env__is_x86_intel_cpu(struct perf_env *env)
@@ -1134,13 +1152,8 @@ bool perf_env__is_x86_intel_cpu(struct perf_env *env)
 
 bool x86__is_intel_cpu(void)
 {
-	struct perf_env env = { .total_mem = 0, };
-	bool is_intel;
-
-	perf_env__init(&env);
-	perf_env__cpuid(&env);
-	is_intel = perf_env__is_x86_intel_cpu(&env);
-	perf_env__exit(&env);
+	struct perf_env *env = host_env();
 
-	return is_intel;
+	perf_env__cpuid(env);
+	return perf_env__is_x86_intel_cpu(env);
 }
diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h
index 23d35425efe3..134102148a5c 100644
--- a/tools/perf/util/env.h
+++ b/tools/perf/util/env.h
@@ -221,6 +221,16 @@ const char *perf_env__cpuid(struct perf_env *env);
 int perf_env__nr_cpus_avail(struct perf_env *env);
 
 void perf_env__init(struct perf_env *env);
+
+/**
+ * host_env() - Return the singleton struct perf_env for the live host.
+ *
+ * Returns a pointer to the statically initialized global struct perf_env
+ * representing the live host.
+ *
+ * Return: Pointer to the live host's struct perf_env.
+ */
+struct perf_env *host_env(void);
 #ifdef HAVE_LIBBPF_SUPPORT
 bool __perf_env__insert_bpf_prog_info(struct perf_env *env,
 				      struct bpf_prog_info_node *info_node);
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 9eec6deee190..b6f86f557caf 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -670,6 +670,9 @@ static int write_cmdline(struct feat_fd *ff,
 	char pbuf[MAXPATHLEN], *buf;
 	int i, ret, n;
 
+	if (!env->cmdline_argv)
+		env = host_env();
+
 	/* actual path to perf binary */
 	buf = perf_exe(pbuf, MAXPATHLEN);
 
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 076d167380f2..7fae861dc646 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -130,7 +130,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
 	return err;
 }
 
-static struct machine *__machine__new_host(struct perf_env *host_env, bool kernel_maps)
+static struct machine *__machine__new_host(bool kernel_maps)
 {
 	struct machine *machine = malloc(sizeof(*machine));
 
@@ -146,13 +146,13 @@ static struct machine *__machine__new_host(struct perf_env *host_env, bool kerne
 		free(machine);
 		return NULL;
 	}
-	machine->env = host_env;
+	machine->env = host_env();
 	return machine;
 }
 
-struct machine *machine__new_host(struct perf_env *host_env)
+struct machine *machine__new_host(void)
 {
-	return __machine__new_host(host_env, /*kernel_maps=*/true);
+	return __machine__new_host(/*kernel_maps=*/true);
 }
 
 static int mmap_handler(const struct perf_tool *tool __maybe_unused,
@@ -172,9 +172,9 @@ static int machine__init_live(struct machine *machine, pid_t pid)
 						  mmap_handler, machine, true);
 }
 
-struct machine *machine__new_live(struct perf_env *host_env, bool kernel_maps, pid_t pid)
+struct machine *machine__new_live(bool kernel_maps, pid_t pid)
 {
-	struct machine *machine = __machine__new_host(host_env, kernel_maps);
+	struct machine *machine = __machine__new_host(kernel_maps);
 
 	if (!machine)
 		return NULL;
@@ -186,9 +186,9 @@ struct machine *machine__new_live(struct perf_env *host_env, bool kernel_maps, p
 	return machine;
 }
 
-struct machine *machine__new_kallsyms(struct perf_env *host_env)
+struct machine *machine__new_kallsyms(void)
 {
-	struct machine *machine = machine__new_host(host_env);
+	struct machine *machine = machine__new_host();
 	/*
 	 * FIXME:
 	 * 1) We should switch to machine__load_kallsyms(), i.e. not explicitly
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 973a59f7c26a..be562b989c26 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -177,9 +177,31 @@ struct thread *machine__findnew_guest_code(struct machine *machine, pid_t pid);
 void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size);
 void machines__set_comm_exec(struct machines *machines, bool comm_exec);
 
-struct machine *machine__new_host(struct perf_env *host_env);
-struct machine *machine__new_kallsyms(struct perf_env *host_env);
-struct machine *machine__new_live(struct perf_env *host_env, bool kernel_maps, pid_t pid);
+/**
+ * machine__new_host() - Allocate and initialize a struct machine for the live
+ *                       host with kernel maps populated.
+ *
+ * Return: Pointer to the newly allocated struct machine, or NULL on failure.
+ */
+struct machine *machine__new_host(void);
+
+/**
+ * machine__new_kallsyms() - Allocate and initialize a struct machine for the
+ *                           live host and load /proc/kallsyms.
+ *
+ * Return: Pointer to the newly allocated struct machine, or NULL on failure.
+ */
+struct machine *machine__new_kallsyms(void);
+
+/**
+ * machine__new_live() - Allocate and initialize a struct machine for live
+ *                       inspection of @pid on the host.
+ * @kernel_maps: Whether to create kernel maps on the machine.
+ * @pid: Process ID whose mmap events should be synthesized.
+ *
+ * Return: Pointer to the newly allocated struct machine, or NULL on failure.
+ */
+struct machine *machine__new_live(bool kernel_maps, pid_t pid);
 int machine__init(struct machine *machine, const char *root_dir, pid_t pid);
 void machine__exit(struct machine *machine);
 void machine__delete_threads(struct machine *machine);
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index f3ba70d4f76b..5ca6b93d8a2a 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -583,13 +583,8 @@ size_t default_breakpoint_len(void)
 #if defined(__i386__)
 	static int len;
 
-	if (len == 0) {
-		struct perf_env env = {};
-
-		perf_env__init(&env);
-		len = perf_env__kernel_is_64_bit(&env) ? sizeof(u64) : sizeof(long);
-		perf_env__exit(&env);
-	}
+	if (len == 0)
+		len = perf_env__kernel_is_64_bit(host_env()) ? sizeof(u64) : sizeof(long);
 	return len;
 #elif defined(__aarch64__)
 	return 4;
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 1534280c0c1d..d042d8f69f59 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -74,14 +74,12 @@ int e_snprintf(char *str, size_t size, const char *format, ...)
 }
 
 static struct machine *host_machine;
-static struct perf_env host_env;
 
 /* Initialize symbol maps and path of vmlinux/modules */
 int init_probe_symbol_maps(bool user_only)
 {
 	int ret;
 
-	perf_env__init(&host_env);
 	symbol_conf.allow_aliases = true;
 	ret = symbol__init(NULL);
 	if (ret < 0) {
@@ -95,7 +93,7 @@ int init_probe_symbol_maps(bool user_only)
 	if (symbol_conf.vmlinux_name)
 		pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name);
 
-	host_machine = machine__new_host(&host_env);
+	host_machine = machine__new_host();
 	if (!host_machine) {
 		pr_debug("machine__new_host() failed.\n");
 		symbol__exit();
@@ -112,7 +110,6 @@ void exit_probe_symbol_maps(void)
 	machine__delete(host_machine);
 	host_machine = NULL;
 	symbol__exit();
-	perf_env__exit(&host_env);
 }
 
 static struct ref_reloc_sym *kernel_get_ref_reloc_sym(struct map **pmap)
diff --git a/tools/perf/util/rwsem.h b/tools/perf/util/rwsem.h
index b102d8143181..d2bf722e409c 100644
--- a/tools/perf/util/rwsem.h
+++ b/tools/perf/util/rwsem.h
@@ -18,6 +18,12 @@ struct LOCKABLE rw_semaphore {
 #endif
 };
 
+#if RWS_ERRORCHECK
+#define __PERF_RWSEM_INITIALIZER { .mtx = { .lock = __PERF_MUTEX_INITIALIZER } }
+#else
+#define __PERF_RWSEM_INITIALIZER { .lock = PTHREAD_RWLOCK_INITIALIZER }
+#endif
+
 int init_rwsem(struct rw_semaphore *sem);
 int exit_rwsem(struct rw_semaphore *sem);
 
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index f35d6867e816..6ff8d97dcf7d 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -151,8 +151,7 @@ static int ordered_events__deliver_event(struct ordered_events *oe,
 
 struct perf_session *__perf_session__new(struct perf_data *data,
 					 struct perf_tool *tool,
-					 bool trace_event_repipe,
-					 struct perf_env *host_env)
+					 bool trace_event_repipe)
 {
 	int ret = -ENOMEM;
 	struct perf_session *session = zalloc(sizeof(*session));
@@ -206,8 +205,7 @@ struct perf_session *__perf_session__new(struct perf_data *data,
 				symbol_conf.kallsyms_name = perf_data__kallsyms_name(data);
 		}
 	} else  {
-		assert(host_env != NULL);
-		session->machines.host.env = host_env;
+		session->machines.host.env = host_env();
 	}
 	if (session->evlist)
 		evlist__set_session(session->evlist, session);
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index ac5803d5fb4e..1e0bef9951d1 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -107,15 +107,31 @@ struct decomp {
 
 struct perf_tool;
 
+/**
+ * __perf_session__new() - Allocate and initialize a new struct perf_session.
+ * @data: Input/output perf_data descriptor, or NULL for a live host session.
+ * @tool: Event processing callbacks, or NULL.
+ * @trace_event_repipe: Whether to repipe trace event records to stdout.
+ *
+ * When @data is NULL, associates the session's host machine with host_env().
+ *
+ * Return: Pointer to the new session, or an ERR_PTR() on failure.
+ */
 struct perf_session *__perf_session__new(struct perf_data *data,
 					 struct perf_tool *tool,
-					 bool trace_event_repipe,
-					 struct perf_env *host_env);
+					 bool trace_event_repipe);
 
+/**
+ * perf_session__new() - Allocate and initialize a new struct perf_session.
+ * @data: Input/output perf_data descriptor, or NULL for a live host session.
+ * @tool: Event processing callbacks, or NULL.
+ *
+ * Return: Pointer to the new session, or an ERR_PTR() on failure.
+ */
 static inline struct perf_session *perf_session__new(struct perf_data *data,
 						     struct perf_tool *tool)
 {
-	return __perf_session__new(data, tool, /*trace_event_repipe=*/false, /*host_env=*/NULL);
+	return __perf_session__new(data, tool, /*trace_event_repipe=*/false);
 }
 
 void perf_session__delete(struct perf_session *session);
-- 
2.56.0.385.gac671c819a-goog


  parent reply	other threads:[~2026-11-03 23:45 UTC|newest]

Thread overview: 83+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-03 23:44 [PATCH v1 00/41] perf: Per-env PMUs, recorded event metrics, and perf sysinfo Ian Rogers
2026-11-03 23:44 ` [PATCH v1 01/41] perf env: Make lazy perf_env initialization thread-safe Ian Rogers
2026-11-03 23:53   ` sashiko-bot
2026-11-03 23:44 ` Ian Rogers [this message]
2026-11-04  0:18   ` [PATCH v1 02/41] perf env: Add host_env() singleton sashiko-bot
2026-11-03 23:44 ` [PATCH v1 03/41] perf pmu: Add from_env parameter to perf_pmu__init() Ian Rogers
2026-11-04  0:31   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 04/41] perf pmus: Introduce struct perf_pmus and perf_env__pmus() Ian Rogers
2026-11-04  0:48   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 05/41] perf pmus: Pass struct perf_pmus to find helpers Ian Rogers
2026-11-04  0:56   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 06/41] perf pmus: Pass struct perf_pmus to scan helpers Ian Rogers
2026-11-04  1:01   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 07/41] perf pmu-events: Add e_machine to struct pmu_events_map Ian Rogers
2026-11-04  1:06   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 08/41] perf pmu-events: Pass e_machine to find_core_*_table() Ian Rogers
2026-11-04  1:14   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 09/41] perf header: Pass e_machine to strcmp_cpuid_str() Ian Rogers
2026-11-04  1:18   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 10/41] perf header: Support CPUID matching across all architectures Ian Rogers
2026-11-04  1:23   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 11/41] perf test: Make the CPUID matching test architecture independent Ian Rogers
2026-11-04  1:32   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 12/41] perf test: Add CPUID matching tests for other architectures Ian Rogers
2026-11-04  1:36   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 13/41] perf pmus: Add perf_pmus__read_from_env() Ian Rogers
2026-11-04  2:05   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 14/41] perf metricgroup: Pass struct perf_pmus to metricgroup__for_each_metric() Ian Rogers
2026-11-04  2:17   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 15/41] perf metricgroup: Move matching of metrics to recorded events from perf script Ian Rogers
2026-11-04  2:36   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 16/41] perf parse-events: Decode metric-id terms when adding events Ian Rogers
2026-11-04  2:44   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 17/41] perf evsel: Generalize metric_id to a set of metric_ids Ian Rogers
2026-11-04  3:17   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 18/41] perf pmu: Add perf_pmu__for_each_name_from_config() Ian Rogers
2026-11-04  3:23   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 19/41] perf metricgroup: Improve matching of metrics to recorded events Ian Rogers
2026-11-04  3:46   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 20/41] perf metricgroup: Add metricgroup__add_recorded_metrics() Ian Rogers
2026-11-04  4:10   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 21/41] perf script: Fix metrics computed from samples Ian Rogers
2026-11-04  4:16   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 22/41] perf script: Don't drop metric samples for CPUs missing from the evsel Ian Rogers
2026-11-04  4:22   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 23/41] perf stat report: Display metrics for recorded events Ian Rogers
2026-11-04  4:39   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 24/41] perf script: Display metrics for perf stat record data Ian Rogers
2026-11-04  4:47   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 25/41] perf test: Add stat record metrics test Ian Rogers
2026-11-04  5:01   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 26/41] perf pmus: Expose duplicate uncore PMU scanning helpers Ian Rogers
2026-11-04  5:08   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 27/41] perf mem-events: Expose PMU init and name formatting helpers Ian Rogers
2026-11-04  5:20   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 28/41] perf pmu: Add perf_pmu__probe() for basic open, counting, and sampling Ian Rogers
2026-11-04  5:39   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 29/41] perf pmu: Probe supported sample_type flags Ian Rogers
2026-11-04  5:49   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 30/41] perf pmu: Probe precise_ip levels Ian Rogers
2026-11-04  5:59   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 31/41] perf pmu: Probe privilege exclusion modifiers Ian Rogers
2026-11-04  6:04   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 32/41] perf pmu: Probe execution and AUX area features Ian Rogers
2026-11-04  6:19   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 33/41] perf pmu: Probe event group size limits Ian Rogers
2026-11-04  6:22   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 34/41] perf pmu: Probe user and interrupt sample register masks Ian Rogers
2026-11-04  6:44   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 35/41] perf pmu: Probe interrupt registers that require precise sampling Ian Rogers
2026-11-04  6:53   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 36/41] perf pmu: Probe memory profiling events and sample formats Ian Rogers
2026-11-04  7:04   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 37/41] perf pmu: Probe user-space mmap capabilities Ian Rogers
2026-11-04  7:27   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 38/41] perf pmu: Probe branch instruction skid Ian Rogers
2026-11-04  7:32   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 39/41] perf sysinfo: Add sysinfo subcommand Ian Rogers
2026-11-04  7:50   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 40/41] perf docs: Add perf-sysinfo man page Ian Rogers
2026-11-04  7:51   ` sashiko-bot
2026-11-03 23:44 ` [PATCH v1 41/41] perf test: Add perf sysinfo shell test Ian Rogers
2026-11-04  7:59   ` sashiko-bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261103234502.1008382-3-irogers@google.com \
    --to=irogers@google.com \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=atrajeev@linux.ibm.com \
    --cc=dapeng1.mi@linux.intel.com \
    --cc=james.clark@linaro.org \
    --cc=john.garry@linux.dev \
    --cc=jolsa@kernel.org \
    --cc=kan.liang@linux.intel.com \
    --cc=leo.yan@arm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=namhyung@kernel.org \
    --cc=peterz@infradead.org \
    --cc=ravi.bangoria@amd.com \
    --cc=sandipan.das@amd.com \
    --cc=thomas.falcon@intel.com \
    --cc=tmricht@linux.ibm.com \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox