diff options
-rw-r--r-- | erts/configure.in | 2 | ||||
-rw-r--r-- | erts/doc/src/erts_alloc.xml | 48 | ||||
-rw-r--r-- | erts/emulator/beam/erl_alloc.c | 50 | ||||
-rw-r--r-- | erts/emulator/beam/erl_alloc_util.c | 25 | ||||
-rw-r--r-- | erts/emulator/beam/erl_alloc_util.h | 7 | ||||
-rw-r--r-- | erts/emulator/sys/common/erl_mmap.c | 12 | ||||
-rw-r--r-- | erts/emulator/sys/common/erl_mmap.h | 4 | ||||
-rw-r--r-- | erts/emulator/test/alloc_SUITE.erl | 12 | ||||
-rw-r--r-- | erts/etc/common/erlexec.c | 4 | ||||
-rw-r--r-- | lib/runtime_tools/src/observer_backend.erl | 4 |
10 files changed, 124 insertions, 44 deletions
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..a0ec89f398 100644 --- a/erts/doc/src/erts_alloc.xml +++ b/erts/doc/src/erts_alloc.xml @@ -271,22 +271,18 @@ 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.</item> - <tag><marker id="MMscmgc"><c><![CDATA[+MMscmgc <amount>]]></c></marker></tag> - <item> - Set <seealso marker="#MMscs">super carrier</seealso> max guaranteed - no of carriers. This parameter defaults to <c>65536</c>. 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. - </item> <tag><marker id="MMsco"><c><![CDATA[+MMsco true|false]]></c></marker></tag> <item> Set <seealso marker="#MMscs">super carrier</seealso> only flag. This flag defaults to <c>true</c>. When a super carrier is used and this - flag is <c>true</c>, the system will crash when a carrier request - cannot be satisfied by the super carrier. When the flag is <c>false</c> - the system will try to create requested carrier by other means. + flag is <c>true</c>, <c>mseg_alloc</c> will only create carriers + in the super carrier. Note that the <c>alloc_util</c> framework may + create <c>sys_alloc</c> carriers, so if you want all carriers to + be created in the super carrier, you therefore want to disable use + of <c>sys_alloc</c> carriers by also passing + <seealso marker="#Musac"><c>+Musac false</c></seealso>. When the flag + is <c>false</c>, <c>mseg_alloc</c> will try to create carriers outside + of the super carrier when the super carrier is full. <br/><br/> <em>NOTE</em>: Setting this flag to <c>false</c> may not be supported on all systems. This flag will in that case be ignored. @@ -295,6 +291,19 @@ disabled on halfword heap systems. This flag will be ignored on halfword heap systems. </item> + <tag><marker id="MMscrfsd"><c><![CDATA[+MMscrfsd <amount>]]></c></marker></tag> + <item> + Set <seealso marker="#MMscs">super carrier</seealso> reserved + free segment descriptors. This parameter defaults to <c>65536</c>. + 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 + <c>erts_mmap</c> tuple part of the result from calling + <seealso marker="erts:erlang#system_info_allocator_tuple">erlang:system_info({allocator, mseg_alloc})</seealso>. + </item> <tag><marker id="MMscrpm"><c><![CDATA[+MMscrpm true|false]]></c></marker></tag> <item> Set <seealso marker="#MMscs">super carrier</seealso> reserve physical @@ -549,6 +558,11 @@ placed in separate memory segments. When this limit has been reached, new carriers will be placed in memory retrieved from <c>sys_alloc</c>.</item> + <tag><marker id="Musac"><c><![CDATA[+Musac <bool>]]></c></marker></tag> + <item> + Allow <c>sys_alloc</c> carriers. By default <c>true</c>. If + set to <c>false</c>, <c>sys_alloc</c> carriers will never be + created by allocators using the <c>alloc_util</c> framework.</item> </taglist> <p>Instrumentation flags:</p> <taglist> @@ -604,6 +618,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..b5ba9bb94a 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; @@ -1486,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); @@ -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 @@ -1639,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; @@ -2749,8 +2784,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 +2883,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/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,17 +4514,22 @@ 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)); #if HAVE_ERTS_MSEG @@ -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/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 c9908caf20..f098e56a2e 100644 --- a/erts/etc/common/erlexec.c +++ b/erts/etc/common/erlexec.c @@ -103,14 +103,16 @@ static char *plusM_other_switches[] = { "ea", "ummc", "uycs", + "usac", "im", "is", "it", + "lpm", "Mamcbf", "Mrmcbf", "Mmcs", "Mscs", - "Mscmgc", + "Mscrfsd", "Msco", "Mscrpm", "Ye", diff --git a/lib/runtime_tools/src/observer_backend.erl b/lib/runtime_tools/src/observer_backend.erl index 670e216d97..202129c61a 100644 --- a/lib/runtime_tools/src/observer_backend.erl +++ b/lib/runtime_tools/src/observer_backend.erl @@ -77,8 +77,8 @@ sys_info() -> | MemInfo]. alloc_info() -> - {_,_,AllocTypes,_} = erlang:system_info(allocator), - try erlang:system_info({allocator_sizes,AllocTypes}) of + AlcuAllocs = erlang:system_info(alloc_util_allocators), + try erlang:system_info({allocator_sizes, AlcuAllocs}) of Allocators -> Allocators catch _:_ -> [] end. |