📄 fix_alloc.c
字号:
/* ``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$ *//* General purpose Memory allocator for fixed block size objects *//* This allocater is at least an order of magnitude faster than malloc() */#define NOPERBLOCK 20#ifdef HAVE_CONFIG_H# include "config.h"#endif#include "sys.h"#include "erl_vm.h"#include "global.h"#include "erl_db.h"#ifdef ERTS_ALC_N_MIN_A_FIXED_SIZE#if ERTS_ALC_MTA_FIXED_SIZE#include "erl_threads.h"#include "erl_smp.h"# ifdef ERTS_SMP# define FA_LOCK(FA) erts_smp_spin_lock(&(FA)->slck)# define FA_UNLOCK(FA) erts_smp_spin_unlock(&(FA)->slck)# else# define FA_LOCK(FA) erts_mtx_lock(&(FA)->mtx)# define FA_UNLOCK(FA) erts_mtx_unlock(&(FA)->mtx)# endif#else# define FA_LOCK(FA)# define FA_UNLOCK(FA)#endiftypedef union {double d; long l;} align_t;typedef struct fix_alloc_block { struct fix_alloc_block *next; align_t mem[1];} FixAllocBlock;typedef struct fix_alloc { Uint item_size; void *freelist; Uint no_free; Uint no_blocks; FixAllocBlock *blocks;#if ERTS_ALC_MTA_FIXED_SIZE# ifdef ERTS_SMP erts_smp_spinlock_t slck;# else erts_mtx_t mtx;# endif#endif} FixAlloc;static void *(*core_alloc)(Uint); static Uint xblk_sz;static FixAlloc **fa;#define FA_SZ (1 + ERTS_ALC_N_MAX_A_FIXED_SIZE - ERTS_ALC_N_MIN_A_FIXED_SIZE)#define FIX_IX(N) ((N) - ERTS_ALC_N_MIN_A_FIXED_SIZE)#define FIX_POOL_SZ(I_SZ) \ ((I_SZ)*NOPERBLOCK + sizeof(FixAllocBlock) - sizeof(align_t))#if defined(DEBUG) && !ERTS_ALC_MTA_FIXED_SIZEstatic int first_time;#endifvoid erts_init_fix_alloc(Uint extra_block_size, void *(*alloc)(Uint)){ int i; xblk_sz = extra_block_size; core_alloc = alloc; fa = (FixAlloc **) (*core_alloc)(FA_SZ * sizeof(FixAlloc *)); if (!fa) erts_alloc_enomem(ERTS_ALC_T_UNDEF, FA_SZ * sizeof(FixAlloc *)); for (i = 0; i < FA_SZ; i++) fa[i] = NULL;#if defined(DEBUG) && !ERTS_ALC_MTA_FIXED_SIZE first_time = 1;#endif}Uinterts_get_fix_size(ErtsAlcType_t type){ Uint i = FIX_IX(ERTS_ALC_T2N(type)); return i < FA_SZ && fa[i] ? fa[i]->item_size : 0;}voiderts_set_fix_size(ErtsAlcType_t type, Uint size){ Uint sz; Uint i; FixAlloc *fs; ErtsAlcType_t t_no = ERTS_ALC_T2N(type); sz = xblk_sz + size;#ifdef DEBUG ASSERT(ERTS_ALC_N_MIN_A_FIXED_SIZE <= t_no); ASSERT(t_no <= ERTS_ALC_N_MAX_A_FIXED_SIZE);#endif while (sz % sizeof(align_t) != 0) /* Alignment */ sz++; i = FIX_IX(t_no); fs = (FixAlloc *) (*core_alloc)(sizeof(FixAlloc)); if (!fs) erts_alloc_n_enomem(t_no, sizeof(FixAlloc)); fs->item_size = sz; fs->no_blocks = 0; fs->no_free = 0; fs->blocks = NULL; fs->freelist = NULL; if (fa[i]) erl_exit(-1, "Attempt to overwrite existing fix size (%d)", i); fa[i] = fs;#if ERTS_ALC_MTA_FIXED_SIZE#ifdef ERTS_SMP erts_smp_spinlock_init_x(&fs->slck, "fix_alloc", make_small(i));#else erts_mtx_init_x(&fs->mtx, "fix_alloc", make_small(i));#endif#endif}voiderts_fix_info(ErtsAlcType_t type, ErtsFixInfo *efip){ Uint i; FixAlloc *f;#ifdef DEBUG FixAllocBlock *b; void *fp;#endif Uint real_item_size; ErtsAlcType_t t_no = ERTS_ALC_T2N(type); ASSERT(ERTS_ALC_N_MIN_A_FIXED_SIZE <= t_no); ASSERT(t_no <= ERTS_ALC_N_MAX_A_FIXED_SIZE); i = FIX_IX(t_no); f = fa[i]; efip->total = sizeof(FixAlloc *); efip->used = 0; if (!f) return; real_item_size = f->item_size - xblk_sz; FA_LOCK(f); efip->total += sizeof(FixAlloc); efip->total += f->no_blocks*FIX_POOL_SZ(real_item_size); efip->used = efip->total - f->no_free*real_item_size;#ifdef DEBUG ASSERT(efip->total >= efip->used); for(i = 0, b = f->blocks; b; i++, b = b->next); ASSERT(f->no_blocks == i); for (i = 0, fp = f->freelist; fp; i++, fp = *((void **) fp)); ASSERT(f->no_free == i);#endif FA_UNLOCK(f);}voiderts_fix_free(ErtsAlcType_t t_no, void *extra, void* ptr){ Uint i; FixAlloc *f; ASSERT(ERTS_ALC_N_MIN_A_FIXED_SIZE <= t_no); ASSERT(t_no <= ERTS_ALC_N_MAX_A_FIXED_SIZE); i = FIX_IX(t_no); f = fa[i]; FA_LOCK(f); *((void **) ptr) = f->freelist; f->freelist = ptr; f->no_free++; FA_UNLOCK(f);}void *erts_fix_realloc(ErtsAlcType_t t_no, void *extra, void* ptr, Uint size){ erts_alc_fatal_error(ERTS_ALC_E_NOTSUP, ERTS_ALC_O_REALLOC, t_no); return NULL;}void *erts_fix_alloc(ErtsAlcType_t t_no, void *extra, Uint size){ void *ret; int i; FixAlloc *f;#if defined(DEBUG) && !ERTS_ALC_MTA_FIXED_SIZE ASSERT(ERTS_ALC_N_MIN_A_FIXED_SIZE <= t_no); ASSERT(t_no <= ERTS_ALC_N_MAX_A_FIXED_SIZE); if (first_time) { /* Check that all sizes have been initialized */ int i; for (i = 0; i < FA_SZ; i++) ASSERT(fa[i]); first_time = 0; }#endif i = FIX_IX(t_no); f = fa[i]; ASSERT(f); ASSERT(f->item_size >= size); FA_LOCK(f); if (f->freelist == NULL) { /* Gotta alloc some more mem */ char *ptr; FixAllocBlock *bl; Uint n; FA_UNLOCK(f); bl = (*core_alloc)(FIX_POOL_SZ(f->item_size)); if (!bl) return NULL; FA_LOCK(f); bl->next = f->blocks; /* link in first */ f->blocks = bl; n = NOPERBLOCK; ptr = (char *) &f->blocks->mem[0]; while(n--) { *((void **) ptr) = f->freelist; f->freelist = (void *) ptr; ptr += f->item_size; }#if !ERTS_ALC_MTA_FIXED_SIZE ASSERT(f->no_free == 0);#endif f->no_free += NOPERBLOCK; f->no_blocks++; } ret = f->freelist; f->freelist = *((void **) f->freelist); ASSERT(f->no_free > 0); f->no_free--; FA_UNLOCK(f); return ret;}#endif /* #ifdef ERTS_ALC_N_MIN_A_FIXED_SIZE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -