From f17532112c6b723a7b025c7d74565e7ac2588cbb Mon Sep 17 00:00:00 2001
From: Rickard Green <rickard@erlang.org>
Date: Mon, 4 Nov 2013 17:18:52 +0100
Subject: Add support for locking mappings to physical memory

Using "+Mlpm all" switch all mappings made by the emulator will
be locked into physical memory.
---
 erts/configure.in              |  2 +-
 erts/doc/src/erts_alloc.xml    | 10 ++++++++++
 erts/emulator/beam/erl_alloc.c | 40 ++++++++++++++++++++++++++++++++++++++--
 erts/etc/common/erlexec.c      |  1 +
 4 files changed, 50 insertions(+), 3 deletions(-)

(limited to 'erts')

diff --git a/erts/configure.in b/erts/configure.in
index 8288a1aab1..b47a6ff094 100644
--- a/erts/configure.in
+++ b/erts/configure.in
@@ -1977,7 +1977,7 @@ AC_CHECK_FUNCS([ieee_handler fpsetmask finite isnan isinf res_gethostbyname dlop
 		gethrtime localtime_r gmtime_r inet_pton \
 		mmap mremap memcpy mallopt sbrk _sbrk __sbrk brk _brk __brk \
 		flockfile fstat strlcpy strlcat setsid posix2time time2posix \
-		setlocale nl_langinfo poll])
+		setlocale nl_langinfo poll mlockall])
 
 
 case X$erl_xcomp_posix_memalign in
diff --git a/erts/doc/src/erts_alloc.xml b/erts/doc/src/erts_alloc.xml
index 9dab5b3876..90bc35cdc9 100644
--- a/erts/doc/src/erts_alloc.xml
+++ b/erts/doc/src/erts_alloc.xml
@@ -604,6 +604,16 @@
         </item>
       </taglist>
       </item>
+      <tag><marker id="Mlpm"><c>+Mlpm all|no</c></marker></tag>
+      <item>Lock physical memory. The default value is <c>no</c>, i.e.,
+      no physical memory will be locked. If set to <c>all</c>, all
+      memory mappings made by the runtime system, will be locked into
+      physical memory. If set to <c>all</c>, the runtime system will fail
+      to start if this feature is not supported, the user has not got enough
+      privileges, or the user is not allowed to lock enough physical memory.
+      The runtime system will also fail with an out of memory condition
+      if the user limit on the amount of locked memory is reached.
+      </item>
     </taglist>
     <p>Only some default values have been presented
       here.
diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c
index d8da616d05..8e20d58161 100644
--- a/erts/emulator/beam/erl_alloc.c
+++ b/erts/emulator/beam/erl_alloc.c
@@ -100,6 +100,8 @@ static Uint install_debug_functions(void);
 #endif
 #endif
 
+static int lock_all_physical_memory = 0;
+
 ErtsAllocatorFunctions_t erts_allctrs[ERTS_ALC_A_MAX+1];
 ErtsAllocatorInfo_t erts_allctrs_info[ERTS_ALC_A_MAX+1];
 ErtsAllocatorThrSpec_t erts_allctr_thr_spec[ERTS_ALC_A_MAX+1];
@@ -618,6 +620,8 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
     hdbg_init();
 #endif
 
+    lock_all_physical_memory = 0;
+
     ncpu = eaiop->ncpu;
     if (ncpu < 1)
 	ncpu = 1;
@@ -641,6 +645,20 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
     if (argc && argv)
 	handle_args(argc, argv, &init);
 
+    if (lock_all_physical_memory) {
+#ifdef HAVE_MLOCKALL
+	errno = 0;
+	if (mlockall(MCL_CURRENT|MCL_FUTURE) != 0) {
+	    int err = errno;
+	    char *errstr = err ? strerror(err) : "unknown";
+	    erl_exit(-1, "Failed to lock physical memory: %s (%d)\n",
+		     errstr, err);
+	}
+#else
+	erl_exit(-1, "Failed to lock physical memory: Not supported\n");
+#endif
+    }
+
 #ifndef ERTS_SMP
     init.sl_alloc.thr_spec = 0;
     init.std_alloc.thr_spec = 0;
@@ -1630,6 +1648,19 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
 			bad_param(param, param+2);
 		    }
 		    break;
+		case 'l':
+		    if (has_prefix("pm", param+2)) {
+			arg = get_value(argv[i]+5, argv, &i);
+			if (strcmp("all", arg) == 0)
+			    lock_all_physical_memory = 1;
+			else if (strcmp("no", arg) == 0)
+			    lock_all_physical_memory = 0;
+			else
+			    bad_value(param, param+4, arg);
+			break;
+		    }
+		    bad_param(param, param+2);
+		    break;
 		case 'u':
 		    if (has_prefix("ycs", argv[i]+3)) {
 			init->alloc_util.ycs
@@ -2749,8 +2780,8 @@ erts_allocator_options(void *proc)
 #endif
     Uint sz, *szp, *hp, **hpp;
     Eterm res, features, settings;
-    Eterm atoms[ERTS_ALC_A_MAX-ERTS_ALC_A_MIN+6];
-    Uint terms[ERTS_ALC_A_MAX-ERTS_ALC_A_MIN+6];
+    Eterm atoms[ERTS_ALC_A_MAX-ERTS_ALC_A_MIN+7];
+    Uint terms[ERTS_ALC_A_MAX-ERTS_ALC_A_MIN+7];
     int a, length;
     SysAllocStat sas;
     Uint *endp = NULL;
@@ -2848,6 +2879,11 @@ erts_allocator_options(void *proc)
 	terms[length++] = erts_bld_2tup_list(hpp, szp, 3, o, v);
     }
 
+    atoms[length] = am_atom_put("lock_physical_memory", 20);
+    terms[length++] = (lock_all_physical_memory
+		       ? am_atom_put("all", 3)
+		       : am_atom_put("no", 2));
+
     settings = erts_bld_2tup_list(hpp, szp, length, atoms, terms);
 
     length = 0;
diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c
index c9908caf20..ffbefce545 100644
--- a/erts/etc/common/erlexec.c
+++ b/erts/etc/common/erlexec.c
@@ -106,6 +106,7 @@ static char *plusM_other_switches[] = {
     "im",
     "is",
     "it",
+    "lpm",
     "Mamcbf",
     "Mrmcbf",
     "Mmcs",
-- 
cgit v1.2.3