aboutsummaryrefslogtreecommitdiffstats
path: root/lib/erl_interface/src/legacy/erl_malloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/erl_interface/src/legacy/erl_malloc.c')
-rw-r--r--lib/erl_interface/src/legacy/erl_malloc.c239
1 files changed, 239 insertions, 0 deletions
diff --git a/lib/erl_interface/src/legacy/erl_malloc.c b/lib/erl_interface/src/legacy/erl_malloc.c
new file mode 100644
index 0000000000..f51a6c69b3
--- /dev/null
+++ b/lib/erl_interface/src/legacy/erl_malloc.c
@@ -0,0 +1,239 @@
+/*
+ * %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%
+ */
+
+#include "eidef.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "erl_interface.h"
+#include "erl_fix_alloc.h"
+#include "erl_malloc.h"
+#include "erl_internal.h"
+#include "erl_eterm.h"
+#include "ei_malloc.h"
+
+void erl_init_malloc(Erl_Heap *hp, long heap_size)
+{
+ erl_init_eterm_alloc();
+} /* erl_init_malloc */
+
+ETERM *erl_alloc_eterm(unsigned char type)
+{
+ ETERM *e;
+
+ /* Use fix size allocator */
+ if (!(e = (ETERM *) erl_eterm_alloc()))
+ erl_err_sys("<ERROR> erl_alloc_eterm: Failed to allocate more memory\n");
+
+ ERL_HEADER(e)->count = 0;
+ ERL_HEADER(e)->type = type;
+ return e;
+
+} /* erl_alloc_eterm */
+
+#define EXTERNAL 1
+#define INTERNAL 0
+#define COMPOUND 1
+#define NOT_COMPOUND 0
+
+static void _erl_free_term (ETERM *ep, int external, int compound);
+
+/*
+ * Free a term, but don't deallocate it until
+ * the reference counter triggers.
+ */
+void erl_free_term(ETERM *ep)
+{
+ _erl_free_term(ep, EXTERNAL, NOT_COMPOUND);
+} /* erl_free_term */
+
+/*
+ * Free a term regardless of its reference
+ * counter value. Use this when you have
+ * built compound terms such as lists or tuples.
+ */
+
+/*
+ * FIXME is this true?!
+ * Tearing down term structures no-matter-what is a horrible idea if
+ * any term happens to be shared (with some other structure or even
+ * with yourself).
+ */
+
+void erl_free_compound (ETERM *ep)
+{
+ _erl_free_term(ep, EXTERNAL, COMPOUND);
+} /* erl_free_compound */
+
+
+/*
+** The actual free'ing is done here in _erl_free_term.
+** It is by nature recursive, but does not recurse
+** on the CDR of a list, which makes it usable for large lists.
+*/
+
+/*
+** Convenience macro, called for variables and lists,
+** avoids deep recursions.
+*/
+#define RESTART(Eterm, External, Compound) \
+do { \
+ ETERM *sep; \
+ sep = (Eterm); \
+ external = (External); \
+ compound = (Compound); \
+ /* Clear header info */ \
+ ERL_TYPE(ep) = ERL_UNDEF; \
+ erl_eterm_free((unsigned int *) ep); \
+ ep = sep; \
+ goto restart; \
+} while(0)
+
+#define FREE_AND_CLEAR(ptr) \
+do { \
+ erl_free(ptr); \
+ (ptr) = NULL; \
+} while (0)
+
+static void _erl_free_term (ETERM *ep, int external, int compound)
+{
+restart:
+ if (ep == NULL)
+ return;
+ if (compound || ERL_NO_REF(ep)) {
+ /* Yes, it's time to *really* free this one ! */
+ switch(ERL_TYPE(ep))
+ {
+ case ERL_ATOM:
+ FREE_AND_CLEAR(ERL_ATOM_PTR(ep));
+ break;
+ case ERL_VARIABLE:
+ FREE_AND_CLEAR(ERL_VAR_NAME(ep));
+ /* Note: It may be unbound ! */
+ if (ERL_VAR_VALUE(ep) != NULL) {
+ ERL_COUNT(ERL_VAR_VALUE(ep))--;
+ /* Cleanup and Restart with the actual value */
+ RESTART(ERL_VAR_VALUE(ep), INTERNAL, compound);
+ }
+ break;
+ case ERL_LIST:
+ if (HEAD(ep)) {
+ ERL_COUNT(HEAD(ep))--;
+ /* FIXME added cast, is this correct? */
+ _erl_free_term((ETERM *)HEAD(ep), INTERNAL, compound);
+ }
+ if (TAIL(ep)) {
+ ERL_COUNT(TAIL(ep))--;
+ /* Clean up and walk on to CDR in list */
+ RESTART(TAIL(ep), INTERNAL, compound);
+ }
+ break;
+ case ERL_TUPLE:
+ {
+ int i;
+ for (i=0; i < ERL_TUPLE_SIZE(ep); i++)
+ if (ERL_TUPLE_ELEMENT(ep, i)) {
+ ERL_COUNT(ERL_TUPLE_ELEMENT(ep, i))--;
+ _erl_free_term(ERL_TUPLE_ELEMENT(ep, i),
+ INTERNAL, compound);
+ }
+ FREE_AND_CLEAR(ERL_TUPLE_ELEMS(ep));
+ }
+ break;
+ case ERL_BINARY:
+ FREE_AND_CLEAR(ERL_BIN_PTR(ep));
+ break;
+ case ERL_PID:
+ FREE_AND_CLEAR(ERL_PID_NODE(ep));
+ break;
+ case ERL_PORT:
+ FREE_AND_CLEAR(ERL_PORT_NODE(ep));
+ break;
+ case ERL_REF:
+ FREE_AND_CLEAR(ERL_REF_NODE(ep));
+ break;
+ case ERL_EMPTY_LIST:
+ case ERL_INTEGER:
+ case ERL_SMALL_BIG:
+ case ERL_U_SMALL_BIG:
+ case ERL_FLOAT:
+ break;
+ case ERL_FUNCTION:
+ {
+ int i;
+
+ _erl_free_term(ERL_FUN_INDEX(ep), INTERNAL, compound);
+ _erl_free_term(ERL_FUN_UNIQ(ep), INTERNAL, compound);
+ _erl_free_term(ERL_FUN_CREATOR(ep), INTERNAL, compound);
+ _erl_free_term(ERL_FUN_MODULE(ep), INTERNAL, compound);
+ if (ERL_CLOSURE(ep) != NULL) {
+ for (i = 0; i < ERL_CLOSURE_SIZE(ep); i++)
+ _erl_free_term(ERL_CLOSURE_ELEMENT(ep,i),
+ INTERNAL, compound);
+ }
+ }
+ break;
+ } /* switch */
+
+ /* Clear header info for those cases where we are done */
+ ERL_TYPE(ep) = ERL_UNDEF;
+ erl_eterm_free(ep);
+ } else if (external) {
+ ERL_COUNT(ep)--;
+ external = INTERNAL;
+ goto restart;
+ }
+} /* _erl_free_term */
+#undef RESTART
+#undef FREE_AND_CLEAR
+
+void erl_free_array(ETERM **arr, int size)
+{
+ int i;
+
+ for (i=0; i<size; i++)
+ erl_free_term(arr[i]);
+
+} /* erl_free_array */
+
+
+void* erl_malloc (long size)
+{
+ void *res;
+
+ if ((res = ei_malloc(size)) == NULL)
+ erl_err_sys("<ERROR> erl_malloc: Failed to allocate more memory");
+
+ return res;
+}
+
+void* erl_realloc(void* orig, long size)
+{
+ void *res;
+
+ if ((res = ei_realloc(orig, size)) == NULL)
+ erl_err_sys("<ERROR> erl_realloc: Failed to allocate more memory");
+ return res;
+}
+
+void erl_free (void *ptr)
+{
+ ei_free(ptr);
+}