diff options
Diffstat (limited to 'erts/emulator/beam/erl_alloc_util.h')
-rw-r--r-- | erts/emulator/beam/erl_alloc_util.h | 342 |
1 files changed, 342 insertions, 0 deletions
diff --git a/erts/emulator/beam/erl_alloc_util.h b/erts/emulator/beam/erl_alloc_util.h new file mode 100644 index 0000000000..10b11661e6 --- /dev/null +++ b/erts/emulator/beam/erl_alloc_util.h @@ -0,0 +1,342 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2002-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +#ifndef ERL_ALLOC_UTIL__ +#define ERL_ALLOC_UTIL__ + +#define ERTS_ALCU_VSN_STR "2.2" + +#include "erl_alloc_types.h" + +typedef struct Allctr_t_ Allctr_t; + +typedef struct { + Uint ycs; + Uint mmc; +} AlcUInit_t; + +typedef struct { + char *name_prefix; + ErtsAlcType_t alloc_no; + int ts; + int tspec; + int tpref; + int ramv; + Uint sbct; + Uint asbcst; + Uint rsbcst; + Uint rsbcmt; + Uint rmbcmt; + Uint mmbcs; + Uint mmsbc; + Uint mmmbc; + Uint lmbcs; + Uint smbcs; + Uint mbcgs; +} AllctrInit_t; + +typedef struct { + Uint blocks; + Uint carriers; +} AllctrSize_t; + +#ifndef SMALL_MEMORY + +#define ERTS_DEFAULT_ALCU_INIT { \ + 1024*1024, /* (bytes) ycs: sys_alloc carrier size */\ + 1024 /* (amount) mmc: max mseg carriers */\ +} + +#define ERTS_DEFAULT_ALLCTR_INIT { \ + NULL, \ + ERTS_ALC_A_INVALID, /* (number) alloc_no: allocator number */\ + 1, /* (bool) ts: thread safe */\ + 0, /* (bool) tspec: thread specific */\ + 0, /* (bool) tpref: thread preferred */\ + 0, /* (bool) ramv: realloc always moves */\ + 512*1024, /* (bytes) sbct: sbc threshold */\ + 2*1024*2024, /* (amount) asbcst: abs sbc shrink threshold */\ + 20, /* (%) rsbcst: rel sbc shrink threshold */\ + 80, /* (%) rsbcmt: rel sbc move threshold */\ + 50, /* (%) rmbcmt: rel mbc move threshold */\ + 1024*1024, /* (bytes) mmbcs: main multiblock carrier size */\ + 256, /* (amount) mmsbc: max mseg sbcs */\ + 10, /* (amount) mmmbc: max mseg mbcs */\ + 10*1024*1024, /* (bytes) lmbcs: largest mbc size */\ + 1024*1024, /* (bytes) smbcs: smallest mbc size */\ + 10 /* (amount) mbcgs: mbc growth stages */\ +} + +#else /* if SMALL_MEMORY */ + +#define ERTS_DEFAULT_ALCU_INIT { \ + 128*1024, /* (bytes) ycs: sys_alloc carrier size */\ + 1024 /* (amount) mmc: max mseg carriers */\ +} + +#define ERTS_DEFAULT_ALLCTR_INIT { \ + NULL, \ + ERTS_ALC_A_INVALID, /* (number) alloc_no: allocator number */\ + 1, /* (bool) ts: thread safe */\ + 0, /* (bool) tspec: thread specific */\ + 0, /* (bool) tpref: thread preferred */\ + 0, /* (bool) ramv: realloc always moves */\ + 64*1024, /* (bytes) sbct: sbc threshold */\ + 2*1024*2024, /* (amount) asbcst: abs sbc shrink threshold */\ + 20, /* (%) rsbcst: rel sbc shrink threshold */\ + 80, /* (%) rsbcmt: rel sbc move threshold */\ + 128*1024, /* (bytes) mmbcs: main multiblock carrier size */\ + 256, /* (amount) mmsbc: max mseg sbcs */\ + 10, /* (amount) mmmbc: max mseg mbcs */\ + 1024*1024, /* (bytes) lmbcs: largest mbc size */\ + 128*1024, /* (bytes) smbcs: smallest mbc size */\ + 10 /* (amount) mbcgs: mbc growth stages */\ +} + +#endif + +void * erts_alcu_alloc(ErtsAlcType_t, void *, Uint); +void * erts_alcu_realloc(ErtsAlcType_t, void *, void *, Uint); +void * erts_alcu_realloc_mv(ErtsAlcType_t, void *, void *, Uint); +void erts_alcu_free(ErtsAlcType_t, void *, void *); +#ifdef USE_THREADS +void * erts_alcu_alloc_ts(ErtsAlcType_t, void *, Uint); +void * erts_alcu_realloc_ts(ErtsAlcType_t, void *, void *, Uint); +void * erts_alcu_realloc_mv_ts(ErtsAlcType_t, void *, void *, Uint); +void erts_alcu_free_ts(ErtsAlcType_t, void *, void *); +void * erts_alcu_alloc_thr_spec(ErtsAlcType_t, void *, Uint); +void * erts_alcu_realloc_thr_spec(ErtsAlcType_t, void *, void *, Uint); +void * erts_alcu_realloc_mv_thr_spec(ErtsAlcType_t, void *, void *, Uint); +void erts_alcu_free_thr_spec(ErtsAlcType_t, void *, void *); +void * erts_alcu_alloc_thr_pref(ErtsAlcType_t, void *, Uint); +void * erts_alcu_realloc_thr_pref(ErtsAlcType_t, void *, void *, Uint); +void * erts_alcu_realloc_mv_thr_pref(ErtsAlcType_t, void *, void *, Uint); +void erts_alcu_free_thr_pref(ErtsAlcType_t, void *, void *); +#endif +Eterm erts_alcu_au_info_options(int *, void *, Uint **, Uint *); +Eterm erts_alcu_info_options(Allctr_t *, int *, void *, Uint **, Uint *); +Eterm erts_alcu_sz_info(Allctr_t *, int, int *, void *, Uint **, Uint *); +Eterm erts_alcu_info(Allctr_t *, int, int *, void *, Uint **, Uint *); +void erts_alcu_init(AlcUInit_t *); +void erts_alcu_current_size(Allctr_t *, AllctrSize_t *); + +#endif + +#if defined(GET_ERL_ALLOC_UTIL_IMPL) && !defined(ERL_ALLOC_UTIL_IMPL__) +#define ERL_ALLOC_UTIL_IMPL__ + +#ifdef USE_THREADS +#define ERL_THREADS_EMU_INTERNAL__ +#include "erl_threads.h" +#endif + +#include "erl_mseg.h" + +#undef ERTS_ALLOC_UTIL_HARD_DEBUG +#ifdef DEBUG +# if 0 +# define ERTS_ALLOC_UTIL_HARD_DEBUG +# endif +#endif + +#undef MIN +#undef MAX +#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) +#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) +#define FLOOR(X, I) (((X)/(I))*(I)) +#define CEILING(X, I) ((((X) - 1)/(I) + 1)*(I)) + +#undef WORD_MASK +#define INV_WORD_MASK ((Uint) (sizeof(Uint) - 1)) +#define WORD_MASK (~INV_WORD_MASK) +#define WORD_FLOOR(X) ((X) & WORD_MASK) +#define WORD_CEILING(X) WORD_FLOOR((X) + INV_WORD_MASK) + +#undef UNIT_MASK +#define INV_UNIT_MASK ((Uint) (sizeof(Unit_t) - 1)) +#define UNIT_MASK (~INV_UNIT_MASK) +#define UNIT_FLOOR(X) ((X) & UNIT_MASK) +#define UNIT_CEILING(X) UNIT_FLOOR((X) + INV_UNIT_MASK) + + +#define SZ_MASK (~((Uint) 0) << 3) +#define FLG_MASK (~(SZ_MASK)) + + +#define BLK_SZ(B) \ + (*((Block_t *) (B)) & SZ_MASK) + +#define CARRIER_SZ(C) \ + ((C)->chdr & SZ_MASK) + +typedef union {char c[8]; long l; double d;} Unit_t; + +typedef struct Carrier_t_ Carrier_t; +struct Carrier_t_ { + Uint chdr; + Carrier_t *next; + Carrier_t *prev; +}; + +typedef struct { + Carrier_t *first; + Carrier_t *last; +} CarrierList_t; + +typedef Uint Block_t; +typedef Uint FreeBlkFtr_t; + +typedef struct { + Uint giga_no; + Uint no; +} CallCounter_t; + +typedef struct { + Uint no; + Uint size; +} StatValues_t; + +typedef struct { + StatValues_t curr_mseg; + StatValues_t curr_sys_alloc; + StatValues_t max; + StatValues_t max_ever; + struct { + StatValues_t curr; + StatValues_t max; + StatValues_t max_ever; + } blocks; +} CarriersStats_t; + +struct Allctr_t_ { + + /* Allocator name prefix */ + char * name_prefix; + + /* Allocator number */ + ErtsAlcType_t alloc_no; + + /* Alloc, realloc and free names as atoms */ + struct { + Eterm alloc; + Eterm realloc; + Eterm free; + } name; + + /* Version string */ + char * vsn_str; + + /* Options */ + int t; + int ramv; + Uint sbc_threshold; + Uint sbc_move_threshold; + Uint mbc_move_threshold; + Uint main_carrier_size; + Uint max_mseg_sbcs; + Uint max_mseg_mbcs; + Uint largest_mbc_size; + Uint smallest_mbc_size; + Uint mbc_growth_stages; +#if HAVE_ERTS_MSEG + ErtsMsegOpt_t mseg_opt; +#endif + + /* */ + Uint mbc_header_size; + Uint sbc_header_size; + Uint min_mbc_size; + Uint min_mbc_first_free_size; + Uint min_block_size; + + /* Carriers */ + CarrierList_t mbc_list; + CarrierList_t sbc_list; + + /* Main carrier (if there is one) */ + Carrier_t * main_carrier; + + /* Callback functions (first 4 are mandatory) */ + Block_t * (*get_free_block) (Allctr_t *, Uint, + Block_t *, Uint); + void (*link_free_block) (Allctr_t *, Block_t *); + void (*unlink_free_block) (Allctr_t *, Block_t *); + Eterm (*info_options) (Allctr_t *, char *, int *, + void *, Uint **, Uint *); + + Uint (*get_next_mbc_size) (Allctr_t *); + void (*creating_mbc) (Allctr_t *, Carrier_t *); + void (*destroying_mbc) (Allctr_t *, Carrier_t *); + void (*init_atoms) (void); + +#ifdef ERTS_ALLOC_UTIL_HARD_DEBUG + void (*check_block) (Allctr_t *, Block_t *, int); + void (*check_mbc) (Allctr_t *, Carrier_t *); +#endif + +#ifdef USE_THREADS + /* Mutex for this allocator */ + erts_mtx_t mutex; + int thread_safe; + struct { + Allctr_t *prev; + Allctr_t *next; + } ts_list; +#endif + + int atoms_initialized; + + int stopped; + + /* Some statistics ... */ + struct { + CallCounter_t this_alloc; + CallCounter_t this_free; + CallCounter_t this_realloc; + CallCounter_t mseg_alloc; + CallCounter_t mseg_dealloc; + CallCounter_t mseg_realloc; + CallCounter_t sys_alloc; + CallCounter_t sys_free; + CallCounter_t sys_realloc; + } calls; + + CarriersStats_t sbcs; + CarriersStats_t mbcs; + +#ifdef DEBUG +#ifdef USE_THREADS + struct { + int saved_tid; + erts_tid_t tid; + } debug; +#endif +#endif +}; + +int erts_alcu_start(Allctr_t *, AllctrInit_t *); +void erts_alcu_stop(Allctr_t *); + +unsigned long erts_alcu_test(unsigned long, unsigned long, unsigned long); + + + +#endif /* #if defined(GET_ERL_ALLOC_UTIL_IMPL) + && !defined(ERL_ALLOC_UTIL_IMPL__) */ + |