aboutsummaryrefslogtreecommitdiffstats
path: root/lib/erl_interface/src/legacy/erl_fix_alloc.c
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
committerErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/erl_interface/src/legacy/erl_fix_alloc.c
downloadotp-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.c193
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:
+ */