File 2613-erts-Add-Mumadtn-true-for-MADV_DONTNEED-instead-of-M.patch of Package erlang

From 81754b0ef920bfe43f4bedd0ff34c03818942de0 Mon Sep 17 00:00:00 2001
From: Sverker Eriksson <sverker@erlang.org>
Date: Mon, 18 Aug 2025 16:50:04 +0200
Subject: [PATCH 3/3] erts: Add +Mumadtn true for MADV_DONTNEED instead of
 MADV_FREE

---
 erts/doc/references/erts_alloc.md   |  8 ++++++++
 erts/emulator/beam/erl_alloc.c      |  4 ++++
 erts/emulator/beam/erl_alloc_util.c |  4 ++++
 erts/emulator/beam/erl_alloc_util.h |  7 +++++--
 erts/emulator/sys/common/erl_mmap.c |  7 +++++++
 erts/emulator/sys/common/erl_mmap.h | 10 +++++-----
 erts/etc/common/erlexec.c           |  1 +
 7 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/erts/doc/references/erts_alloc.md b/erts/doc/references/erts_alloc.md
index c4d95b244b..57c5e2a711 100644
--- a/erts/doc/references/erts_alloc.md
+++ b/erts/doc/references/erts_alloc.md
@@ -413,6 +413,9 @@ identifier is effected.
   used. The value chosen depends on the allocator type and can be changed
   between ERTS versions.
 
+  On Unix flag [`+Mumadtn`](erts_alloc.md#Mumadtn) may also be set to pass
+  `MADV_DONTNEED` instead of `MADV_FREE` as argument to `madvise()`.
+
   See also [`acul`](erts_alloc.md#M_acul).
 
 - **`+M<S>as bf|aobf|aoff|aoffcbf|aoffcaobf|ageffcaoff|ageffcbf|ageffcaobf|gf|af`{:
@@ -581,6 +584,11 @@ All allocators based on `alloc_util` are effected.
   `true`. If set to `false`, `sys_alloc` carriers are never created by
   allocators using the `alloc_util` framework.
 
+- **`+Mumadtn <bool>`{: #Mumadtn }** - Control how to mark memory as re-usable
+  on Unix when [`+M<S>acful`](erts_alloc.md#M_acful) is set. Default is `false`
+  which means `MADV_FREE` is passed to `madvise()`. If set to `true`,
+  `MADV_DONTNEED` is passed instead.
+
 ### Special Flag for literal_alloc
 
 - **`+MIscs <size in MB>`{: #MIscs }** - `literal_alloc` super carrier size (in
diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c
index f173a9223c..f5bc19fdbb 100644
--- a/erts/emulator/beam/erl_alloc.c
+++ b/erts/emulator/beam/erl_alloc.c
@@ -1825,6 +1825,10 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
 			init->alloc_util.sac
 			    = get_bool_value(argv[i]+6, argv, &i);
 		    }
+                    else if (has_prefix("madtn", argv[i]+3)) {
+                        init->alloc_util.madtn
+                            = get_bool_value(argv[i]+8, argv, &i);
+                    }
 		    else {
 			int a;
 			int start = i;
diff --git a/erts/emulator/beam/erl_alloc_util.c b/erts/emulator/beam/erl_alloc_util.c
index 9a15b68e21..8c3dd7b460 100644
--- a/erts/emulator/beam/erl_alloc_util.c
+++ b/erts/emulator/beam/erl_alloc_util.c
@@ -7028,6 +7028,10 @@ erts_alcu_init(AlcUInit_t *init)
 #endif
     allow_sys_alloc_carriers = init->sac;
 
+#if defined(HAVE_MADVISE) && defined(MADV_FREE)
+    erts_madvise_discard_advice = (init->madtn ? MADV_DONTNEED : MADV_FREE);
+#endif
+
 #ifdef DEBUG
     carrier_alignment = sizeof(Unit_t);
 #endif
diff --git a/erts/emulator/beam/erl_alloc_util.h b/erts/emulator/beam/erl_alloc_util.h
index 6c017b815a..ecff02dd91 100644
--- a/erts/emulator/beam/erl_alloc_util.h
+++ b/erts/emulator/beam/erl_alloc_util.h
@@ -42,6 +42,7 @@ typedef struct {
     UWord ycs;
     UWord mmc;
     int   sac;
+    int   madtn;
 } AlcUInit_t;
 
 typedef struct {
@@ -102,7 +103,8 @@ typedef struct {
 #define ERTS_DEFAULT_ALCU_INIT {                                           \
     .ycs = 1024*1024,		/* (bytes):    sys_alloc carrier size    */\
     .mmc = ~((UWord) 0),	/* (amount):   max mseg carriers         */\
-    .sac = 1			/* (bool):     sys_alloc carriers        */\
+    .sac = 1,			/* (bool):     sys_alloc carriers        */\
+    .madtn = 0                  /* (bool) => erts_madvise_discard_advice */\
 }
 
 #define ERTS_DEFAULT_ALLCTR_INIT {                                         \
@@ -143,7 +145,8 @@ typedef struct {
 #define ERTS_DEFAULT_ALCU_INIT {                                           \
     .ycs = 128*1024,    /* (bytes):         sys_alloc carrier size       */\
     .mmc = 1024,        /* (amount):        max mseg carriers            */\
-    .sac = 1		/* (bool):          sys_alloc carriers           */\
+    .sac = 1,		/* (bool):          sys_alloc carriers           */\
+    .madtn = 0          /* (bool) =>        erts_madvise_discard_advice  */\
 }
 
 #define ERTS_DEFAULT_ALLCTR_INIT {                                         \
diff --git a/erts/emulator/sys/common/erl_mmap.c b/erts/emulator/sys/common/erl_mmap.c
index 03cf6f7e9d..e07a1622b3 100644
--- a/erts/emulator/sys/common/erl_mmap.c
+++ b/erts/emulator/sys/common/erl_mmap.c
@@ -34,6 +34,13 @@
 #include <sys/mman.h>
 #endif
 
+#if defined(HAVE_MADVISE) && defined(MADV_FREE)
+/* Note that we don't default to MADV_DONTNEED since it promises that
+ * the given region will be zeroed on access, which turned out to be
+ * too much of a performance hit. */
+int erts_madvise_discard_advice = MADV_FREE;
+#endif
+
 int erts_mem_guard(void *p, UWord size, int readable, int writable) {
 
 #if defined(WIN32)
diff --git a/erts/emulator/sys/common/erl_mmap.h b/erts/emulator/sys/common/erl_mmap.h
index 20acd528e3..3218f67974 100644
--- a/erts/emulator/sys/common/erl_mmap.h
+++ b/erts/emulator/sys/common/erl_mmap.h
@@ -156,7 +156,6 @@ Eterm erts_mmap_info_options(ErtsMemMapper*,
                              char *prefix, fmtfn_t *print_to_p, void *print_to_arg,
                              Uint **hpp, Uint *szp);
 
-
 #ifdef ERTS_WANT_MEM_MAPPERS
 #  include "erl_alloc_types.h"
 
@@ -194,6 +193,10 @@ int erts_mem_guard(void *p, UWord size, int readable, int writable);
  * its contents) the next time it's accessed. */
 ERTS_GLB_INLINE void erts_mem_discard(void *p, UWord size);
 
+#if defined(HAVE_MADVISE) && defined(MADV_FREE)
+extern int erts_madvise_discard_advice; // MADV_FREE or MADV_DONTNEED
+#endif
+
 #if ERTS_GLB_INLINE_INCL_FUNC_DEF
 
 #ifdef VALGRIND
@@ -220,11 +223,8 @@ ERTS_GLB_INLINE void erts_mem_discard(void *p, UWord size);
     #include <sys/mman.h>
 
     ERTS_GLB_INLINE void erts_mem_discard(void *ptr, UWord size) {
-        /* Note that we don't fall back to MADV_DONTNEED since it promises that
-         * the given region will be zeroed on access, which turned out to be
-         * too much of a performance hit. */
     #ifdef MADV_FREE
-        madvise(ptr, size, MADV_FREE);
+        madvise(ptr, size, erts_madvise_discard_advice);
     #else
         (void)ptr;
         (void)size;
diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c
index 6da1971cad..fdad5b0d5e 100644
--- a/erts/etc/common/erlexec.c
+++ b/erts/etc/common/erlexec.c
@@ -100,6 +100,7 @@ static char *plusM_au_alloc_switches[] = {
 /* +M other arguments */
 static char *plusM_other_switches[] = {
     "ea",
+    "umadtn",
     "ummc",
     "uycs",
     "usac",
-- 
2.51.0

openSUSE Build Service is sponsored by