PageRenderTime 427ms CodeModel.GetById 91ms app.highlight 551ms RepoModel.GetById 103ms app.codeStats 2ms

/erts/emulator/beam/erl_alloc.c

https://github.com/system/erlang-otp
C | 3055 lines | 2635 code | 342 blank | 78 comment | 443 complexity | f49953c83fc3db4a6ff99a12b29922ac MD5 | raw file

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

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

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