From f17532112c6b723a7b025c7d74565e7ac2588cbb Mon Sep 17 00:00:00 2001 From: Rickard Green 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 @@ + +Mlpm all|no + Lock physical memory. The default value is no, i.e., + no physical memory will be locked. If set to all, all + memory mappings made by the runtime system, will be locked into + physical memory. If set to all, 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. +

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 From bb59a8fcf1f6cf4162a2a97c13087843d1b9dac4 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Tue, 5 Nov 2013 15:37:49 +0100 Subject: Add switch for disabling sys_alloc carriers The switch "+Musac " controls if sys_alloc carriers are allowed. --- erts/doc/src/erts_alloc.xml | 5 +++++ erts/emulator/beam/erl_alloc.c | 4 ++++ erts/emulator/beam/erl_alloc_util.c | 25 ++++++++++++++++++------- erts/emulator/beam/erl_alloc_util.h | 7 +++++-- erts/etc/common/erlexec.c | 1 + 5 files changed, 33 insertions(+), 9 deletions(-) (limited to 'erts') diff --git a/erts/doc/src/erts_alloc.xml b/erts/doc/src/erts_alloc.xml index 90bc35cdc9..70029dbeab 100644 --- a/erts/doc/src/erts_alloc.xml +++ b/erts/doc/src/erts_alloc.xml @@ -549,6 +549,11 @@ placed in separate memory segments. When this limit has been reached, new carriers will be placed in memory retrieved from sys_alloc. + ]]> + + Allow sys_alloc carriers. By default true. If + set to false, sys_alloc carriers will never be + created by allocators using the alloc_util framework.

Instrumentation flags:

diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c index 8e20d58161..fb0f47d1b7 100644 --- a/erts/emulator/beam/erl_alloc.c +++ b/erts/emulator/beam/erl_alloc.c @@ -1670,6 +1670,10 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init) init->alloc_util.mmc = get_amount_value(argv[i]+6, argv, &i); } + else if (has_prefix("sac", argv[i]+3)) { + init->alloc_util.sac + = get_bool_value(argv[i]+6, 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 1fdee4db2c..b0fc653f32 100644 --- a/erts/emulator/beam/erl_alloc_util.c +++ b/erts/emulator/beam/erl_alloc_util.c @@ -98,6 +98,7 @@ static Uint sys_alloc_carrier_size; #if HAVE_ERTS_MSEG static Uint max_mseg_carriers; #endif +static int allow_sys_alloc_carriers; #define ONE_GIGA (1000000000) @@ -3256,13 +3257,15 @@ create_carrier(Allctr_t *allctr, Uint umem_sz, UWord flags) int is_mseg = 0; #endif -#if HALFWORD_HEAP - flags |= CFLG_FORCE_MSEG; -#elif ERTS_SUPER_ALIGNED_MSEG_ONLY - if (flags & CFLG_MBC) { + if (HALFWORD_HEAP + || (ERTS_SUPER_ALIGNED_MSEG_ONLY && (flags & CFLG_MBC)) + || !allow_sys_alloc_carriers) { flags |= CFLG_FORCE_MSEG; - } + flags &= ~CFLG_FORCE_SYS_ALLOC; +#if !HAVE_ERTS_MSEG + return NULL; #endif + } ASSERT((flags & CFLG_SBC && !(flags & CFLG_MBC)) || (flags & CFLG_MBC && !(flags & CFLG_SBC))); @@ -3697,6 +3700,7 @@ static struct { Eterm mmc; #endif Eterm ycs; + Eterm sac; Eterm fix_types; @@ -3789,6 +3793,7 @@ init_atoms(Allctr_t *allctr) AM_INIT(mmc); #endif AM_INIT(ycs); + AM_INIT(sac); AM_INIT(fix_types); @@ -4509,16 +4514,21 @@ erts_alcu_au_info_options(int *print_to_p, void *print_to_arg, #if HAVE_ERTS_MSEG "option mmc: %beu\n" #endif - "option ycs: %beu\n", + "option ycs: %beu\n" + "option sac: %s\n", #if HAVE_ERTS_MSEG max_mseg_carriers, #endif - sys_alloc_carrier_size); + sys_alloc_carrier_size, + allow_sys_alloc_carriers ? "true" : "false"); } if (hpp || szp) { res = NIL; ensure_atoms_initialized(NULL); + add_2tup(hpp, szp, &res, + am.sac, + allow_sys_alloc_carriers ? am_true : am_false); add_2tup(hpp, szp, &res, am.ycs, bld_uint(hpp, szp, sys_alloc_carrier_size)); @@ -5681,6 +5691,7 @@ erts_alcu_init(AlcUInit_t *init) #else /* #if HAVE_ERTS_MSEG */ sys_alloc_carrier_size = ((init->ycs + 4095) / 4096) * 4096; #endif + allow_sys_alloc_carriers = init->sac; #ifdef DEBUG carrier_alignment = sizeof(Unit_t); diff --git a/erts/emulator/beam/erl_alloc_util.h b/erts/emulator/beam/erl_alloc_util.h index 222f137024..7be6b1ed9d 100644 --- a/erts/emulator/beam/erl_alloc_util.h +++ b/erts/emulator/beam/erl_alloc_util.h @@ -32,6 +32,7 @@ typedef struct Allctr_t_ Allctr_t; typedef struct { UWord ycs; UWord mmc; + int sac; } AlcUInit_t; typedef struct { @@ -75,7 +76,8 @@ typedef struct { #define ERTS_DEFAULT_ALCU_INIT { \ 1024*1024, /* (bytes) ycs: sys_alloc carrier size */\ - ~((UWord) 0) /* (amount) mmc: max mseg carriers */ \ + ~((UWord) 0), /* (amount) mmc: max mseg carriers */\ + 1 /* (bool) sac: sys_alloc carriers */\ } #define ERTS_DEFAULT_ALLCTR_INIT { \ @@ -109,7 +111,8 @@ typedef struct { #define ERTS_DEFAULT_ALCU_INIT { \ 128*1024, /* (bytes) ycs: sys_alloc carrier size */\ - 1024 /* (amount) mmc: max mseg carriers */\ + 1024, /* (amount) mmc: max mseg carriers */\ + 1 /* (bool) sac: sys_alloc carriers */\ } #define ERTS_DEFAULT_ALLCTR_INIT { \ diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c index ffbefce545..6fd3dd83e2 100644 --- a/erts/etc/common/erlexec.c +++ b/erts/etc/common/erlexec.c @@ -103,6 +103,7 @@ static char *plusM_other_switches[] = { "ea", "ummc", "uycs", + "usac", "im", "is", "it", -- cgit v1.2.3 From e526cb32336afc4feb4b92665d31ccc2af3e741c Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Tue, 5 Nov 2013 17:00:38 +0100 Subject: Replace the +MMscmgc switch with +MMscrfsd Replaced the +MMscmgc switch with the +MMscrfsd switch. The old switch didn't reflect what it controlled. --- erts/doc/src/erts_alloc.xml | 22 +++++++++++++--------- erts/emulator/beam/erl_alloc.c | 6 +++--- erts/emulator/sys/common/erl_mmap.c | 12 ++++++------ erts/emulator/sys/common/erl_mmap.h | 4 ++-- erts/emulator/test/alloc_SUITE.erl | 12 ++++++------ erts/etc/common/erlexec.c | 2 +- 6 files changed, 31 insertions(+), 27 deletions(-) (limited to 'erts') diff --git a/erts/doc/src/erts_alloc.xml b/erts/doc/src/erts_alloc.xml index 70029dbeab..8f5e8cd10b 100644 --- a/erts/doc/src/erts_alloc.xml +++ b/erts/doc/src/erts_alloc.xml @@ -271,15 +271,6 @@ memory segment cache is not reused if its size exceeds the requested size with more than relative max cache bad fit percent of the requested size. Default value is 20. - ]]> - - Set super carrier max guaranteed - no of carriers. This parameter defaults to 65536. This - parameter determines an amount of pre-allocated structures that is - needed in order to keep track of different areas in the super carrier. - When the system runs out of such structures it may crash due to an - out of memory condition. - Set super carrier only flag. This @@ -295,6 +286,19 @@ disabled on halfword heap systems. This flag will be ignored on halfword heap systems. + ]]> + + Set super carrier reserved + free segment descriptors. This parameter defaults to 65536. + This parameter determines the amount of memory to reserve for + free segment descriptors used by the super carrier. If the system + runs out of reserved memory for free segment descriptors, other + memory will be used. This may however cause fragmentation issues, + so you want to ensure that this never happens. The maximum amount + of free segment descriptors used can be retrieved from the + erts_mmap tuple part of the result from calling + erlang:system_info({allocator, mseg_alloc}). + Set super carrier reserve physical diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c index fb0f47d1b7..b5ba9bb94a 100644 --- a/erts/emulator/beam/erl_alloc.c +++ b/erts/emulator/beam/erl_alloc.c @@ -1504,11 +1504,11 @@ handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init) #endif get_bool_value(argv[i]+8, argv, &i); } - else if (has_prefix("scmgc", argv[i]+3)) { + else if (has_prefix("scrfsd", argv[i]+3)) { #if HAVE_ERTS_MSEG - init->mseg.mmap.scmgc = + init->mseg.mmap.scrfsd = #endif - get_amount_value(argv[i]+8, argv, &i); + get_amount_value(argv[i]+9, argv, &i); } else { bad_param(param, param+2); diff --git a/erts/emulator/sys/common/erl_mmap.c b/erts/emulator/sys/common/erl_mmap.c index a9da7430fb..3f6813e1a5 100644 --- a/erts/emulator/sys/common/erl_mmap.c +++ b/erts/emulator/sys/common/erl_mmap.c @@ -2057,7 +2057,7 @@ static struct { Eterm scs; Eterm sco; Eterm scrpm; - Eterm scmgc; + Eterm scrfsd; int is_initialized; erts_mtx_t init_mutex; @@ -2090,7 +2090,7 @@ static void init_atoms(void) AM_INIT(scs); AM_INIT(sco); AM_INIT(scrpm); - AM_INIT(scmgc); + AM_INIT(scrfsd); am.is_initialized = 1; } erts_mtx_unlock(&am.init_mutex); @@ -2121,7 +2121,7 @@ erts_mmap_init(ErtsMMapInit *init) #if defined(HARD_DEBUG) || 0 erts_fprintf(stderr, "erts_mmap: scs = %bpu\n", init->scs); erts_fprintf(stderr, "erts_mmap: sco = %i\n", init->sco); - erts_fprintf(stderr, "erts_mmap: scmgc = %i\n", init->scmgc); + erts_fprintf(stderr, "erts_mmap: scrfsd = %i\n", init->scrfsd); #endif erts_page_inv_mask = pagesize - 1; if (pagesize & erts_page_inv_mask) @@ -2234,7 +2234,7 @@ erts_mmap_init(ErtsMMapInit *init) mmap_state.no_os_mmap = init->sco; - desc_size = init->scmgc; + desc_size = init->scrfsd; if (desc_size < 100) desc_size = 100; desc_size *= sizeof(ErtsFreeSegDesc); @@ -2418,7 +2418,7 @@ Eterm erts_mmap_info_options(char *prefix, if (mmap_state.supercarrier) { erts_print(to, arg, "%ssco: %T\n", prefix, sco); erts_print(to, arg, "%sscrpm: %T\n", prefix, scrpm); - erts_print(to, arg, "%sscmgc: %beu\n", prefix, mmap_state.desc.reserved); + erts_print(to, arg, "%sscrfsd: %beu\n", prefix, mmap_state.desc.reserved); } } @@ -2429,7 +2429,7 @@ Eterm erts_mmap_info_options(char *prefix, res = NIL; if (mmap_state.supercarrier) { - add_2tup(hpp, szp, &res, am.scmgc, + add_2tup(hpp, szp, &res, am.scrfsd, erts_bld_uint(hpp,szp, mmap_state.desc.reserved)); add_2tup(hpp, szp, &res, am.scrpm, scrpm); add_2tup(hpp, szp, &res, am.sco, sco); diff --git a/erts/emulator/sys/common/erl_mmap.h b/erts/emulator/sys/common/erl_mmap.h index e6934dbb26..778a8e0e80 100644 --- a/erts/emulator/sys/common/erl_mmap.h +++ b/erts/emulator/sys/common/erl_mmap.h @@ -45,8 +45,8 @@ typedef struct { } predefined_area; UWord scs; /* super carrier size */ int sco; /* super carrier only? */ - Uint scmgc; /* super carrier: max guaranteed (number of) carriers */ - int scrpm; + UWord scrfsd; /* super carrier reserved free segment descriptors */ + int scrpm; /* super carrier reserve physical memory */ }ErtsMMapInit; #define ERTS_MMAP_INIT_DEFAULT_INITER \ diff --git a/erts/emulator/test/alloc_SUITE.erl b/erts/emulator/test/alloc_SUITE.erl index f6ff6bb813..cd2d043f7e 100644 --- a/erts/emulator/test/alloc_SUITE.erl +++ b/erts/emulator/test/alloc_SUITE.erl @@ -114,8 +114,8 @@ cpool(Cfg) -> ?line drv_case(Cfg). erts_mmap(Config) when is_list(Config) -> case {?t:os_type(), is_halfword_vm()} of {{unix, _}, false} -> - [erts_mmap_do(Config, SCO, SCRPM, SCMGC) - || SCO <-[true,false], SCMGC <-[1234,0], SCRPM <- [true,false]]; + [erts_mmap_do(Config, SCO, SCRPM, SCRFSD) + || SCO <-[true,false], SCRFSD <-[1234,0], SCRPM <- [true,false]]; {_,true} -> {skipped, "No supercarrier support on halfword vm"}; @@ -126,14 +126,14 @@ erts_mmap(Config) when is_list(Config) -> end. -erts_mmap_do(Config, SCO, SCRPM, SCMGC) -> +erts_mmap_do(Config, SCO, SCRPM, SCRFSD) -> SCS = 100, % Mb O1 = "+MMscs" ++ integer_to_list(SCS) ++ " +MMsco" ++ atom_to_list(SCO) ++ " +MMscrpm" ++ atom_to_list(SCRPM), - Opts = case SCMGC of + Opts = case SCRFSD of 0 -> O1; - _ -> O1 ++ " +MMscmgc"++integer_to_list(SCMGC) + _ -> O1 ++ " +MMscrfsd"++integer_to_list(SCRFSD) end, {ok, Node} = start_node(Config, Opts), Self = self(), @@ -148,7 +148,7 @@ erts_mmap_do(Config, SCO, SCRPM, SCMGC) -> Total = SCS*1024*1024, {reserved,Reserved} = lists:keyfind(reserved,1,Segs), - true = (Reserved >= SCMGC), + true = (Reserved >= SCRFSD), case {SCO,lists:keyfind(os,1,EM)} of {true, false} -> ok; diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c index 6fd3dd83e2..f098e56a2e 100644 --- a/erts/etc/common/erlexec.c +++ b/erts/etc/common/erlexec.c @@ -112,7 +112,7 @@ static char *plusM_other_switches[] = { "Mrmcbf", "Mmcs", "Mscs", - "Mscmgc", + "Mscrfsd", "Msco", "Mscrpm", "Ye", -- cgit v1.2.3 From b82549dfb985e4b55a6531d634e46446f7a8dbee Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Tue, 5 Nov 2013 17:13:35 +0100 Subject: Fix documentation of the +MMsco switch --- erts/doc/src/erts_alloc.xml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'erts') diff --git a/erts/doc/src/erts_alloc.xml b/erts/doc/src/erts_alloc.xml index 8f5e8cd10b..a0ec89f398 100644 --- a/erts/doc/src/erts_alloc.xml +++ b/erts/doc/src/erts_alloc.xml @@ -275,9 +275,14 @@ Set super carrier only flag. This flag defaults to true. When a super carrier is used and this - flag is true, the system will crash when a carrier request - cannot be satisfied by the super carrier. When the flag is false - the system will try to create requested carrier by other means. + flag is true, mseg_alloc will only create carriers + in the super carrier. Note that the alloc_util framework may + create sys_alloc carriers, so if you want all carriers to + be created in the super carrier, you therefore want to disable use + of sys_alloc carriers by also passing + +Musac false. When the flag + is false, mseg_alloc will try to create carriers outside + of the super carrier when the super carrier is full.

NOTE: Setting this flag to false may not be supported on all systems. This flag will in that case be ignored. -- cgit v1.2.3