File 1531-Add-support-to-erl-for-JPperfdirectory-directory.patch of Package erlang
From b759c1b059eceefcedb4bdc13e2c442425da63a0 Mon Sep 17 00:00:00 2001
From: Freddie Lamble <flamble1@bloomberg.net>
Date: Mon, 24 Mar 2025 10:35:32 +0000
Subject: [PATCH] Add support to `erl` for `+JPperfdirectory <directory>`
This adds support for a `+JPperfdirectory <directory>` cli arg which
allows changing the location used for the `jit<pid>.dump` and `perf<pid>.map`
files which prior to this always went into `/tmp`.
The motivation is so that a different mount from `/tmp` can be used.
Example usage:
```console
[ ~/otp/bin @issue/9500 ] $ mkdir /testdir
[ ~/otp/bin @issue/9500 ] $ ./erl -noinput -eval 'io:format("I am ~s~n", [os:getpid()]).' -s init stop +JPperf true +JPperfdirectory /testdir
I am 149279
[ ~/otp/bin @issue/9500 ] $ ls /testdir/
jit-149279.dump perf-149279.map
```
Without it, they still go to `/tmp/`:
```console
[ ~/otp/bin @issue/9500 ] $ ./erl -noinput -eval 'io:format("I am ~s~n", [os:getpid()]).' -s init stop +JPperf true
I am 209905
[ ~/otp/bin @issue/9500 ] $ ls /tmp/*209905*
/tmp/jit-209905.dump /tmp/perf-209905.map
```
Closes #9500.
---
erts/doc/references/erl_cmd.md | 4 +++
erts/emulator/beam/erl_init.c | 13 +++++++++-
erts/emulator/beam/jit/beam_asm.h | 1 +
erts/emulator/beam/jit/beam_jit_main.cpp | 1 +
erts/emulator/beam/jit/beam_jit_metadata.cpp | 12 +++++++--
erts/emulator/test/jit_SUITE.erl | 27 ++++++++++++++++++--
6 files changed, 53 insertions(+), 5 deletions(-)
diff --git a/erts/doc/references/erl_cmd.md b/erts/doc/references/erl_cmd.md
index 2b2214cce2..c37319f46f 100644
--- a/erts/doc/references/erl_cmd.md
+++ b/erts/doc/references/erl_cmd.md
@@ -772,6 +772,10 @@ behavior of earlier flags.
[perf support](BeamAsm.md#linux-perf-support) section in the BeamAsm internal
documentation.
+- **`+JPperfdirectory <directory>`{: #+JPperfdirectory }** - Set the directory
+ used to store `perf` dump and map files when running with the JIT on Linux.
+ Defaults to `/tmp`.
+
- **`+JMsingle true|false`{: #+JMsingle }** - Enables or disables the use of
single-mapped RWX memory for JIT code.
diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c
index 5c20f55fd8..1b7f91b100 100644
--- a/erts/emulator/beam/erl_init.c
+++ b/erts/emulator/beam/erl_init.c
@@ -594,6 +594,7 @@ __decl_noreturn void __noreturn erts_usage(void)
erts_fprintf(stderr, "-JDdump bool enable or disable dumping of generated assembly code for each module loaded\n");
erts_fprintf(stderr, "-JPcover true|false|line|line_counters|function|function_counters enable or disable instrumentation for coverage\n");
erts_fprintf(stderr, "-JPperf true|false|dump|map|fp|no_fp enable or disable support for perf on Linux\n");
+ erts_fprintf(stderr, "-JPperfdirectory <directory> set the directory perf files are stored. Default: /tmp\n");
erts_fprintf(stderr, "-JMsingle bool enable the use of single-mapped RWX memory for JIT:ed code\n");
erts_fprintf(stderr, "\n");
#endif
@@ -1686,7 +1687,17 @@ erl_start(int argc, char **argv)
case 'P':
sub_param++;
- if (has_prefix("perf", sub_param)) {
+ if (has_prefix("perfdirectory", sub_param)){
+ arg = get_arg(sub_param+13, argv[i + 1], &i);
+#ifdef HAVE_LINUX_PERF_SUPPORT
+ sys_strncpy(etrs_jit_perf_directory, arg, sizeof(etrs_jit_perf_directory));
+ etrs_jit_perf_directory[sizeof(etrs_jit_perf_directory) -1 ] = '\0';
+#else
+ erts_fprintf(stderr, "+JPperfdirectory is not supported on this platform\n");
+ erts_usage();
+#endif
+ }
+ else if (has_prefix("perf", sub_param)) {
arg = get_arg(sub_param+4, argv[i + 1], &i);
#ifdef HAVE_LINUX_PERF_SUPPORT
diff --git a/erts/emulator/beam/jit/beam_asm.h b/erts/emulator/beam/jit/beam_asm.h
index 8966abce9a..0fdeba7b4f 100644
--- a/erts/emulator/beam/jit/beam_asm.h
+++ b/erts/emulator/beam/jit/beam_asm.h
@@ -47,6 +47,7 @@ enum beamasm_perf_flags {
BEAMASM_PERF_DISABLED = 0,
};
extern enum beamasm_perf_flags erts_jit_perf_support;
+extern char etrs_jit_perf_directory[MAXPATHLEN];
# endif
extern int erts_jit_single_map;
diff --git a/erts/emulator/beam/jit/beam_jit_main.cpp b/erts/emulator/beam/jit/beam_jit_main.cpp
index 69a4f7ebb5..f178d60ac3 100644
--- a/erts/emulator/beam/jit/beam_jit_main.cpp
+++ b/erts/emulator/beam/jit/beam_jit_main.cpp
@@ -44,6 +44,7 @@ ErtsFrameLayout ERTS_WRITE_UNLIKELY(erts_frame_layout);
/* Global configuration variables (under the `+J` prefix) */
#ifdef HAVE_LINUX_PERF_SUPPORT
enum beamasm_perf_flags erts_jit_perf_support;
+char etrs_jit_perf_directory[MAXPATHLEN] = "/tmp";
#endif
/* Force use of single-mapped RWX memory for JIT code */
int erts_jit_single_map = 0;
diff --git a/erts/emulator/beam/jit/beam_jit_metadata.cpp b/erts/emulator/beam/jit/beam_jit_metadata.cpp
index 2f08f0487e..5953058168 100644
--- a/erts/emulator/beam/jit/beam_jit_metadata.cpp
+++ b/erts/emulator/beam/jit/beam_jit_metadata.cpp
@@ -332,7 +332,11 @@ public:
/* LLVM places this file in ~/.debug/jit/ maybe we should do that to? */
- erts_snprintf(name, sizeof(name), "/tmp/jit-%d.dump", getpid());
+ erts_snprintf(name,
+ sizeof(name),
+ "%s/jit-%d.dump",
+ etrs_jit_perf_directory,
+ getpid());
file = fopen(name, "w+");
@@ -473,7 +477,11 @@ public:
if (erts_sys_explicit_host_getenv("ERL_SYM_MAP_FILE", name, &namesz) !=
1) {
- snprintf(name, sizeof(name), "/tmp/perf-%i.map", getpid());
+ erts_snprintf(name,
+ sizeof(name),
+ "%s/perf-%i.map",
+ etrs_jit_perf_directory,
+ getpid());
}
file = fopen(name, "w");
if (!file) {
diff --git a/erts/emulator/test/jit_SUITE.erl b/erts/emulator/test/jit_SUITE.erl
index c6a16968ad..23e79953fd 100644
--- a/erts/emulator/test/jit_SUITE.erl
+++ b/erts/emulator/test/jit_SUITE.erl
@@ -26,7 +26,7 @@
init_per_suite/1, end_per_suite/1,
init_per_group/2, end_per_group/2,
init_per_testcase/2, end_per_testcase/2]).
--export([annotate/1, jmsingle/1, named_labels/1, symbols/1]).
+-export([annotate/1, jmsingle/1, named_labels/1, symbols/1, perfdirectory_set/1, perfdirectory_not_set/1]).
suite() ->
[{timetrap, {minutes, 4}}].
@@ -35,7 +35,7 @@ groups() ->
[{perf, [symbols, annotate]}].
all() ->
- [{group, perf}, jmsingle, named_labels].
+ [{group, perf}, jmsingle, named_labels, perfdirectory_set, perfdirectory_not_set].
init_per_suite(Config) ->
case erlang:system_info(emu_flavor) of
@@ -286,3 +286,26 @@ named_labels(_Config) ->
_ ->
ct:fail("No labels found in assembly dump")
end.
+
+perfdirectory_set(_Config) ->
+ %% Confirm that when +JPperfdirectory is set, the jit/perf files
+ %% end up in the appropriate directory
+ TempDir = string:strip(os:cmd("mktemp -d"), right, $\n),
+ run_perfdirectory_test("+JPperfdirectory " ++ TempDir, TempDir).
+
+perfdirectory_not_set(_Config) ->
+ %% Confirm that when +JPperfdirectory is not set, the jit/perf files
+ %% end up in /tmp
+ run_perfdirectory_test("", "/tmp").
+
+run_perfdirectory_test(AdditionalFlags, ExpectedDirectory) ->
+ Cmd = "erl -noinput -eval 'io:format(\"~s~n\", [os:getpid()]).' -s init stop +JPperf true " ++ AdditionalFlags,
+ ThePid = string:strip(os:cmd(Cmd), right, $\n),
+ JitDumpFile = ExpectedDirectory ++ "/jit-" ++ ThePid ++ ".dump",
+ PerfMapFile = ExpectedDirectory ++ "/perf-" ++ ThePid ++ ".map",
+ case lists:all(fun filelib:is_file/1, [JitDumpFile, PerfMapFile]) of
+ true ->
+ ok;
+ _ ->
+ ct:fail("Expected ~s and ~s to exist", [JitDumpFile, PerfMapFile])
+ end.
--
2.43.0