erl_fix_alloc.c
来自「OTP是开放电信平台的简称」· C语言 代码 · 共 193 行
C
193 行
/* ``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$ *//* * Function: General purpose Memory allocator for fixed block * size objects. This allocater is at least an order of * magnitude faster than malloc(). */#include "eidef.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include "ei_locking.h"#include "erl_interface.h"#include "erl_error.h"#include "erl_malloc.h"#include "erl_fix_alloc.h"#include "erl_eterm.h"#define WIPE_CHAR ((char)0xaa) /* 10101010 *//* the freelist is a singly linked list of these *//* i.e. the user structure and a link pointer */struct fix_block { ETERM term; struct fix_block *next; int free;};/* this is a struct just to keep namespace pollution low on VxWorks */struct eterm_stateinfo { struct fix_block *freelist; unsigned long freed; unsigned long allocated;#ifdef _REENTRANT ei_mutex_t *lock;#endif /* _REENTRANT */};/* FIXME problem for threaded ? */static struct eterm_stateinfo *erl_eterm_state=NULL;int erl_init_eterm_alloc (void){#if defined(PURIFY) && defined (DEBUG) fprintf(stderr,"erl_fix_alloc() compiled for Purify - using \"real\" malloc()");#endif erl_eterm_state = malloc(sizeof(*erl_eterm_state)); if (erl_eterm_state == NULL) goto err1; erl_eterm_state->freelist = NULL; erl_eterm_state->freed = 0; erl_eterm_state->allocated = 0;#ifdef _REENTRANT erl_eterm_state->lock = ei_mutex_create(); if (erl_eterm_state->lock == NULL) goto err2;#endif /* _REENTRANT */ return 1; /* Error cleanup */#ifdef _REENTRANT err2: /* FIXME ENOMEM is not what went wrong... */ free(erl_eterm_state);#endif /* _REENTRANT */ err1: erl_errno = ENOMEM; return 0;}/* get an eterm, from the freelist if possible or from malloc() */void *erl_eterm_alloc (void){#ifdef PURIFY ETERM *p; if ((p = malloc(sizeof(*p)))) { memset(p, WIPE_CHAR, sizeof(*p)); } return p;#else struct fix_block *b;#ifdef _REENTRANT ei_mutex_lock(erl_eterm_state->lock, 0);#endif /* _REENTRANT */ /* try to pop block from head of freelist */ if ((b = erl_eterm_state->freelist) != NULL) { erl_eterm_state->freelist = b->next; erl_eterm_state->freed--; } else if ((b = malloc(sizeof(*b))) == NULL) { erl_errno = ENOMEM; } erl_eterm_state->allocated++; b->free = 0; b->next = NULL;#ifdef _REENTRANT ei_mutex_unlock(erl_eterm_state->lock);#endif /* _REENTRANT */ return (void *) &b->term;#endif /* !PURIFY */}/* free an eterm back to the freelist */void erl_eterm_free(void *p){#ifdef PURIFY if (p) { memset(p, WIPE_CHAR, sizeof(ETERM)); } free(p);#else struct fix_block *b = p; if (b) { if (b->free) {#ifdef DEBUG fprintf(stderr,"erl_eterm_free: attempt to free already freed block %p\n",b);#endif return; }#ifdef _REENTRANT ei_mutex_lock(erl_eterm_state->lock,0);#endif /* _REENTRANT */ b->free = 1; b->next = erl_eterm_state->freelist; erl_eterm_state->freelist = b; erl_eterm_state->freed++; erl_eterm_state->allocated--;#ifdef _REENTRANT ei_mutex_unlock(erl_eterm_state->lock);#endif /* _REENTRANT */ }#endif /* !PURIFY */}/* really free the freelist */void erl_eterm_release (void){#if !defined(PURIFY) struct fix_block *b;#ifdef _REENTRANT ei_mutex_lock(erl_eterm_state->lock,0);#endif /* _REENTRANT */ { while (erl_eterm_state->freelist != NULL) { b = erl_eterm_state->freelist; erl_eterm_state->freelist = b->next; free(b); erl_eterm_state->freed--; } }#ifdef _REENTRANT ei_mutex_unlock(erl_eterm_state->lock);#endif /* _REENTRANT */#endif /* !PURIFY */}void erl_eterm_statistics (unsigned long *allocd, unsigned long *freed){ if (allocd) *allocd = erl_eterm_state->allocated; if (freed) *freed = erl_eterm_state->freed; return;}/* * Local Variables: * compile-command: "cd ..; ERL_TOP=/clearcase/otp/erts make -k" * End: */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?