PageRenderTime 213ms CodeModel.GetById 10ms app.highlight 164ms RepoModel.GetById 15ms app.codeStats 1ms

/erts/emulator/beam/erl_alloc.c

http://github.com/mfoemmel/erlang-otp
C | 3157 lines | 2717 code | 358 blank | 82 comment | 473 complexity | cff6ee5a5ff97ab66693758e2ce40916 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-2009. All Rights Reserved.
   5 * 
   6 * The contents of this file are subject to the Erlang Public License,
   7 * Version 1.1, (the "License"); you may not use this file except in
   8 * compliance with the License. You should have received a copy of the
   9 * Erlang Public License along with this software. If not, it can be
  10 * retrieved online at http://www.erlang.org/.
  11 * 
  12 * Software distributed under the License is distributed on an "AS IS"
  13 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  14 * the License for the specific language governing rights and limitations
  15 * under the License.
  16 * 
  17 * %CopyrightEnd%
  18 */
  19
  20
  21/*
  22 * Description:	Management of memory allocators.
  23 *
  24 * Author: 	Rickard Green
  25 */
  26
  27#ifdef HAVE_CONFIG_H
  28#  include "config.h"
  29#endif
  30#define ERTS_ALLOC_C__
  31#define ERTS_ALC_INTERNAL__
  32#include "sys.h"
  33#define ERL_THREADS_EMU_INTERNAL__
  34#include "erl_threads.h"
  35#include "global.h"
  36#include "erl_db.h"
  37#include "erl_binary.h"
  38#include "erl_bits.h"
  39#include "erl_instrument.h"
  40#include "erl_mseg.h"
  41#ifdef ELIB_ALLOC_IS_CLIB
  42#include "erl_version.h"
  43#endif
  44#include "erl_monitors.h"
  45#include "erl_bif_timer.h"
  46#if defined(ERTS_ALC_T_DRV_SEL_D_STATE) || defined(ERTS_ALC_T_DRV_EV_D_STATE)
  47#include "erl_check_io.h"
  48#endif
  49
  50#define GET_ERL_GF_ALLOC_IMPL
  51#include "erl_goodfit_alloc.h"
  52#define GET_ERL_BF_ALLOC_IMPL
  53#include "erl_bestfit_alloc.h"
  54#define GET_ERL_AF_ALLOC_IMPL
  55#include "erl_afit_alloc.h"
  56
  57#define ERTS_ALC_DEFAULT_MAX_THR_PREF 16
  58
  59#if defined(SMALL_MEMORY) || defined(PURIFY) || defined(VALGRIND)
  60#define AU_ALLOC_DEFAULT_ENABLE(X)	0
  61#else
  62#define AU_ALLOC_DEFAULT_ENABLE(X)	(X)
  63#endif
  64
  65#ifdef DEBUG
  66static Uint install_debug_functions(void);
  67#endif
  68extern void elib_ensure_initialized(void);
  69
  70ErtsAllocatorFunctions_t erts_allctrs[ERTS_ALC_A_MAX+1];
  71ErtsAllocatorInfo_t erts_allctrs_info[ERTS_ALC_A_MAX+1];
  72ErtsAllocatorThrSpec_t erts_allctr_thr_spec[ERTS_ALC_A_MAX+1];
  73
  74#define ERTS_MIN(A, B) ((A) < (B) ? (A) : (B))
  75#define ERTS_MAX(A, B) ((A) > (B) ? (A) : (B))
  76
  77typedef union {
  78    GFAllctr_t gfa;
  79    char align_gfa[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(GFAllctr_t))];
  80    BFAllctr_t bfa;
  81    char align_bfa[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(BFAllctr_t))];
  82    AFAllctr_t afa;
  83    char align_afa[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(AFAllctr_t))];
  84} ErtsAllocatorState_t;
  85
  86static ErtsAllocatorState_t sl_alloc_state;
  87static ErtsAllocatorState_t std_alloc_state;
  88static ErtsAllocatorState_t ll_alloc_state;
  89static ErtsAllocatorState_t temp_alloc_state;
  90static ErtsAllocatorState_t eheap_alloc_state;
  91static ErtsAllocatorState_t binary_alloc_state;
  92static ErtsAllocatorState_t ets_alloc_state;
  93static ErtsAllocatorState_t driver_alloc_state;
  94
  95ErtsAlcType_t erts_fix_core_allocator_ix;
  96#ifdef ERTS_ALC_N_MIN_A_FIXED_SIZE
  97static void *(*fix_core_allocator)(ErtsAlcType_t, void *, Uint);
  98static void *fix_core_extra;
  99static void *fix_core_alloc(Uint size)
 100{
 101    void *res;
 102    res = (*fix_core_allocator)(ERTS_ALC_T_UNDEF, fix_core_extra, size);
 103    if (erts_mtrace_enabled)
 104	erts_mtrace_crr_alloc(res,
 105			      ERTS_ALC_A_FIXED_SIZE,
 106			      erts_fix_core_allocator_ix,
 107			      size);
 108    return res;
 109}
 110#endif
 111
 112enum allctr_type {
 113    GOODFIT,
 114    BESTFIT,
 115    AFIT
 116};
 117
 118struct au_init {
 119    int enable;
 120    int thr_spec;
 121    enum allctr_type	atype;
 122    struct {
 123	AllctrInit_t	util;
 124	GFAllctrInit_t	gf;
 125	BFAllctrInit_t	bf;
 126	AFAllctrInit_t	af;
 127    } init;
 128    struct {
 129	int mmbcs;
 130	int lmbcs;
 131	int smbcs;
 132	int mmmbc;
 133    } default_;
 134};
 135
 136#define DEFAULT_ALLCTR_INIT {		\
 137    ERTS_DEFAULT_ALLCTR_INIT,		\
 138    ERTS_DEFAULT_GF_ALLCTR_INIT,	\
 139    ERTS_DEFAULT_BF_ALLCTR_INIT,	\
 140    ERTS_DEFAULT_AF_ALLCTR_INIT		\
 141}
 142
 143typedef struct {
 144    int erts_alloc_config;
 145#if HAVE_ERTS_MSEG
 146    ErtsMsegInit_t mseg;
 147#endif
 148    int trim_threshold;
 149    int top_pad;
 150    AlcUInit_t alloc_util;
 151    struct {
 152	int stat;
 153	int map;
 154	char *mtrace;
 155	char *nodename;
 156    } instr;
 157    struct au_init sl_alloc;
 158    struct au_init std_alloc;
 159    struct au_init ll_alloc;
 160    struct au_init temp_alloc;
 161    struct au_init eheap_alloc;
 162    struct au_init binary_alloc;
 163    struct au_init ets_alloc;
 164    struct au_init driver_alloc;
 165} erts_alc_hndl_args_init_t;
 166
 167#define ERTS_AU_INIT__ {0, 0, GOODFIT, DEFAULT_ALLCTR_INIT, {1,1,1,1}}
 168
 169#define SET_DEFAULT_ALLOC_OPTS(IP)					\
 170do {									\
 171    struct au_init aui__ = ERTS_AU_INIT__;				\
 172    sys_memcpy((void *) (IP), (void *) &aui__, sizeof(struct au_init));	\
 173} while (0)
 174
 175static void
 176set_default_sl_alloc_opts(struct au_init *ip)
 177{
 178    SET_DEFAULT_ALLOC_OPTS(ip);
 179    ip->enable			= AU_ALLOC_DEFAULT_ENABLE(1);
 180    ip->thr_spec		= 1;
 181    ip->atype			= GOODFIT;
 182    ip->init.util.name_prefix	= "sl_";
 183    ip->init.util.mmmbc		= 5;
 184    ip->init.util.alloc_no	= ERTS_ALC_A_SHORT_LIVED;
 185#ifndef SMALL_MEMORY
 186    ip->init.util.mmbcs 	= 128*1024; /* Main carrier size */
 187#else
 188    ip->init.util.mmbcs 	= 32*1024; /* Main carrier size */
 189#endif
 190    ip->init.util.ts 		= ERTS_ALC_MTA_SHORT_LIVED;
 191    ip->init.util.rsbcst	= 80;
 192}
 193
 194static void
 195set_default_std_alloc_opts(struct au_init *ip)
 196{
 197    SET_DEFAULT_ALLOC_OPTS(ip);
 198    ip->enable			= AU_ALLOC_DEFAULT_ENABLE(1);
 199    ip->thr_spec		= 1;
 200    ip->atype			= BESTFIT;
 201    ip->init.util.name_prefix	= "std_";
 202    ip->init.util.mmmbc		= 5;
 203    ip->init.util.alloc_no	= ERTS_ALC_A_STANDARD;
 204#ifndef SMALL_MEMORY
 205    ip->init.util.mmbcs 	= 128*1024; /* Main carrier size */
 206#else
 207    ip->init.util.mmbcs 	= 32*1024; /* Main carrier size */
 208#endif
 209    ip->init.util.ts 		= ERTS_ALC_MTA_STANDARD;
 210}
 211
 212static void
 213set_default_ll_alloc_opts(struct au_init *ip)
 214{
 215    SET_DEFAULT_ALLOC_OPTS(ip);
 216    ip->enable			= AU_ALLOC_DEFAULT_ENABLE(1);
 217    ip->thr_spec		= 0;
 218    ip->atype			= BESTFIT;
 219    ip->init.bf.ao		= 1;
 220    ip->init.util.ramv		= 0;
 221    ip->init.util.mmsbc		= 0;
 222    ip->init.util.mmmbc		= 0;
 223    ip->init.util.sbct		= ~((Uint) 0);
 224    ip->init.util.name_prefix	= "ll_";
 225    ip->init.util.alloc_no	= ERTS_ALC_A_LONG_LIVED;
 226#ifndef SMALL_MEMORY
 227    ip->init.util.mmbcs 	= 2*1024*1024; /* Main carrier size */
 228#else
 229    ip->init.util.mmbcs 	= 1*1024*1024; /* Main carrier size */
 230#endif
 231    ip->init.util.ts 		= ERTS_ALC_MTA_LONG_LIVED;
 232    ip->init.util.asbcst	= 0;
 233    ip->init.util.rsbcst	= 0;
 234    ip->init.util.rsbcmt	= 0;
 235    ip->init.util.rmbcmt	= 0;
 236}
 237
 238static void
 239set_default_temp_alloc_opts(struct au_init *ip)
 240{
 241    SET_DEFAULT_ALLOC_OPTS(ip);
 242    ip->enable			= AU_ALLOC_DEFAULT_ENABLE(1);
 243    ip->thr_spec		= 1;
 244    ip->atype			= AFIT;
 245    ip->init.util.name_prefix	= "temp_";
 246    ip->init.util.alloc_no	= ERTS_ALC_A_TEMPORARY;
 247#ifndef SMALL_MEMORY
 248    ip->init.util.mmbcs 	= 128*1024; /* Main carrier size */
 249#else
 250    ip->init.util.mmbcs 	= 32*1024; /* Main carrier size */
 251#endif
 252    ip->init.util.ts 		= ERTS_ALC_MTA_TEMPORARY;
 253    ip->init.util.rsbcst	= 90;
 254    ip->init.util.rmbcmt	= 100;
 255}
 256
 257static void
 258set_default_eheap_alloc_opts(struct au_init *ip)
 259{
 260    SET_DEFAULT_ALLOC_OPTS(ip);
 261    ip->enable			= AU_ALLOC_DEFAULT_ENABLE(1);
 262    ip->thr_spec		= 1;
 263    ip->atype			= GOODFIT;
 264    ip->init.util.mmmbc		= 100;
 265    ip->init.util.name_prefix	= "eheap_";
 266    ip->init.util.alloc_no	= ERTS_ALC_A_EHEAP;
 267#ifndef SMALL_MEMORY
 268    ip->init.util.mmbcs 	= 512*1024; /* Main carrier size */
 269#else
 270    ip->init.util.mmbcs 	= 256*1024; /* Main carrier size */
 271#endif
 272    ip->init.util.ts 		= ERTS_ALC_MTA_EHEAP;
 273    ip->init.util.rsbcst	= 50;
 274}
 275
 276static void
 277set_default_binary_alloc_opts(struct au_init *ip)
 278{
 279    SET_DEFAULT_ALLOC_OPTS(ip);
 280    ip->enable			= AU_ALLOC_DEFAULT_ENABLE(1);
 281    ip->thr_spec		= 1;
 282    ip->atype			= BESTFIT;
 283    ip->init.util.mmmbc		= 50;
 284    ip->init.util.name_prefix	= "binary_";
 285    ip->init.util.alloc_no	= ERTS_ALC_A_BINARY;
 286#ifndef SMALL_MEMORY
 287    ip->init.util.mmbcs 	= 128*1024; /* Main carrier size */
 288#else
 289    ip->init.util.mmbcs 	= 32*1024; /* Main carrier size */
 290#endif
 291    ip->init.util.ts 		= ERTS_ALC_MTA_BINARY;
 292}
 293
 294static void
 295set_default_ets_alloc_opts(struct au_init *ip)
 296{
 297    SET_DEFAULT_ALLOC_OPTS(ip);
 298    ip->enable			= AU_ALLOC_DEFAULT_ENABLE(1);
 299    ip->thr_spec		= 1;
 300    ip->atype			= BESTFIT;
 301    ip->init.util.mmmbc		= 100;
 302    ip->init.util.name_prefix	= "ets_";
 303    ip->init.util.alloc_no	= ERTS_ALC_A_ETS;
 304#ifndef SMALL_MEMORY
 305    ip->init.util.mmbcs 	= 128*1024; /* Main carrier size */
 306#else
 307    ip->init.util.mmbcs 	= 32*1024; /* Main carrier size */
 308#endif
 309    ip->init.util.ts 		= ERTS_ALC_MTA_ETS;
 310}
 311
 312static void
 313set_default_driver_alloc_opts(struct au_init *ip)
 314{
 315    SET_DEFAULT_ALLOC_OPTS(ip);
 316    ip->enable			= AU_ALLOC_DEFAULT_ENABLE(1);
 317    ip->thr_spec		= 1;
 318    ip->atype			= BESTFIT;
 319    ip->init.util.name_prefix	= "driver_";
 320    ip->init.util.alloc_no	= ERTS_ALC_A_DRIVER;
 321#ifndef SMALL_MEMORY
 322    ip->init.util.mmbcs 	= 128*1024; /* Main carrier size */
 323#else
 324    ip->init.util.mmbcs 	= 32*1024; /* Main carrier size */
 325#endif
 326    ip->init.util.ts 		= ERTS_ALC_MTA_DRIVER;
 327}
 328
 329#ifdef ERTS_SMP
 330
 331static void
 332adjust_tpref(struct au_init *ip, int no_sched)
 333{
 334    if (ip->thr_spec) {
 335	Uint allocs;
 336	if (ip->thr_spec < 0) {/* User specified amount */
 337	    allocs = abs(ip->thr_spec);
 338	    if (allocs > no_sched)
 339		allocs = no_sched;
 340	}
 341	else if (no_sched > ERTS_ALC_DEFAULT_MAX_THR_PREF)
 342	    allocs = ERTS_ALC_DEFAULT_MAX_THR_PREF;
 343	else 
 344	    allocs = no_sched;
 345	if (allocs <= 1)
 346	    ip->thr_spec = 0;
 347	else {
 348	    ip->thr_spec = (int) allocs;
 349	    ip->thr_spec *= -1; /* thread preferred */
 350
 351	    /* If default ... */
 352
 353	    /* ... shrink main multi-block carrier size */
 354	    if (ip->default_.mmbcs)
 355		ip->init.util.mmbcs /= ERTS_MIN(4, allocs);
 356	    /* ... shrink largest multi-block carrier size */
 357	    if (ip->default_.lmbcs)
 358		ip->init.util.lmbcs /= ERTS_MIN(2, allocs);
 359	    /* ... shrink smallest multi-block carrier size */
 360	    if (ip->default_.smbcs)
 361		ip->init.util.smbcs /= ERTS_MIN(4, allocs);
 362	    /* ... and more than three allocators shrink
 363	       max mseg multi-block carriers */
 364	    if (ip->default_.mmmbc && allocs > 2) {
 365		ip->init.util.mmmbc /= ERTS_MIN(4, allocs - 1);
 366		if (ip->init.util.mmmbc < 3)
 367		    ip->init.util.mmmbc = 3;
 368	    }
 369	}
 370    }
 371}
 372
 373#endif
 374
 375static void handle_args(int *, char **, erts_alc_hndl_args_init_t *);
 376
 377static void
 378set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init);
 379
 380static void
 381start_au_allocator(ErtsAlcType_t alctr_n,
 382		   struct au_init *init,
 383		   ErtsAllocatorState_t *state);
 384
 385static void
 386refuse_af_strategy(struct au_init *init)
 387{
 388    if (init->atype == AFIT)
 389	init->atype = GOODFIT;
 390}
 391
 392static void init_thr_ix(int static_ixs);
 393
 394void
 395erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop)
 396{
 397    Uint extra_block_size = 0;
 398    int i;
 399    erts_alc_hndl_args_init_t init = {
 400	0,
 401#if HAVE_ERTS_MSEG
 402	ERTS_MSEG_INIT_DEFAULT_INITIALIZER,
 403#endif
 404	ERTS_DEFAULT_TRIM_THRESHOLD,
 405	ERTS_DEFAULT_TOP_PAD,
 406	ERTS_DEFAULT_ALCU_INIT
 407    };
 408
 409    erts_sys_alloc_init();
 410    init_thr_ix(erts_no_schedulers);
 411    erts_init_utils_mem();
 412
 413    set_default_sl_alloc_opts(&init.sl_alloc);
 414    set_default_std_alloc_opts(&init.std_alloc);
 415    set_default_ll_alloc_opts(&init.ll_alloc);
 416    set_default_temp_alloc_opts(&init.temp_alloc);
 417    set_default_eheap_alloc_opts(&init.eheap_alloc);
 418    set_default_binary_alloc_opts(&init.binary_alloc);
 419    set_default_ets_alloc_opts(&init.ets_alloc);
 420    set_default_driver_alloc_opts(&init.driver_alloc);
 421
 422    if (argc && argv)
 423	handle_args(argc, argv, &init);
 424
 425    if (erts_no_schedulers <= 1) {
 426	init.sl_alloc.thr_spec = 0;
 427	init.std_alloc.thr_spec = 0;
 428	init.ll_alloc.thr_spec = 0;
 429	init.eheap_alloc.thr_spec = 0;
 430	init.binary_alloc.thr_spec = 0;
 431	init.ets_alloc.thr_spec = 0;
 432	init.driver_alloc.thr_spec = 0;
 433    }
 434
 435    if (init.erts_alloc_config) {
 436	/* Adjust flags that erts_alloc_config won't like */
 437	init.temp_alloc.thr_spec = 0;
 438	init.sl_alloc.thr_spec = 0;
 439	init.std_alloc.thr_spec = 0;
 440	init.ll_alloc.thr_spec = 0;
 441	init.eheap_alloc.thr_spec = 0;
 442	init.binary_alloc.thr_spec = 0;
 443	init.ets_alloc.thr_spec = 0;
 444	init.driver_alloc.thr_spec = 0;
 445    }
 446
 447#ifdef ERTS_SMP
 448    /* Only temp_alloc can use thread specific interface */
 449    if (init.temp_alloc.thr_spec)
 450	init.temp_alloc.thr_spec = erts_no_schedulers;
 451
 452    /* Others must use thread preferred interface */
 453    adjust_tpref(&init.sl_alloc, erts_no_schedulers);
 454    adjust_tpref(&init.std_alloc, erts_no_schedulers);
 455    adjust_tpref(&init.ll_alloc, erts_no_schedulers);
 456    adjust_tpref(&init.eheap_alloc, erts_no_schedulers);
 457    adjust_tpref(&init.binary_alloc, erts_no_schedulers);
 458    adjust_tpref(&init.ets_alloc, erts_no_schedulers);
 459    adjust_tpref(&init.driver_alloc, erts_no_schedulers);
 460
 461#else
 462    /* No thread specific if not smp */
 463    init.temp_alloc.thr_spec = 0;
 464#endif
 465
 466    /*
 467     * The following allocators cannot be run with afit strategy.
 468     * Make sure they don't...
 469     */
 470    refuse_af_strategy(&init.sl_alloc);
 471    refuse_af_strategy(&init.std_alloc);
 472    refuse_af_strategy(&init.ll_alloc);
 473    refuse_af_strategy(&init.eheap_alloc);
 474    refuse_af_strategy(&init.binary_alloc);
 475    refuse_af_strategy(&init.ets_alloc);
 476    refuse_af_strategy(&init.driver_alloc);
 477
 478#ifdef ERTS_SMP 
 479    if (!init.temp_alloc.thr_spec)
 480	refuse_af_strategy(&init.temp_alloc);
 481#endif
 482
 483    erts_mtrace_pre_init();
 484#if HAVE_ERTS_MSEG
 485    erts_mseg_init(&init.mseg);
 486#endif
 487    erts_alcu_init(&init.alloc_util);
 488    erts_afalc_init();
 489    erts_bfalc_init();
 490    erts_gfalc_init();
 491
 492    for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {
 493	erts_allctrs[i].alloc		= NULL;
 494	erts_allctrs[i].realloc		= NULL;
 495	erts_allctrs[i].free		= NULL;
 496	erts_allctrs[i].extra		= NULL;
 497	erts_allctrs_info[i].alloc_util	= 0;
 498	erts_allctrs_info[i].enabled	= 0;
 499	erts_allctrs_info[i].thr_spec	= 0;
 500	erts_allctrs_info[i].extra	= NULL;
 501    }
 502
 503#ifdef ERTS_ALC_N_MIN_A_FIXED_SIZE
 504#if !defined(PURIFY) && !defined(VALGRIND)
 505    erts_allctrs[ERTS_ALC_A_FIXED_SIZE].alloc		= erts_fix_alloc;
 506    erts_allctrs[ERTS_ALC_A_FIXED_SIZE].realloc		= erts_fix_realloc;
 507    erts_allctrs[ERTS_ALC_A_FIXED_SIZE].free		= erts_fix_free;
 508    erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].enabled	= 1;
 509#else
 510    erts_allctrs[ERTS_ALC_A_FIXED_SIZE].alloc		= erts_sys_alloc;
 511    erts_allctrs[ERTS_ALC_A_FIXED_SIZE].realloc		= erts_sys_realloc;
 512    erts_allctrs[ERTS_ALC_A_FIXED_SIZE].free		= erts_sys_free;
 513    erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].enabled	= 0;
 514#endif
 515#endif
 516
 517    erts_allctrs[ERTS_ALC_A_SYSTEM].alloc		= erts_sys_alloc;
 518    erts_allctrs[ERTS_ALC_A_SYSTEM].realloc		= erts_sys_realloc;
 519    erts_allctrs[ERTS_ALC_A_SYSTEM].free		= erts_sys_free;
 520    erts_allctrs_info[ERTS_ALC_A_SYSTEM].enabled	= 1;
 521
 522    set_au_allocator(ERTS_ALC_A_TEMPORARY, &init.temp_alloc);
 523    set_au_allocator(ERTS_ALC_A_SHORT_LIVED, &init.sl_alloc);
 524    set_au_allocator(ERTS_ALC_A_STANDARD, &init.std_alloc);
 525    set_au_allocator(ERTS_ALC_A_LONG_LIVED, &init.ll_alloc);
 526    set_au_allocator(ERTS_ALC_A_EHEAP, &init.eheap_alloc);
 527    set_au_allocator(ERTS_ALC_A_BINARY, &init.binary_alloc);
 528    set_au_allocator(ERTS_ALC_A_ETS, &init.ets_alloc);
 529    set_au_allocator(ERTS_ALC_A_DRIVER, &init.driver_alloc);
 530
 531    for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {
 532	if (!erts_allctrs[i].alloc)
 533	    erl_exit(ERTS_ABORT_EXIT,
 534		     "Missing alloc function for %s\n", ERTS_ALC_A2AD(i));
 535	if (!erts_allctrs[i].realloc)
 536	    erl_exit(ERTS_ABORT_EXIT,
 537		     "Missing realloc function for %s\n", ERTS_ALC_A2AD(i));
 538	if (!erts_allctrs[i].free)
 539	    erl_exit(ERTS_ABORT_EXIT,
 540		     "Missing free function for %s\n", ERTS_ALC_A2AD(i));
 541    }
 542
 543    sys_alloc_opt(SYS_ALLOC_OPT_TRIM_THRESHOLD, init.trim_threshold);
 544    sys_alloc_opt(SYS_ALLOC_OPT_TOP_PAD, init.top_pad);
 545
 546    if (erts_allctrs_info[ERTS_FIX_CORE_ALLOCATOR].enabled)
 547	erts_fix_core_allocator_ix = ERTS_FIX_CORE_ALLOCATOR;
 548    else
 549	erts_fix_core_allocator_ix = ERTS_ALC_A_SYSTEM;
 550
 551    erts_mtrace_init(init.instr.mtrace, init.instr.nodename);
 552
 553    start_au_allocator(ERTS_ALC_A_TEMPORARY,
 554		       &init.temp_alloc,
 555		       &temp_alloc_state);
 556
 557    start_au_allocator(ERTS_ALC_A_SHORT_LIVED,
 558		       &init.sl_alloc,
 559		       &sl_alloc_state);
 560
 561    start_au_allocator(ERTS_ALC_A_STANDARD,
 562		       &init.std_alloc,
 563		       &std_alloc_state);
 564
 565    start_au_allocator(ERTS_ALC_A_LONG_LIVED,
 566		       &init.ll_alloc,
 567		       &ll_alloc_state);
 568
 569    start_au_allocator(ERTS_ALC_A_EHEAP,
 570		       &init.eheap_alloc,
 571		       &eheap_alloc_state);
 572
 573    start_au_allocator(ERTS_ALC_A_BINARY,
 574		       &init.binary_alloc,
 575		       &binary_alloc_state);
 576
 577    start_au_allocator(ERTS_ALC_A_ETS,
 578		       &init.ets_alloc,
 579		       &ets_alloc_state);
 580
 581    start_au_allocator(ERTS_ALC_A_DRIVER,
 582		       &init.driver_alloc,
 583		       &driver_alloc_state);
 584
 585    fix_core_allocator	= erts_allctrs[erts_fix_core_allocator_ix].alloc;
 586    fix_core_extra	= erts_allctrs[erts_fix_core_allocator_ix].extra;
 587
 588    erts_mtrace_install_wrapper_functions();
 589    extra_block_size += erts_instr_init(init.instr.stat, init.instr.map);
 590
 591#ifdef DEBUG
 592    extra_block_size += install_debug_functions();
 593#endif
 594
 595#ifdef ERTS_ALC_N_MIN_A_FIXED_SIZE
 596
 597    erts_init_fix_alloc(extra_block_size, fix_core_alloc);
 598
 599
 600#if !defined(PURIFY) && !defined(VALGRIND)
 601    erts_set_fix_size(ERTS_ALC_T_PROC,		sizeof(Process));
 602    erts_set_fix_size(ERTS_ALC_T_DB_TABLE,	sizeof(DbTable));
 603    erts_set_fix_size(ERTS_ALC_T_ATOM,		sizeof(Atom));
 604    erts_set_fix_size(ERTS_ALC_T_EXPORT,	sizeof(Export));
 605    erts_set_fix_size(ERTS_ALC_T_MODULE,	sizeof(Module));
 606    erts_set_fix_size(ERTS_ALC_T_REG_PROC,	sizeof(RegProc));
 607    erts_set_fix_size(ERTS_ALC_T_MONITOR_SH,	ERTS_MONITOR_SH_SIZE*sizeof(Uint));
 608    erts_set_fix_size(ERTS_ALC_T_NLINK_SH,	ERTS_LINK_SH_SIZE*sizeof(Uint));
 609    erts_set_fix_size(ERTS_ALC_T_FUN_ENTRY,	sizeof(ErlFunEntry));
 610#ifdef ERTS_ALC_T_DRV_EV_D_STATE
 611    erts_set_fix_size(ERTS_ALC_T_DRV_EV_D_STATE,
 612		      sizeof(ErtsDrvEventDataState));
 613#endif
 614#ifdef ERTS_ALC_T_DRV_SEL_D_STATE
 615    erts_set_fix_size(ERTS_ALC_T_DRV_SEL_D_STATE,
 616		      sizeof(ErtsDrvSelectDataState));
 617#endif
 618#endif
 619#endif
 620
 621}
 622
 623static void
 624set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init)
 625{
 626    ErtsAllocatorFunctions_t *af = &erts_allctrs[alctr_n];
 627    ErtsAllocatorInfo_t *ai = &erts_allctrs_info[alctr_n];
 628    ErtsAllocatorThrSpec_t *tspec = &erts_allctr_thr_spec[alctr_n];
 629
 630    if (!init->enable) {
 631	af->alloc = erts_sys_alloc;
 632	af->realloc = erts_sys_realloc;
 633	af->free = erts_sys_free;
 634	af->extra = NULL;
 635	ai->alloc_util = 0;
 636	ai->enabled = 0;
 637	ai->extra = NULL;
 638	return;
 639    }
 640
 641    tspec->enabled = 0;
 642    tspec->all_thr_safe = 0;
 643    ai->thr_spec = 0;
 644#ifdef USE_THREADS
 645    if (init->thr_spec) {
 646	if (init->thr_spec > 0) {
 647	    af->alloc = erts_alcu_alloc_thr_spec;
 648	    if (init->init.util.ramv)
 649		af->realloc = erts_alcu_realloc_mv_thr_spec;
 650	    else
 651		af->realloc = erts_alcu_realloc_thr_spec;
 652	    af->free = erts_alcu_free_thr_spec;
 653	}
 654	else {
 655	    af->alloc = erts_alcu_alloc_thr_pref;
 656	    if (init->init.util.ramv)
 657		af->realloc = erts_alcu_realloc_mv_thr_pref;
 658	    else
 659		af->realloc = erts_alcu_realloc_thr_pref;
 660	    af->free = erts_alcu_free_thr_pref;
 661	    tspec->all_thr_safe = 1;
 662	}
 663
 664	tspec->enabled	= 1;
 665	tspec->size	= abs(init->thr_spec) + 1;
 666
 667	ai->thr_spec	= tspec->size;
 668    }
 669    else if (init->init.util.ts) {
 670	af->alloc = erts_alcu_alloc_ts;
 671	if (init->init.util.ramv)
 672	    af->realloc = erts_alcu_realloc_mv_ts;
 673	else
 674	    af->realloc = erts_alcu_realloc_ts;
 675	af->free = erts_alcu_free_ts;
 676    }
 677    else
 678#endif
 679    {
 680	af->alloc = erts_alcu_alloc;
 681	if (init->init.util.ramv)
 682	    af->realloc = erts_alcu_realloc_mv;
 683	else
 684	    af->realloc = erts_alcu_realloc;
 685	af->free = erts_alcu_free;
 686    }
 687    af->extra	= NULL;
 688    ai->alloc_util	= 1;
 689    ai->enabled		= 1;
 690}
 691
 692static void
 693start_au_allocator(ErtsAlcType_t alctr_n,
 694		   struct au_init *init,
 695		   ErtsAllocatorState_t *state)
 696{
 697    int i;
 698    int size = 1;
 699    void *as0;
 700    enum allctr_type atype;
 701    ErtsAllocatorFunctions_t *af = &erts_allctrs[alctr_n];
 702    ErtsAllocatorInfo_t *ai = &erts_allctrs_info[alctr_n];
 703    ErtsAllocatorThrSpec_t *tspec = &erts_allctr_thr_spec[alctr_n];
 704
 705    if (!init->enable)
 706	return;
 707
 708    if (init->thr_spec) {
 709	void *states = erts_sys_alloc(0,
 710				      NULL,
 711				      ((sizeof(Allctr_t *)
 712					* (tspec->size + 1))
 713				       + (sizeof(ErtsAllocatorState_t)
 714					  * tspec->size)
 715				       + ERTS_CACHE_LINE_SIZE - 1));
 716	if (!states)
 717	    erl_exit(ERTS_ABORT_EXIT,
 718		     "Failed to allocate allocator states for %salloc\n",
 719		     init->init.util.name_prefix);
 720	tspec->allctr = (Allctr_t **) states;
 721	states = ((char *) states) + sizeof(Allctr_t *) * (tspec->size + 1);
 722	states = ((((Uint) states) & ERTS_CACHE_LINE_MASK)
 723		  ? (void *) ((((Uint) states) & ~ERTS_CACHE_LINE_MASK)
 724			      + ERTS_CACHE_LINE_SIZE)
 725		  : (void *) states);
 726	tspec->allctr[0] = init->thr_spec > 0 ? (Allctr_t *) state : (Allctr_t *) NULL;
 727	size = tspec->size;
 728	for (i = 1; i < size; i++)
 729	    tspec->allctr[i] = (Allctr_t *)
 730		&((ErtsAllocatorState_t *) states)[i-1];
 731    }
 732
 733    for (i = 0; i < size; i++) {
 734	void *as;
 735	atype = init->atype;
 736
 737	if (!init->thr_spec)
 738	    as0 = state;
 739	else {
 740	    as0 = (void *) tspec->allctr[i];
 741	    if (!as0)
 742		continue;
 743	    if (i == 0) {
 744		if (atype == AFIT)
 745		    atype = GOODFIT;
 746		init->init.util.ts = 1;
 747	    }
 748	    else {
 749		if (init->thr_spec < 0) {
 750		    init->init.util.ts = 1;
 751		    init->init.util.tspec = 0;
 752		    init->init.util.tpref = -1*init->thr_spec;
 753		}
 754		else {
 755		    init->init.util.ts = 0;
 756		    init->init.util.tspec = init->thr_spec + 1;
 757		    init->init.util.tpref = 0;
 758		}   
 759	    }
 760	}
 761
 762	switch (atype) {
 763	case GOODFIT:
 764	    as = (void *) erts_gfalc_start((GFAllctr_t *) as0,
 765					   &init->init.gf,
 766					   &init->init.util);
 767	    break;
 768	case BESTFIT:
 769	    as = (void *) erts_bfalc_start((BFAllctr_t *) as0,
 770					   &init->init.bf,
 771					   &init->init.util);
 772	    break;
 773	case AFIT:
 774	    as = (void *) erts_afalc_start((AFAllctr_t *) as0,
 775					   &init->init.af,
 776					   &init->init.util);
 777	    break;
 778	default:
 779	    as = NULL;
 780	    ASSERT(0);
 781	}
 782
 783	if (!as)
 784	    erl_exit(ERTS_ABORT_EXIT,
 785		     "Failed to start %salloc\n", init->init.util.name_prefix);
 786
 787	ASSERT(as == (void *) as0);
 788	af->extra = as;
 789    }
 790
 791    if (init->thr_spec) {
 792	af->extra = tspec;
 793	init->init.util.ts = 1;
 794    }
 795
 796    ai->extra = af->extra;
 797}
 798
 799
 800static void bad_param(char *param_start, char *param_end)
 801{
 802    size_t len = param_end - param_start;
 803    char param[100];
 804    if (len > 99)
 805	len = 99;
 806    sys_memcpy((void *) param, (void *) param_start, len);
 807    param[len] = '\0';
 808    erts_fprintf(stderr, "bad \"%s\" parameter\n", param);
 809    erts_usage();
 810}
 811
 812static void bad_value(char *param_start, char *param_end, char *value)
 813{
 814    size_t len = param_end - param_start;
 815    char param[100];
 816    if (len > 99)
 817	len = 99;
 818    sys_memcpy((void *) param, (void *) param_start, len);
 819    param[len] = '\0';
 820    erts_fprintf(stderr, "bad \"%s\" value: %s\n", param, value);
 821    erts_usage();
 822}
 823
 824/* Get arg marks argument as handled by
 825   putting NULL in argv */
 826static char *
 827get_value(char* rest, char** argv, int* ip)
 828{
 829    char *param = argv[*ip]+1;
 830    argv[*ip] = NULL;
 831    if (*rest == '\0') {
 832	char *next = argv[*ip + 1];
 833	if (next[0] == '-'
 834	    && next[1] == '-'
 835	    &&  next[2] == '\0') {
 836	    bad_value(param, rest, "");
 837	}
 838	(*ip)++;
 839	argv[*ip] = NULL;
 840	return next;
 841    }
 842    return rest;
 843}
 844
 845static ERTS_INLINE int
 846has_prefix(const char *prefix, const char *string)
 847{
 848    int i;
 849    for (i = 0; prefix[i]; i++)
 850	if (prefix[i] != string[i])
 851	    return 0;
 852    return 1;
 853}
 854
 855static int
 856get_bool_value(char *param_end, char** argv, int* ip)
 857{
 858    char *param = argv[*ip]+1;
 859    char *value = get_value(param_end, argv, ip);
 860    if (strcmp(value, "true") == 0)
 861	return 1;
 862    else if (strcmp(value, "false") == 0)
 863	return 0;
 864    else
 865	bad_value(param, param_end, value);
 866    return -1;
 867}
 868
 869static Uint
 870get_kb_value(char *param_end, char** argv, int* ip)
 871{
 872    Sint tmp;
 873    Uint max = ((~((Uint) 0))/1024) + 1;
 874    char *rest;
 875    char *param = argv[*ip]+1;
 876    char *value = get_value(param_end, argv, ip);
 877    errno = 0;
 878    tmp = (Sint) strtol(value, &rest, 10);
 879    if (errno != 0 || rest == value || tmp < 0 || max < ((Uint) tmp))
 880	bad_value(param, param_end, value);
 881    if (max == (Uint) tmp)
 882	return ~((Uint) 0);
 883    else
 884	return ((Uint) tmp)*1024;
 885}
 886
 887static Uint
 888get_amount_value(char *param_end, char** argv, int* ip)
 889{
 890    Sint tmp;
 891    char *rest;
 892    char *param = argv[*ip]+1;
 893    char *value = get_value(param_end, argv, ip);
 894    errno = 0;
 895    tmp = (Sint) strtol(value, &rest, 10);
 896    if (errno != 0 || rest == value || tmp < 0)
 897	bad_value(param, param_end, value);
 898    return (Uint) tmp;
 899}
 900
 901static int
 902get_bool_or_possitive_amount_value(int *bool, Uint *amount,
 903				   char *param_end, char** argv, int* ip)
 904{
 905    char *param = argv[*ip]+1;
 906    char *value = get_value(param_end, argv, ip);
 907    if (strcmp(value, "true") == 0) {
 908	*bool = 1; 
 909	return 1;
 910    }
 911    else if (strcmp(value, "false") == 0) {
 912	*bool = 0; 
 913	return 1;
 914    }
 915    else {
 916	Sint tmp;
 917	char *rest;
 918	errno = 0;
 919	tmp = (Sint) strtol(value, &rest, 10);
 920	if (errno != 0 || rest == value || tmp <= 0) {
 921	    bad_value(param, param_end, value);
 922	    return -1;
 923	}
 924	*amount = (Uint) tmp;
 925	return 0;
 926    }
 927}
 928
 929static void
 930handle_au_arg(struct au_init *auip,
 931	      char* sub_param,
 932	      char** argv,
 933	      int* ip)
 934{
 935    char *param = argv[*ip]+1;
 936
 937    switch (sub_param[0]) {
 938    case 'a':
 939	if(has_prefix("asbcst", sub_param)) {
 940	    auip->init.util.asbcst = get_kb_value(sub_param + 6, argv, ip);
 941	}
 942	else if(has_prefix("as", sub_param)) {
 943	    char *alg = get_value(sub_param + 2, argv, ip);
 944	    if (strcmp("bf", alg) == 0) {
 945		auip->atype = BESTFIT;
 946		auip->init.bf.ao = 0;
 947	    }
 948	    else if (strcmp("aobf", alg) == 0) {
 949		auip->atype = BESTFIT;
 950		auip->init.bf.ao = 1;
 951	    }
 952	    else if (strcmp("gf", alg) == 0) {
 953		auip->atype = GOODFIT;
 954	    }
 955	    else if (strcmp("af", alg) == 0) {
 956		auip->atype = AFIT;
 957	    }
 958	    else {
 959		bad_value(param, sub_param + 1, alg);
 960	    }
 961	}
 962	else
 963	    goto bad_switch;
 964	break;
 965    case 'e':
 966	auip->enable = get_bool_value(sub_param+1, argv, ip);
 967	break;
 968    case 'l':
 969	if (has_prefix("lmbcs", sub_param)) {
 970	    auip->default_.lmbcs = 0;
 971	    auip->init.util.lmbcs = get_kb_value(sub_param + 5, argv, ip);
 972	}
 973	else
 974	    goto bad_switch;
 975	break;
 976    case 'm':
 977	if (has_prefix("mbcgs", sub_param)) {
 978	    auip->init.util.mbcgs = get_amount_value(sub_param + 5, argv, ip);
 979
 980	}
 981	else if (has_prefix("mbsd", sub_param)) {
 982	    auip->init.gf.mbsd = get_amount_value(sub_param + 4, argv, ip);
 983	    if (auip->init.gf.mbsd < 1)
 984		auip->init.gf.mbsd = 1;
 985	}
 986	else if (has_prefix("mmbcs", sub_param)) {
 987	    auip->default_.mmbcs = 0;
 988	    auip->init.util.mmbcs = get_kb_value(sub_param + 5, argv, ip);
 989	}
 990	else if (has_prefix("mmmbc", sub_param)) {
 991	    auip->default_.mmmbc = 0;
 992	    auip->init.util.mmmbc = get_amount_value(sub_param + 5, argv, ip);
 993	}
 994	else if (has_prefix("mmsbc", sub_param)) {
 995	    auip->init.util.mmsbc = get_amount_value(sub_param + 5, argv, ip);
 996	}
 997	else
 998	    goto bad_switch;
 999	break;
1000    case 'r':
1001	if(has_prefix("rsbcmt", sub_param)) {
1002	    auip->init.util.rsbcmt = get_amount_value(sub_param + 6, argv, ip);
1003	    if (auip->init.util.rsbcmt > 100)
1004		auip->init.util.rsbcmt = 100;
1005	}
1006	else if(has_prefix("rsbcst", sub_param)) {
1007	    auip->init.util.rsbcst = get_amount_value(sub_param + 6, argv, ip);
1008	    if (auip->init.util.rsbcst > 100)
1009		auip->init.util.rsbcst = 100;
1010	}
1011	else if (has_prefix("rmbcmt", sub_param)) {
1012	    auip->init.util.rmbcmt = get_amount_value(sub_param + 6, argv, ip);
1013	    if (auip->init.util.rmbcmt > 100)
1014		auip->init.util.rmbcmt = 100;
1015	}
1016	else if (has_prefix("ramv", sub_param)) {
1017	    auip->init.util.ramv = get_bool_value(sub_param + 4, argv, ip);
1018	}
1019	else
1020	    goto bad_switch;
1021	break;
1022    case 's':
1023	if(has_prefix("sbct", sub_param)) {
1024	    auip->init.util.sbct = get_kb_value(sub_param + 4, argv, ip);
1025	}
1026	else if (has_prefix("smbcs", sub_param)) {
1027	    auip->default_.smbcs = 0;
1028	    auip->init.util.smbcs = get_kb_value(sub_param + 5, argv, ip);
1029	}
1030	else
1031	    goto bad_switch;
1032	break;
1033    case 't': {
1034	Uint no;
1035	int enable;
1036	int res = get_bool_or_possitive_amount_value(&enable,
1037						     &no,
1038						     sub_param+1,
1039						     argv,
1040						     ip);
1041	if (res > 0)
1042	    auip->thr_spec = enable ? 1 : 0;
1043	else if (res == 0) {
1044	    int allocs = (int) no;
1045	    if (allocs < 0)
1046		allocs = INT_MIN;
1047	    else {
1048		allocs *= -1;
1049	    }
1050	    auip->thr_spec = allocs;
1051	}
1052	break;
1053    }
1054    default:
1055    bad_switch:
1056	bad_param(param, sub_param);
1057    }
1058}
1059
1060static void
1061handle_args(int *argc, char **argv, erts_alc_hndl_args_init_t *init)
1062{
1063    struct au_init *aui[] = {
1064	&init->binary_alloc,
1065	&init->std_alloc,
1066	&init->ets_alloc,
1067	&init->eheap_alloc,
1068	&init->ll_alloc,
1069	&init->driver_alloc,
1070	&init->sl_alloc,
1071	&init->temp_alloc
1072    };
1073    int aui_sz = (int) sizeof(aui)/sizeof(aui[0]);
1074    char *arg;
1075    char *rest;
1076    int i, j;
1077
1078    i = 1;
1079
1080    ASSERT(argc && argv && init);
1081
1082    while (i < *argc) {
1083	if(argv[i][0] == '-') {
1084	    char *param = argv[i]+1;
1085	    switch (argv[i][1]) {
1086	    case 'M':
1087		switch (argv[i][2]) {
1088		case 'B':
1089		    handle_au_arg(&init->binary_alloc, &argv[i][3], argv, &i);
1090		    break;
1091		case 'D':
1092		    handle_au_arg(&init->std_alloc, &argv[i][3], argv, &i);
1093		    break;
1094		case 'E':
1095		    handle_au_arg(&init->ets_alloc, &argv[i][3], argv, &i);
1096		    break;
1097		case 'F': /* fix_alloc */
1098		    if (has_prefix("e", param+2)) {
1099			arg = get_value(param+3, argv, &i);
1100			if (strcmp("true", arg) != 0)
1101			    bad_value(param, param+3, arg);
1102		    }
1103		    else
1104			bad_param(param, param+2);
1105		    break;
1106		case 'H':
1107		    handle_au_arg(&init->eheap_alloc, &argv[i][3], argv, &i);
1108		    break;
1109		case 'L':
1110		    handle_au_arg(&init->ll_alloc, &argv[i][3], argv, &i);
1111		    break;
1112		case 'M':
1113		    if (has_prefix("amcbf", argv[i]+3)) {
1114#if HAVE_ERTS_MSEG
1115			init->mseg.amcbf =
1116#endif
1117			    get_kb_value(argv[i]+8, argv, &i);
1118		    }
1119		    else if (has_prefix("rmcbf", argv[i]+3)) {
1120#if HAVE_ERTS_MSEG
1121			init->mseg.rmcbf =
1122#endif
1123			    get_amount_value(argv[i]+8, argv, &i);
1124		    }
1125		    else if (has_prefix("mcs", argv[i]+3)) {
1126#if HAVE_ERTS_MSEG
1127			init->mseg.mcs =
1128#endif
1129			    get_amount_value(argv[i]+6, argv, &i);
1130		    }
1131		    else if (has_prefix("cci", argv[i]+3)) {
1132#if HAVE_ERTS_MSEG
1133			init->mseg.cci =
1134#endif
1135			    get_amount_value(argv[i]+6, argv, &i);
1136		    }
1137		    else {
1138			bad_param(param, param+2);
1139		    }
1140		    break;
1141		case 'R':
1142		    handle_au_arg(&init->driver_alloc, &argv[i][3], argv, &i);
1143		    break;
1144		case 'S':
1145		    handle_au_arg(&init->sl_alloc, &argv[i][3], argv, &i);
1146		    break;
1147		case 'T':
1148		    handle_au_arg(&init->temp_alloc, &argv[i][3], argv, &i);
1149		    break;
1150		case 'Y': { /* sys_alloc */
1151		    if (has_prefix("tt", param+2)) {
1152			/* set trim threshold */
1153			arg = get_value(param+4, argv, &i);
1154			errno = 0;
1155			init->trim_threshold = (int) strtol(arg, &rest, 10);
1156			if (errno != 0
1157			    || rest == arg
1158			    || init->trim_threshold < 0
1159			    || (INT_MAX/1024) < init->trim_threshold) {
1160			    bad_value(param, param+4, arg);
1161			}
1162			VERBOSE(DEBUG_SYSTEM,
1163                                ("using trim threshold: %d\n",
1164                                 init->trim_threshold));
1165			init->trim_threshold *= 1024;
1166		    }
1167		    else if (has_prefix("tp", param+2)) {
1168			/* set top pad */
1169			arg = get_value(param+4, argv, &i);
1170			errno = 0;
1171			init->top_pad = (int) strtol(arg, &rest, 10);
1172			if (errno != 0
1173			    || rest == arg
1174			    || init->top_pad < 0
1175			    || (INT_MAX/1024) < init->top_pad) {
1176			    bad_value(param, param+4, arg);
1177			}
1178			VERBOSE(DEBUG_SYSTEM,
1179                                ("using top pad: %d\n",init->top_pad));
1180			init->top_pad *= 1024;
1181		    }
1182		    else if (has_prefix("m", param+2)) {
1183			/* Has been handled by erlexec */
1184			(void) get_value(param+3, argv, &i);
1185		    }
1186		    else if (has_prefix("e", param+2)) {
1187			arg = get_value(param+3, argv, &i);
1188			if (strcmp("true", arg) != 0)
1189			    bad_value(param, param+3, arg);
1190		    }
1191		    else
1192			bad_param(param, param+2);
1193		    break;
1194		}
1195		case 'e':
1196		    switch (argv[i][3]) {
1197		    case 'a': {
1198			int a;
1199			arg = get_value(argv[i]+4, argv, &i);
1200			if (strcmp("min", arg) == 0) {
1201			    for (a = 0; a < aui_sz; a++)
1202				aui[a]->enable = 0;
1203			}
1204			else if (strcmp("max", arg) == 0) {
1205			    for (a = 0; a < aui_sz; a++)
1206				aui[a]->enable = 1;
1207			}
1208			else if (strcmp("config", arg) == 0) {
1209			    init->erts_alloc_config = 1;
1210			}
1211			else if (strcmp("r9c", arg) == 0
1212				 || strcmp("r10b", arg) == 0
1213				 || strcmp("r11b", arg) == 0) {
1214			    set_default_sl_alloc_opts(&init->sl_alloc);
1215			    set_default_std_alloc_opts(&init->std_alloc);
1216			    set_default_ll_alloc_opts(&init->ll_alloc);
1217			    set_default_temp_alloc_opts(&init->temp_alloc);
1218			    set_default_eheap_alloc_opts(&init->eheap_alloc);
1219			    set_default_binary_alloc_opts(&init->binary_alloc);
1220			    set_default_ets_alloc_opts(&init->ets_alloc);
1221			    set_default_driver_alloc_opts(&init->driver_alloc);
1222
1223			    init->driver_alloc.enable = 0;
1224			    if (strcmp("r9c", arg) == 0) {
1225				init->sl_alloc.enable = 0;
1226				init->std_alloc.enable = 0;
1227				init->binary_alloc.enable = 0;
1228				init->ets_alloc.enable = 0;
1229			    }
1230
1231			    for (a = 0; a < aui_sz; a++) {
1232				aui[a]->thr_spec = 0;
1233				aui[a]->init.util.ramv = 0;
1234				aui[a]->init.util.mmmbc = 10;
1235				aui[a]->init.util.lmbcs = 5*1024*1024;
1236			    }
1237			}
1238			else {
1239			    bad_param(param, param+3);
1240			}
1241			break;
1242		    }
1243		    default:
1244			bad_param(param, param+1);
1245		    }
1246		    break;
1247		case 'i':
1248		    switch (argv[i][3]) {
1249		    case 's':
1250			arg = get_value(argv[i]+4, argv, &i);
1251			if (strcmp("true", arg) == 0)
1252			    init->instr.stat = 1;
1253			else if (strcmp("false", arg) == 0)
1254			    init->instr.stat = 0;
1255			else
1256			    bad_value(param, param+3, arg);
1257			break;
1258		    case 'm':
1259			arg = get_value(argv[i]+4, argv, &i);
1260			if (strcmp("true", arg) == 0)
1261			    init->instr.map = 1;
1262			else if (strcmp("false", arg) == 0)
1263			    init->instr.map = 0;
1264			else
1265			    bad_value(param, param+3, arg);
1266			break;
1267		    case 't':
1268			init->instr.mtrace = get_value(argv[i]+4, argv, &i);
1269			break;
1270		    default:
1271			bad_param(param, param+2);
1272		    }
1273		    break;
1274		case 'u':
1275		    if (has_prefix("ycs", argv[i]+3)) {
1276			init->alloc_util.ycs
1277			    = get_kb_value(argv[i]+6, argv, &i);
1278		    }
1279		    else if (has_prefix("mmc", argv[i]+3)) {
1280			init->alloc_util.mmc
1281			    = get_amount_value(argv[i]+6, argv, &i);
1282		    }
1283		    else {
1284			int a;
1285			int start = i;
1286			char *param = argv[i];
1287			char *val = i+1 < *argc ? argv[i+1] : NULL;
1288
1289			for (a = 0; a < aui_sz; a++) {
1290			    if (a > 0) {
1291				ASSERT(i == start || i == start+1);
1292				argv[start] = param;
1293				if (i != start)
1294				    argv[start + 1] = val;
1295				i = start;
1296			    }
1297			    handle_au_arg(aui[a], &argv[i][3], argv, &i);
1298			}
1299		    }
1300		    break;
1301		default:
1302		    bad_param(param, param+1);
1303		}
1304		break;
1305	    case '-':
1306		if (argv[i][2] == '\0') {
1307		    /* End of system flags reached */
1308		    if (init->instr.mtrace
1309			/* || init->instr.stat
1310			   || init->instr.map */) {
1311			while (i < *argc) {
1312			    if(strcmp(argv[i], "-sname") == 0
1313			       || strcmp(argv[i], "-name") == 0) {
1314				if (i + 1 <*argc) {
1315				    init->instr.nodename = argv[i+1];
1316				    break;
1317				}
1318			    }
1319			    i++;
1320			}
1321		    }
1322		    goto args_parsed;
1323		}
1324		break;
1325	    default:
1326		break;
1327	    }
1328	}
1329	i++;
1330    }
1331
1332 args_parsed:
1333    /* Handled arguments have been marked with NULL. Slide arguments
1334       not handled towards the beginning of argv. */
1335    for (i = 0, j = 0; i < *argc; i++) {
1336	if (argv[i])
1337	    argv[j++] = argv[i];
1338    }
1339    *argc = j;
1340    
1341}
1342
1343static char *type_no_str(ErtsAlcType_t n)
1344{
1345
1346#if ERTS_ALC_N_MIN != 0
1347    if (n < ERTS_ALC_N_MIN)
1348	return NULL;
1349#endif
1350    if (n > ERTS_ALC_N_MAX)
1351	return NULL;
1352    return (char *) ERTS_ALC_N2TD(n);
1353}
1354
1355#define type_str(T) type_no_str(ERTS_ALC_T2N((T)))
1356
1357erts_tsd_key_t thr_ix_key;
1358erts_spinlock_t alloc_thr_ix_lock;
1359int last_thr_ix;
1360int first_dyn_thr_ix;
1361
1362static void
1363init_thr_ix(int static_ixs)
1364{
1365    erts_tsd_key_create(&thr_ix_key);
1366    erts_spinlock_init(&alloc_thr_ix_lock, "alloc_thr_ix_lock");
1367    last_thr_ix = -4711;
1368    first_dyn_thr_ix = static_ixs+1;
1369}
1370
1371int
1372erts_alc_get_thr_ix(void)
1373{
1374    int ix = (int)(long) erts_tsd_get(thr_ix_key);
1375    if (ix == 0) {
1376	erts_spin_lock(&alloc_thr_ix_lock);
1377	last_thr_ix++;
1378	if (last_thr_ix < 0) 
1379	    last_thr_ix = first_dyn_thr_ix;
1380	ix = last_thr_ix;
1381	erts_spin_unlock(&alloc_thr_ix_lock);
1382	erts_tsd_set(thr_ix_key, (void *)(long) ix);
1383    }
1384    ASSERT(ix > 0);
1385    return ix;
1386}
1387
1388void erts_alloc_reg_scheduler_id(Uint id)
1389{
1390    int ix = (int) id;
1391    ASSERT(0 < ix && ix <= first_dyn_thr_ix);
1392    ASSERT(0 == (int) (long) erts_tsd_get(thr_ix_key));
1393    erts_tsd_set(thr_ix_key, (void *)(long) ix);
1394}
1395
1396__decl_noreturn void
1397erts_alc_fatal_error(int error, int func, ErtsAlcType_t n, ...)
1398{
1399    char buf[10];
1400    char *t_str;
1401    char *allctr_str;
1402
1403    ASSERT(n >= ERTS_ALC_N_MIN);
1404    ASSERT(n <= ERTS_ALC_N_MAX);
1405
1406
1407    if (n < ERTS_ALC_N_MIN || ERTS_ALC_N_MAX < n)
1408	allctr_str = "UNKNOWN";
1409    else {
1410	ErtsAlcType_t a = ERTS_ALC_T2A(ERTS_ALC_N2T(n));
1411	if (erts_allctrs_info[a].enabled)
1412	    allctr_str = (char *) ERTS_ALC_A2AD(a);
1413	else
1414	    allctr_str = (char *) ERTS_ALC_A2AD(ERTS_ALC_A_SYSTEM);
1415    }
1416
1417    t_str = type_no_str(n);
1418    if (!t_str) {
1419	sprintf(buf, "%d", (int) n);
1420	t_str = buf;
1421    }
1422
1423    switch (error) {
1424    case ERTS_ALC_E_NOTSUP: {
1425	char *op_str;
1426	switch (func) {
1427	case ERTS_ALC_O_ALLOC:		op_str = "alloc";	break;
1428	case ERTS_ALC_O_REALLOC:	op_str = "realloc";	break;
1429	case ERTS_ALC_O_FREE:		op_str = "free";	break;
1430	default:			op_str = "UNKNOWN";	break;
1431	}
1432	erl_exit(ERTS_ABORT_EXIT,
1433		 "%s: %s operation not supported (memory type: \"%s\")\n",
1434		 allctr_str, op_str, t_str);
1435	break;
1436    }
1437    case ERTS_ALC_E_NOMEM: {
1438	Uint size;
1439	va_list argp;
1440	char *op = func == ERTS_ALC_O_REALLOC ? "reallocate" : "allocate";
1441	
1442
1443	va_start(argp, n);
1444	size = va_arg(argp, Uint);
1445	va_end(argp);
1446	erl_exit(1,
1447		 "%s: Cannot %s %lu bytes of memory (of type \"%s\").\n",
1448		 allctr_str, op, size, t_str);
1449	break;
1450    }
1451    case ERTS_ALC_E_NOALLCTR:
1452	erl_exit(ERTS_ABORT_EXIT,
1453		 "erts_alloc: Unknown allocator type: %d\n",
1454		 ERTS_ALC_T2A(ERTS_ALC_N2T(n)));
1455	break;
1456    default:
1457	erl_exit(ERTS_ABORT_EXIT, "erts_alloc: Unknown error: %d\n", error);
1458	break;
1459    }
1460}
1461
1462__decl_noreturn void
1463erts_alloc_enomem(ErtsAlcType_t type, Uint size)
1464{
1465    erts_alloc_n_enomem(ERTS_ALC_T2N(type), size);
1466}
1467
1468__decl_noreturn void
1469erts_alloc_n_enomem(ErtsAlcType_t n, Uint size)
1470{
1471    erts_alc_fatal_error(ERTS_ALC_E_NOMEM, ERTS_ALC_O_ALLOC, n, size);
1472}
1473
1474__decl_noreturn void
1475erts_realloc_enomem(ErtsAlcType_t type, void *ptr, Uint size)
1476{
1477    erts_realloc_n_enomem(ERTS_ALC_T2N(type), ptr, size);
1478}
1479
1480__decl_noreturn void
1481erts_realloc_n_enomem(ErtsAlcType_t n, void *ptr, Uint size)
1482{
1483    erts_alc_fatal_error(ERTS_ALC_E_NOMEM, ERTS_ALC_O_REALLOC, n, size);
1484}
1485
1486static ERTS_INLINE Uint
1487alcu_size(ErtsAlcType_t ai)
1488{
1489    Uint res = 0;
1490
1491    ASSERT(erts_allctrs_info[ai].enabled);
1492    ASSERT(erts_allctrs_info[ai].alloc_util);
1493
1494    if (!erts_allctrs_info[ai].thr_spec) {
1495	Allctr_t *allctr = erts_allctrs_info[ai].extra;
1496	AllctrSize_t asize;
1497	erts_alcu_current_size(allctr, &asize);
1498	res += asize.blocks;
1499    }
1500    else {
1501	ErtsAllocatorThrSpec_t *tspec = &erts_allctr_thr_spec[ai];
1502	int i;
1503
1504	ASSERT(tspec->all_thr_safe);
1505
1506	ASSERT(tspec->enabled);
1507
1508	for (i = tspec->size - 1; i >= 0; i--) {
1509	    Allctr_t *allctr = tspec->allctr[i];
1510	    AllctrSize_t asize;
1511	    if (allctr) {
1512		erts_alcu_current_size(allctr, &asize);
1513		res += asize.blocks;
1514	    }
1515	}
1516    }
1517
1518    return res;
1519}
1520
1521Eterm
1522erts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg)
1523{
1524#define ERTS_MEM_NEED_ALL_ALCU (!erts_instr_stat && want_tot_or_sys)
1525    ErtsFixInfo efi;
1526    struct {
1527	int total;
1528	int processes;
1529	int processes_used;
1530	int system;
1531	int atom;
1532	int atom_used;
1533	int binary;
1534	int code;
1535	int ets;
1536	int maximum;
1537    } want = {0};
1538    struct {
1539	Uint total;
1540	Uint processes;
1541	Uint processes_used;
1542	Uint system;
1543	Uint atom;
1544	Uint atom_used;
1545	Uint binary;
1546	Uint code;
1547	Uint ets;
1548	Uint maximum;
1549    } size = {0};
1550    Eterm atoms[sizeof(size)/sizeof(Uint)];
1551    Uint *uintps[sizeof(size)/sizeof(Uint)];
1552    Eterm euints[sizeof(size)/sizeof(Uint)];
1553    int need_atom;
1554    int want_tot_or_sys;
1555    int length;
1556    Eterm res = THE_NON_VALUE;
1557    ErtsAlcType_t ai;
1558    int only_one_value = 0;
1559
1560    /* Figure out whats wanted... */
1561
1562    length = 0;
1563    if (is_non_value(earg)) { /* i.e. wants all */
1564	want.total = 1;
1565	atoms[length] = am_total;
1566	uintps[length++] = &size.total;
1567
1568	want.processes = 1;
1569	atoms[length] = am_processes;
1570	uintps[length++] = &size.processes;
1571
1572	want.processes_used = 1;
1573	atoms[length] = am_processes_used;
1574	uintps[length++] = &size.processes_used;
1575
1576	want.system = 1;
1577	atoms[length] = am_system;
1578	uintps[length++] = &size.system;
1579
1580	want.atom = 1;
1581	atoms[length] = am_atom;
1582	uintps[length++] = &size.atom;
1583
1584	want.atom_used = 1;
1585	atoms[length] = am_atom_used;
1586	uintps[length++] = &size.atom_used;
1587
1588	want.binary = 1;
1589	atoms[length] = am_binary;
1590	uintps[length++] = &size.binary;
1591
1592	want.code = 1;
1593	atoms[length] = am_code;
1594	uintps[length++] = &size.code;
1595
1596	want.ets = 1;
1597	atoms[length] = am_ets;
1598	uintps[length++] = &size.ets;
1599
1600	want.maximum = erts_instr_stat;
1601	if (want.maximum) {
1602	    atoms[length] = am_maximum;
1603	    uintps[length++] = &size.maximum;
1604	}
1605
1606    }
1607    else {
1608	Eterm tmp_heap[2];
1609	Eterm wanted_list;
1610
1611	if (is_nil(earg))
1612	    return NIL;
1613
1614	if (is_not_atom(earg))
1615	    wanted_list = earg;
1616	else {
1617	    wanted_list = CONS(&tmp_heap[0], earg, NIL);
1618	    only_one_value = 1;
1619	}
1620	    
1621	while (is_list(wanted_list)) {
1622	    switch (CAR(list_val(wanted_list))) {
1623	    case am_total:
1624		if (!want.total) {
1625		    want.total = 1;
1626		    atoms[length] = am_total;
1627		    uintps[length++] = &size.total;
1628		}
1629		break;
1630	    case am_processes:
1631		if (!want.processes) {
1632		    want.processes = 1;
1633		    atoms[length] = am_processes;
1634		    uintps[length++] = &size.processes;
1635		}
1636		break;
1637	    case am_processes_used:
1638		if (!want.processes_used) {
1639		    want.processes_used = 1;
1640		    atoms[length] = am_processes_used;
1641		    uintps[length++] = &size.processes_used;
1642		}
1643		break;
1644	    case am_system:
1645		if (!want.system) {
1646		    want.system = 1;
1647		    atoms[length] = am_system;
1648		    uintps[length++] = &size.system;
1649		}
1650		break;
1651	    case am_atom:
1652		if (!want.atom) {
1653		    want.atom = 1;
1654		    atoms[length] = am_atom;
1655		    uintps[length++] = &size.atom;
1656		}
1657		break;
1658	    case am_atom_used:
1659		if (!want.atom_used) {
1660		    want.atom_used = 1;
1661		    atoms[length] = am_atom_used;
1662		    uintps[length++] = &size.atom_used;
1663		}
1664		break;
1665	    case am_binary:
1666		if (!want.binary) {
1667		    want.binary = 1;
1668		    atoms[length] = am_binary;
1669		    uintps[length++] = &size.binary;
1670		}
1671		break;
1672	    case am_code:
1673		if (!want.code) {
1674		    want.code = 1;
1675		    atoms[length] = am_code;
1676		    uintps[length++] = &size.code;
1677		}
1678		break;
1679	    case am_ets:
1680		if (!want.ets) {
1681		    want.ets = 1;
1682		    atoms[length] = am_ets;
1683		    uintps[length++] = &size.ets;
1684		}
1685		break;
1686	    case am_maximum:
1687		if (erts_instr_stat) {
1688		    if (!want.maximum) {
1689			want.maximum = 1;
1690			atoms[length] = am_maximum;
1691			uintps[length++] = &size.maximum;
1692		    }
1693		}
1694		else
1695		    return am_badarg;
1696		break;
1697	    default:
1698		return am_badarg;
1699	    }
1700	    wanted_list = CDR(list_val(wanted_list));
1701	}
1702	if (is_not_nil(wanted_list))
1703	    return am_badarg;
1704    }
1705
1706    /* All alloc_util allocators *have* to be enabled */
1707    
1708    for (ai = ERTS_ALC_A_MIN; ai <= ERTS_ALC_A_MAX; ai++) {
1709	switch (ai) {
1710	case ERTS_ALC_A_SYSTEM:
1711	case ERTS_ALC_A_FIXED_SIZE:
1712	    break;
1713	default:
1714	    if (!erts_allctrs_info[ai].enabled
1715		|| !erts_allctrs_info[ai].alloc_util) {
1716		return am_notsup;
1717	    }
1718	    break;
1719	}
1720    }
1721
1722    ASSERT(length <= sizeof(atoms)/sizeof(Eterm));
1723    ASSERT(length <= sizeof(euints)/sizeof(Eterm));
1724    ASSERT(length <= sizeof(uintps)/sizeof(Uint));
1725
1726
1727    if (proc) {
1728	ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN
1729			   == erts_proc_lc_my_proc_locks(proc));
1730	/* We'll need locks early in the lock order */
1731	erts_smp_proc_unlock(proc, ERTS_PROC_LOCK_MAIN);
1732    }
1733
1734    /* Calculate values needed... */
1735
1736    want_tot_or_sys = want.total || want.system;
1737    need_atom = ERTS_MEM_NEED_ALL_ALCU || want.atom;
1738
1739    if (ERTS_MEM_NEED_ALL_ALCU) {
1740	size.total = 0;
1741
1742	for (ai = ERTS_ALC_A_MIN; ai <= ERTS_ALC_A_MAX; ai++) {
1743	    if (erts_allctrs_info[ai].alloc_util) {
1744		Uint *save;
1745		Uint asz;
1746		switch (ai) {
1747		case ERTS_ALC_A_TEMPORARY:
1748		     /*
1749		      * Often not thread safe and usually never
1750		      * contain any allocated memory.
1751		      */
1752		    continue;
1753		case ERTS_ALC_A_EHEAP:
1754		    save = &size.processes;
1755		    break;
1756		case ERTS_ALC_A_ETS:
1757		    save = &size.ets;
1758		    break;
1759		case ERTS_ALC_A_BINARY:
1760		    save = &size.binary;
1761		    break;
1762		default:
1763		    save = NULL;
1764		    break;
1765		}
1766		asz = alcu_size(ai);
1767		if (save)
1768		    *save = asz;
1769		size.total += asz;
1770	    }
1771	}
1772    }
1773
1774
1775
1776    if (want_tot_or_sys || want.processes || want.processes_used) {
1777	Uint tmp;
1778
1779	if (ERTS_MEM_NEED_ALL_ALCU)
1780	    tmp = size.processes;
1781	else
1782	    tmp = alcu_size(ERTS_ALC_A_EHEAP);
1783	tmp += erts_max_processes*sizeof(Process*);
1784#ifdef HYBRID
1785	tmp += erts_max_processes*sizeof(Process*);
1786#endif
1787	tmp += erts_bif_timer_memory_size();
1788	tmp += erts_tot_link_lh_size();
1789
1790	size.processes = size.processes_used = tmp;
1791
1792	erts_fix_info(ERTS_ALC_T_NLINK_SH, &efi);
1793	size.processes += efi.total;
1794	size.processes_used += efi.used;
1795
1796	erts_fix_info(ERTS_ALC_T_MONITOR_SH, &efi);
1797	size.processes += efi.total;
1798	size.processes_used += efi.used;
1799
1800	erts_fix_info(ERTS_ALC_T_PROC, &efi);
1801	size.processes += efi.total;
1802	size.processes_used += efi.used;
1803
1804	erts_fix_info(ERTS_ALC_T_REG_PROC, &efi);
1805	size.processes += efi.total;
1806	size.processes_used += efi.used;
1807
1808    }
1809
1810    if (want.atom || want.atom_used) {
1811	Uint reserved_atom_space, atom_space;
1812	erts_atom_get_text_space_sizes(&reserved_atom_space, &atom_space);
1813	size.atom = size.atom_used = atom_table_sz();
1814	erts_fix_info(ERTS_ALC_T_ATOM, &efi);
1815
1816	if (want.atom) {
1817	    size.atom += reserved_atom_space;
1818	    size.atom += efi.total;
1819	}
1820
1821	if (want.atom_used) {
1822	    size.atom_used += atom_space;
1823	    size.atom_used += efi.used;
1824	}
1825    }
1826
1827    if (!ERTS_MEM_NEED_ALL_ALCU && want.binary)
1828	size.binary = alcu_size(ERTS_ALC_A_BINARY);
1829
1830    if (want.code) {
1831	size.code = module_table_sz();
1832	erts_fix_info(ERTS_ALC_T_MODULE, &efi);
1833	size.code += efi.used;
1834	size.code += export_table_sz();
1835	erts_fix_info(ERTS_ALC_T_EXPORT, &efi);
1836	size.code += efi.used;
1837	size.code += erts_fun_table_sz();
1838	erts_fix_info(ERTS_ALC_T_FUN_ENTRY, &efi);
1839	size.code += efi.used;
1840	size.code += allocated_modules*sizeof(Range);
1841	size.code += erts_total_code_size;
1842    }
1843
1844    if (want.ets) {
1845	if (!ERTS_MEM_NEED_ALL_ALCU)
1846	    size.ets = alcu_size(ERTS_ALC_A_ETS);
1847	size.ets += erts_get_ets_misc_mem_size();
1848    }
1849
1850    if (erts_instr_stat && (want_tot_or_sys || want.maximum)) {
1851	if (want_tot_or_sys) {
1852	    size.total = erts_instr_get_total();
1853	    size.system = size.total - size.processes;
1854	}
1855	size.maximum = erts_instr_get_max_total();
1856    }
1857    else if (want_tot_or_sys) {
1858	size.system = size.total - size.processes;
1859    }
1860
1861    if (print_to_p) {
1862	int i;
1863	int to = *print_to_p;
1864	void *arg = print_to_arg;
1865
1866	/* Print result... */
1867	erts_print(to, arg, "=memory\n");
1868	for (i = 0; i < length; i++)
1869	    erts_print(to, arg, "%T: %bpu\n", atoms[i], *uintps[i]);
1870    }
1871
1872    if (proc) {
1873	/* Build erlang term result... */
1874	Uint *hp;
1875	Uint hsz;
1876
1877	erts_smp_proc_lock(proc, ERTS_PROC_LOCK_MAIN);
1878
1879	if (only_one_value) {
1880	    ASSERT(length == 1);
1881	    hsz = 0;
1882	    erts_bld_uint(NULL, &hsz, *uintps[0]);
1883	    hp = hsz ? HAlloc((Process *) proc, hsz) : NULL;
1884	    res = erts_bld_uint(&hp, NULL, *uintps[0]);
1885	}
1886	else {
1887	    Uint **hpp = NULL;
1888	    Uint *hszp = &hsz;
1889	    hsz = 0;
1890
1891	    while (1) {
1892		int i;
1893		for (i = 0; i < length; i++)
1894		    euints[i] = erts_bld_uint(hpp, hszp, *uintps[i]);
1895		res = erts_bld_2tup_list(hpp, hszp, length, atoms, euints);
1896		if (hpp)
1897		    break;
1898		hp = HAlloc((Process *) proc, hsz);
1899		hpp = &hp;
1900		hszp = NULL;
1901	    }
1902	}
1903    }
1904
1905    return res;
1906
1907#undef ERTS_MEM_NEED_ALL_ALCU
1908}
1909
1910struct aa_values {
1911    Uint arity;
1912    const char *name;
1913    Uint ui[2];
1914};
1915
1916Eterm
1917erts_allocated_areas(int *print_to_p, void *print_to_arg, void *proc)
1918{
1919#define MAX_AA_VALUES \
1920  (20 + (ERTS_ALC_N_MAX_A_FIXED_SIZE - ERTS_ALC_N_MIN_A_FIXED_SIZE + 1))
1921
1922    struct aa_values values[MAX_AA_VALUES];
1923    Eterm res = THE_NON_VALUE;
1924    int i, length;
1925    ErtsFixInfo efi;
1926    Uint reserved_atom_space, atom_space;
1927
1928    if (proc) {
1929	ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN
1930			   == erts_proc_lc_my_proc_locks(proc));
1931
1932	/* We'll need locks early in the lock order */
1933	erts_smp_proc_unlock(proc, ERTS_PROC_LOCK_MAIN);
1934    }
1935
1936    i = 0;
1937
1938    if (erts_instr_stat) {
1939	values[i].arity = 2;
1940	values[i].name = "total";
1941	values[i].ui[0] = erts_instr_get_total();
1942	i++;
1943
1944	values[i].arity = 2;
1945	values[i].name = "maximum";
1946	values[i].ui[0] = erts_instr_get_max_total();
1947	i++;
1948    }
1949
1950    values[i].arity = 2;
1951    values[i].name = "sys_misc";
1952    values[i].ui[0] = erts_sys_misc_mem_sz();
1953    i++;
1954
1955    values[i].arity = 2;
1956    values[i].name = "static";
1957    values[i].ui[0] = 
1958	erts_max_ports*sizeof(Port)		/* Port table */
1959	+ erts_timer_wheel_memory_size()	/* Timer wheel */
1960#ifdef SYS_TMP_BUF_SIZE
1961	+ SYS_TMP_BUF_SIZE		/* tmp_buf in sys on vxworks & ose */
1962#endif
1963	;
1964    i++;
1965
1966    erts_atom_get_text_space_sizes(&reserved_atom_space, &atom_space);
1967
1968    values[i].arity = 3;
1969    values[i].name = "atom_space";
1970    values[i].ui[0] = reserved_atom_space;
1971    values[i].ui[1] = atom_space;
1972    i++;
1973
1974    values[i].arity = 2;
1975    values[i].name = "atom_table";
1976    values[i].ui[0] = atom_table_sz();
1977    i++;
1978
1979    values[i].arity = 2;
1980    values[i].name = "module_table";
1981    values[i].ui[0] = module_table_sz();
1982    i++;
1983
1984    values[i].arity = 2;
1985    va

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