/erts/emulator/beam/erl_alloc.c
C | 4119 lines | 3549 code | 457 blank | 113 comment | 601 complexity | b24d5370c4eb8ca1a3d6f0838fc7007e MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0, Unlicense, LGPL-2.1, MPL-2.0-no-copyleft-exception
Large files files are truncated, but you can click here to view the full file
- /*
- * %CopyrightBegin%
- *
- * Copyright Ericsson AB 2002-2020. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * %CopyrightEnd%
- */
- /*
- * Description: Management of memory allocators.
- *
- * Author: Rickard Green
- */
- #ifdef HAVE_CONFIG_H
- # include "config.h"
- #endif
- #define ERTS_ALLOC_C__
- #define ERTS_ALC_INTERNAL__
- #define ERTS_WANT_MEM_MAPPERS
- #include "sys.h"
- #define ERL_THREADS_EMU_INTERNAL__
- #include "erl_threads.h"
- #include "global.h"
- #include "erl_db.h"
- #include "erl_binary.h"
- #include "erl_bits.h"
- #include "erl_mtrace.h"
- #include "erl_mseg.h"
- #include "erl_monitor_link.h"
- #include "erl_hl_timer.h"
- #include "erl_cpu_topology.h"
- #include "erl_thr_queue.h"
- #include "erl_nfunc_sched.h"
- #if defined(ERTS_ALC_T_DRV_SEL_D_STATE) || defined(ERTS_ALC_T_DRV_EV_D_STATE)
- #include "erl_check_io.h"
- #endif
- #include "erl_bif_unique.h"
- #define GET_ERL_GF_ALLOC_IMPL
- #include "erl_goodfit_alloc.h"
- #define GET_ERL_BF_ALLOC_IMPL
- #include "erl_bestfit_alloc.h"
- #define GET_ERL_AF_ALLOC_IMPL
- #include "erl_afit_alloc.h"
- #define GET_ERL_AOFF_ALLOC_IMPL
- #include "erl_ao_firstfit_alloc.h"
- #if ERTS_MAX_NO_OF_SCHEDULERS > ERTS_AU_MAX_PREF_ALLOC_INSTANCES
- # error "Too many schedulers; cannot create that many pref alloc instances"
- #endif
- #define ERTS_ALC_DEFAULT_MAX_THR_PREF ERTS_MAX_NO_OF_SCHEDULERS
- #if defined(SMALL_MEMORY) || defined(PURIFY) || defined(VALGRIND)
- #define AU_ALLOC_DEFAULT_ENABLE(X) 0
- #else
- #define AU_ALLOC_DEFAULT_ENABLE(X) (X)
- #endif
- #define ERTS_ALC_DEFAULT_ENABLED_ACUL 60
- #define ERTS_ALC_DEFAULT_ENABLED_ACUL_EHEAP_ALLOC 45
- #define ERTS_ALC_DEFAULT_ENABLED_ACUL_LL_ALLOC 85
- #define ERTS_ALC_DEFAULT_ACUL ERTS_ALC_DEFAULT_ENABLED_ACUL
- #define ERTS_ALC_DEFAULT_ACUL_EHEAP_ALLOC ERTS_ALC_DEFAULT_ENABLED_ACUL_EHEAP_ALLOC
- #define ERTS_ALC_DEFAULT_ACUL_LL_ALLOC ERTS_ALC_DEFAULT_ENABLED_ACUL_LL_ALLOC
- #ifdef DEBUG
- static Uint install_debug_functions(void);
- #if 0
- #define HARD_DEBUG
- #ifdef __GNUC__
- #warning "* * * * * * * * * * * * * *"
- #warning "* HARD DEBUG IS ENABLED! *"
- #warning "* * * * * * * * * * * * * *"
- #endif
- #endif
- #endif
- static int lock_all_physical_memory = 0;
- ErtsAllocatorFunctions_t ERTS_WRITE_UNLIKELY(erts_allctrs[ERTS_ALC_A_MAX+1]);
- ErtsAllocatorInfo_t erts_allctrs_info[ERTS_ALC_A_MAX+1];
- ErtsAllocatorThrSpec_t ERTS_WRITE_UNLIKELY(erts_allctr_thr_spec[ERTS_ALC_A_MAX+1]);
- #define ERTS_MIN(A, B) ((A) < (B) ? (A) : (B))
- #define ERTS_MAX(A, B) ((A) > (B) ? (A) : (B))
- typedef union {
- GFAllctr_t gfa;
- char align_gfa[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(GFAllctr_t))];
- BFAllctr_t bfa;
- char align_bfa[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(BFAllctr_t))];
- AFAllctr_t afa;
- char align_afa[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(AFAllctr_t))];
- AOFFAllctr_t aoffa;
- char align_aoffa[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(AOFFAllctr_t))];
- } ErtsAllocatorState_t erts_align_attribute(ERTS_CACHE_LINE_SIZE);
- static ErtsAllocatorState_t std_alloc_state;
- static ErtsAllocatorState_t ll_alloc_state;
- static ErtsAllocatorState_t sl_alloc_state;
- static ErtsAllocatorState_t temp_alloc_state;
- static ErtsAllocatorState_t eheap_alloc_state;
- static ErtsAllocatorState_t binary_alloc_state;
- static ErtsAllocatorState_t ets_alloc_state;
- static ErtsAllocatorState_t driver_alloc_state;
- static ErtsAllocatorState_t fix_alloc_state;
- static ErtsAllocatorState_t literal_alloc_state;
- #ifdef ERTS_ALC_A_EXEC
- static ErtsAllocatorState_t exec_alloc_state;
- #endif
- static ErtsAllocatorState_t test_alloc_state;
- enum {
- ERTS_ALC_INFO_A_ALLOC_UTIL = ERTS_ALC_A_MAX + 1,
- ERTS_ALC_INFO_A_MSEG_ALLOC,
- ERTS_ALC_INFO_A_ERTS_MMAP,
- ERTS_ALC_INFO_A_DISABLED_EXEC, /* fake a disabled "exec_alloc" */
- ERTS_ALC_INFO_A_END
- };
- typedef struct {
- erts_atomic32_t refc;
- int only_sz;
- int internal;
- Uint req_sched;
- Process *proc;
- ErtsIRefStorage iref;
- int allocs[ERTS_ALC_INFO_A_END - ERTS_ALC_A_MIN + 1];
- } ErtsAllocInfoReq;
- ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(aireq,
- ErtsAllocInfoReq,
- 5,
- ERTS_ALC_T_AINFO_REQ)
- ErtsAlcType_t erts_fix_core_allocator_ix;
- struct au_init {
- int enable;
- int thr_spec;
- int disable_allowed;
- int thr_spec_allowed;
- int carrier_migration_allowed;
- ErtsAlcStrat_t astrat;
- struct {
- AllctrInit_t util;
- GFAllctrInit_t gf;
- BFAllctrInit_t bf;
- AFAllctrInit_t af;
- AOFFAllctrInit_t aoff;
- } init;
- struct {
- int mmbcs;
- int lmbcs;
- int smbcs;
- int mmmbc;
- } default_;
- };
- #define DEFAULT_ALLCTR_INIT { \
- ERTS_DEFAULT_ALLCTR_INIT, \
- ERTS_DEFAULT_GF_ALLCTR_INIT, \
- ERTS_DEFAULT_BF_ALLCTR_INIT, \
- ERTS_DEFAULT_AF_ALLCTR_INIT, \
- ERTS_DEFAULT_AOFF_ALLCTR_INIT \
- }
- typedef struct {
- int erts_alloc_config;
- #if HAVE_ERTS_MSEG
- ErtsMsegInit_t mseg;
- #endif
- int trim_threshold;
- int top_pad;
- AlcUInit_t alloc_util;
- struct {
- char *mtrace;
- char *nodename;
- } instr;
- struct au_init sl_alloc;
- struct au_init std_alloc;
- struct au_init ll_alloc;
- struct au_init temp_alloc;
- struct au_init eheap_alloc;
- struct au_init binary_alloc;
- struct au_init ets_alloc;
- struct au_init driver_alloc;
- struct au_init fix_alloc;
- struct au_init literal_alloc;
- struct au_init exec_alloc;
- struct au_init test_alloc;
- } erts_alc_hndl_args_init_t;
- #define ERTS_AU_INIT__ {0, 0, 1, 1, 1, \
- ERTS_ALC_S_GOODFIT, DEFAULT_ALLCTR_INIT, \
- {1,1,1,1}}
- #define SET_DEFAULT_ALLOC_OPTS(IP) \
- do { \
- struct au_init aui__ = ERTS_AU_INIT__; \
- sys_memcpy((void *) (IP), (void *) &aui__, sizeof(struct au_init)); \
- } while (0)
- static void
- set_default_sl_alloc_opts(struct au_init *ip)
- {
- SET_DEFAULT_ALLOC_OPTS(ip);
- ip->enable = AU_ALLOC_DEFAULT_ENABLE(1);
- ip->thr_spec = 1;
- ip->astrat = ERTS_ALC_S_GOODFIT;
- ip->init.util.name_prefix = "sl_";
- ip->init.util.alloc_no = ERTS_ALC_A_SHORT_LIVED;
- #ifndef SMALL_MEMORY
- ip->init.util.mmbcs = 128*1024; /* Main carrier size */
- #else
- ip->init.util.mmbcs = 32*1024; /* Main carrier size */
- #endif
- ip->init.util.ts = ERTS_ALC_MTA_SHORT_LIVED;
- ip->init.util.rsbcst = 80;
- ip->init.util.acul = ERTS_ALC_DEFAULT_ACUL;
- }
- static void
- set_default_std_alloc_opts(struct au_init *ip)
- {
- SET_DEFAULT_ALLOC_OPTS(ip);
- ip->enable = AU_ALLOC_DEFAULT_ENABLE(1);
- ip->thr_spec = 1;
- ip->astrat = ERTS_ALC_S_BESTFIT;
- ip->init.util.name_prefix = "std_";
- ip->init.util.alloc_no = ERTS_ALC_A_STANDARD;
- #ifndef SMALL_MEMORY
- ip->init.util.mmbcs = 128*1024; /* Main carrier size */
- #else
- ip->init.util.mmbcs = 32*1024; /* Main carrier size */
- #endif
- ip->init.util.ts = ERTS_ALC_MTA_STANDARD;
- ip->init.util.acul = ERTS_ALC_DEFAULT_ACUL;
- }
- static void
- set_default_ll_alloc_opts(struct au_init *ip)
- {
- SET_DEFAULT_ALLOC_OPTS(ip);
- ip->enable = AU_ALLOC_DEFAULT_ENABLE(1);
- ip->thr_spec = 0;
- ip->astrat = ERTS_ALC_S_BESTFIT;
- ip->init.bf.ao = 1;
- ip->init.util.ramv = 0;
- ip->init.util.mmsbc = 0;
- ip->init.util.sbct = ~((UWord) 0);
- ip->init.util.name_prefix = "ll_";
- ip->init.util.alloc_no = ERTS_ALC_A_LONG_LIVED;
- #ifndef SMALL_MEMORY
- ip->init.util.mmbcs = 2*1024*1024; /* Main carrier size */
- #else
- ip->init.util.mmbcs = 1*1024*1024; /* Main carrier size */
- #endif
- ip->init.util.ts = ERTS_ALC_MTA_LONG_LIVED;
- ip->init.util.asbcst = 0;
- ip->init.util.rsbcst = 0;
- ip->init.util.rsbcmt = 0;
- ip->init.util.rmbcmt = 0;
- ip->init.util.acul = ERTS_ALC_DEFAULT_ACUL_LL_ALLOC;
- }
- static void
- set_default_literal_alloc_opts(struct au_init *ip)
- {
- SET_DEFAULT_ALLOC_OPTS(ip);
- ip->enable = 1;
- ip->thr_spec = 0;
- ip->disable_allowed = 0;
- ip->thr_spec_allowed = 0;
- ip->carrier_migration_allowed = 0;
- ip->astrat = ERTS_ALC_S_BESTFIT;
- ip->init.bf.ao = 1;
- ip->init.util.ramv = 0;
- ip->init.util.mmsbc = 0;
- ip->init.util.sbct = ~((UWord) 0);
- ip->init.util.name_prefix = "literal_";
- ip->init.util.alloc_no = ERTS_ALC_A_LITERAL;
- #ifndef SMALL_MEMORY
- ip->init.util.mmbcs = 1024*1024; /* Main carrier size */
- #else
- ip->init.util.mmbcs = 256*1024; /* Main carrier size */
- #endif
- ip->init.util.ts = ERTS_ALC_MTA_LITERAL;
- ip->init.util.asbcst = 0;
- ip->init.util.rsbcst = 0;
- ip->init.util.rsbcmt = 0;
- ip->init.util.rmbcmt = 0;
- ip->init.util.acul = 0;
- #if defined(ARCH_32)
- # if HAVE_ERTS_MSEG
- ip->init.util.mseg_alloc = &erts_alcu_literal_32_mseg_alloc;
- ip->init.util.mseg_realloc = &erts_alcu_literal_32_mseg_realloc;
- ip->init.util.mseg_dealloc = &erts_alcu_literal_32_mseg_dealloc;
- # endif
- ip->init.util.sys_alloc = &erts_alcu_literal_32_sys_alloc;
- ip->init.util.sys_realloc = &erts_alcu_literal_32_sys_realloc;
- ip->init.util.sys_dealloc = &erts_alcu_literal_32_sys_dealloc;
- #elif defined(ARCH_64)
- # ifdef ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION
- ip->init.util.mseg_alloc = &erts_alcu_mmapper_mseg_alloc;
- ip->init.util.mseg_realloc = &erts_alcu_mmapper_mseg_realloc;
- ip->init.util.mseg_dealloc = &erts_alcu_mmapper_mseg_dealloc;
- ip->init.util.mseg_mmapper = &erts_literal_mmapper;
- # endif
- #else
- # error Unknown architecture
- #endif
- }
- #ifdef ERTS_ALC_A_EXEC
- static void
- set_default_exec_alloc_opts(struct au_init *ip)
- {
- SET_DEFAULT_ALLOC_OPTS(ip);
- ip->enable = 1;
- ip->thr_spec = 0;
- ip->disable_allowed = 0;
- ip->thr_spec_allowed = 0;
- ip->carrier_migration_allowed = 0;
- ip->astrat = ERTS_ALC_S_BESTFIT;
- ip->init.bf.ao = 1;
- ip->init.util.ramv = 0;
- ip->init.util.mmsbc = 0;
- ip->init.util.sbct = ~((UWord) 0);
- ip->init.util.name_prefix = "exec_";
- ip->init.util.alloc_no = ERTS_ALC_A_EXEC;
- ip->init.util.mmbcs = 0; /* No main carrier */
- ip->init.util.ts = ERTS_ALC_MTA_EXEC;
- ip->init.util.asbcst = 0;
- ip->init.util.rsbcst = 0;
- ip->init.util.rsbcmt = 0;
- ip->init.util.rmbcmt = 0;
- ip->init.util.acul = 0;
- ip->init.util.mseg_alloc = &erts_alcu_exec_mseg_alloc;
- ip->init.util.mseg_realloc = &erts_alcu_exec_mseg_realloc;
- ip->init.util.mseg_dealloc = &erts_alcu_exec_mseg_dealloc;
- }
- #endif /* ERTS_ALC_A_EXEC */
- static void
- set_default_temp_alloc_opts(struct au_init *ip)
- {
- SET_DEFAULT_ALLOC_OPTS(ip);
- ip->enable = AU_ALLOC_DEFAULT_ENABLE(1);
- ip->thr_spec = 1;
- ip->disable_allowed = 0;
- ip->carrier_migration_allowed = 0;
- ip->astrat = ERTS_ALC_S_AFIT;
- ip->init.util.name_prefix = "temp_";
- ip->init.util.alloc_no = ERTS_ALC_A_TEMPORARY;
- #ifndef SMALL_MEMORY
- ip->init.util.mmbcs = 128*1024; /* Main carrier size */
- #else
- ip->init.util.mmbcs = 32*1024; /* Main carrier size */
- #endif
- ip->init.util.ts = ERTS_ALC_MTA_TEMPORARY;
- ip->init.util.rsbcst = 90;
- ip->init.util.rmbcmt = 100;
- }
- static void
- set_default_eheap_alloc_opts(struct au_init *ip)
- {
- SET_DEFAULT_ALLOC_OPTS(ip);
- ip->enable = AU_ALLOC_DEFAULT_ENABLE(1);
- ip->thr_spec = 1;
- ip->astrat = ERTS_ALC_S_GOODFIT;
- ip->init.util.name_prefix = "eheap_";
- ip->init.util.alloc_no = ERTS_ALC_A_EHEAP;
- #ifndef SMALL_MEMORY
- ip->init.util.mmbcs = 512*1024; /* Main carrier size */
- #else
- ip->init.util.mmbcs = 256*1024; /* Main carrier size */
- #endif
- ip->init.util.ts = ERTS_ALC_MTA_EHEAP;
- ip->init.util.rsbcst = 50;
- ip->init.util.acul = ERTS_ALC_DEFAULT_ACUL_EHEAP_ALLOC;
- }
- static void
- set_default_binary_alloc_opts(struct au_init *ip)
- {
- SET_DEFAULT_ALLOC_OPTS(ip);
- ip->enable = AU_ALLOC_DEFAULT_ENABLE(1);
- ip->thr_spec = 1;
- ip->astrat = ERTS_ALC_S_BESTFIT;
- ip->init.util.name_prefix = "binary_";
- ip->init.util.alloc_no = ERTS_ALC_A_BINARY;
- #ifndef SMALL_MEMORY
- ip->init.util.mmbcs = 128*1024; /* Main carrier size */
- #else
- ip->init.util.mmbcs = 32*1024; /* Main carrier size */
- #endif
- ip->init.util.ts = ERTS_ALC_MTA_BINARY;
- ip->init.util.acul = ERTS_ALC_DEFAULT_ACUL;
- ip->init.util.atags = 1;
- }
- static void
- set_default_ets_alloc_opts(struct au_init *ip)
- {
- SET_DEFAULT_ALLOC_OPTS(ip);
- ip->enable = AU_ALLOC_DEFAULT_ENABLE(1);
- ip->thr_spec = 1;
- ip->astrat = ERTS_ALC_S_BESTFIT;
- ip->init.util.name_prefix = "ets_";
- ip->init.util.alloc_no = ERTS_ALC_A_ETS;
- #ifndef SMALL_MEMORY
- ip->init.util.mmbcs = 128*1024; /* Main carrier size */
- #else
- ip->init.util.mmbcs = 32*1024; /* Main carrier size */
- #endif
- ip->init.util.ts = ERTS_ALC_MTA_ETS;
- ip->init.util.acul = ERTS_ALC_DEFAULT_ACUL;
- }
- static void
- set_default_driver_alloc_opts(struct au_init *ip)
- {
- SET_DEFAULT_ALLOC_OPTS(ip);
- ip->enable = AU_ALLOC_DEFAULT_ENABLE(1);
- ip->thr_spec = 1;
- ip->astrat = ERTS_ALC_S_BESTFIT;
- ip->init.util.name_prefix = "driver_";
- ip->init.util.alloc_no = ERTS_ALC_A_DRIVER;
- #ifndef SMALL_MEMORY
- ip->init.util.mmbcs = 128*1024; /* Main carrier size */
- #else
- ip->init.util.mmbcs = 32*1024; /* Main carrier size */
- #endif
- ip->init.util.ts = ERTS_ALC_MTA_DRIVER;
- ip->init.util.acul = ERTS_ALC_DEFAULT_ACUL;
- ip->init.util.atags = 1;
- }
- static void
- set_default_fix_alloc_opts(struct au_init *ip,
- size_t *fix_type_sizes)
- {
- SET_DEFAULT_ALLOC_OPTS(ip);
- ip->enable = AU_ALLOC_DEFAULT_ENABLE(1);
- ip->thr_spec = 1;
- ip->astrat = ERTS_ALC_S_BESTFIT;
- ip->init.bf.ao = 1;
- ip->init.util.name_prefix = "fix_";
- ip->init.util.fix_type_size = fix_type_sizes;
- ip->init.util.alloc_no = ERTS_ALC_A_FIXED_SIZE;
- #ifndef SMALL_MEMORY
- ip->init.util.mmbcs = 128*1024; /* Main carrier size */
- #else
- ip->init.util.mmbcs = 128*1024; /* Main carrier size */
- #endif
- ip->init.util.ts = ERTS_ALC_MTA_FIXED_SIZE;
- ip->init.util.acul = ERTS_ALC_DEFAULT_ACUL;
- }
- static void
- set_default_test_alloc_opts(struct au_init *ip)
- {
- SET_DEFAULT_ALLOC_OPTS(ip);
- ip->enable = 0; /* Disabled by default */
- ip->thr_spec = -1 * erts_no_schedulers;
- ip->astrat = ERTS_ALC_S_FIRSTFIT;
- ip->init.aoff.crr_order = FF_AOFF;
- ip->init.aoff.blk_order = FF_BF;
- ip->init.util.name_prefix = "test_";
- ip->init.util.alloc_no = ERTS_ALC_A_TEST;
- ip->init.util.mmbcs = 0; /* Main carrier size */
- ip->init.util.ts = ERTS_ALC_MTA_TEST;
- ip->init.util.acul = ERTS_ALC_DEFAULT_ACUL;
- ip->init.util.atags = 1;
- /* Use a constant minimal MBC size */
- #if ERTS_SA_MB_CARRIERS
- ip->init.util.smbcs = ERTS_SACRR_UNIT_SZ;
- ip->init.util.lmbcs = ERTS_SACRR_UNIT_SZ;
- ip->init.util.sbct = ERTS_SACRR_UNIT_SZ;
- #else
- ip->init.util.smbcs = 1 << 12;
- ip->init.util.lmbcs = 1 << 12;
- ip->init.util.sbct = 1 << 12;
- #endif
- }
- static void
- adjust_tpref(struct au_init *ip, int no_sched)
- {
- if (ip->thr_spec) {
- ip->thr_spec = no_sched;
- ip->thr_spec *= -1; /* thread preferred */
- /* If default ... */
- /* ... shrink main multi-block carrier size */
- if (ip->default_.mmbcs)
- ip->init.util.mmbcs /= ERTS_MIN(4, no_sched);
- /* ... shrink largest multi-block carrier size */
- if (ip->default_.lmbcs)
- ip->init.util.lmbcs /= ERTS_MIN(2, no_sched);
- /* ... shrink smallest multi-block carrier size */
- if (ip->default_.smbcs)
- ip->init.util.smbcs /= ERTS_MIN(4, no_sched);
- }
- }
- static void handle_args(int *, char **, erts_alc_hndl_args_init_t *);
- static void
- set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init, int ncpu);
- static void
- start_au_allocator(ErtsAlcType_t alctr_n,
- struct au_init *init,
- ErtsAllocatorState_t *state);
- static void
- refuse_af_strategy(struct au_init *init)
- {
- if (init->astrat == ERTS_ALC_S_AFIT)
- init->astrat = ERTS_ALC_S_GOODFIT;
- }
- #ifdef HARD_DEBUG
- static void hdbg_init(void);
- #endif
- static void adjust_fix_alloc_sizes(UWord extra_block_size)
- {
-
- if (extra_block_size && erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].enabled) {
- int j;
- if (erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].thr_spec) {
- int i;
- ErtsAllocatorThrSpec_t* tspec;
- tspec = &erts_allctr_thr_spec[ERTS_ALC_A_FIXED_SIZE];
- ASSERT(tspec->enabled);
- for (i=0; i < tspec->size; i++) {
- Allctr_t* allctr = tspec->allctr[i];
- for (j=0; j < ERTS_ALC_NO_FIXED_SIZES; ++j) {
- size_t size = allctr->fix[j].type_size;
- size = MAX(size + extra_block_size,
- sizeof(ErtsAllctrDDBlock_t));
- allctr->fix[j].type_size = size;
- }
- }
- }
- else
- {
- Allctr_t* allctr = erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].extra;
- for (j=0; j < ERTS_ALC_NO_FIXED_SIZES; ++j) {
- size_t size = allctr->fix[j].type_size;
- size = MAX(size + extra_block_size,
- sizeof(ErtsAllctrDDBlock_t));
- allctr->fix[j].type_size = size;
- }
- }
- }
- }
- static ERTS_INLINE int
- strategy_support_carrier_migration(struct au_init *auip)
- {
- /*
- * Currently only aoff* and ageff* support carrier
- * migration, i.e, type AOFIRSTFIT.
- */
- return auip->astrat == ERTS_ALC_S_FIRSTFIT;
- }
- static ERTS_INLINE void
- adjust_carrier_migration_support(struct au_init *auip)
- {
- if (auip->init.util.acul) {
- auip->thr_spec = -1; /* Need thread preferred */
- /*
- * If strategy cannot handle carrier migration,
- * default to a strategy that can...
- */
- if (!strategy_support_carrier_migration(auip)) {
- /* Default to aoffcbf */
- auip->astrat = ERTS_ALC_S_FIRSTFIT;
- auip->init.aoff.crr_order = FF_AOFF;
- auip->init.aoff.blk_order = FF_BF;
- }
- }
- }
- void
- erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
- {
- UWord extra_block_size = 0;
- int i, ncpu;
- erts_alc_hndl_args_init_t init = {
- 0,
- #if HAVE_ERTS_MSEG
- ERTS_MSEG_INIT_DEFAULT_INITIALIZER,
- #endif
- ERTS_DEFAULT_TRIM_THRESHOLD,
- ERTS_DEFAULT_TOP_PAD,
- ERTS_DEFAULT_ALCU_INIT,
- };
- size_t fix_type_sizes[ERTS_ALC_NO_FIXED_SIZES] = {0};
- fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_PROC)]
- = sizeof(Process);
- fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_MONITOR)]
- = sizeof(ErtsMonitorDataHeap);
- fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_LINK)]
- = sizeof(ErtsLinkData);
- fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_DRV_SEL_D_STATE)]
- = sizeof(ErtsDrvSelectDataState);
- fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_NIF_SEL_D_STATE)]
- = sizeof(ErtsNifSelectDataState);
- fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_MSG_REF)]
- = sizeof(ErtsMessageRef);
- fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_THR_Q_EL_SL)]
- = sizeof(ErtsThrQElement_t);
- fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_LL_PTIMER)]
- = erts_timer_type_size(ERTS_ALC_T_LL_PTIMER);
- fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_HL_PTIMER)]
- = erts_timer_type_size(ERTS_ALC_T_HL_PTIMER);
- fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_BIF_TIMER)]
- = erts_timer_type_size(ERTS_ALC_T_BIF_TIMER);
- fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_MREF_NSCHED_ENT)]
- = sizeof(ErtsNSchedMagicRefTableEntry);
- fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_MINDIRECTION)]
- = ERTS_MAGIC_BIN_UNALIGNED_SIZE(sizeof(ErtsMagicIndirectionWord));
- #ifdef HARD_DEBUG
- hdbg_init();
- #endif
- lock_all_physical_memory = 0;
- ncpu = eaiop->ncpu;
- if (ncpu < 1)
- ncpu = 1;
- erts_tsd_key_create(&erts_allctr_prelock_tsd_key,
- "erts_allctr_prelock_tsd_key");
- erts_sys_alloc_init();
- erts_init_utils_mem();
- set_default_sl_alloc_opts(&init.sl_alloc);
- set_default_std_alloc_opts(&init.std_alloc);
- set_default_ll_alloc_opts(&init.ll_alloc);
- set_default_temp_alloc_opts(&init.temp_alloc);
- set_default_eheap_alloc_opts(&init.eheap_alloc);
- set_default_binary_alloc_opts(&init.binary_alloc);
- set_default_ets_alloc_opts(&init.ets_alloc);
- set_default_driver_alloc_opts(&init.driver_alloc);
- set_default_fix_alloc_opts(&init.fix_alloc,
- fix_type_sizes);
- set_default_literal_alloc_opts(&init.literal_alloc);
- #ifdef ERTS_ALC_A_EXEC
- set_default_exec_alloc_opts(&init.exec_alloc);
- #endif
- set_default_test_alloc_opts(&init.test_alloc);
- 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";
- erts_exit(1, "Failed to lock physical memory: %s (%d)\n",
- errstr, err);
- }
- #else
- erts_exit(1, "Failed to lock physical memory: Not supported\n");
- #endif
- }
- /* Make adjustments for carrier migration support */
- init.temp_alloc.init.util.acul = 0;
- adjust_carrier_migration_support(&init.sl_alloc);
- adjust_carrier_migration_support(&init.std_alloc);
- adjust_carrier_migration_support(&init.ll_alloc);
- adjust_carrier_migration_support(&init.eheap_alloc);
- adjust_carrier_migration_support(&init.binary_alloc);
- adjust_carrier_migration_support(&init.ets_alloc);
- adjust_carrier_migration_support(&init.driver_alloc);
- adjust_carrier_migration_support(&init.fix_alloc);
- adjust_carrier_migration_support(&init.literal_alloc);
- #ifdef ERTS_ALC_A_EXEC
- adjust_carrier_migration_support(&init.exec_alloc);
- #endif
- if (init.erts_alloc_config) {
- /* Adjust flags that erts_alloc_config won't like */
- /* No thread specific instances */
- init.temp_alloc.thr_spec = 0;
- init.sl_alloc.thr_spec = 0;
- init.std_alloc.thr_spec = 0;
- init.ll_alloc.thr_spec = 0;
- init.eheap_alloc.thr_spec = 0;
- init.binary_alloc.thr_spec = 0;
- init.ets_alloc.thr_spec = 0;
- init.driver_alloc.thr_spec = 0;
- init.fix_alloc.thr_spec = 0;
- init.literal_alloc.thr_spec = 0;
- #ifdef ERTS_ALC_A_EXEC
- init.exec_alloc.thr_spec = 0;
- #endif
- /* No carrier migration */
- init.temp_alloc.init.util.acul = 0;
- init.sl_alloc.init.util.acul = 0;
- init.std_alloc.init.util.acul = 0;
- init.ll_alloc.init.util.acul = 0;
- init.eheap_alloc.init.util.acul = 0;
- init.binary_alloc.init.util.acul = 0;
- init.ets_alloc.init.util.acul = 0;
- init.driver_alloc.init.util.acul = 0;
- init.fix_alloc.init.util.acul = 0;
- init.literal_alloc.init.util.acul = 0;
- #ifdef ERTS_ALC_A_EXEC
- init.exec_alloc.init.util.acul = 0;
- #endif
- }
- /* Only temp_alloc can use thread specific interface */
- if (init.temp_alloc.thr_spec)
- init.temp_alloc.thr_spec = erts_no_schedulers;
- /* Others must use thread preferred interface */
- adjust_tpref(&init.sl_alloc, erts_no_schedulers);
- adjust_tpref(&init.std_alloc, erts_no_schedulers);
- adjust_tpref(&init.ll_alloc, erts_no_schedulers);
- adjust_tpref(&init.eheap_alloc, erts_no_schedulers);
- adjust_tpref(&init.binary_alloc, erts_no_schedulers);
- adjust_tpref(&init.ets_alloc, erts_no_schedulers);
- adjust_tpref(&init.driver_alloc, erts_no_schedulers);
- adjust_tpref(&init.fix_alloc, erts_no_schedulers);
- adjust_tpref(&init.literal_alloc, erts_no_schedulers);
- #ifdef ERTS_ALC_A_EXEC
- adjust_tpref(&init.exec_alloc, erts_no_schedulers);
- #endif
- /*
- * The following allocators cannot be run with afit strategy.
- * Make sure they don't...
- */
- refuse_af_strategy(&init.sl_alloc);
- refuse_af_strategy(&init.std_alloc);
- refuse_af_strategy(&init.ll_alloc);
- refuse_af_strategy(&init.eheap_alloc);
- refuse_af_strategy(&init.binary_alloc);
- refuse_af_strategy(&init.ets_alloc);
- refuse_af_strategy(&init.driver_alloc);
- refuse_af_strategy(&init.fix_alloc);
- refuse_af_strategy(&init.literal_alloc);
- #ifdef ERTS_ALC_A_EXEC
- refuse_af_strategy(&init.exec_alloc);
- #endif
- if (!init.temp_alloc.thr_spec)
- refuse_af_strategy(&init.temp_alloc);
- erts_mtrace_pre_init();
- #if HAVE_ERTS_MSEG
- init.mseg.nos = erts_no_schedulers;
- erts_mseg_init(&init.mseg);
- #endif
- erts_alcu_init(&init.alloc_util);
- erts_afalc_init();
- erts_bfalc_init();
- erts_gfalc_init();
- erts_aoffalc_init();
- for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {
- erts_allctrs[i].alloc = NULL;
- erts_allctrs[i].realloc = NULL;
- erts_allctrs[i].free = NULL;
- erts_allctrs[i].extra = NULL;
- erts_allctrs_info[i].alloc_util = 0;
- erts_allctrs_info[i].enabled = 0;
- erts_allctrs_info[i].thr_spec = 0;
- erts_allctrs_info[i].extra = NULL;
- }
- erts_allctrs[ERTS_ALC_A_SYSTEM].alloc = erts_sys_alloc;
- erts_allctrs[ERTS_ALC_A_SYSTEM].realloc = erts_sys_realloc;
- erts_allctrs[ERTS_ALC_A_SYSTEM].free = erts_sys_free;
- erts_allctrs_info[ERTS_ALC_A_SYSTEM].enabled = 1;
- set_au_allocator(ERTS_ALC_A_TEMPORARY, &init.temp_alloc, ncpu);
- set_au_allocator(ERTS_ALC_A_SHORT_LIVED, &init.sl_alloc, ncpu);
- set_au_allocator(ERTS_ALC_A_STANDARD, &init.std_alloc, ncpu);
- set_au_allocator(ERTS_ALC_A_LONG_LIVED, &init.ll_alloc, ncpu);
- set_au_allocator(ERTS_ALC_A_EHEAP, &init.eheap_alloc, ncpu);
- set_au_allocator(ERTS_ALC_A_BINARY, &init.binary_alloc, ncpu);
- set_au_allocator(ERTS_ALC_A_ETS, &init.ets_alloc, ncpu);
- set_au_allocator(ERTS_ALC_A_DRIVER, &init.driver_alloc, ncpu);
- set_au_allocator(ERTS_ALC_A_FIXED_SIZE, &init.fix_alloc, ncpu);
- set_au_allocator(ERTS_ALC_A_LITERAL, &init.literal_alloc, ncpu);
- #ifdef ERTS_ALC_A_EXEC
- set_au_allocator(ERTS_ALC_A_EXEC, &init.exec_alloc, ncpu);
- #endif
- set_au_allocator(ERTS_ALC_A_TEST, &init.test_alloc, ncpu);
- for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {
- if (!erts_allctrs[i].alloc)
- erts_exit(ERTS_ABORT_EXIT,
- "Missing alloc function for %s\n", ERTS_ALC_A2AD(i));
- if (!erts_allctrs[i].realloc)
- erts_exit(ERTS_ABORT_EXIT,
- "Missing realloc function for %s\n", ERTS_ALC_A2AD(i));
- if (!erts_allctrs[i].free)
- erts_exit(ERTS_ABORT_EXIT,
- "Missing free function for %s\n", ERTS_ALC_A2AD(i));
- }
- sys_alloc_opt(SYS_ALLOC_OPT_TRIM_THRESHOLD, init.trim_threshold);
- sys_alloc_opt(SYS_ALLOC_OPT_TOP_PAD, init.top_pad);
- erts_mtrace_init(init.instr.mtrace, init.instr.nodename);
- start_au_allocator(ERTS_ALC_A_TEMPORARY,
- &init.temp_alloc,
- &temp_alloc_state);
- start_au_allocator(ERTS_ALC_A_SHORT_LIVED,
- &init.sl_alloc,
- &sl_alloc_state);
- start_au_allocator(ERTS_ALC_A_STANDARD,
- &init.std_alloc,
- &std_alloc_state);
- start_au_allocator(ERTS_ALC_A_LONG_LIVED,
- &init.ll_alloc,
- &ll_alloc_state);
- start_au_allocator(ERTS_ALC_A_EHEAP,
- &init.eheap_alloc,
- &eheap_alloc_state);
- start_au_allocator(ERTS_ALC_A_BINARY,
- &init.binary_alloc,
- &binary_alloc_state);
- start_au_allocator(ERTS_ALC_A_ETS,
- &init.ets_alloc,
- &ets_alloc_state);
- start_au_allocator(ERTS_ALC_A_DRIVER,
- &init.driver_alloc,
- &driver_alloc_state);
- start_au_allocator(ERTS_ALC_A_FIXED_SIZE,
- &init.fix_alloc,
- &fix_alloc_state);
- start_au_allocator(ERTS_ALC_A_LITERAL,
- &init.literal_alloc,
- &literal_alloc_state);
- #ifdef ERTS_ALC_A_EXEC
- start_au_allocator(ERTS_ALC_A_EXEC,
- &init.exec_alloc,
- &exec_alloc_state);
- #endif
- start_au_allocator(ERTS_ALC_A_TEST,
- &init.test_alloc,
- &test_alloc_state);
- erts_mtrace_install_wrapper_functions();
- init_aireq_alloc();
- #ifdef DEBUG
- extra_block_size += install_debug_functions();
- #endif
- adjust_fix_alloc_sizes(extra_block_size);
- }
- void
- erts_alloc_late_init(void)
- {
- }
- static void *
- erts_realloc_fixed_size(ErtsAlcType_t type, void *extra, void *p, Uint size)
- {
- erts_exit(ERTS_ABORT_EXIT,
- "Attempt to reallocate a block of the fixed size type %s\n",
- ERTS_ALC_T2TD(type));
- }
- static void
- set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init, int ncpu)
- {
- ErtsAllocatorFunctions_t *af = &erts_allctrs[alctr_n];
- ErtsAllocatorInfo_t *ai = &erts_allctrs_info[alctr_n];
- ErtsAllocatorThrSpec_t *tspec = &erts_allctr_thr_spec[alctr_n];
- /*
- * Some allocators are forced on if halfword heap is used.
- */
- if (init->init.util.force)
- init->enable = 1;
- tspec->enabled = 0;
- tspec->dd = 0;
- tspec->aix = alctr_n;
- tspec->size = 0;
- ai->thr_spec = 0;
- if (!init->enable) {
- af->alloc = erts_sys_alloc;
- af->realloc = erts_sys_realloc;
- af->free = erts_sys_free;
- af->extra = NULL;
- ai->alloc_util = 0;
- ai->enabled = 0;
- ai->extra = NULL;
- return;
- }
- if (init->thr_spec) {
- if (init->thr_spec > 0) {
- af->alloc = erts_alcu_alloc_thr_spec;
- if (init->init.util.fix_type_size)
- af->realloc = erts_realloc_fixed_size;
- else if (init->init.util.ramv)
- af->realloc = erts_alcu_realloc_mv_thr_spec;
- else
- af->realloc = erts_alcu_realloc_thr_spec;
- af->free = erts_alcu_free_thr_spec;
- }
- else {
- af->alloc = erts_alcu_alloc_thr_pref;
- if (init->init.util.fix_type_size)
- af->realloc = erts_realloc_fixed_size;
- else if (init->init.util.ramv)
- af->realloc = erts_alcu_realloc_mv_thr_pref;
- else
- af->realloc = erts_alcu_realloc_thr_pref;
- af->free = erts_alcu_free_thr_pref;
- tspec->dd = 1;
- }
- tspec->enabled = 1;
- tspec->size = abs(init->thr_spec) + 1;
- ai->thr_spec = tspec->size;
- }
- else
- if (init->init.util.ts) {
- af->alloc = erts_alcu_alloc_ts;
- if (init->init.util.fix_type_size)
- af->realloc = erts_realloc_fixed_size;
- else if (init->init.util.ramv)
- af->realloc = erts_alcu_realloc_mv_ts;
- else
- af->realloc = erts_alcu_realloc_ts;
- af->free = erts_alcu_free_ts;
- }
- else
- {
- erts_exit(ERTS_ABORT_EXIT, "%salloc is not thread safe\n",
- init->init.util.name_prefix);
- }
- af->extra = NULL;
- ai->alloc_util = 1;
- ai->enabled = 1;
- }
- static void
- start_au_allocator(ErtsAlcType_t alctr_n,
- struct au_init *init,
- ErtsAllocatorState_t *state)
- {
- int i;
- int size = 1;
- void *as0;
- ErtsAlcStrat_t astrat;
- ErtsAllocatorFunctions_t *af = &erts_allctrs[alctr_n];
- ErtsAllocatorInfo_t *ai = &erts_allctrs_info[alctr_n];
- ErtsAllocatorThrSpec_t *tspec = &erts_allctr_thr_spec[alctr_n];
- ErtsAlcFixList_t *fix_lists = NULL;
- size_t fix_list_size = 0;
- if (!init->enable)
- return;
- if (init->thr_spec) {
- char *states = erts_sys_alloc(0,
- NULL,
- ((sizeof(Allctr_t *)
- * (tspec->size + 1))
- + (sizeof(ErtsAllocatorState_t)
- * tspec->size)
- + ERTS_CACHE_LINE_SIZE - 1));
- if (!states)
- erts_exit(ERTS_ABORT_EXIT,
- "Failed to allocate allocator states for %salloc\n",
- init->init.util.name_prefix);
- tspec->allctr = (Allctr_t **) states;
- states += sizeof(Allctr_t *) * (tspec->size + 1);
- states = ((((UWord) states) & ERTS_CACHE_LINE_MASK)
- ? (char *) ((((UWord) states) & ~ERTS_CACHE_LINE_MASK)
- + ERTS_CACHE_LINE_SIZE)
- : (char *) states);
- tspec->allctr[0] = (Allctr_t *) state;
- size = tspec->size;
- for (i = 1; i < size; i++)
- tspec->allctr[i] = (Allctr_t *)
- &((ErtsAllocatorState_t *) states)[i-1];
- }
- if (init->init.util.fix_type_size) {
- size_t tot_fix_list_size;
- fix_list_size = sizeof(ErtsAlcFixList_t)*ERTS_ALC_NO_FIXED_SIZES;
- fix_list_size = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(fix_list_size);
- tot_fix_list_size = fix_list_size;
- if (init->thr_spec)
- tot_fix_list_size *= tspec->size;
- fix_lists = erts_sys_alloc(0,
- NULL,
- (tot_fix_list_size
- + ERTS_CACHE_LINE_SIZE - 1));
- if (!fix_lists)
- erts_exit(ERTS_ABORT_EXIT,
- "Failed to allocate fix lists for %salloc\n",
- init->init.util.name_prefix);
- if (((UWord) fix_lists) & ERTS_CACHE_LINE_MASK)
- fix_lists = ((ErtsAlcFixList_t *)
- ((((UWord) fix_lists) & ~ERTS_CACHE_LINE_MASK)
- + ERTS_CACHE_LINE_SIZE));
- }
- for (i = 0; i < size; i++) {
- Allctr_t *as;
- astrat = init->astrat;
- if (!init->thr_spec)
- as0 = state;
- else {
- as0 = (void *) tspec->allctr[i];
- if (!as0)
- continue;
- if (init->thr_spec < 0) {
- init->init.util.ts = i == 0;
- init->init.util.tspec = 0;
- init->init.util.tpref = -1*init->thr_spec + 1;
- }
- else {
- if (i != 0)
- init->init.util.ts = 0;
- else {
- if (astrat == ERTS_ALC_S_AFIT)
- astrat = ERTS_ALC_S_GOODFIT;
- init->init.util.ts = 1;
- }
- init->init.util.tspec = init->thr_spec + 1;
- init->init.util.tpref = 0;
- }
- }
- if (fix_lists) {
- init->init.util.fix = fix_lists;
- fix_lists = ((ErtsAlcFixList_t *)
- (((char *) fix_lists) + fix_list_size));
- }
- init->init.util.alloc_strat = astrat;
- init->init.util.ix = i;
- switch (astrat) {
- case ERTS_ALC_S_GOODFIT:
- as = erts_gfalc_start((GFAllctr_t *) as0,
- &init->init.gf,
- &init->init.util);
- break;
- case ERTS_ALC_S_BESTFIT:
- as = erts_bfalc_start((BFAllctr_t *) as0,
- &init->init.bf,
- &init->init.util);
- break;
- case ERTS_ALC_S_AFIT:
- as = erts_afalc_start((AFAllctr_t *) as0,
- &init->init.af,
- &init->init.util);
- break;
- case ERTS_ALC_S_FIRSTFIT:
- as = erts_aoffalc_start((AOFFAllctr_t *) as0,
- &init->init.aoff,
- &init->init.util);
- break;
- default:
- as = NULL;
- ASSERT(0);
- }
- if (!as)
- erts_exit(ERTS_ABORT_EXIT,
- "Failed to start %salloc\n", init->init.util.name_prefix);
- ASSERT(as == (void *) as0);
- af->extra = as;
- }
- if (init->thr_spec)
- af->extra = tspec;
- ai->extra = af->extra;
- }
- static void bad_param(char *param_start, char *param_end)
- {
- size_t len = param_end - param_start;
- char param[100];
- if (len > 99)
- len = 99;
- sys_memcpy((void *) param, (void *) param_start, len);
- param[len] = '\0';
- erts_fprintf(stderr, "bad \"%s\" parameter\n", param);
- erts_usage();
- }
- static void bad_value(char *param_start, char *param_end, char *value)
- {
- size_t len = param_end - param_start;
- char param[100];
- if (len > 99)
- len = 99;
- sys_memcpy((void *) param, (void *) param_start, len);
- param[len] = '\0';
- erts_fprintf(stderr, "bad \"%s\" value: %s\n", param, value);
- erts_usage();
- }
- /* Get arg marks argument as handled by
- putting NULL in argv */
- static char *
- get_value(char* rest, char** argv, int* ip)
- {
- char *param = argv[*ip]+1;
- argv[*ip] = NULL;
- if (*rest == '\0') {
- char *next = argv[*ip + 1];
- if (next[0] == '-'
- && next[1] == '-'
- && next[2] == '\0') {
- bad_value(param, rest, "");
- }
- (*ip)++;
- argv[*ip] = NULL;
- return next;
- }
- return rest;
- }
- static ERTS_INLINE int
- has_prefix(const char *prefix, const char *string)
- {
- int i;
- for (i = 0; prefix[i]; i++)
- if (prefix[i] != string[i])
- return 0;
- return 1;
- }
- static int
- get_bool_value(char *param_end, char** argv, int* ip)
- {
- char *param = argv[*ip]+1;
- char *value = get_value(param_end, argv, ip);
- if (sys_strcmp(value, "true") == 0)
- return 1;
- else if (sys_strcmp(value, "false") == 0)
- return 0;
- else
- bad_value(param, param_end, value);
- return -1;
- }
- static Uint kb_to_bytes(Sint kb, Uint *bytes)
- {
- const Uint max = ((~((Uint) 0))/1024) + 1;
- if (kb < 0 || (Uint)kb > max)
- return 0;
- if ((Uint)kb == max)
- *bytes = ~((Uint) 0);
- else
- *bytes = ((Uint) kb)*1024;
- return 1;
- }
- static Uint
- get_kb_value(char *param_end, char** argv, int* ip)
- {
- Sint tmp;
- Uint bytes = 0;
- char *rest;
- char *param = argv[*ip]+1;
- char *value = get_value(param_end, argv, ip);
- errno = 0;
- tmp = (Sint) ErtsStrToSint(value, &rest, 10);
- if (errno != 0 || rest == value || !kb_to_bytes(tmp, &bytes))
- bad_value(param, param_end, value);
- return bytes;
- }
- static UWord
- get_mb_value(char *param_end, char** argv, int* ip)
- {
- SWord tmp;
- UWord max = ((~((UWord) 0))/(1024*1024)) + 1;
- char *rest;
- char *param = argv[*ip]+1;
- char *value = get_value(param_end, argv, ip);
- errno = 0;
- tmp = (SWord) ErtsStrToSint(value, &rest, 10);
- if (errno != 0 || rest == value || tmp < 0 || max < ((UWord) tmp))
- bad_value(param, param_end, value);
- if (max == (UWord) tmp)
- return ~((UWord) 0);
- else
- return ((UWord) tmp)*1024*1024;
- }
- #if 0
- static Uint
- get_byte_value(char *param_end, char** argv, int* ip)
- {
- Sint tmp;
- char *rest;
- char *param = argv[*ip]+1;
- char *value = get_value(param_end, argv, ip);
- errno = 0;
- tmp = (Sint) ErtsStrToSint(value, &rest, 10);
- if (errno != 0 || rest == value || tmp < 0)
- bad_value(param, param_end, value);
- return (Uint) tmp;
- }
- #endif
- static Uint
- get_amount_value(char *param_end, char** argv, int* ip)
- {
- Sint tmp;
- char *rest;
- char *param = argv[*ip]+1;
- char *value = get_value(param_end, argv, ip);
- errno = 0;
- tmp = (Sint) ErtsStrToSint(value, &rest, 10);
- if (errno != 0 || rest == value || tmp < 0)
- bad_value(param, param_end, value);
- return (Uint) tmp;
- }
- static Uint
- get_acul_value(struct au_init *auip, char *param_end, char** argv, int* ip)
- {
- Sint tmp;
- char *rest;
- char *param = argv[*ip]+1;
- char *value = get_value(param_end, argv, ip);
- if (sys_strcmp(value, "de") == 0) {
- switch (auip->init.util.alloc_no) {
- case ERTS_ALC_A_LONG_LIVED:
- return ERTS_ALC_DEFAULT_ENABLED_ACUL_LL_ALLOC;
- case ERTS_ALC_A_EHEAP:
- return ERTS_ALC_DEFAULT_ENABLED_ACUL_EHEAP_ALLOC;
- default:
- return ERTS_ALC_DEFAULT_ENABLED_ACUL;
- }
- }
- errno = 0;
- tmp = (Sint) ErtsStrToSint(value, &rest, 10);
- if (errno != 0 || rest == value || tmp < 0 || 100 < tmp)
- bad_value(param, param_end, value);
- return (Uint) tmp;
- }
- static void
- handle_au_arg(struct au_init *auip,
- char* sub_param,
- char** argv,
- int* ip,
- int u_switch)
- {
- char *param = argv[*ip]+1;
- switch (sub_param[0]) {
- case 'a':
- if (sub_param[1] == 'c') { /* Migration parameters "ac*" */
- UWord value;
- UWord* wp;
- if (!auip->carrier_migration_allowed && !u_switch)
- goto bad_switch;
- if (has_prefix("acul", sub_param)) {
- value = get_acul_value(auip, sub_param + 4, argv, ip);
- wp = &auip->init.util.acul;
- }
- else if (has_prefix("acnl", sub_param)) {
- value = get_amount_value(sub_param + 4, argv, ip);
- wp = &auip->init.util.acnl;
- }
- else if (has_prefix("acfml", sub_param)) {
- value = get_amount_value(sub_param + 5, argv, ip);
- wp = &auip->init.util.acfml;
- }
- else
- goto bad_switch;
- if (auip->carrier_migration_allowed)
- *wp = value;
- }
- else if(has_prefix("asbcst", sub_param)) {
- auip->init.util.asbcst = get_kb_value(sub_param + 6, argv, ip);
- }
- else if(has_prefix("as", sub_param)) {
- char *alg = get_value(sub_param + 2, argv, ip);
- if (sys_strcmp("bf", alg) == 0) {
- auip->astrat = ERTS_ALC_S_BESTFIT;
- auip->init.bf.ao = 0;
- }
- else if (sys_strcmp("aobf", alg) == 0) {
- auip->astrat = ERTS_ALC_S_BESTFIT;
- auip->init.bf.ao = 1;
- }
- else if (sys_strcmp("gf", alg) == 0) {
- auip->astrat = ERTS_ALC_S_GOODFIT;
- }
- else if (sys_strcmp("af", alg) == 0) {
- auip->astrat = ERTS_ALC_S_AFIT;
- }
- else if (sys_strcmp("aoff", alg) == 0) {
- auip->astrat = ERTS_ALC_S_FIRSTFIT;
- auip->init.aoff.crr_order = FF_AOFF;
- auip->init.aoff.blk_order = FF_AOFF;
- }
- else if (sys_strcmp("aoffcbf", alg) == 0) {
- auip->astrat = ERTS_ALC_S_FIRSTFIT;
- auip->init.aoff.crr_order = FF_AOFF;
- auip->init.aoff.blk_order = FF_BF;
- }
- else if (sys_strcmp("aoffcaobf", alg) == 0) {
- auip->astrat = ERTS_ALC_S_FIRSTFIT;
- auip->init.aoff.crr_order = FF_AOFF;
- auip->init.aoff.blk_order = FF_AOBF;
- }
- else if (sys_strcmp("ageffcaoff", alg) == 0) {
- auip->astrat = ERTS_ALC_S_FIRSTFIT;
- auip->init.aoff.crr_order = FF_AGEFF;
- auip->init.aoff.blk_order = FF_AOFF;
- }
- else if (sys_strcmp("ageffcbf", alg) == 0) {
- auip->astrat = ERTS_ALC_S_FIRSTFIT;
- auip->init.aoff.crr_order = FF_AGEFF;
- auip->init.aoff.blk_order = FF_BF;
- }
- else if (sys_strcmp("ageffcaobf", alg) == 0) {
- auip->astrat = ERTS_ALC_S_FIRSTFIT;
- auip->init.aoff.crr_order = FF_AGEFF;
- auip->init.aoff.blk_order = FF_AOBF;
- }
- else {
- if (auip->init.util.alloc_no == ERTS_ALC_A_TEST
- && sys_strcmp("chaosff", alg) == 0) {
- auip->astrat = ERTS_ALC_S_FIRSTFIT;
- auip->init.aoff.crr_order = FF_CHAOS;
- auip->init.aoff.blk_order = FF_CHAOS;
- }
- else {
- bad_value(param, sub_param + 1, alg);
- }
- }
- if (!strategy_support_carrier_migration(auip))
- auip->init.util.acul = 0;
- } else if (has_prefix("atags", sub_param)) {
- auip->init.util.atags = get_bool_value(sub_param + 5, argv, ip);
- }
- else
- goto bad_switch;
- break;
- case 'e': {
- int e = get_bool_value(sub_param + 1, argv, ip);
- if (!auip->disable_allowed && !e) {
- if (!u_switch)
- bad_value(param, sub_param + 1, "false");
- else
- ASSERT(auip->enable); /* ignore */
- }
- else auip->enable = e;
- break;
- }
- case 'l':
- if (has_prefix("lmbcs", sub_param)) {
- auip->default_.lmbcs = 0;
- auip->init.util.lmbcs = get_kb_value(sub_param + 5, argv, ip);
- }
- else
- goto bad_switch;
- break;
- case 'm':
- if (has_prefix("mbcgs", sub_param)) {
- auip->init.util.mbcgs = get_amount_value(sub_param + 5, argv, ip);
- }
- else if (has_prefix("mbsd", sub_param)) {
- auip->init.gf.mbsd = get_amount_value(sub_param + 4, argv, ip);
- if (auip->init.gf.mbsd < 1)
- auip->init.gf.mbsd = 1;
- }
- else if (has_prefix("mmbcs", sub_param)) {
- auip->default_.mmbcs = 0;
- auip->init.util.mmbcs = get_kb_value(sub_param + 5, argv, ip);
- }
- else if (has_prefix("mmmbc", sub_param)) {
- auip->default_.mmmbc = 0;
- auip->init.util.mmmbc = get_amount_value(sub_param + 5, argv, ip);
- }
- else if (has_prefix("mmsbc", sub_param)) {
- auip->init.util.mmsbc = get_amount_value(sub_param + 5, argv, ip);
- }
- else
- goto bad_switch;
- break;
- case 'r':
- if(has_prefix("rsbcmt", sub_param)) {
- auip->init.util.rsbcmt = get_amount_value(sub_param + 6, argv, ip);
- if (auip->init.util.rsbcmt > 100)
- auip->init.util.rsbcmt = 100;
- }
- else if(has_prefix("rsbcst", sub_param)) {
- auip->init.util.rsbcst = get_amount_value(sub_param + 6, argv, ip);
- if (auip->init.util.rsbcst > 100)
- auip->init.util.rsbcst = 100;
- }
- else if (has_prefix("rmbcmt", sub_param)) {
- auip->init.util.rmbcmt = get_amount_value(sub_param + 6, argv, ip);
- if (auip->init.util.rmbcmt > 100)
- auip->init.util.rmbcmt = 100;
- }
- else if (has_prefix("ramv", sub_param)) {
- auip->init.util.ramv = get_bool_value(sub_param + 4, argv, ip);
- }
- else
- goto bad_switch;
- break;
- case 's':
- if(has_prefix("sbct", sub_param)) {
- auip->init.util.sbct = get_kb_value(sub_param + 4, argv, ip);
- }
- else if (has_prefix("smbcs", sub_param)) {
- auip->default_.smbcs = 0;
- auip->init.util.smbcs = get_kb_value(sub_param + 5, argv, ip);
- }
- else
- goto bad_switch;
- break;
- case 't': {
- int res = get_bool_value(sub_param+1, argv, ip);
- if (res > 0) {
- if (!auip->thr_spec_allowed) {
- if (!u_switch)
- bad_value(param, sub_param + 1, "true");
- else
- ASSERT(!auip->thr_spec); /* ignore */
- }
- else
- auip->thr_spec = 1;
- break;
- }
- else if (res == 0) {
- auip->thr_spec = 0;
- auip->init.util.acul = 0;
- break;
- }
- goto bad_switch;
- }
- default:
- bad_switch:
- bad_param(param, sub_param);
- }
- }
- static void
- handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
- {
- struct au_init *aui[] = {
- &init->binary_alloc,
- &init->std_alloc,
- &init->ets_alloc,
- &init->eheap_alloc,
- &init->ll_alloc,
- &init->driver_alloc,
- &init->fix_alloc,
- &init->sl_alloc
- /* test_alloc not affected by +Mea??? or +Mu??? */
- };
- int aui_sz = (int) sizeof(aui)/sizeof(aui[0]);
- char *arg;
- char *rest;
- int i, j;
- i = 1;
- ASSERT(argc && argv && init);
- while (i < *argc) {
- if(argv[i][0] == '-') {
- char *param = argv[i]+1;
- switch (argv[i][1]) {
- case 'M':
- switch (argv[i][2]) {
- case 'B':
- handle_au_arg(&init->binary_alloc, &argv[i][3], argv, &i, 0);
- break;
- case 'I':
- if (has_prefix("scs", argv[i]+3)) {
- #if HAVE_ERTS_MSEG
- init->mseg.literal_mmap.scs =
- #endif
- get_mb_value(argv[i]+6, argv, &i);
- }
- else
- handle_au_arg(&init->literal_alloc, &argv[i][3], argv, &i, 0);
- break;
- case 'X':
- if (has_prefix("scs", argv[i]+3)) {
- /* Ignore obsolete */
- (void) get_mb_value(argv[i]+6, argv, &i);
- }
- else
- handle_au_arg(&init->exec_alloc, &argv[i][3], argv, &i, 0);
- break;
- case 'D':
- handle_au_arg(&init->std_alloc, &argv[i][3], argv, &i, 0);
- break;
- case 'E':
- handle_au_arg(&init->ets_alloc, &argv[i][3], argv, &i, 0);
- break;
- case 'F':
- handle_au_arg(&init->fix_alloc, &argv[i][3], argv, &i, 0);
- break;
- case 'H':
- handle_au_arg(&init->eheap_alloc, &argv[i][3], argv, &i, 0);
- break;
- case 'L':
- handle_au_arg(&init->ll_alloc, &argv[i][3], argv, &i, 0);
- break;
- case 'M':
- if (has_prefix("amcbf", argv[i]+3)) {
- #if HAVE_ERTS_MSEG
- init->mseg.amcbf =
- #endif
- get_kb_value(argv[i]+8, argv, &i);
- }
- else if (has_prefix("rmcbf", argv[i]+3)) {
- #if HAVE_ERTS_MSEG
- init->mseg.rmcbf =
- #endif
- get_amount_value(argv[i]+8, argv, &i);
- }
- else if (has_prefix("mcs", argv[i]+3)) {
- #if HAVE_ERTS_MSEG
- init->mseg.mcs =
- #endif
- get_amount_value(argv[i]+6, argv, &i);
- }
- else if (has_prefix("scs", argv[i]+3)) {
- #if HAVE_ERTS_MSEG
- init->mseg.dflt_mmap.scs =
- #endif
- get_mb_value(argv[i]+6, argv, &i);
- }
- else if (has_prefix("sco", argv[i]+3)) {
- #if HAVE_ERTS_MSEG
- init->mseg.dflt_mmap.sco =
- #endif
- get_bool_value(argv[i]+6, argv, &i);
- }
- else if (has_prefix("scrpm", argv[i]+3)) {
- #if HAVE_ERTS_MSEG
- init->mseg.dflt_mmap.scrpm =
- #endif
- get_bool_value(argv[i]+8, argv, &i);
- }
- else if (has_prefix("scrfsd", argv[i]+3)) {
- #if HAVE_ERTS_MSEG
- init->mseg.dflt_mmap.scrfsd =
- #endif
- get_amount_value(argv[i]+9, argv, &i);
- }
- else {
- bad_param(param, param+2);
- }
- break;
- case 'R':
- handle_au_arg(&init->driver_alloc, &argv[i][3], argv, &i, 0);
- break;
- case 'S':
- handle_au_arg(&init->sl_alloc, &argv[i][3], argv, &i, 0);
- break;
- case 'T':
- handle_au_arg(&init->temp_alloc, &argv[i][3], argv, &i, 0);
- break;
- case 'Z':
- handle_au_arg(&init->test_alloc, &argv[i][3], argv, &i, 0);
- break;
- case 'Y': { /* sys_alloc */
- if (has_prefix("tt", param+2)) {
- /* set trim threshold */
- arg = get_value(param+4, argv, &i);
- errno = 0;
- init->trim_threshold = (int) strtol(arg, &rest, 10);
- if (errno != 0
- || rest == arg
- || init->trim_threshold < 0
- || (INT_MAX/1024) < init->trim_threshold) {
- bad_value(param, param+4, arg);
- }
- VERBOSE(DEBUG_SYSTEM,
- ("using trim threshold: %d\n",
- init->trim_threshold));
- init->trim_threshold *= 1024;
- }
- else if (has_prefix("tp", param+2)) {
- /* set top pad */
- arg = get_value(param+4, argv, &i);
- errno = 0;
- init->top_pad = (int) strtol(arg, &rest, 10);
- if (errno != 0
- || rest == arg
- || init->top_pad < 0
- || (INT_MAX/1024) < init->top_pad) {
- bad_value(param, param+4, arg);
- }
- VERBOSE(DEBUG_SYSTEM,
- ("using top pad: %d\n",init->top_pad));
- init->top_pad *= 1024;
- }
- else if (has_prefix("m", param+2)) {
- /* Has been handled by erlexec */
- (void) get_value(param+3, argv, &i);
- }
- else if (has_prefix("e", param+2)) {
- arg = get_value(param+3, argv, &i);
- if (sys_strcmp("true", arg) != 0)
- bad_value(param, param+3, arg);
- }
- else
- bad_param(param, param+2);
- break;
- }
- case 'e':
- switch (argv[i][3]) {
- case 'a': {
- int a;
- arg = get_value(argv[i]+4, argv, &i);
- if (sys_strcmp("min", arg) == 0) {
- for (a = 0; a < aui_sz; a++)
- aui[a]->enable = 0;
- }
- else if (sys_strcmp("max", arg) == 0) {
- for (a = 0; a < aui_sz; a++)
- aui[a]->enable = 1;
- }
- else if (sys_strcmp("config", arg) == 0) {
- init->erts_alloc_config = 1;
- }
- else if (sys_strcmp("r9c", arg) == 0
- || sys_strcmp("r10b", arg) == 0
- || sys_strcmp("r11b", arg) == 0) {
- set_default_sl_alloc_opts(&init->sl_alloc);
- set_default_std_alloc_opts(&init->std_alloc);
- set_default_ll_alloc_opts(&init->ll_alloc);
- set_default_temp_alloc_opts(&init->temp_alloc);
- set_default_eheap_alloc_opts(&init->eheap_alloc);
- set_default_binary_alloc_opts(&init->binary_alloc);
- set_default_ets_alloc_opts(&init->ets_alloc);
- set_default_driver_alloc_opts(&init->driver…
Large files files are truncated, but you can click here to view the full file