feature/igc3 5f4458c796c: On Linux, set an initial MPS commit limit

Helmut Eller <[email protected]> Wed, 5 Aug 2026 03:58:55 -0400 (EDT)
Newsgroups gmane.emacs.diffs
Message-ID <[email protected]>
branch: feature/igc3
commit 5f4458c796c095d00d5828fd4461508c1836881e
Author: Helmut Eller <[email protected]>
Commit: Helmut Eller <[email protected]>

    On Linux, set an initial MPS commit limit
    
    Use the minimum of the available physical RAM or RLIMIT_DATA.  It's
    rarely desired to allocate more memory than available RAM and the
    RLIMIT_DATA part is convenient in combination with 'ulimit -Sd'.
    
    Users can override this with igc--set-commit-limit.
    
    * src/igc.c (read_commit_limit): New helper.
    (make_arena): Use it to initialize MPS_KEY_COMMIT_LIMIT.  When
    EMACS_IGC_VERBOSE is set also print the value of mps_arena_reserved.
---
 src/igc.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/src/igc.c b/src/igc.c
index 2fa0589b952..ab09e708e73 100644
--- a/src/igc.c
+++ b/src/igc.c
@@ -100,6 +100,11 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>. */
 # include "xwidget.h"
 #endif
 
+#ifdef GNU_LINUX
+#include <sys/resource.h>
+#include <errno.h>
+#endif
+
 #if !USE_LSB_TAG
 # error "USE_LSB_TAG required"
 #endif
@@ -5909,6 +5914,26 @@ read_arena_size (size_t *size)
   return ok;
 }
 
+static bool
+read_commit_limit (size_t *size_o)
+{
+  size_t limit = SIZE_MAX;
+#ifdef GNU_LINUX
+  {
+    errno = 0;
+    long phys_limit = sysconf (_SC_PHYS_PAGES);
+    if (phys_limit != -1 && errno == 0)
+      limit = min (limit, (size_t) phys_limit * getpagesize ());
+
+    struct rlimit data_limit;
+    if (getrlimit (RLIMIT_DATA, &data_limit) == 0)
+      limit = min (limit, data_limit.rlim_cur);
+  }
+#endif
+  *size_o = limit;
+  return limit != SIZE_MAX;
+}
+
 static void
 make_arena (struct igc *gc)
 {
@@ -5919,6 +5944,9 @@ make_arena (struct igc *gc)
     size_t size;
     if (read_arena_size (&size))
       MPS_ARGS_ADD (args, MPS_KEY_ARENA_SIZE, size);
+    size_t commit_limit;
+    if (read_commit_limit (&commit_limit))
+      MPS_ARGS_ADD (args, MPS_KEY_COMMIT_LIMIT, commit_limit);
     res = mps_arena_create_k (&gc->arena, mps_arena_class_vm (), args);
   }
   MPS_ARGS_END (args);
@@ -5938,6 +5966,7 @@ make_arena (struct igc *gc)
       for (int i = 0; i < ngens; ++i)
 	fprintf (stderr, "gen %d: %zu %lf\n", i, gens[i].mps_capacity,
 		 gens[i].mps_mortality);
+      fprintf (stderr, "reserved %zu\n", mps_arena_reserved (gc->arena));
       fprintf (stderr, "pause time %lf\n", mps_arena_pause_time (gc->arena));
       fprintf (stderr, "commit limit %zu\n",
 	       mps_arena_commit_limit (gc->arena));