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 + -
显示快捷键?