PageRenderTime 124ms CodeModel.GetById 12ms app.highlight 85ms RepoModel.GetById 3ms app.codeStats 2ms

/erts/emulator/beam/erl_alloc.c

http://github.com/erlang/otp
C | 4119 lines | 3549 code | 457 blank | 113 comment | 601 complexity | b24d5370c4eb8ca1a3d6f0838fc7007e MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2 * %CopyrightBegin%
   3 *
   4 * Copyright Ericsson AB 2002-2020. All Rights Reserved.
   5 *
   6 * Licensed under the Apache License, Version 2.0 (the "License");
   7 * you may not use this file except in compliance with the License.
   8 * You may obtain a copy of the License at
   9 *
  10 *     http://www.apache.org/licenses/LICENSE-2.0
  11 *
  12 * Unless required by applicable law or agreed to in writing, software
  13 * distributed under the License is distributed on an "AS IS" BASIS,
  14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15 * See the License for the specific language governing permissions and
  16 * limitations under the License.
  17 *
  18 * %CopyrightEnd%
  19 */
  20
  21
  22/*
  23 * Description:	Management of memory allocators.
  24 *
  25 * Author: 	Rickard Green
  26 */
  27
  28#ifdef HAVE_CONFIG_H
  29#  include "config.h"
  30#endif
  31#define ERTS_ALLOC_C__
  32#define ERTS_ALC_INTERNAL__
  33#define ERTS_WANT_MEM_MAPPERS
  34#include "sys.h"
  35#define ERL_THREADS_EMU_INTERNAL__
  36#include "erl_threads.h"
  37#include "global.h"
  38#include "erl_db.h"
  39#include "erl_binary.h"
  40#include "erl_bits.h"
  41#include "erl_mtrace.h"
  42#include "erl_mseg.h"
  43#include "erl_monitor_link.h"
  44#include "erl_hl_timer.h"
  45#include "erl_cpu_topology.h"
  46#include "erl_thr_queue.h"
  47#include "erl_nfunc_sched.h"
  48#if defined(ERTS_ALC_T_DRV_SEL_D_STATE) || defined(ERTS_ALC_T_DRV_EV_D_STATE)
  49#include "erl_check_io.h"
  50#endif
  51#include "erl_bif_unique.h"
  52
  53#define GET_ERL_GF_ALLOC_IMPL
  54#include "erl_goodfit_alloc.h"
  55#define GET_ERL_BF_ALLOC_IMPL
  56#include "erl_bestfit_alloc.h"
  57#define GET_ERL_AF_ALLOC_IMPL
  58#include "erl_afit_alloc.h"
  59#define GET_ERL_AOFF_ALLOC_IMPL
  60#include "erl_ao_firstfit_alloc.h"
  61
  62
  63#if ERTS_MAX_NO_OF_SCHEDULERS > ERTS_AU_MAX_PREF_ALLOC_INSTANCES
  64#  error "Too many schedulers; cannot create that many pref alloc instances"
  65#endif
  66
  67#define ERTS_ALC_DEFAULT_MAX_THR_PREF ERTS_MAX_NO_OF_SCHEDULERS
  68
  69#if defined(SMALL_MEMORY) || defined(PURIFY) || defined(VALGRIND)
  70#define AU_ALLOC_DEFAULT_ENABLE(X)	0
  71#else
  72#define AU_ALLOC_DEFAULT_ENABLE(X)	(X)
  73#endif
  74
  75#define ERTS_ALC_DEFAULT_ENABLED_ACUL 60
  76#define ERTS_ALC_DEFAULT_ENABLED_ACUL_EHEAP_ALLOC 45
  77#define ERTS_ALC_DEFAULT_ENABLED_ACUL_LL_ALLOC 85
  78
  79#define ERTS_ALC_DEFAULT_ACUL ERTS_ALC_DEFAULT_ENABLED_ACUL
  80#define ERTS_ALC_DEFAULT_ACUL_EHEAP_ALLOC ERTS_ALC_DEFAULT_ENABLED_ACUL_EHEAP_ALLOC
  81#define ERTS_ALC_DEFAULT_ACUL_LL_ALLOC ERTS_ALC_DEFAULT_ENABLED_ACUL_LL_ALLOC
  82
  83
  84#ifdef DEBUG
  85static Uint install_debug_functions(void);
  86#if 0
  87#define HARD_DEBUG
  88#ifdef __GNUC__
  89#warning "* * * * * * * * * * * * * *"
  90#warning "* HARD DEBUG IS ENABLED!  *"
  91#warning "* * * * * * * * * * * * * *"
  92#endif
  93#endif
  94#endif
  95
  96static int lock_all_physical_memory = 0;
  97
  98ErtsAllocatorFunctions_t ERTS_WRITE_UNLIKELY(erts_allctrs[ERTS_ALC_A_MAX+1]);
  99ErtsAllocatorInfo_t erts_allctrs_info[ERTS_ALC_A_MAX+1];
 100ErtsAllocatorThrSpec_t ERTS_WRITE_UNLIKELY(erts_allctr_thr_spec[ERTS_ALC_A_MAX+1]);
 101
 102#define ERTS_MIN(A, B) ((A) < (B) ? (A) : (B))
 103#define ERTS_MAX(A, B) ((A) > (B) ? (A) : (B))
 104
 105typedef union {
 106    GFAllctr_t gfa;
 107    char align_gfa[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(GFAllctr_t))];
 108    BFAllctr_t bfa;
 109    char align_bfa[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(BFAllctr_t))];
 110    AFAllctr_t afa;
 111    char align_afa[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(AFAllctr_t))];
 112    AOFFAllctr_t aoffa;
 113    char align_aoffa[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(AOFFAllctr_t))];
 114} ErtsAllocatorState_t erts_align_attribute(ERTS_CACHE_LINE_SIZE);
 115
 116static ErtsAllocatorState_t std_alloc_state;
 117static ErtsAllocatorState_t ll_alloc_state;
 118static ErtsAllocatorState_t sl_alloc_state;
 119static ErtsAllocatorState_t temp_alloc_state;
 120static ErtsAllocatorState_t eheap_alloc_state;
 121static ErtsAllocatorState_t binary_alloc_state;
 122static ErtsAllocatorState_t ets_alloc_state;
 123static ErtsAllocatorState_t driver_alloc_state;
 124static ErtsAllocatorState_t fix_alloc_state;
 125static ErtsAllocatorState_t literal_alloc_state;
 126#ifdef ERTS_ALC_A_EXEC
 127static ErtsAllocatorState_t exec_alloc_state;
 128#endif
 129static ErtsAllocatorState_t test_alloc_state;
 130
 131enum {
 132    ERTS_ALC_INFO_A_ALLOC_UTIL = ERTS_ALC_A_MAX + 1,
 133    ERTS_ALC_INFO_A_MSEG_ALLOC,
 134    ERTS_ALC_INFO_A_ERTS_MMAP,
 135    ERTS_ALC_INFO_A_DISABLED_EXEC,  /* fake a disabled "exec_alloc" */
 136    ERTS_ALC_INFO_A_END
 137};
 138
 139typedef struct {
 140    erts_atomic32_t refc;
 141    int only_sz;
 142    int internal;
 143    Uint req_sched;
 144    Process *proc;
 145    ErtsIRefStorage iref;
 146    int allocs[ERTS_ALC_INFO_A_END - ERTS_ALC_A_MIN + 1];
 147} ErtsAllocInfoReq;
 148
 149ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(aireq,
 150                                 ErtsAllocInfoReq,
 151                                 5,
 152                                 ERTS_ALC_T_AINFO_REQ)
 153
 154ErtsAlcType_t erts_fix_core_allocator_ix;
 155
 156struct au_init {
 157    int enable;
 158    int thr_spec;
 159    int disable_allowed;
 160    int thr_spec_allowed;
 161    int carrier_migration_allowed;
 162    ErtsAlcStrat_t	astrat;
 163    struct {
 164	AllctrInit_t	util;
 165	GFAllctrInit_t	gf;
 166	BFAllctrInit_t	bf;
 167	AFAllctrInit_t	af;
 168	AOFFAllctrInit_t aoff;
 169    } init;
 170    struct {
 171	int mmbcs;
 172	int lmbcs;
 173	int smbcs;
 174	int mmmbc;
 175    } default_;
 176};
 177
 178#define DEFAULT_ALLCTR_INIT {		\
 179    ERTS_DEFAULT_ALLCTR_INIT,		\
 180    ERTS_DEFAULT_GF_ALLCTR_INIT,	\
 181    ERTS_DEFAULT_BF_ALLCTR_INIT,	\
 182    ERTS_DEFAULT_AF_ALLCTR_INIT,	\
 183    ERTS_DEFAULT_AOFF_ALLCTR_INIT       \
 184}
 185
 186typedef struct {
 187    int erts_alloc_config;
 188#if HAVE_ERTS_MSEG
 189    ErtsMsegInit_t mseg;
 190#endif
 191    int trim_threshold;
 192    int top_pad;
 193    AlcUInit_t alloc_util;
 194    struct {
 195	char *mtrace;
 196	char *nodename;
 197    } instr;
 198    struct au_init sl_alloc;
 199    struct au_init std_alloc;
 200    struct au_init ll_alloc;
 201    struct au_init temp_alloc;
 202    struct au_init eheap_alloc;
 203    struct au_init binary_alloc;
 204    struct au_init ets_alloc;
 205    struct au_init driver_alloc;
 206    struct au_init fix_alloc;
 207    struct au_init literal_alloc;
 208    struct au_init exec_alloc;
 209    struct au_init test_alloc;
 210} erts_alc_hndl_args_init_t;
 211
 212#define ERTS_AU_INIT__ {0, 0, 1, 1, 1, \
 213                        ERTS_ALC_S_GOODFIT, DEFAULT_ALLCTR_INIT, \
 214                        {1,1,1,1}}
 215
 216#define SET_DEFAULT_ALLOC_OPTS(IP)					\
 217do {									\
 218    struct au_init aui__ = ERTS_AU_INIT__;				\
 219    sys_memcpy((void *) (IP), (void *) &aui__, sizeof(struct au_init));	\
 220} while (0)
 221
 222static void
 223set_default_sl_alloc_opts(struct au_init *ip)
 224{
 225    SET_DEFAULT_ALLOC_OPTS(ip);
 226    ip->enable			= AU_ALLOC_DEFAULT_ENABLE(1);
 227    ip->thr_spec		= 1;
 228    ip->astrat			= ERTS_ALC_S_GOODFIT;
 229    ip->init.util.name_prefix	= "sl_";
 230    ip->init.util.alloc_no	= ERTS_ALC_A_SHORT_LIVED;
 231#ifndef SMALL_MEMORY
 232    ip->init.util.mmbcs 	= 128*1024; /* Main carrier size */
 233#else
 234    ip->init.util.mmbcs 	= 32*1024; /* Main carrier size */
 235#endif
 236    ip->init.util.ts 		= ERTS_ALC_MTA_SHORT_LIVED;
 237    ip->init.util.rsbcst	= 80;
 238    ip->init.util.acul		= ERTS_ALC_DEFAULT_ACUL;
 239}
 240
 241static void
 242set_default_std_alloc_opts(struct au_init *ip)
 243{
 244    SET_DEFAULT_ALLOC_OPTS(ip);
 245    ip->enable			= AU_ALLOC_DEFAULT_ENABLE(1);
 246    ip->thr_spec		= 1;
 247    ip->astrat			= ERTS_ALC_S_BESTFIT;
 248    ip->init.util.name_prefix	= "std_";
 249    ip->init.util.alloc_no	= ERTS_ALC_A_STANDARD;
 250#ifndef SMALL_MEMORY
 251    ip->init.util.mmbcs 	= 128*1024; /* Main carrier size */
 252#else
 253    ip->init.util.mmbcs 	= 32*1024; /* Main carrier size */
 254#endif
 255    ip->init.util.ts 		= ERTS_ALC_MTA_STANDARD;
 256    ip->init.util.acul		= ERTS_ALC_DEFAULT_ACUL;
 257}
 258
 259static void
 260set_default_ll_alloc_opts(struct au_init *ip)
 261{
 262    SET_DEFAULT_ALLOC_OPTS(ip);
 263    ip->enable			= AU_ALLOC_DEFAULT_ENABLE(1);
 264    ip->thr_spec		= 0;
 265    ip->astrat			= ERTS_ALC_S_BESTFIT;
 266    ip->init.bf.ao		= 1;
 267    ip->init.util.ramv		= 0;
 268    ip->init.util.mmsbc		= 0;
 269    ip->init.util.sbct		= ~((UWord) 0);
 270    ip->init.util.name_prefix	= "ll_";
 271    ip->init.util.alloc_no	= ERTS_ALC_A_LONG_LIVED;
 272#ifndef SMALL_MEMORY
 273    ip->init.util.mmbcs 	= 2*1024*1024; /* Main carrier size */
 274#else
 275    ip->init.util.mmbcs 	= 1*1024*1024; /* Main carrier size */
 276#endif
 277    ip->init.util.ts 		= ERTS_ALC_MTA_LONG_LIVED;
 278    ip->init.util.asbcst	= 0;
 279    ip->init.util.rsbcst	= 0;
 280    ip->init.util.rsbcmt	= 0;
 281    ip->init.util.rmbcmt	= 0;
 282    ip->init.util.acul		= ERTS_ALC_DEFAULT_ACUL_LL_ALLOC;
 283}
 284
 285static void
 286set_default_literal_alloc_opts(struct au_init *ip)
 287{
 288    SET_DEFAULT_ALLOC_OPTS(ip);
 289    ip->enable			= 1;
 290    ip->thr_spec		= 0;
 291    ip->disable_allowed         = 0;
 292    ip->thr_spec_allowed        = 0;
 293    ip->carrier_migration_allowed = 0;
 294    ip->astrat			= ERTS_ALC_S_BESTFIT;
 295    ip->init.bf.ao		= 1;
 296    ip->init.util.ramv		= 0;
 297    ip->init.util.mmsbc		= 0;
 298    ip->init.util.sbct		= ~((UWord) 0);
 299    ip->init.util.name_prefix	= "literal_";
 300    ip->init.util.alloc_no	= ERTS_ALC_A_LITERAL;
 301#ifndef SMALL_MEMORY
 302    ip->init.util.mmbcs 	= 1024*1024; /* Main carrier size */
 303#else
 304    ip->init.util.mmbcs 	= 256*1024; /* Main carrier size */
 305#endif
 306    ip->init.util.ts 		= ERTS_ALC_MTA_LITERAL;
 307    ip->init.util.asbcst	= 0;
 308    ip->init.util.rsbcst	= 0;
 309    ip->init.util.rsbcmt	= 0;
 310    ip->init.util.rmbcmt	= 0;
 311    ip->init.util.acul		= 0;
 312
 313#if defined(ARCH_32)
 314# if HAVE_ERTS_MSEG
 315    ip->init.util.mseg_alloc   = &erts_alcu_literal_32_mseg_alloc;
 316    ip->init.util.mseg_realloc = &erts_alcu_literal_32_mseg_realloc;
 317    ip->init.util.mseg_dealloc = &erts_alcu_literal_32_mseg_dealloc;
 318# endif
 319    ip->init.util.sys_alloc    = &erts_alcu_literal_32_sys_alloc;
 320    ip->init.util.sys_realloc  = &erts_alcu_literal_32_sys_realloc;
 321    ip->init.util.sys_dealloc  = &erts_alcu_literal_32_sys_dealloc;
 322#elif defined(ARCH_64)
 323# ifdef ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION
 324    ip->init.util.mseg_alloc    = &erts_alcu_mmapper_mseg_alloc;
 325    ip->init.util.mseg_realloc  = &erts_alcu_mmapper_mseg_realloc;
 326    ip->init.util.mseg_dealloc  = &erts_alcu_mmapper_mseg_dealloc;
 327    ip->init.util.mseg_mmapper  = &erts_literal_mmapper;
 328# endif
 329#else
 330# error Unknown architecture
 331#endif
 332}
 333
 334#ifdef ERTS_ALC_A_EXEC
 335static void
 336set_default_exec_alloc_opts(struct au_init *ip)
 337{
 338    SET_DEFAULT_ALLOC_OPTS(ip);
 339    ip->enable			= 1;
 340    ip->thr_spec		= 0;
 341    ip->disable_allowed         = 0;
 342    ip->thr_spec_allowed        = 0;
 343    ip->carrier_migration_allowed = 0;
 344    ip->astrat			= ERTS_ALC_S_BESTFIT;
 345    ip->init.bf.ao		= 1;
 346    ip->init.util.ramv		= 0;
 347    ip->init.util.mmsbc		= 0;
 348    ip->init.util.sbct		= ~((UWord) 0);
 349    ip->init.util.name_prefix	= "exec_";
 350    ip->init.util.alloc_no	= ERTS_ALC_A_EXEC;
 351    ip->init.util.mmbcs 	= 0; /* No main carrier */
 352    ip->init.util.ts 		= ERTS_ALC_MTA_EXEC;
 353    ip->init.util.asbcst	= 0;
 354    ip->init.util.rsbcst	= 0;
 355    ip->init.util.rsbcmt	= 0;
 356    ip->init.util.rmbcmt	= 0;
 357    ip->init.util.acul		= 0;
 358
 359    ip->init.util.mseg_alloc    = &erts_alcu_exec_mseg_alloc;
 360    ip->init.util.mseg_realloc  = &erts_alcu_exec_mseg_realloc;
 361    ip->init.util.mseg_dealloc  = &erts_alcu_exec_mseg_dealloc;
 362}
 363#endif /* ERTS_ALC_A_EXEC */
 364
 365static void
 366set_default_temp_alloc_opts(struct au_init *ip)
 367{
 368    SET_DEFAULT_ALLOC_OPTS(ip);
 369    ip->enable			= AU_ALLOC_DEFAULT_ENABLE(1);
 370    ip->thr_spec		= 1;
 371    ip->disable_allowed         = 0;
 372    ip->carrier_migration_allowed = 0;
 373    ip->astrat			= ERTS_ALC_S_AFIT;
 374    ip->init.util.name_prefix	= "temp_";
 375    ip->init.util.alloc_no	= ERTS_ALC_A_TEMPORARY;
 376#ifndef SMALL_MEMORY
 377    ip->init.util.mmbcs 	= 128*1024; /* Main carrier size */
 378#else
 379    ip->init.util.mmbcs 	= 32*1024; /* Main carrier size */
 380#endif
 381    ip->init.util.ts 		= ERTS_ALC_MTA_TEMPORARY;
 382    ip->init.util.rsbcst	= 90;
 383    ip->init.util.rmbcmt	= 100;
 384}
 385
 386static void
 387set_default_eheap_alloc_opts(struct au_init *ip)
 388{
 389    SET_DEFAULT_ALLOC_OPTS(ip);
 390    ip->enable			= AU_ALLOC_DEFAULT_ENABLE(1);
 391    ip->thr_spec		= 1;
 392    ip->astrat			= ERTS_ALC_S_GOODFIT;
 393    ip->init.util.name_prefix	= "eheap_";
 394    ip->init.util.alloc_no	= ERTS_ALC_A_EHEAP;
 395#ifndef SMALL_MEMORY
 396    ip->init.util.mmbcs 	= 512*1024; /* Main carrier size */
 397#else
 398    ip->init.util.mmbcs 	= 256*1024; /* Main carrier size */
 399#endif
 400    ip->init.util.ts 		= ERTS_ALC_MTA_EHEAP;
 401    ip->init.util.rsbcst	= 50;
 402    ip->init.util.acul		= ERTS_ALC_DEFAULT_ACUL_EHEAP_ALLOC;
 403}
 404
 405static void
 406set_default_binary_alloc_opts(struct au_init *ip)
 407{
 408    SET_DEFAULT_ALLOC_OPTS(ip);
 409    ip->enable			= AU_ALLOC_DEFAULT_ENABLE(1);
 410    ip->thr_spec		= 1;
 411    ip->astrat			= ERTS_ALC_S_BESTFIT;
 412    ip->init.util.name_prefix	= "binary_";
 413    ip->init.util.alloc_no	= ERTS_ALC_A_BINARY;
 414#ifndef SMALL_MEMORY
 415    ip->init.util.mmbcs 	= 128*1024; /* Main carrier size */
 416#else
 417    ip->init.util.mmbcs 	= 32*1024; /* Main carrier size */
 418#endif
 419    ip->init.util.ts 		= ERTS_ALC_MTA_BINARY;
 420    ip->init.util.acul		= ERTS_ALC_DEFAULT_ACUL;
 421    ip->init.util.atags		= 1;
 422}
 423
 424static void
 425set_default_ets_alloc_opts(struct au_init *ip)
 426{
 427    SET_DEFAULT_ALLOC_OPTS(ip);
 428    ip->enable			= AU_ALLOC_DEFAULT_ENABLE(1);
 429    ip->thr_spec		= 1;
 430    ip->astrat			= ERTS_ALC_S_BESTFIT;
 431    ip->init.util.name_prefix	= "ets_";
 432    ip->init.util.alloc_no	= ERTS_ALC_A_ETS;
 433#ifndef SMALL_MEMORY
 434    ip->init.util.mmbcs 	= 128*1024; /* Main carrier size */
 435#else
 436    ip->init.util.mmbcs 	= 32*1024; /* Main carrier size */
 437#endif
 438    ip->init.util.ts 		= ERTS_ALC_MTA_ETS;
 439    ip->init.util.acul		= ERTS_ALC_DEFAULT_ACUL;
 440}
 441
 442static void
 443set_default_driver_alloc_opts(struct au_init *ip)
 444{
 445    SET_DEFAULT_ALLOC_OPTS(ip);
 446    ip->enable			= AU_ALLOC_DEFAULT_ENABLE(1);
 447    ip->thr_spec		= 1;
 448    ip->astrat			= ERTS_ALC_S_BESTFIT;
 449    ip->init.util.name_prefix	= "driver_";
 450    ip->init.util.alloc_no	= ERTS_ALC_A_DRIVER;
 451#ifndef SMALL_MEMORY
 452    ip->init.util.mmbcs 	= 128*1024; /* Main carrier size */
 453#else
 454    ip->init.util.mmbcs 	= 32*1024; /* Main carrier size */
 455#endif
 456    ip->init.util.ts 		= ERTS_ALC_MTA_DRIVER;
 457    ip->init.util.acul		= ERTS_ALC_DEFAULT_ACUL;
 458    ip->init.util.atags		= 1;
 459}
 460
 461static void
 462set_default_fix_alloc_opts(struct au_init *ip,
 463			   size_t *fix_type_sizes)
 464{
 465    SET_DEFAULT_ALLOC_OPTS(ip);
 466    ip->enable			= AU_ALLOC_DEFAULT_ENABLE(1);
 467    ip->thr_spec		= 1;
 468    ip->astrat			= ERTS_ALC_S_BESTFIT;
 469    ip->init.bf.ao = 1;
 470    ip->init.util.name_prefix	= "fix_";
 471    ip->init.util.fix_type_size	= fix_type_sizes;
 472    ip->init.util.alloc_no	= ERTS_ALC_A_FIXED_SIZE;
 473#ifndef SMALL_MEMORY
 474    ip->init.util.mmbcs 	= 128*1024; /* Main carrier size */
 475#else
 476    ip->init.util.mmbcs 	= 128*1024; /* Main carrier size */
 477#endif
 478    ip->init.util.ts 		= ERTS_ALC_MTA_FIXED_SIZE;
 479    ip->init.util.acul		= ERTS_ALC_DEFAULT_ACUL;
 480}
 481
 482static void
 483set_default_test_alloc_opts(struct au_init *ip)
 484{
 485    SET_DEFAULT_ALLOC_OPTS(ip);
 486    ip->enable			= 0; /* Disabled by default */
 487    ip->thr_spec		= -1 * erts_no_schedulers;
 488    ip->astrat			= ERTS_ALC_S_FIRSTFIT;
 489    ip->init.aoff.crr_order     = FF_AOFF;
 490    ip->init.aoff.blk_order     = FF_BF;
 491    ip->init.util.name_prefix	= "test_";
 492    ip->init.util.alloc_no	= ERTS_ALC_A_TEST;
 493    ip->init.util.mmbcs 	= 0; /* Main carrier size */
 494    ip->init.util.ts 		= ERTS_ALC_MTA_TEST;
 495    ip->init.util.acul		= ERTS_ALC_DEFAULT_ACUL;
 496    ip->init.util.atags		= 1;
 497
 498    /* Use a constant minimal MBC size */
 499#if ERTS_SA_MB_CARRIERS
 500    ip->init.util.smbcs = ERTS_SACRR_UNIT_SZ;
 501    ip->init.util.lmbcs = ERTS_SACRR_UNIT_SZ;
 502    ip->init.util.sbct  = ERTS_SACRR_UNIT_SZ;
 503#else
 504    ip->init.util.smbcs = 1 << 12;
 505    ip->init.util.lmbcs = 1 << 12;
 506    ip->init.util.sbct  = 1 << 12;
 507#endif
 508}
 509
 510
 511
 512static void
 513adjust_tpref(struct au_init *ip, int no_sched)
 514{
 515    if (ip->thr_spec) {
 516	ip->thr_spec = no_sched;
 517	ip->thr_spec *= -1; /* thread preferred */
 518
 519	/* If default ... */
 520
 521	/* ... shrink main multi-block carrier size */
 522	if (ip->default_.mmbcs)
 523	    ip->init.util.mmbcs /= ERTS_MIN(4, no_sched);
 524	/* ... shrink largest multi-block carrier size */
 525	if (ip->default_.lmbcs)
 526	    ip->init.util.lmbcs /= ERTS_MIN(2, no_sched);
 527	/* ... shrink smallest multi-block carrier size */
 528	if (ip->default_.smbcs)
 529	    ip->init.util.smbcs /= ERTS_MIN(4, no_sched);
 530    }
 531}
 532
 533
 534static void handle_args(int *, char **, erts_alc_hndl_args_init_t *);
 535
 536static void
 537set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init, int ncpu);
 538
 539static void
 540start_au_allocator(ErtsAlcType_t alctr_n,
 541		   struct au_init *init,
 542		   ErtsAllocatorState_t *state);
 543
 544static void
 545refuse_af_strategy(struct au_init *init)
 546{
 547    if (init->astrat == ERTS_ALC_S_AFIT)
 548	init->astrat = ERTS_ALC_S_GOODFIT;
 549}
 550
 551#ifdef HARD_DEBUG
 552static void hdbg_init(void);
 553#endif
 554
 555static void adjust_fix_alloc_sizes(UWord extra_block_size)
 556{
 557    
 558    if (extra_block_size && erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].enabled) {
 559	int j;
 560
 561	if (erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].thr_spec) {
 562	    int i;
 563	    ErtsAllocatorThrSpec_t* tspec;
 564
 565	    tspec = &erts_allctr_thr_spec[ERTS_ALC_A_FIXED_SIZE];	
 566	    ASSERT(tspec->enabled);
 567
 568	    for (i=0; i < tspec->size; i++) {
 569		Allctr_t* allctr = tspec->allctr[i];
 570		for (j=0; j < ERTS_ALC_NO_FIXED_SIZES; ++j) {
 571                    size_t size = allctr->fix[j].type_size;
 572                    size = MAX(size + extra_block_size,
 573                               sizeof(ErtsAllctrDDBlock_t));
 574		    allctr->fix[j].type_size = size;
 575		}
 576	    }
 577	}
 578	else
 579	{
 580	    Allctr_t* allctr = erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].extra;
 581	    for (j=0; j < ERTS_ALC_NO_FIXED_SIZES; ++j) {
 582                size_t size = allctr->fix[j].type_size;
 583                size = MAX(size + extra_block_size,
 584                           sizeof(ErtsAllctrDDBlock_t));
 585                allctr->fix[j].type_size = size;
 586	    }
 587	}
 588    }
 589}
 590
 591static ERTS_INLINE int
 592strategy_support_carrier_migration(struct au_init *auip)
 593{
 594    /*
 595     * Currently only aoff* and ageff* support carrier
 596     * migration, i.e, type AOFIRSTFIT.
 597     */
 598    return auip->astrat == ERTS_ALC_S_FIRSTFIT;
 599}
 600
 601static ERTS_INLINE void
 602adjust_carrier_migration_support(struct au_init *auip)
 603{
 604    if (auip->init.util.acul) {
 605	auip->thr_spec = -1; /* Need thread preferred */
 606
 607	/*
 608	 * If strategy cannot handle carrier migration,
 609	 * default to a strategy that can...
 610	 */
 611	if (!strategy_support_carrier_migration(auip)) {
 612	    /* Default to aoffcbf */
 613	    auip->astrat = ERTS_ALC_S_FIRSTFIT;
 614	    auip->init.aoff.crr_order = FF_AOFF;
 615	    auip->init.aoff.blk_order = FF_BF;
 616	}
 617    }
 618}
 619
 620void
 621erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
 622{
 623    UWord extra_block_size = 0;
 624    int i, ncpu;
 625    erts_alc_hndl_args_init_t init = {
 626	0,
 627#if HAVE_ERTS_MSEG
 628	ERTS_MSEG_INIT_DEFAULT_INITIALIZER,
 629#endif
 630	ERTS_DEFAULT_TRIM_THRESHOLD,
 631	ERTS_DEFAULT_TOP_PAD,
 632	ERTS_DEFAULT_ALCU_INIT,
 633    };
 634    size_t fix_type_sizes[ERTS_ALC_NO_FIXED_SIZES] = {0};
 635
 636    fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_PROC)]
 637	= sizeof(Process);
 638    fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_MONITOR)]
 639	= sizeof(ErtsMonitorDataHeap);
 640    fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_LINK)]
 641	= sizeof(ErtsLinkData);
 642    fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_DRV_SEL_D_STATE)]
 643	= sizeof(ErtsDrvSelectDataState);
 644    fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_NIF_SEL_D_STATE)]
 645        = sizeof(ErtsNifSelectDataState);
 646    fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_MSG_REF)]
 647	= sizeof(ErtsMessageRef);
 648    fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_THR_Q_EL_SL)]
 649	= sizeof(ErtsThrQElement_t);
 650    fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_LL_PTIMER)]
 651	= erts_timer_type_size(ERTS_ALC_T_LL_PTIMER);
 652    fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_HL_PTIMER)]
 653	= erts_timer_type_size(ERTS_ALC_T_HL_PTIMER);
 654    fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_BIF_TIMER)]
 655	= erts_timer_type_size(ERTS_ALC_T_BIF_TIMER);
 656    fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_MREF_NSCHED_ENT)]
 657	= sizeof(ErtsNSchedMagicRefTableEntry);
 658    fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_MINDIRECTION)]
 659	= ERTS_MAGIC_BIN_UNALIGNED_SIZE(sizeof(ErtsMagicIndirectionWord));
 660
 661#ifdef HARD_DEBUG
 662    hdbg_init();
 663#endif
 664
 665    lock_all_physical_memory = 0;
 666
 667    ncpu = eaiop->ncpu;
 668    if (ncpu < 1)
 669	ncpu = 1;
 670
 671    erts_tsd_key_create(&erts_allctr_prelock_tsd_key,
 672			"erts_allctr_prelock_tsd_key");
 673
 674    erts_sys_alloc_init();
 675    erts_init_utils_mem();
 676
 677    set_default_sl_alloc_opts(&init.sl_alloc);
 678    set_default_std_alloc_opts(&init.std_alloc);
 679    set_default_ll_alloc_opts(&init.ll_alloc);
 680    set_default_temp_alloc_opts(&init.temp_alloc);
 681    set_default_eheap_alloc_opts(&init.eheap_alloc);
 682    set_default_binary_alloc_opts(&init.binary_alloc);
 683    set_default_ets_alloc_opts(&init.ets_alloc);
 684    set_default_driver_alloc_opts(&init.driver_alloc);
 685    set_default_fix_alloc_opts(&init.fix_alloc,
 686			       fix_type_sizes);
 687    set_default_literal_alloc_opts(&init.literal_alloc);
 688#ifdef ERTS_ALC_A_EXEC
 689    set_default_exec_alloc_opts(&init.exec_alloc);
 690#endif
 691    set_default_test_alloc_opts(&init.test_alloc);
 692
 693    if (argc && argv)
 694	handle_args(argc, argv, &init);
 695
 696    if (lock_all_physical_memory) {
 697#ifdef HAVE_MLOCKALL
 698	errno = 0;
 699	if (mlockall(MCL_CURRENT|MCL_FUTURE) != 0) {
 700	    int err = errno;
 701	    char *errstr = err ? strerror(err) : "unknown";
 702	    erts_exit(1, "Failed to lock physical memory: %s (%d)\n",
 703		     errstr, err);
 704	}
 705#else
 706	erts_exit(1, "Failed to lock physical memory: Not supported\n");
 707#endif
 708    }
 709
 710
 711    /* Make adjustments for carrier migration support */
 712    init.temp_alloc.init.util.acul = 0;
 713    adjust_carrier_migration_support(&init.sl_alloc);
 714    adjust_carrier_migration_support(&init.std_alloc);
 715    adjust_carrier_migration_support(&init.ll_alloc);
 716    adjust_carrier_migration_support(&init.eheap_alloc);
 717    adjust_carrier_migration_support(&init.binary_alloc);
 718    adjust_carrier_migration_support(&init.ets_alloc);
 719    adjust_carrier_migration_support(&init.driver_alloc);
 720    adjust_carrier_migration_support(&init.fix_alloc);
 721    adjust_carrier_migration_support(&init.literal_alloc);
 722#ifdef ERTS_ALC_A_EXEC
 723    adjust_carrier_migration_support(&init.exec_alloc);
 724#endif
 725
 726    if (init.erts_alloc_config) {
 727	/* Adjust flags that erts_alloc_config won't like */
 728
 729	/* No thread specific instances */
 730	init.temp_alloc.thr_spec = 0;
 731	init.sl_alloc.thr_spec = 0;
 732	init.std_alloc.thr_spec = 0;
 733	init.ll_alloc.thr_spec = 0;
 734	init.eheap_alloc.thr_spec = 0;
 735	init.binary_alloc.thr_spec = 0;
 736	init.ets_alloc.thr_spec = 0;
 737	init.driver_alloc.thr_spec = 0;
 738	init.fix_alloc.thr_spec = 0;
 739        init.literal_alloc.thr_spec = 0;
 740#ifdef ERTS_ALC_A_EXEC
 741        init.exec_alloc.thr_spec = 0;
 742#endif
 743
 744	/* No carrier migration */
 745	init.temp_alloc.init.util.acul = 0;
 746	init.sl_alloc.init.util.acul = 0;
 747	init.std_alloc.init.util.acul = 0;
 748	init.ll_alloc.init.util.acul = 0;
 749	init.eheap_alloc.init.util.acul = 0;
 750	init.binary_alloc.init.util.acul = 0;
 751	init.ets_alloc.init.util.acul = 0;
 752	init.driver_alloc.init.util.acul = 0;
 753	init.fix_alloc.init.util.acul = 0;
 754        init.literal_alloc.init.util.acul = 0;
 755#ifdef ERTS_ALC_A_EXEC
 756        init.exec_alloc.init.util.acul = 0;
 757#endif
 758    }
 759
 760    /* Only temp_alloc can use thread specific interface */
 761    if (init.temp_alloc.thr_spec)
 762	init.temp_alloc.thr_spec = erts_no_schedulers;
 763
 764    /* Others must use thread preferred interface */
 765    adjust_tpref(&init.sl_alloc, erts_no_schedulers);
 766    adjust_tpref(&init.std_alloc, erts_no_schedulers);
 767    adjust_tpref(&init.ll_alloc, erts_no_schedulers);
 768    adjust_tpref(&init.eheap_alloc, erts_no_schedulers);
 769    adjust_tpref(&init.binary_alloc, erts_no_schedulers);
 770    adjust_tpref(&init.ets_alloc, erts_no_schedulers);
 771    adjust_tpref(&init.driver_alloc, erts_no_schedulers);
 772    adjust_tpref(&init.fix_alloc, erts_no_schedulers);
 773    adjust_tpref(&init.literal_alloc, erts_no_schedulers);
 774#ifdef ERTS_ALC_A_EXEC
 775    adjust_tpref(&init.exec_alloc, erts_no_schedulers);
 776#endif
 777
 778
 779    /*
 780     * The following allocators cannot be run with afit strategy.
 781     * Make sure they don't...
 782     */
 783    refuse_af_strategy(&init.sl_alloc);
 784    refuse_af_strategy(&init.std_alloc);
 785    refuse_af_strategy(&init.ll_alloc);
 786    refuse_af_strategy(&init.eheap_alloc);
 787    refuse_af_strategy(&init.binary_alloc);
 788    refuse_af_strategy(&init.ets_alloc);
 789    refuse_af_strategy(&init.driver_alloc);
 790    refuse_af_strategy(&init.fix_alloc);
 791    refuse_af_strategy(&init.literal_alloc);
 792#ifdef ERTS_ALC_A_EXEC
 793    refuse_af_strategy(&init.exec_alloc);
 794#endif
 795
 796    if (!init.temp_alloc.thr_spec)
 797	refuse_af_strategy(&init.temp_alloc);
 798
 799    erts_mtrace_pre_init();
 800#if HAVE_ERTS_MSEG
 801    init.mseg.nos = erts_no_schedulers;
 802    erts_mseg_init(&init.mseg);
 803#endif
 804
 805    erts_alcu_init(&init.alloc_util);
 806    erts_afalc_init();
 807    erts_bfalc_init();
 808    erts_gfalc_init();
 809    erts_aoffalc_init();
 810
 811    for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {
 812	erts_allctrs[i].alloc		= NULL;
 813	erts_allctrs[i].realloc		= NULL;
 814	erts_allctrs[i].free		= NULL;
 815	erts_allctrs[i].extra		= NULL;
 816	erts_allctrs_info[i].alloc_util	= 0;
 817	erts_allctrs_info[i].enabled	= 0;
 818	erts_allctrs_info[i].thr_spec	= 0;
 819	erts_allctrs_info[i].extra	= NULL;
 820    }
 821
 822    erts_allctrs[ERTS_ALC_A_SYSTEM].alloc		= erts_sys_alloc;
 823    erts_allctrs[ERTS_ALC_A_SYSTEM].realloc		= erts_sys_realloc;
 824    erts_allctrs[ERTS_ALC_A_SYSTEM].free		= erts_sys_free;
 825    erts_allctrs_info[ERTS_ALC_A_SYSTEM].enabled	= 1;
 826
 827    set_au_allocator(ERTS_ALC_A_TEMPORARY, &init.temp_alloc, ncpu);
 828    set_au_allocator(ERTS_ALC_A_SHORT_LIVED, &init.sl_alloc, ncpu);
 829    set_au_allocator(ERTS_ALC_A_STANDARD, &init.std_alloc, ncpu);
 830    set_au_allocator(ERTS_ALC_A_LONG_LIVED, &init.ll_alloc, ncpu);
 831    set_au_allocator(ERTS_ALC_A_EHEAP, &init.eheap_alloc, ncpu);
 832    set_au_allocator(ERTS_ALC_A_BINARY, &init.binary_alloc, ncpu);
 833    set_au_allocator(ERTS_ALC_A_ETS, &init.ets_alloc, ncpu);
 834    set_au_allocator(ERTS_ALC_A_DRIVER, &init.driver_alloc, ncpu);
 835    set_au_allocator(ERTS_ALC_A_FIXED_SIZE, &init.fix_alloc, ncpu);
 836    set_au_allocator(ERTS_ALC_A_LITERAL, &init.literal_alloc, ncpu);
 837#ifdef ERTS_ALC_A_EXEC
 838    set_au_allocator(ERTS_ALC_A_EXEC, &init.exec_alloc, ncpu);
 839#endif
 840    set_au_allocator(ERTS_ALC_A_TEST, &init.test_alloc, ncpu);
 841
 842    for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {
 843	if (!erts_allctrs[i].alloc)
 844	    erts_exit(ERTS_ABORT_EXIT,
 845		     "Missing alloc function for %s\n", ERTS_ALC_A2AD(i));
 846	if (!erts_allctrs[i].realloc)
 847	    erts_exit(ERTS_ABORT_EXIT,
 848		     "Missing realloc function for %s\n", ERTS_ALC_A2AD(i));
 849	if (!erts_allctrs[i].free)
 850	    erts_exit(ERTS_ABORT_EXIT,
 851		     "Missing free function for %s\n", ERTS_ALC_A2AD(i));
 852    }
 853
 854    sys_alloc_opt(SYS_ALLOC_OPT_TRIM_THRESHOLD, init.trim_threshold);
 855    sys_alloc_opt(SYS_ALLOC_OPT_TOP_PAD, init.top_pad);
 856
 857    erts_mtrace_init(init.instr.mtrace, init.instr.nodename);
 858
 859    start_au_allocator(ERTS_ALC_A_TEMPORARY,
 860		       &init.temp_alloc,
 861		       &temp_alloc_state);
 862
 863    start_au_allocator(ERTS_ALC_A_SHORT_LIVED,
 864		       &init.sl_alloc,
 865		       &sl_alloc_state);
 866
 867    start_au_allocator(ERTS_ALC_A_STANDARD,
 868		       &init.std_alloc,
 869		       &std_alloc_state);
 870
 871    start_au_allocator(ERTS_ALC_A_LONG_LIVED,
 872		       &init.ll_alloc,
 873		       &ll_alloc_state);
 874    start_au_allocator(ERTS_ALC_A_EHEAP,
 875		       &init.eheap_alloc,
 876		       &eheap_alloc_state);
 877
 878    start_au_allocator(ERTS_ALC_A_BINARY,
 879		       &init.binary_alloc,
 880		       &binary_alloc_state);
 881
 882    start_au_allocator(ERTS_ALC_A_ETS,
 883		       &init.ets_alloc,
 884		       &ets_alloc_state);
 885
 886    start_au_allocator(ERTS_ALC_A_DRIVER,
 887		       &init.driver_alloc,
 888		       &driver_alloc_state);
 889
 890    start_au_allocator(ERTS_ALC_A_FIXED_SIZE,
 891		       &init.fix_alloc,
 892		       &fix_alloc_state);
 893    start_au_allocator(ERTS_ALC_A_LITERAL,
 894                       &init.literal_alloc,
 895                       &literal_alloc_state);
 896#ifdef ERTS_ALC_A_EXEC
 897    start_au_allocator(ERTS_ALC_A_EXEC,
 898                       &init.exec_alloc,
 899                       &exec_alloc_state);
 900#endif
 901    start_au_allocator(ERTS_ALC_A_TEST,
 902		       &init.test_alloc,
 903		       &test_alloc_state);
 904
 905    erts_mtrace_install_wrapper_functions();
 906
 907    init_aireq_alloc();
 908
 909#ifdef DEBUG
 910    extra_block_size += install_debug_functions();
 911#endif
 912    adjust_fix_alloc_sizes(extra_block_size);
 913}
 914
 915void
 916erts_alloc_late_init(void)
 917{
 918
 919}
 920
 921static void *
 922erts_realloc_fixed_size(ErtsAlcType_t type, void *extra, void *p, Uint size)
 923{
 924    erts_exit(ERTS_ABORT_EXIT,
 925	     "Attempt to reallocate a block of the fixed size type %s\n",
 926	     ERTS_ALC_T2TD(type));
 927}
 928
 929
 930static void
 931set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init, int ncpu)
 932{
 933    ErtsAllocatorFunctions_t *af = &erts_allctrs[alctr_n];
 934    ErtsAllocatorInfo_t *ai = &erts_allctrs_info[alctr_n];
 935    ErtsAllocatorThrSpec_t *tspec = &erts_allctr_thr_spec[alctr_n];
 936
 937    /*
 938     * Some allocators are forced on if halfword heap is used.
 939     */
 940    if (init->init.util.force)
 941	init->enable = 1;
 942
 943    tspec->enabled = 0;
 944    tspec->dd = 0;
 945    tspec->aix = alctr_n;
 946    tspec->size	= 0;
 947    ai->thr_spec = 0;
 948
 949    if (!init->enable) {
 950	af->alloc = erts_sys_alloc;
 951	af->realloc = erts_sys_realloc;
 952	af->free = erts_sys_free;
 953	af->extra = NULL;
 954	ai->alloc_util = 0;
 955	ai->enabled = 0;
 956	ai->extra = NULL;
 957	return;
 958    }
 959
 960    if (init->thr_spec) {
 961	if (init->thr_spec > 0) {
 962	    af->alloc = erts_alcu_alloc_thr_spec;
 963	    if (init->init.util.fix_type_size)
 964		af->realloc = erts_realloc_fixed_size;
 965	    else if (init->init.util.ramv)
 966		af->realloc = erts_alcu_realloc_mv_thr_spec;
 967	    else
 968		af->realloc = erts_alcu_realloc_thr_spec;
 969	    af->free = erts_alcu_free_thr_spec;
 970	}
 971	else {
 972	    af->alloc = erts_alcu_alloc_thr_pref;
 973	    if (init->init.util.fix_type_size)
 974		af->realloc = erts_realloc_fixed_size;
 975	    else if (init->init.util.ramv)
 976		af->realloc = erts_alcu_realloc_mv_thr_pref;
 977	    else
 978		af->realloc = erts_alcu_realloc_thr_pref;
 979	    af->free = erts_alcu_free_thr_pref;
 980	    tspec->dd = 1;
 981	}
 982
 983	tspec->enabled	= 1;
 984	tspec->size	= abs(init->thr_spec) + 1;
 985
 986	ai->thr_spec	= tspec->size;
 987    }
 988    else
 989	if (init->init.util.ts) {
 990	af->alloc = erts_alcu_alloc_ts;
 991	if (init->init.util.fix_type_size)
 992	    af->realloc = erts_realloc_fixed_size;
 993	else if (init->init.util.ramv)
 994	    af->realloc = erts_alcu_realloc_mv_ts;
 995	else
 996	    af->realloc = erts_alcu_realloc_ts;
 997	af->free = erts_alcu_free_ts;
 998    }
 999    else
1000    {
1001        erts_exit(ERTS_ABORT_EXIT, "%salloc is not thread safe\n",
1002                 init->init.util.name_prefix);
1003    }
1004    af->extra	= NULL;
1005    ai->alloc_util	= 1;
1006    ai->enabled		= 1;
1007}
1008
1009static void
1010start_au_allocator(ErtsAlcType_t alctr_n,
1011		   struct au_init *init,
1012		   ErtsAllocatorState_t *state)
1013{
1014    int i;
1015    int size = 1;
1016    void *as0;
1017    ErtsAlcStrat_t astrat;
1018    ErtsAllocatorFunctions_t *af = &erts_allctrs[alctr_n];
1019    ErtsAllocatorInfo_t *ai = &erts_allctrs_info[alctr_n];
1020    ErtsAllocatorThrSpec_t *tspec = &erts_allctr_thr_spec[alctr_n];
1021    ErtsAlcFixList_t *fix_lists = NULL;
1022    size_t fix_list_size = 0;
1023
1024    if (!init->enable)
1025	return;
1026
1027    if (init->thr_spec) {
1028	char *states = erts_sys_alloc(0,
1029				      NULL,
1030				      ((sizeof(Allctr_t *)
1031					* (tspec->size + 1))
1032				       + (sizeof(ErtsAllocatorState_t)
1033					  * tspec->size)
1034				       + ERTS_CACHE_LINE_SIZE - 1));
1035	if (!states)
1036	    erts_exit(ERTS_ABORT_EXIT,
1037		     "Failed to allocate allocator states for %salloc\n",
1038		     init->init.util.name_prefix);
1039	tspec->allctr = (Allctr_t **) states;
1040	states += sizeof(Allctr_t *) * (tspec->size + 1);
1041	states = ((((UWord) states) & ERTS_CACHE_LINE_MASK)
1042		  ? (char *) ((((UWord) states) & ~ERTS_CACHE_LINE_MASK)
1043			      + ERTS_CACHE_LINE_SIZE)
1044		  : (char *) states);
1045	tspec->allctr[0] = (Allctr_t *) state;
1046	size = tspec->size;
1047	for (i = 1; i < size; i++)
1048	    tspec->allctr[i] = (Allctr_t *)
1049		&((ErtsAllocatorState_t *) states)[i-1];
1050    }
1051
1052    if (init->init.util.fix_type_size) {
1053	size_t tot_fix_list_size;
1054	fix_list_size = sizeof(ErtsAlcFixList_t)*ERTS_ALC_NO_FIXED_SIZES;
1055	fix_list_size = ERTS_ALC_CACHE_LINE_ALIGN_SIZE(fix_list_size);
1056	tot_fix_list_size = fix_list_size;
1057	if (init->thr_spec)
1058	    tot_fix_list_size *= tspec->size;
1059	fix_lists = erts_sys_alloc(0,
1060				   NULL,
1061				   (tot_fix_list_size
1062				    + ERTS_CACHE_LINE_SIZE - 1));
1063	if (!fix_lists)
1064	    erts_exit(ERTS_ABORT_EXIT,
1065		     "Failed to allocate fix lists for %salloc\n",
1066		     init->init.util.name_prefix);
1067
1068	if (((UWord) fix_lists) & ERTS_CACHE_LINE_MASK)
1069		fix_lists = ((ErtsAlcFixList_t *)
1070		       ((((UWord) fix_lists) & ~ERTS_CACHE_LINE_MASK)
1071			+ ERTS_CACHE_LINE_SIZE));
1072    }
1073
1074    for (i = 0; i < size; i++) {
1075	Allctr_t *as;
1076	astrat = init->astrat;
1077
1078	if (!init->thr_spec)
1079	    as0 = state;
1080	else {
1081	    as0 = (void *) tspec->allctr[i];
1082	    if (!as0)
1083		continue;
1084	    if (init->thr_spec < 0) {
1085		init->init.util.ts = i == 0;
1086		init->init.util.tspec = 0;
1087		init->init.util.tpref = -1*init->thr_spec + 1;
1088	    }
1089	    else {
1090		if (i != 0)
1091		    init->init.util.ts = 0;
1092		else {
1093		    if (astrat == ERTS_ALC_S_AFIT)
1094			astrat = ERTS_ALC_S_GOODFIT;
1095		    init->init.util.ts = 1;
1096		}
1097		init->init.util.tspec = init->thr_spec + 1;
1098		init->init.util.tpref = 0;
1099	    }   
1100	}
1101
1102	if (fix_lists) {
1103	    init->init.util.fix = fix_lists;
1104	    fix_lists = ((ErtsAlcFixList_t *)
1105			 (((char *) fix_lists) + fix_list_size));
1106	}
1107
1108        init->init.util.alloc_strat = astrat;
1109	init->init.util.ix = i;
1110
1111	switch (astrat) {
1112	case ERTS_ALC_S_GOODFIT:
1113	    as = erts_gfalc_start((GFAllctr_t *) as0,
1114					   &init->init.gf,
1115					   &init->init.util);
1116	    break;
1117	case ERTS_ALC_S_BESTFIT:
1118	    as = erts_bfalc_start((BFAllctr_t *) as0,
1119					   &init->init.bf,
1120					   &init->init.util);
1121	    break;
1122	case ERTS_ALC_S_AFIT:
1123	    as = erts_afalc_start((AFAllctr_t *) as0,
1124					   &init->init.af,
1125					   &init->init.util);
1126	    break;
1127	case ERTS_ALC_S_FIRSTFIT:
1128	    as = erts_aoffalc_start((AOFFAllctr_t *) as0,
1129					     &init->init.aoff,
1130					     &init->init.util);
1131	    break;
1132
1133	default:
1134	    as = NULL;
1135	    ASSERT(0);
1136	}
1137
1138	if (!as)
1139	    erts_exit(ERTS_ABORT_EXIT,
1140		     "Failed to start %salloc\n", init->init.util.name_prefix);
1141
1142	ASSERT(as == (void *) as0);
1143	af->extra = as;
1144    }
1145
1146    if (init->thr_spec)
1147	af->extra = tspec;
1148    ai->extra = af->extra;
1149}
1150
1151
1152static void bad_param(char *param_start, char *param_end)
1153{
1154    size_t len = param_end - param_start;
1155    char param[100];
1156    if (len > 99)
1157	len = 99;
1158    sys_memcpy((void *) param, (void *) param_start, len);
1159    param[len] = '\0';
1160    erts_fprintf(stderr, "bad \"%s\" parameter\n", param);
1161    erts_usage();
1162}
1163
1164static void bad_value(char *param_start, char *param_end, char *value)
1165{
1166    size_t len = param_end - param_start;
1167    char param[100];
1168    if (len > 99)
1169	len = 99;
1170    sys_memcpy((void *) param, (void *) param_start, len);
1171    param[len] = '\0';
1172    erts_fprintf(stderr, "bad \"%s\" value: %s\n", param, value);
1173    erts_usage();
1174}
1175
1176/* Get arg marks argument as handled by
1177   putting NULL in argv */
1178static char *
1179get_value(char* rest, char** argv, int* ip)
1180{
1181    char *param = argv[*ip]+1;
1182    argv[*ip] = NULL;
1183    if (*rest == '\0') {
1184	char *next = argv[*ip + 1];
1185	if (next[0] == '-'
1186	    && next[1] == '-'
1187	    &&  next[2] == '\0') {
1188	    bad_value(param, rest, "");
1189	}
1190	(*ip)++;
1191	argv[*ip] = NULL;
1192	return next;
1193    }
1194    return rest;
1195}
1196
1197static ERTS_INLINE int
1198has_prefix(const char *prefix, const char *string)
1199{
1200    int i;
1201    for (i = 0; prefix[i]; i++)
1202	if (prefix[i] != string[i])
1203	    return 0;
1204    return 1;
1205}
1206
1207static int
1208get_bool_value(char *param_end, char** argv, int* ip)
1209{
1210    char *param = argv[*ip]+1;
1211    char *value = get_value(param_end, argv, ip);
1212    if (sys_strcmp(value, "true") == 0)
1213	return 1;
1214    else if (sys_strcmp(value, "false") == 0)
1215	return 0;
1216    else
1217	bad_value(param, param_end, value);
1218    return -1;
1219}
1220
1221static Uint kb_to_bytes(Sint kb, Uint *bytes)
1222{
1223    const Uint max = ((~((Uint) 0))/1024) + 1;
1224
1225    if (kb < 0 || (Uint)kb > max)
1226        return 0;
1227    if ((Uint)kb == max)
1228        *bytes = ~((Uint) 0);
1229    else
1230        *bytes = ((Uint) kb)*1024;
1231    return 1;
1232}
1233
1234static Uint
1235get_kb_value(char *param_end, char** argv, int* ip)
1236{
1237    Sint tmp;
1238    Uint bytes = 0;
1239    char *rest;
1240    char *param = argv[*ip]+1;
1241    char *value = get_value(param_end, argv, ip);
1242    errno = 0;
1243    tmp = (Sint) ErtsStrToSint(value, &rest, 10);
1244    if (errno != 0 || rest == value || !kb_to_bytes(tmp, &bytes))
1245	bad_value(param, param_end, value);
1246    return bytes;
1247}
1248
1249static UWord
1250get_mb_value(char *param_end, char** argv, int* ip)
1251{
1252    SWord tmp;
1253    UWord max = ((~((UWord) 0))/(1024*1024)) + 1;
1254    char *rest;
1255    char *param = argv[*ip]+1;
1256    char *value = get_value(param_end, argv, ip);
1257    errno = 0;
1258    tmp = (SWord) ErtsStrToSint(value, &rest, 10);
1259    if (errno != 0 || rest == value || tmp < 0 || max < ((UWord) tmp))
1260	bad_value(param, param_end, value);
1261    if (max == (UWord) tmp)
1262	return ~((UWord) 0);
1263    else
1264	return ((UWord) tmp)*1024*1024;
1265}
1266
1267
1268#if 0
1269static Uint
1270get_byte_value(char *param_end, char** argv, int* ip)
1271{
1272    Sint tmp;
1273    char *rest;
1274    char *param = argv[*ip]+1;
1275    char *value = get_value(param_end, argv, ip);
1276    errno = 0;
1277    tmp = (Sint) ErtsStrToSint(value, &rest, 10);
1278    if (errno != 0 || rest == value || tmp < 0)
1279	bad_value(param, param_end, value);
1280    return (Uint) tmp;
1281}
1282#endif
1283
1284static Uint
1285get_amount_value(char *param_end, char** argv, int* ip)
1286{
1287    Sint tmp;
1288    char *rest;
1289    char *param = argv[*ip]+1;
1290    char *value = get_value(param_end, argv, ip);
1291    errno = 0;
1292    tmp = (Sint) ErtsStrToSint(value, &rest, 10);
1293    if (errno != 0 || rest == value || tmp < 0)
1294	bad_value(param, param_end, value);
1295    return (Uint) tmp;
1296}
1297
1298static Uint
1299get_acul_value(struct au_init *auip, char *param_end, char** argv, int* ip)
1300{
1301    Sint tmp;
1302    char *rest;
1303    char *param = argv[*ip]+1;
1304    char *value = get_value(param_end, argv, ip);
1305    if (sys_strcmp(value, "de") == 0) {
1306	switch (auip->init.util.alloc_no) {
1307	case ERTS_ALC_A_LONG_LIVED:
1308	    return ERTS_ALC_DEFAULT_ENABLED_ACUL_LL_ALLOC;
1309	case ERTS_ALC_A_EHEAP:
1310	    return ERTS_ALC_DEFAULT_ENABLED_ACUL_EHEAP_ALLOC;
1311	default:
1312	    return ERTS_ALC_DEFAULT_ENABLED_ACUL;
1313	}
1314    }
1315    errno = 0;
1316    tmp = (Sint) ErtsStrToSint(value, &rest, 10);
1317    if (errno != 0 || rest == value || tmp < 0 || 100 < tmp)
1318	bad_value(param, param_end, value);
1319    return (Uint) tmp;
1320}
1321
1322static void
1323handle_au_arg(struct au_init *auip,
1324	      char* sub_param,
1325	      char** argv,
1326	      int* ip,
1327	      int u_switch)
1328{
1329    char *param = argv[*ip]+1;
1330
1331    switch (sub_param[0]) {
1332    case 'a':
1333        if (sub_param[1] == 'c') { /* Migration parameters "ac*" */
1334            UWord value;
1335            UWord* wp;
1336            if (!auip->carrier_migration_allowed && !u_switch)
1337                goto bad_switch;
1338
1339            if (has_prefix("acul", sub_param)) {
1340                value = get_acul_value(auip, sub_param + 4, argv, ip);
1341                wp = &auip->init.util.acul;
1342            }
1343            else if (has_prefix("acnl", sub_param)) {
1344                value = get_amount_value(sub_param + 4, argv, ip);
1345                wp = &auip->init.util.acnl;
1346            }
1347            else if (has_prefix("acfml", sub_param)) {
1348                value = get_amount_value(sub_param + 5, argv, ip);
1349                wp = &auip->init.util.acfml;
1350            }
1351            else
1352                goto bad_switch;
1353
1354            if (auip->carrier_migration_allowed)
1355                *wp = value;
1356        }
1357	else if(has_prefix("asbcst", sub_param)) {
1358	    auip->init.util.asbcst = get_kb_value(sub_param + 6, argv, ip);
1359	}
1360	else if(has_prefix("as", sub_param)) {
1361	    char *alg = get_value(sub_param + 2, argv, ip);
1362	    if (sys_strcmp("bf", alg) == 0) {
1363		auip->astrat = ERTS_ALC_S_BESTFIT;
1364		auip->init.bf.ao = 0;
1365	    }
1366	    else if (sys_strcmp("aobf", alg) == 0) {
1367		auip->astrat = ERTS_ALC_S_BESTFIT;
1368		auip->init.bf.ao = 1;
1369	    }
1370	    else if (sys_strcmp("gf", alg) == 0) {
1371		auip->astrat = ERTS_ALC_S_GOODFIT;
1372	    }
1373	    else if (sys_strcmp("af", alg) == 0) {
1374		auip->astrat = ERTS_ALC_S_AFIT;
1375	    }
1376	    else if (sys_strcmp("aoff", alg) == 0) {
1377		auip->astrat = ERTS_ALC_S_FIRSTFIT;
1378		auip->init.aoff.crr_order = FF_AOFF;
1379		auip->init.aoff.blk_order = FF_AOFF;
1380	    }
1381	    else if (sys_strcmp("aoffcbf", alg) == 0) {
1382		auip->astrat = ERTS_ALC_S_FIRSTFIT;
1383		auip->init.aoff.crr_order = FF_AOFF;
1384		auip->init.aoff.blk_order = FF_BF;
1385	    }
1386	    else if (sys_strcmp("aoffcaobf", alg) == 0) {
1387		auip->astrat = ERTS_ALC_S_FIRSTFIT;
1388		auip->init.aoff.crr_order = FF_AOFF;
1389		auip->init.aoff.blk_order = FF_AOBF;
1390	    }
1391            else if (sys_strcmp("ageffcaoff", alg) == 0) {
1392                auip->astrat = ERTS_ALC_S_FIRSTFIT;
1393		auip->init.aoff.crr_order = FF_AGEFF;
1394		auip->init.aoff.blk_order = FF_AOFF;
1395            }
1396            else if (sys_strcmp("ageffcbf", alg) == 0) {
1397                auip->astrat = ERTS_ALC_S_FIRSTFIT;
1398		auip->init.aoff.crr_order = FF_AGEFF;
1399		auip->init.aoff.blk_order = FF_BF;
1400            }
1401            else if (sys_strcmp("ageffcaobf", alg) == 0) {
1402                auip->astrat = ERTS_ALC_S_FIRSTFIT;
1403		auip->init.aoff.crr_order = FF_AGEFF;
1404		auip->init.aoff.blk_order = FF_AOBF;
1405            }
1406	    else {
1407                if (auip->init.util.alloc_no == ERTS_ALC_A_TEST
1408                    && sys_strcmp("chaosff", alg) == 0) {
1409                    auip->astrat = ERTS_ALC_S_FIRSTFIT;
1410                    auip->init.aoff.crr_order = FF_CHAOS;
1411                    auip->init.aoff.blk_order = FF_CHAOS;
1412                }
1413                else {
1414                    bad_value(param, sub_param + 1, alg);
1415                }
1416	    }
1417	    if (!strategy_support_carrier_migration(auip))
1418		auip->init.util.acul = 0;
1419	} else if (has_prefix("atags", sub_param)) {
1420            auip->init.util.atags = get_bool_value(sub_param + 5, argv, ip);
1421        }
1422	else
1423	    goto bad_switch;
1424	break;
1425    case 'e': {
1426	int e = get_bool_value(sub_param + 1, argv, ip);
1427        if (!auip->disable_allowed && !e) {
1428            if (!u_switch)
1429                bad_value(param, sub_param + 1, "false");
1430	    else
1431		ASSERT(auip->enable); /* ignore */
1432        }
1433	else auip->enable = e;
1434	break;
1435    }
1436    case 'l':
1437	if (has_prefix("lmbcs", sub_param)) {
1438	    auip->default_.lmbcs = 0;
1439	    auip->init.util.lmbcs = get_kb_value(sub_param + 5, argv, ip);
1440	}
1441	else
1442	    goto bad_switch;
1443	break;
1444    case 'm':
1445	if (has_prefix("mbcgs", sub_param)) {
1446	    auip->init.util.mbcgs = get_amount_value(sub_param + 5, argv, ip);
1447
1448	}
1449	else if (has_prefix("mbsd", sub_param)) {
1450	    auip->init.gf.mbsd = get_amount_value(sub_param + 4, argv, ip);
1451	    if (auip->init.gf.mbsd < 1)
1452		auip->init.gf.mbsd = 1;
1453	}
1454	else if (has_prefix("mmbcs", sub_param)) {
1455	    auip->default_.mmbcs = 0;
1456	    auip->init.util.mmbcs = get_kb_value(sub_param + 5, argv, ip);
1457	}
1458	else if (has_prefix("mmmbc", sub_param)) {
1459	    auip->default_.mmmbc = 0;
1460	    auip->init.util.mmmbc = get_amount_value(sub_param + 5, argv, ip);
1461	}
1462	else if (has_prefix("mmsbc", sub_param)) {
1463	    auip->init.util.mmsbc = get_amount_value(sub_param + 5, argv, ip);
1464	}
1465	else
1466	    goto bad_switch;
1467	break;
1468    case 'r':
1469	if(has_prefix("rsbcmt", sub_param)) {
1470	    auip->init.util.rsbcmt = get_amount_value(sub_param + 6, argv, ip);
1471	    if (auip->init.util.rsbcmt > 100)
1472		auip->init.util.rsbcmt = 100;
1473	}
1474	else if(has_prefix("rsbcst", sub_param)) {
1475	    auip->init.util.rsbcst = get_amount_value(sub_param + 6, argv, ip);
1476	    if (auip->init.util.rsbcst > 100)
1477		auip->init.util.rsbcst = 100;
1478	}
1479	else if (has_prefix("rmbcmt", sub_param)) {
1480	    auip->init.util.rmbcmt = get_amount_value(sub_param + 6, argv, ip);
1481	    if (auip->init.util.rmbcmt > 100)
1482		auip->init.util.rmbcmt = 100;
1483	}
1484	else if (has_prefix("ramv", sub_param)) {
1485	    auip->init.util.ramv = get_bool_value(sub_param + 4, argv, ip);
1486	}
1487	else
1488	    goto bad_switch;
1489	break;
1490    case 's':
1491	if(has_prefix("sbct", sub_param)) {
1492	    auip->init.util.sbct = get_kb_value(sub_param + 4, argv, ip);
1493	}
1494	else if (has_prefix("smbcs", sub_param)) {
1495	    auip->default_.smbcs = 0;
1496	    auip->init.util.smbcs = get_kb_value(sub_param + 5, argv, ip);
1497	}
1498	else
1499	    goto bad_switch;
1500	break;
1501    case 't': {
1502	int res = get_bool_value(sub_param+1, argv, ip);
1503	if (res > 0) {
1504	    if (!auip->thr_spec_allowed) {
1505		if (!u_switch)
1506                    bad_value(param, sub_param + 1, "true");
1507		else
1508		    ASSERT(!auip->thr_spec); /* ignore */
1509	    }
1510	    else
1511		auip->thr_spec = 1;
1512	    break;
1513	}
1514	else if (res == 0) {
1515	    auip->thr_spec = 0;
1516	    auip->init.util.acul = 0;
1517	    break;
1518	}
1519	goto bad_switch;
1520    }
1521    default:
1522    bad_switch:
1523	bad_param(param, sub_param);
1524    }
1525}
1526
1527static void
1528handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
1529{
1530    struct au_init *aui[] = {
1531	&init->binary_alloc,
1532	&init->std_alloc,
1533	&init->ets_alloc,
1534	&init->eheap_alloc,
1535	&init->ll_alloc,
1536	&init->driver_alloc,
1537	&init->fix_alloc,
1538	&init->sl_alloc
1539	/* test_alloc not affected by +Mea??? or +Mu???  */
1540    };
1541    int aui_sz = (int) sizeof(aui)/sizeof(aui[0]);
1542    char *arg;
1543    char *rest;
1544    int i, j;
1545
1546    i = 1;
1547
1548    ASSERT(argc && argv && init);
1549
1550    while (i < *argc) {
1551	if(argv[i][0] == '-') {
1552	    char *param = argv[i]+1;
1553	    switch (argv[i][1]) {
1554	    case 'M':
1555		switch (argv[i][2]) {
1556		case 'B':
1557		    handle_au_arg(&init->binary_alloc, &argv[i][3], argv, &i, 0);
1558		    break;
1559                case 'I':
1560                    if (has_prefix("scs", argv[i]+3)) {
1561#if HAVE_ERTS_MSEG
1562			init->mseg.literal_mmap.scs =
1563#endif
1564			    get_mb_value(argv[i]+6, argv, &i);
1565		    }
1566                    else
1567                        handle_au_arg(&init->literal_alloc, &argv[i][3], argv, &i, 0);
1568		    break;
1569                case 'X':
1570                    if (has_prefix("scs", argv[i]+3)) {
1571                        /* Ignore obsolete */
1572                        (void) get_mb_value(argv[i]+6, argv, &i);
1573                    }
1574                    else
1575                        handle_au_arg(&init->exec_alloc, &argv[i][3], argv, &i, 0);
1576                    break;
1577		case 'D':
1578		    handle_au_arg(&init->std_alloc, &argv[i][3], argv, &i, 0);
1579		    break;
1580		case 'E':
1581		    handle_au_arg(&init->ets_alloc, &argv[i][3], argv, &i, 0);
1582		    break;
1583		case 'F':
1584		    handle_au_arg(&init->fix_alloc, &argv[i][3], argv, &i, 0);
1585		    break;
1586		case 'H':
1587		    handle_au_arg(&init->eheap_alloc, &argv[i][3], argv, &i, 0);
1588		    break;
1589		case 'L':
1590		    handle_au_arg(&init->ll_alloc, &argv[i][3], argv, &i, 0);
1591		    break;
1592		case 'M':
1593		    if (has_prefix("amcbf", argv[i]+3)) {
1594#if HAVE_ERTS_MSEG
1595			init->mseg.amcbf =
1596#endif
1597			    get_kb_value(argv[i]+8, argv, &i);
1598		    }
1599		    else if (has_prefix("rmcbf", argv[i]+3)) {
1600#if HAVE_ERTS_MSEG
1601			init->mseg.rmcbf =
1602#endif
1603			    get_amount_value(argv[i]+8, argv, &i);
1604		    }
1605		    else if (has_prefix("mcs", argv[i]+3)) {
1606#if HAVE_ERTS_MSEG
1607			init->mseg.mcs =
1608#endif
1609			    get_amount_value(argv[i]+6, argv, &i);
1610		    }
1611		    else if (has_prefix("scs", argv[i]+3)) {
1612#if HAVE_ERTS_MSEG
1613			init->mseg.dflt_mmap.scs =
1614#endif
1615			    get_mb_value(argv[i]+6, argv, &i);
1616		    }
1617		    else if (has_prefix("sco", argv[i]+3)) {
1618#if HAVE_ERTS_MSEG
1619			init->mseg.dflt_mmap.sco =
1620#endif
1621			    get_bool_value(argv[i]+6, argv, &i);
1622		    }
1623		    else if (has_prefix("scrpm", argv[i]+3)) {
1624#if HAVE_ERTS_MSEG
1625			init->mseg.dflt_mmap.scrpm =
1626#endif
1627			    get_bool_value(argv[i]+8, argv, &i);
1628		    }
1629		    else if (has_prefix("scrfsd", argv[i]+3)) {
1630#if HAVE_ERTS_MSEG
1631			init->mseg.dflt_mmap.scrfsd =
1632#endif
1633			    get_amount_value(argv[i]+9, argv, &i);
1634		    }
1635		    else {
1636			bad_param(param, param+2);
1637		    }
1638		    break;
1639		case 'R':
1640		    handle_au_arg(&init->driver_alloc, &argv[i][3], argv, &i, 0);
1641		    break;
1642		case 'S':
1643		    handle_au_arg(&init->sl_alloc, &argv[i][3], argv, &i, 0);
1644		    break;
1645		case 'T':
1646		    handle_au_arg(&init->temp_alloc, &argv[i][3], argv, &i, 0);
1647		    break;
1648		case 'Z':
1649		    handle_au_arg(&init->test_alloc, &argv[i][3], argv, &i, 0);
1650		    break;
1651		case 'Y': { /* sys_alloc */
1652		    if (has_prefix("tt", param+2)) {
1653			/* set trim threshold */
1654			arg = get_value(param+4, argv, &i);
1655			errno = 0;
1656			init->trim_threshold = (int) strtol(arg, &rest, 10);
1657			if (errno != 0
1658			    || rest == arg
1659			    || init->trim_threshold < 0
1660			    || (INT_MAX/1024) < init->trim_threshold) {
1661			    bad_value(param, param+4, arg);
1662			}
1663			VERBOSE(DEBUG_SYSTEM,
1664                                ("using trim threshold: %d\n",
1665                                 init->trim_threshold));
1666			init->trim_threshold *= 1024;
1667		    }
1668		    else if (has_prefix("tp", param+2)) {
1669			/* set top pad */
1670			arg = get_value(param+4, argv, &i);
1671			errno = 0;
1672			init->top_pad = (int) strtol(arg, &rest, 10);
1673			if (errno != 0
1674			    || rest == arg
1675			    || init->top_pad < 0
1676			    || (INT_MAX/1024) < init->top_pad) {
1677			    bad_value(param, param+4, arg);
1678			}
1679			VERBOSE(DEBUG_SYSTEM,
1680                                ("using top pad: %d\n",init->top_pad));
1681			init->top_pad *= 1024;
1682		    }
1683		    else if (has_prefix("m", param+2)) {
1684			/* Has been handled by erlexec */
1685			(void) get_value(param+3, argv, &i);
1686		    }
1687		    else if (has_prefix("e", param+2)) {
1688			arg = get_value(param+3, argv, &i);
1689			if (sys_strcmp("true", arg) != 0)
1690			    bad_value(param, param+3, arg);
1691		    }
1692		    else
1693			bad_param(param, param+2);
1694		    break;
1695		}
1696		case 'e':
1697		    switch (argv[i][3]) {
1698		    case 'a': {
1699			int a;
1700			arg = get_value(argv[i]+4, argv, &i);
1701			if (sys_strcmp("min", arg) == 0) {
1702			    for (a = 0; a < aui_sz; a++)
1703				aui[a]->enable = 0;
1704			}
1705			else if (sys_strcmp("max", arg) == 0) {
1706			    for (a = 0; a < aui_sz; a++)
1707				aui[a]->enable = 1;
1708			}
1709			else if (sys_strcmp("config", arg) == 0) {
1710			    init->erts_alloc_config = 1;
1711			}
1712			else if (sys_strcmp("r9c", arg) == 0
1713				 || sys_strcmp("r10b", arg) == 0
1714				 || sys_strcmp("r11b", arg) == 0) {
1715			    set_default_sl_alloc_opts(&init->sl_alloc);
1716			    set_default_std_alloc_opts(&init->std_alloc);
1717			    set_default_ll_alloc_opts(&init->ll_alloc);
1718			    set_default_temp_alloc_opts(&init->temp_alloc);
1719			    set_default_eheap_alloc_opts(&init->eheap_alloc);
1720			    set_default_binary_alloc_opts(&init->binary_alloc);
1721			    set_default_ets_alloc_opts(&init->ets_alloc);
1722			    set_default_driver_alloc_opts(&init->driver

Large files files are truncated, but you can click here to view the full file