📄 elib_malloc.c
字号:
erts_mtx_lock(&malloc_mutex); if (elib_need_init) locked_elib_init(NULL,(EWord)0); if (p != 0) { pp = (AllocatedBlock*) (p-1); if (nb > 0) { if ((pp = reallocate(pp, nb, 1)) != 0) { ELIB_ALIGN_CHECK(pp->v); res = pp->v; } } else deallocate(pp, 1); } else if (nb > 0) { if ((pp = allocate(nb, ELIB_ALIGN, 0)) != 0) { ELIB_ALIGN_CHECK(pp->v); res = pp->v; } else res = heap_exhausted(); } erts_mtx_unlock(&malloc_mutex); return res;}/*** Resize the memory area pointed to by p with nb number of bytes*/void* ELIB_PREFIX(memresize, (EWord* p, int nb)){ void *res = NULL; AllocatedBlock* pp; erts_mtx_lock(&malloc_mutex); if (elib_need_init) locked_elib_init(NULL,(EWord)0); if (p != 0) { pp = (AllocatedBlock*) (p-1); if (nb > 0) { if ((pp = reallocate(pp, nb, 0)) != 0) { ELIB_ALIGN_CHECK(pp->v); res = pp->v; } } else deallocate(pp, 1); } else if (nb > 0) { if ((pp = allocate(nb, ELIB_ALIGN, 0)) != 0) { ELIB_ALIGN_CHECK(pp->v); res = pp->v; } else res = heap_exhausted(); } erts_mtx_unlock(&malloc_mutex); return res;}/* Create aligned memory a must be a power of 2 !!! */void* ELIB_PREFIX(memalign, (int a, int nb)){ void *res; AllocatedBlock* p; erts_mtx_lock(&malloc_mutex); if (elib_need_init) locked_elib_init(NULL,(EWord)0); if (nb == 0 || a <= 0) res = NULL; else if ((p = allocate(nb, a, 0)) != 0) { ALIGN_CHECK(a, p->v); res = p->v; } else res = heap_exhausted(); erts_mtx_unlock(&malloc_mutex); return res;}void* ELIB_PREFIX(valloc, (int nb)){ return ELIB_PREFIX(memalign, (page_size, nb));}void* ELIB_PREFIX(pvalloc, (int nb)){ return ELIB_PREFIX(memalign, (page_size, PAGES(nb)*page_size));}/* Return memory size for pointer p in bytes */int ELIB_PREFIX(memsize, (p))EWord* p;{ return SIZEOF((AllocatedBlock*)(p-1))*4;}/*** --------------------------------------------------------------------------** DEBUG LIBRARY** --------------------------------------------------------------------------*/#ifdef ELIB_DEBUG#define IN_HEAP(p) (((p) >= (char*) eheap) && (p) < (char*) eheap_top)/*** ptr_to_block: return the pointer to heap block pointed into by ptr** Returns 0 if not pointing into a block*/static EWord* ptr_to_block(char* ptr){ AllocatedBlock* p = heap_head; EWord sz; while((sz = SIZEOF(p)) != 0) { if ((ptr >= (char*) p->v) && (ptr < (char*)(p->v+sz))) return p->v; p = (AllocatedBlock*) (p->v + sz); } return 0;}/*** Validate a pointer** returns:** 0 - if points to start of a block** 1 - if points outsize heap** -1 - if points inside block***/static int check_pointer(char* ptr){ if (IN_HEAP(ptr)) { if (ptr_to_block(ptr) == 0) return 1; return 0; } return -1;}/*** Validate a memory area** returns:** 0 - if area is included in a block** -1 - if area overlap a heap block** 1 - if area is outside heap*/static int check_area(char* ptr, int n){ if (IN_HEAP(ptr)) { if (IN_HEAP(ptr+n-1)) { EWord* p1 = ptr_to_block(ptr); EWord* p2 = ptr_to_block(ptr+n-1); if (p1 == p2) return (p1 == 0) ? -1 : 0; return -1; } } else if (IN_HEAP(ptr+n-1)) return -1; return 1;}/*** Check if a block write will overwrite heap block*/static void check_write(char* ptr, int n, char* file, int line, char* fun){ if (check_area(ptr, n) == -1) { elib_printf(stderr, "RUNTIME ERROR: %s heap overwrite\n", fun); elib_printf(stderr, "File: %s Line: %d\n", file, line); ELIB_FAILURE; }}/*** Check if a pointer is an allocated object*/static void check_allocated_block(char* ptr, char* file, int line, char* fun){ EWord* q; if (!IN_HEAP(ptr) || ((q=ptr_to_block(ptr)) == 0) || (ptr != (char*) q)) { elib_printf(stderr, "RUNTIME ERROR: %s non heap pointer\n", fun); elib_printf(stderr, "File: %s Line: %d\n", file, line); ELIB_FAILURE; } if (IS_FREE((AllocatedBlock*)(q-1))) { elib_printf(stderr, "RUNTIME ERROR: %s free pointer\n", fun); elib_printf(stderr, "File: %s Line: %d\n", file, line); ELIB_FAILURE; }}/*** --------------------------------------------------------------------------** DEBUG VERSIONS (COMPILED WITH THE ELIB.H)** --------------------------------------------------------------------------*/void* elib_dbg_malloc(int n, char* file, int line){ return elib__malloc(n);}void* elib_dbg_calloc(int n, int s, char* file, int line){ return elib__calloc(n, s);}void* elib_dbg_realloc(EWord* p, int n, char* file, int line){ if (p == 0) return elib__malloc(n); check_allocated_block(p, file, line, "elib_realloc"); return elib__realloc(p, n);}void elib_dbg_free(EWord* p, char* file, int line){ if (p == 0) return; check_allocated_block(p, file, line, "elib_free"); elib__free(p);}void elib_dbg_cfree(EWord* p, char* file, int line){ if (p == 0) return; check_allocated_block(p, file, line, "elib_free"); elib__cfree(p);}void* elib_dbg_memalign(int a, int n, char* file, int line){ return elib__memalign(a, n);}void* elib_dbg_valloc(int n, char* file, int line){ return elib__valloc(n);}void* elib_dbg_pvalloc(int n, char* file, int line){ return elib__pvalloc(n);}void* elib_dbg_memresize(EWord* p, int n, char* file, int line){ if (p == 0) return elib__malloc(n); check_allocated_block(p, file, line, "elib_memresize"); return elib__memresize(p, n);}int elib_dbg_memsize(void* p, char* file, int line){ check_allocated_block(p, file, line, "elib_memsize"); return elib__memsize(p);}/*** --------------------------------------------------------------------------** LINK TIME FUNCTIONS (NOT COMPILED CALLS)** --------------------------------------------------------------------------*/void* elib_malloc(int n){ return elib_dbg_malloc(n, "", -1);}void* elib_calloc(int n, int s){ return elib_dbg_calloc(n, s, "", -1);}void* elib_realloc(EWord* p, int n){ return elib_dbg_realloc(p, n, "", -1);}void elib_free(EWord* p){ elib_dbg_free(p, "", -1);}void elib_cfree(EWord* p){ elib_dbg_cfree(p, "", -1);}void* elib_memalign(int a, int n){ return elib_dbg_memalign(a, n, "", -1);}void* elib_valloc(int n){ return elib_dbg_valloc(n, "", -1);}void* elib_pvalloc(int n){ return elib_dbg_pvalloc(n, "", -1);}void* elib_memresize(EWord* p, int n){ return elib_dbg_memresize(p, n, "", -1);}int elib_memsize(EWord* p){ return elib_dbg_memsize(p, "", -1);}#endif /* ELIB_DEBUG *//*** --------------------------------------------------------------------------** Map c library functions to elib** --------------------------------------------------------------------------*/#if defined(ELIB_ALLOC_IS_CLIB)void* malloc(size_t nb){ return elib_malloc(nb);}void* calloc(size_t nelem, size_t size){ return elib_calloc(nelem, size);}void free(void *p){ elib_free(p);}void cfree(void *p){ elib_cfree(p);}void* realloc(void* p, size_t nb){ return elib_realloc(p, nb);}void* memalign(size_t a, size_t s){ return elib_memalign(a, s);}void* valloc(size_t nb){ return elib_valloc(nb);}void* pvalloc(size_t nb){ return elib_pvalloc(nb);}#if 0void* memresize(void* p, int nb){ return elib_memresize(p, nb);}int memsize(void* p){ return elib_memsize(p);}#endif#endif /* ELIB_ALLOC_IS_CLIB */#endif /* ENABLE_ELIB_MALLOC */void elib_ensure_initialized(void){#ifdef ENABLE_ELIB_MALLOC#ifndef ELIB_DONT_INITIALIZE elib_init(NULL, 0);#endif#endif}#ifdef ENABLE_ELIB_MALLOC/** ** A Slightly modified version of the "address order best fit" algorithm ** used in erl_bestfit_alloc.c. Comments refer to that implementation. **//* * Description: A combined "address order best fit"/"best fit" allocator * based on a Red-Black (binary search) Tree. The search, * insert, and delete operations are all O(log n) operations * on a Red-Black Tree. In the "address order best fit" case * n equals number of free blocks, and in the "best fit" case * n equals number of distinct sizes of free blocks. Red-Black * Trees are described in "Introduction to Algorithms", by * Thomas H. Cormen, Charles E. Leiserson, and * Ronald L. Riverest. * * This module is a callback-module for erl_alloc_util.c * * Author: Rickard Green */#ifdef DEBUG#if 0#define HARD_DEBUG#endif#else#undef HARD_DEBUG#endif#define SZ_MASK SIZE_MASK#define FLG_MASK (~(SZ_MASK))#define BLK_SZ(B) (*((Block_t *) (B)) & SZ_MASK)#define TREE_NODE_FLG (((Uint) 1) << 0)#define RED_FLG (((Uint) 1) << 1)#ifdef HARD_DEBUG# define LEFT_VISITED_FLG (((Uint) 1) << 2)# define RIGHT_VISITED_FLG (((Uint) 1) << 3)#endif#define IS_TREE_NODE(N) (((RBTree_t *) (N))->flags & TREE_NODE_FLG)#define IS_LIST_ELEM(N) (!IS_TREE_NODE(((RBTree_t *) (N))))#define SET_TREE_NODE(N) (((RBTree_t *) (N))->flags |= TREE_NODE_FLG)#define SET_LIST_ELEM(N) (((RBTree_t *) (N))->flags &= ~TREE_NODE_FLG)#define IS_RED(N) (((RBTree_t *) (N)) \ && ((RBTree_t *) (N))->flags & RED_FLG)#define IS_BLACK(N) (!IS_RED(((RBTree_t *) (N))))#define SET_RED(N) (((RBTree_t *) (N))->flags |= RED_FLG)#define SET_BLACK(N) (((RBTree_t *) (N))->flags &= ~RED_FLG)#undef ASSERT#define ASSERT ASSERT_EXPR#if 1#define RBT_ASSERT ASSERT#else#define RBT_ASSERT(x)#endif#ifdef HARD_DEBUGstatic RBTree_t * check_tree(Uint);#endif#ifdef ERTS_INLINE# ifndef ERTS_CAN_INLINE# define ERTS_CAN_INLINE 1# endif#else# if defined(__GNUC__)# define ERTS_CAN_INLINE 1# define ERTS_INLINE __inline__# elif defined(__WIN32__)# define ERTS_CAN_INLINE 1# define ERTS_INLINE __inline# else# define ERTS_CAN_INLINE 0# define ERTS_INLINE# endif#endif/* Types... */#if 0typedef struct RBTree_t_ RBTree_t;struct RBTree_t_ { Block_t hdr; Uint flags; RBTree_t *parent; RBTree_t *left; RBTree_t *right;};#endif#if 0typedef struct { RBTree_t t; RBTree_t *next;} RBTreeList_t;#define LIST_NEXT(N) (((RBTreeList_t *) (N))->next)#define LIST_PREV(N) (((RBTreeList_t *) (N))->t.parent)#endif#ifdef DEBUG/* Destroy all tree fields */#define DESTROY_TREE_NODE(N) \ sys_memset((void *) (((Block_t *) (N)) + 1), \ 0xff, \ (sizeof(RBTree_t) - sizeof(Block_t)))/* Destroy all tree and list fields */#define DESTROY_LIST_ELEM(N) \ sys_memset((void *) (((Block_t *) (N)) + 1), \ 0xff, \ (sizeof(RBTreeList_t) - sizeof(Block_t)))#else#define DESTROY_TREE_NODE(N)#define DESTROY_LIST_ELEM(N)#endif/* * Red-Black Tree operations needed */static ERTS_INLINE voidleft_rotate(RBTree_t **root, RBTree_t *x){ RBTree_t *y = x->right; x->right = y->left; if (y->left) y->left->parent = x; y->parent = x->parent; if (!y->parent) { RBT_ASSERT(*root == x); *root = y; } else if (x == x->parent->left) x->parent->left = y; else { RBT_ASSERT(x == x->parent->right); x->parent->right = y; } y->left = x; x->parent = y;}static ERTS_INLINE voidright_rotate(RBTree_t **root, RBTree_t *x){ RBTree_t *y = x->left; x->left = y->right; if (y->right) y->right->parent = x; y->parent = x->parent; if (!y->parent) { RBT_ASSERT(*root == x); *root = y; } else if (x == x->parent->right)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -