erl_alloc.c

来自「OTP是开放电信平台的简称」· C语言 代码 · 共 2,572 行 · 第 1/5 页

C
2,572
字号
/* ``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 via the world wide web 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. *  * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' *  *     $Id$ *//* * Description:	Management of memory allocators. * * Author: 	Rickard Green */#ifdef HAVE_CONFIG_H#  include "config.h"#endif#define ERTS_ALLOC_C__#define ERTS_ALC_INTERNAL__#include "sys.h"#define ERL_THREADS_EMU_INTERNAL__#include "erl_threads.h"#include "global.h"#include "erl_db.h"#include "erl_binary.h"#include "erl_bits.h"#include "erl_instrument.h"#include "erl_mseg.h"#ifdef ELIB_ALLOC_IS_CLIB#include "erl_version.h"#endif#include "erl_monitors.h"#include "erl_bif_timer.h"#if defined(ERTS_ALC_T_DRV_SEL_D_STATE) || defined(ERTS_ALC_T_DRV_EV_D_STATE)#include "erl_check_io.h"#endif#define GET_ERL_GF_ALLOC_IMPL#include "erl_goodfit_alloc.h"#define GET_ERL_BF_ALLOC_IMPL#include "erl_bestfit_alloc.h"#define GET_ERL_AF_ALLOC_IMPL#include "erl_afit_alloc.h"#if defined(SMALL_MEMORY) || defined(PURIFY) || defined(VALGRIND)#define AU_ALLOC_DEFAULT_ENABLE(X)	0#else#define AU_ALLOC_DEFAULT_ENABLE(X)	(X)#endif#ifdef DEBUGstatic Uint install_debug_functions(void);#endifextern void elib_ensure_initialized(void);ErtsAllocatorFunctions_t erts_allctrs[ERTS_ALC_A_MAX+1];ErtsAllocatorInfo_t erts_allctrs_info[ERTS_ALC_A_MAX+1];#ifdef ERTS_ALC_THR_SPEC_ALLOCSErtsAllocatorThrSpec_t erts_allctr_thr_spec[ERTS_ALC_A_MAX+1];#endiftypedef union {    GFAllctr_t gfa;    BFAllctr_t bfa;    AFAllctr_t afa;} allocator_state;static allocator_state sl_alloc_state;static allocator_state std_alloc_state;static allocator_state ll_alloc_state;static allocator_state temp_alloc_state;static allocator_state eheap_alloc_state;static allocator_state binary_alloc_state;static allocator_state ets_alloc_state;ErtsAlcType_t erts_fix_core_allocator_ix;#ifdef ERTS_ALC_N_MIN_A_FIXED_SIZEstatic void *(*fix_core_allocator)(ErtsAlcType_t, void *, Uint);static void *fix_core_extra;static void *fix_core_alloc(Uint size){    void *res;    res = (*fix_core_allocator)(ERTS_ALC_T_UNDEF, fix_core_extra, size);    if (erts_mtrace_enabled)	erts_mtrace_crr_alloc(res,			      ERTS_ALC_A_FIXED_SIZE,			      erts_fix_core_allocator_ix,			      size);    return res;}#endifenum allctr_type {    GOODFIT,    BESTFIT,    AFIT};struct au_init {    int enable;    enum allctr_type	atype;    struct {	AllctrInit_t	util;	GFAllctrInit_t	gf;	BFAllctrInit_t	bf;	AFAllctrInit_t	af;    } init;};#define DEFAULT_ALLCTR_INIT {		\    ERTS_DEFAULT_ALLCTR_INIT,		\    ERTS_DEFAULT_GF_ALLCTR_INIT,	\    ERTS_DEFAULT_BF_ALLCTR_INIT,	\    ERTS_DEFAULT_AF_ALLCTR_INIT		\}typedef struct {#if HAVE_ERTS_MSEG    ErtsMsegInit_t mseg;#endif    int trim_threshold;    int top_pad;    AlcUInit_t alloc_util;    struct {	int stat;	int map;	char *mtrace;	char *nodename;    } instr;    struct au_init sl_alloc;    struct au_init std_alloc;    struct au_init ll_alloc;    struct au_init temp_alloc;    struct au_init eheap_alloc;    struct au_init binary_alloc;    struct au_init ets_alloc;} init_t;#define SET_DEFAULT_ALLOC_OPTS(IP)					\do {									\    struct au_init aui__ = {0, GOODFIT, DEFAULT_ALLCTR_INIT};		\    sys_memcpy((void *) (IP), (void *) &aui__, sizeof(struct au_init));	\} while (0)static voidset_default_sl_alloc_opts(struct au_init *ip){    SET_DEFAULT_ALLOC_OPTS(ip);    ip->enable			= AU_ALLOC_DEFAULT_ENABLE(1);    ip->atype			= GOODFIT;    ip->init.util.name_prefix	= "sl_";    ip->init.util.alloc_no	= ERTS_ALC_A_SHORT_LIVED;#ifndef SMALL_MEMORY    ip->init.util.mmbcs 	= 128*1024; /* Main carrier size */#else    ip->init.util.mmbcs 	= 32*1024; /* Main carrier size */#endif    ip->init.util.ts 		= ERTS_ALC_MTA_SHORT_LIVED;    ip->init.util.rsbcst	= 80;}static voidset_default_std_alloc_opts(struct au_init *ip){    SET_DEFAULT_ALLOC_OPTS(ip);    ip->enable			= AU_ALLOC_DEFAULT_ENABLE(1);    ip->atype			= BESTFIT;    ip->init.util.name_prefix	= "std_";    ip->init.util.alloc_no	= ERTS_ALC_A_STANDARD;#ifndef SMALL_MEMORY    ip->init.util.mmbcs 	= 128*1024; /* Main carrier size */#else    ip->init.util.mmbcs 	= 32*1024; /* Main carrier size */#endif    ip->init.util.ts 		= ERTS_ALC_MTA_STANDARD;}static voidset_default_ll_alloc_opts(struct au_init *ip){    SET_DEFAULT_ALLOC_OPTS(ip);    ip->enable			= AU_ALLOC_DEFAULT_ENABLE(1);    ip->atype			= BESTFIT;    ip->init.bf.ao		= 1;    ip->init.util.mmsbc		= 0;    ip->init.util.mmmbc		= 0;    ip->init.util.sbct		= ~((Uint) 0);    ip->init.util.name_prefix	= "ll_";    ip->init.util.alloc_no	= ERTS_ALC_A_LONG_LIVED;#ifndef SMALL_MEMORY    ip->init.util.mmbcs 	= 2*1024*1024; /* Main carrier size */#else    ip->init.util.mmbcs 	= 1*1024*1024; /* Main carrier size */#endif    ip->init.util.ts 		= ERTS_ALC_MTA_LONG_LIVED;    ip->init.util.asbcst	= 0;    ip->init.util.rsbcst	= 0;    ip->init.util.rsbcmt	= 0;}static voidset_default_temp_alloc_opts(struct au_init *ip){    SET_DEFAULT_ALLOC_OPTS(ip);    ip->enable			= AU_ALLOC_DEFAULT_ENABLE(1);#ifdef ERTS_SMP    ip->atype			= GOODFIT;#else    ip->atype			= AFIT;#endif    ip->init.util.name_prefix	= "temp_";    ip->init.util.alloc_no	= ERTS_ALC_A_TEMPORARY;#ifndef SMALL_MEMORY    ip->init.util.mmbcs 	= 128*1024; /* Main carrier size */#else    ip->init.util.mmbcs 	= 32*1024; /* Main carrier size */#endif    ip->init.util.ts 		= ERTS_ALC_MTA_TEMPORARY;    ip->init.util.rsbcst	= 90;#ifdef ERTS_SMP    ip->init.util.mmbcs 	*= 2; /* Main carrier size */#endif}static voidset_default_eheap_alloc_opts(struct au_init *ip){    SET_DEFAULT_ALLOC_OPTS(ip);    ip->enable			= AU_ALLOC_DEFAULT_ENABLE(1);    ip->atype			= GOODFIT;    ip->init.util.name_prefix	= "eheap_";    ip->init.util.alloc_no	= ERTS_ALC_A_EHEAP;#ifndef SMALL_MEMORY    ip->init.util.mmbcs 	= 512*1024; /* Main carrier size */#else    ip->init.util.mmbcs 	= 256*1024; /* Main carrier size */#endif    ip->init.util.ts 		= ERTS_ALC_MTA_EHEAP;    ip->init.util.rsbcst	= 50;}static voidset_default_binary_alloc_opts(struct au_init *ip){    SET_DEFAULT_ALLOC_OPTS(ip);    ip->enable			= AU_ALLOC_DEFAULT_ENABLE(1);    ip->atype			= BESTFIT;    ip->init.util.name_prefix	= "binary_";    ip->init.util.alloc_no	= ERTS_ALC_A_BINARY;#ifndef SMALL_MEMORY    ip->init.util.mmbcs 	= 128*1024; /* Main carrier size */#else    ip->init.util.mmbcs 	= 32*1024; /* Main carrier size */#endif    ip->init.util.ts 		= ERTS_ALC_MTA_BINARY;}static voidset_default_ets_alloc_opts(struct au_init *ip){    SET_DEFAULT_ALLOC_OPTS(ip);    ip->enable			= AU_ALLOC_DEFAULT_ENABLE(1);    ip->atype			= BESTFIT;    ip->init.util.name_prefix	= "ets_";    ip->init.util.alloc_no	= ERTS_ALC_A_ETS;#ifndef SMALL_MEMORY    ip->init.util.mmbcs 	= 128*1024; /* Main carrier size */#else    ip->init.util.mmbcs 	= 32*1024; /* Main carrier size */#endif    ip->init.util.ts 		= ERTS_ALC_MTA_ETS;}static void handle_args(int *, char **, init_t *);static voidset_au_allocator(ErtsAllocatorFunctions_t *af,		 ErtsAllocatorInfo_t *ai,		 struct au_init *init,		 ErtsAllocatorFunctions_t *disable_af);static voidstart_au_allocator(ErtsAllocatorFunctions_t *af,		   ErtsAllocatorInfo_t *ai,		   struct au_init *init,		   allocator_state *state);voiderts_alloc_init(int *argc, char **argv){    Uint extra_block_size = 0;    int i;    init_t init = {#if HAVE_ERTS_MSEG	ERTS_MSEG_INIT_DEFAULT_INITIALIZER,#endif	ERTS_DEFAULT_TRIM_THRESHOLD,	ERTS_DEFAULT_TOP_PAD,	ERTS_DEFAULT_ALCU_INIT    };    erts_sys_alloc_init();    erts_init_utils_mem();    set_default_sl_alloc_opts(&init.sl_alloc);    set_default_std_alloc_opts(&init.std_alloc);    set_default_ll_alloc_opts(&init.ll_alloc);    set_default_temp_alloc_opts(&init.temp_alloc);    set_default_eheap_alloc_opts(&init.eheap_alloc);    set_default_binary_alloc_opts(&init.binary_alloc);    set_default_ets_alloc_opts(&init.ets_alloc);    if (argc && argv)	handle_args(argc, argv, &init);    erts_mtrace_pre_init();#if HAVE_ERTS_MSEG    erts_mseg_init(&init.mseg);#endif    erts_alcu_init(&init.alloc_util);    erts_afalc_init();    erts_bfalc_init();    erts_gfalc_init();    for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {	erts_allctrs[i].alloc		= NULL;	erts_allctrs[i].realloc		= NULL;	erts_allctrs[i].free		= NULL;	erts_allctrs[i].extra		= NULL;	erts_allctrs_info[i].alloc_util	= 0;	erts_allctrs_info[i].enabled	= 0;	erts_allctrs_info[i].extra	= NULL;#ifdef ERTS_ALC_THR_SPEC_ALLOCS	erts_allctr_thr_spec[i].start	= NULL;#endif    }#ifdef ERTS_ALC_N_MIN_A_FIXED_SIZE#if !defined(PURIFY) && !defined(VALGRIND)    erts_allctrs[ERTS_ALC_A_FIXED_SIZE].alloc		= erts_fix_alloc;    erts_allctrs[ERTS_ALC_A_FIXED_SIZE].realloc		= erts_fix_realloc;    erts_allctrs[ERTS_ALC_A_FIXED_SIZE].free		= erts_fix_free;    erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].enabled	= 1;#else    erts_allctrs[ERTS_ALC_A_FIXED_SIZE].alloc		= erts_sys_alloc;    erts_allctrs[ERTS_ALC_A_FIXED_SIZE].realloc		= erts_sys_realloc;    erts_allctrs[ERTS_ALC_A_FIXED_SIZE].free		= erts_sys_free;    erts_allctrs_info[ERTS_ALC_A_FIXED_SIZE].enabled	= 0;#endif#endif    erts_allctrs[ERTS_ALC_A_SYSTEM].alloc		= erts_sys_alloc;    erts_allctrs[ERTS_ALC_A_SYSTEM].realloc		= erts_sys_realloc;    erts_allctrs[ERTS_ALC_A_SYSTEM].free		= erts_sys_free;    erts_allctrs_info[ERTS_ALC_A_SYSTEM].enabled	= 1;    set_au_allocator(&erts_allctrs[ERTS_ALC_A_TEMPORARY],		     &erts_allctrs_info[ERTS_ALC_A_TEMPORARY],		     &init.temp_alloc,		     &erts_allctrs[ERTS_ALC_A_SYSTEM]);    set_au_allocator(&erts_allctrs[ERTS_ALC_A_SHORT_LIVED],		     &erts_allctrs_info[ERTS_ALC_A_SHORT_LIVED],		     &init.sl_alloc,		     &erts_allctrs[ERTS_ALC_A_SYSTEM]);    set_au_allocator(&erts_allctrs[ERTS_ALC_A_STANDARD],		     &erts_allctrs_info[ERTS_ALC_A_STANDARD],		     &init.std_alloc,		     &erts_allctrs[ERTS_ALC_A_SYSTEM]);    set_au_allocator(&erts_allctrs[ERTS_ALC_A_LONG_LIVED],		     &erts_allctrs_info[ERTS_ALC_A_LONG_LIVED],		     &init.ll_alloc,		     &erts_allctrs[ERTS_ALC_A_SYSTEM]);    set_au_allocator(&erts_allctrs[ERTS_ALC_A_EHEAP],		     &erts_allctrs_info[ERTS_ALC_A_EHEAP],		     &init.eheap_alloc,		     &erts_allctrs[ERTS_ALC_A_SYSTEM]);    set_au_allocator(&erts_allctrs[ERTS_ALC_A_BINARY],		     &erts_allctrs_info[ERTS_ALC_A_BINARY],		     &init.binary_alloc,		     &erts_allctrs[ERTS_ALC_A_SYSTEM]);    set_au_allocator(&erts_allctrs[ERTS_ALC_A_ETS],		     &erts_allctrs_info[ERTS_ALC_A_ETS],		     &init.ets_alloc,		     &erts_allctrs[ERTS_ALC_A_SYSTEM]);    for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {	if (!erts_allctrs[i].alloc)	    erl_exit(ERTS_ABORT_EXIT,		     "Missing alloc function for %s\n", ERTS_ALC_A2AD(i));	if (!erts_allctrs[i].realloc)	    erl_exit(ERTS_ABORT_EXIT,		     "Missing realloc function for %s\n", ERTS_ALC_A2AD(i));	if (!erts_allctrs[i].free)	    erl_exit(ERTS_ABORT_EXIT,		     "Missing free function for %s\n", ERTS_ALC_A2AD(i));    }    sys_alloc_opt(SYS_ALLOC_OPT_TRIM_THRESHOLD, init.trim_threshold);    sys_alloc_opt(SYS_ALLOC_OPT_TOP_PAD, init.top_pad);    if (erts_allctrs_info[ERTS_FIX_CORE_ALLOCATOR].enabled)	erts_fix_core_allocator_ix = ERTS_FIX_CORE_ALLOCATOR;    else	erts_fix_core_allocator_ix = ERTS_ALC_A_SYSTEM;    erts_mtrace_init(init.instr.mtrace, init.instr.nodename);    start_au_allocator(&erts_allctrs[ERTS_ALC_A_TEMPORARY],		       &erts_allctrs_info[ERTS_ALC_A_TEMPORARY],		       &init.temp_alloc,		       &temp_alloc_state);    start_au_allocator(&erts_allctrs[ERTS_ALC_A_SHORT_LIVED],		       &erts_allctrs_info[ERTS_ALC_A_SHORT_LIVED],		       &init.sl_alloc,		       &sl_alloc_state);    start_au_allocator(&erts_allctrs[ERTS_ALC_A_STANDARD],		       &erts_allctrs_info[ERTS_ALC_A_STANDARD],		       &init.std_alloc,		       &std_alloc_state);    start_au_allocator(&erts_allctrs[ERTS_ALC_A_LONG_LIVED],		       &erts_allctrs_info[ERTS_ALC_A_LONG_LIVED],		       &init.ll_alloc,		       &ll_alloc_state);    start_au_allocator(&erts_allctrs[ERTS_ALC_A_EHEAP],		       &erts_allctrs_info[ERTS_ALC_A_EHEAP],		       &init.eheap_alloc,		       &eheap_alloc_state);    start_au_allocator(&erts_allctrs[ERTS_ALC_A_BINARY],		       &erts_allctrs_info[ERTS_ALC_A_BINARY],		       &init.binary_alloc,		       &binary_alloc_state);    start_au_allocator(&erts_allctrs[ERTS_ALC_A_ETS],		       &erts_allctrs_info[ERTS_ALC_A_ETS],		       &init.ets_alloc,		       &ets_alloc_state);    fix_core_allocator	= erts_allctrs[erts_fix_core_allocator_ix].alloc;    fix_core_extra	= erts_allctrs[erts_fix_core_allocator_ix].extra;    erts_mtrace_install_wrapper_functions();    extra_block_size += erts_instr_init(init.instr.stat, init.instr.map);#ifdef DEBUG    extra_block_size += install_debug_functions();#endif#ifdef ERTS_ALC_N_MIN_A_FIXED_SIZE    erts_init_fix_alloc(extra_block_size, fix_core_alloc);#if !defined(PURIFY) && !defined(VALGRIND)    erts_set_fix_size(ERTS_ALC_T_PROC,		sizeof(Process));    erts_set_fix_size(ERTS_ALC_T_DB_TABLE,	sizeof(DbTable));    erts_set_fix_size(ERTS_ALC_T_ATOM,		sizeof(Atom));    erts_set_fix_size(ERTS_ALC_T_EXPORT,	sizeof(Export));    erts_set_fix_size(ERTS_ALC_T_MODULE,	sizeof(Module));    erts_set_fix_size(ERTS_ALC_T_REG_PROC,	sizeof(RegProc));    erts_set_fix_size(ERTS_ALC_T_MONITOR_SH,	ERTS_MONITOR_SH_SIZE*sizeof(Uint));    erts_set_fix_size(ERTS_ALC_T_NLINK_SH,	ERTS_LINK_SH_SIZE*sizeof(Uint));    erts_set_fix_size(ERTS_ALC_T_PROC_LIST,	sizeof(ProcessList));    erts_set_fix_size(ERTS_ALC_T_FUN_ENTRY,	sizeof(ErlFunEntry));#ifdef ERTS_ALC_T_DRV_EV_D_STATE    erts_set_fix_size(ERTS_ALC_T_DRV_EV_D_STATE,		      sizeof(ErtsDrvEventDataState));#endif#ifdef ERTS_ALC_T_DRV_SEL_D_STATE    erts_set_fix_size(ERTS_ALC_T_DRV_SEL_D_STATE,		      sizeof(ErtsDrvSelectDataState));#endif#endif#endif}static voidset_au_allocator(ErtsAllocatorFunctions_t *af,		 ErtsAllocatorInfo_t *ai,		 struct au_init *init,		 ErtsAllocatorFunctions_t *disable_af){    if (!init->enable) {	sys_memcpy((void *) af,		   (void *) disable_af,		   sizeof(ErtsAllocatorFunctions_t));	ai->alloc_util	= 0;	ai->enabled	= 0;	ai->extra	= NULL;	return;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?