diff options
author | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
---|---|---|
committer | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
commit | 84adefa331c4159d432d22840663c38f155cd4c1 (patch) | |
tree | bff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/erl_interface/src/legacy/erl_fix_alloc.c | |
download | otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2 otp-84adefa331c4159d432d22840663c38f155cd4c1.zip |
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/erl_interface/src/legacy/erl_fix_alloc.c')
-rw-r--r-- | lib/erl_interface/src/legacy/erl_fix_alloc.c | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/lib/erl_interface/src/legacy/erl_fix_alloc.c b/lib/erl_interface/src/legacy/erl_fix_alloc.c new file mode 100644 index 0000000000..20f3024e41 --- /dev/null +++ b/lib/erl_interface/src/legacy/erl_fix_alloc.c @@ -0,0 +1,193 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1996-2009. All Rights Reserved. + * + * 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 online 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. + * + * %CopyrightEnd% + */ +/* + * 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: + */ |