mirror of
https://gitlab.com/embeddable-common-lisp/ecl.git
synced 2026-01-11 19:53:52 -08:00
291 lines
6.1 KiB
D
291 lines
6.1 KiB
D
/*
|
|
alloc_2.c -- Memory allocation based on the Boehmn GC.
|
|
*/
|
|
/*
|
|
Copyright (c) 2001, Juan Jose Garcia Ripoll.
|
|
|
|
ECLS is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
See file '../Copyright' for full details.
|
|
*/
|
|
|
|
#include "ecls.h"
|
|
#include "page.h"
|
|
|
|
/**********************************************************
|
|
* OBJECT ALLOCATION *
|
|
**********************************************************/
|
|
|
|
struct typemanager tm_table[(int)t_end];
|
|
|
|
#ifdef alloc_object
|
|
#undef alloc_object
|
|
#endif
|
|
|
|
cl_object
|
|
alloc_object(enum type t)
|
|
{
|
|
register cl_object obj;
|
|
register struct typemanager *tm;
|
|
|
|
switch (t) {
|
|
case t_fixnum:
|
|
return MAKE_FIXNUM(0); /* Immediate fixnum */
|
|
case t_character:
|
|
return code_char(' '); /* Immediate character */
|
|
default:
|
|
}
|
|
if (t < t_start || t >= t_end) {
|
|
printf("\ttype = %d\n", t);
|
|
error("alloc botch.");
|
|
}
|
|
tm = tm_of(t);
|
|
|
|
start_critical_section();
|
|
obj = GC_malloc(tm->tm_size);
|
|
obj->d.t = t;
|
|
/* GC_malloc already resets objects */
|
|
end_critical_section();
|
|
|
|
return obj;
|
|
}
|
|
|
|
#ifdef make_cons
|
|
#undef make_cons
|
|
#endif
|
|
|
|
cl_object
|
|
make_cons(cl_object a, cl_object d)
|
|
{
|
|
cl_object obj;
|
|
|
|
start_critical_section();
|
|
|
|
obj = GC_malloc(sizeof(struct cons));
|
|
obj->d.t = (short)t_cons;
|
|
CAR(obj) = a;
|
|
CDR(obj) = d;
|
|
|
|
end_critical_section();
|
|
|
|
return obj;
|
|
}
|
|
|
|
cl_object
|
|
alloc_instance(cl_index slots)
|
|
{
|
|
cl_object i;
|
|
i = alloc_object(t_instance);
|
|
i->instance.slots = alloc_align(sizeof(cl_object) * slots, sizeof(cl_object));
|
|
i->instance.length = slots;
|
|
return i;
|
|
}
|
|
|
|
void *
|
|
alloc(size_t n)
|
|
{
|
|
void *output;
|
|
start_critical_section();
|
|
output = GC_malloc(n);
|
|
end_critical_section();
|
|
return output;
|
|
}
|
|
|
|
void *
|
|
alloc_atomic(size_t n)
|
|
{
|
|
void *output;
|
|
start_critical_section();
|
|
output = GC_malloc_atomic(n);
|
|
end_critical_section();
|
|
return output;
|
|
}
|
|
|
|
/*
|
|
* adds a contblock to the list of available ones, pointed by cb_pointer,
|
|
* sorted by increasing size.
|
|
*/
|
|
void
|
|
dealloc(void *p, size_t s)
|
|
{
|
|
GC_free(p);
|
|
}
|
|
|
|
/*
|
|
* align must be a power of 2 representing the alignment boundary
|
|
* required for the block.
|
|
*/
|
|
void *
|
|
alloc_align(size_t size, size_t align)
|
|
{
|
|
char *output;
|
|
start_critical_section();
|
|
align--;
|
|
output = GC_malloc(size + align);
|
|
output = (char*)(((cl_fixnum)output + align) & ~align);
|
|
end_critical_section();
|
|
return output;
|
|
}
|
|
|
|
/*
|
|
* align must be a power of 2 representing the alignment boundary
|
|
* required for the block.
|
|
*/
|
|
void *
|
|
alloc_atomic_align(size_t size, size_t align)
|
|
{
|
|
char *output;
|
|
start_critical_section();
|
|
align--;
|
|
output = GC_malloc(size + align);
|
|
output = (char*)(((cl_fixnum)output + align) & ~align);
|
|
end_critical_section();
|
|
return output;
|
|
}
|
|
|
|
static void
|
|
init_tm(enum type t, char *name, size_t elsize)
|
|
{
|
|
struct typemanager *tm = &tm_table[(int)t];
|
|
tm->tm_name = name;
|
|
tm->tm_size = elsize;
|
|
}
|
|
|
|
static int alloc_initialized = FALSE;
|
|
|
|
void
|
|
init_alloc(void)
|
|
{
|
|
if (alloc_initialized) return;
|
|
alloc_initialized = TRUE;
|
|
|
|
init_tm(t_shortfloat, "SHORT-FLOAT", /* 8 */
|
|
sizeof(struct shortfloat_struct));
|
|
init_tm(t_cons, "CONS", sizeof(struct cons)); /* 12 */
|
|
init_tm(t_longfloat, "LONG-FLOAT", /* 16 */
|
|
sizeof(struct longfloat_struct));
|
|
init_tm(t_bytecodes, "bBYTECODES", sizeof(struct bytecodes));
|
|
init_tm(t_string, "STRING", sizeof(struct string)); /* 20 */
|
|
init_tm(t_array, "ARRAY", sizeof(struct array)); /* 24 */
|
|
init_tm(t_pathname, "PATHNAME", sizeof(struct pathname)); /* 28 */
|
|
init_tm(t_symbol, "SYMBOL", sizeof(struct symbol)); /* 32 */
|
|
init_tm(t_package, "PACKAGE", sizeof(struct package)); /* 36 */
|
|
init_tm(t_codeblock, "CODEBLOCK", sizeof(struct codeblock));
|
|
init_tm(t_bignum, "BIGNUM", sizeof(struct bignum));
|
|
init_tm(t_ratio, "RATIO", sizeof(struct ratio));
|
|
init_tm(t_complex, "COMPLEX", sizeof(struct complex));
|
|
init_tm(t_hashtable, "HASH-TABLE", sizeof(struct hashtable));
|
|
init_tm(t_vector, "VECTOR", sizeof(struct vector));
|
|
init_tm(t_bitvector, "BIT-VECTOR", sizeof(struct vector));
|
|
init_tm(t_stream, "STREAM", sizeof(struct stream));
|
|
init_tm(t_random, "RANDOM-STATE", sizeof(struct random));
|
|
init_tm(t_readtable, "READTABLE", sizeof(struct readtable));
|
|
init_tm(t_cfun, "CFUN", sizeof(struct cfun));
|
|
init_tm(t_cclosure, "CCLOSURE", sizeof(struct cclosure));
|
|
#ifndef CLOS
|
|
init_tm(t_structure, "STRUCTURE", sizeof(struct structure));
|
|
#else
|
|
init_tm(t_instance, "INSTANCE", sizeof(struct instance));
|
|
init_tm(t_gfun, "GFUN", sizeof(struct gfun));
|
|
#endif CLOS
|
|
#ifdef THREADS
|
|
init_tm(t_cont, "CONT", sizeof(struct cont));
|
|
init_tm(t_thread, "THREAD", sizeof(struct thread));
|
|
#endif THREADS
|
|
}
|
|
|
|
/**********************************************************
|
|
* MALLOC SUBSTITUTION *
|
|
**********************************************************/
|
|
|
|
#if 0 && defined(NEED_MALLOC)
|
|
#undef malloc
|
|
#undef calloc
|
|
#undef free
|
|
#undef cfree
|
|
#undef realloc
|
|
|
|
/* FIXME! Shouldn't this be thread safe? */
|
|
void *
|
|
malloc(size_t size)
|
|
{
|
|
return GC_malloc(size);
|
|
}
|
|
|
|
void
|
|
free(void *ptr)
|
|
{
|
|
GC_free(ptr);
|
|
}
|
|
|
|
void *
|
|
realloc(void *ptr, size_t size)
|
|
{
|
|
return GC_realloc(ptr, size);
|
|
}
|
|
|
|
void *
|
|
calloc(size_t nelem, size_t elsize)
|
|
{
|
|
char *ptr;
|
|
size_t i;
|
|
ptr = GC_malloc(i = nelem*elsize);
|
|
memset(ptr, 0 , i);
|
|
return ptr;
|
|
}
|
|
|
|
void
|
|
cfree(void *ptr)
|
|
{
|
|
GC_free(ptr);
|
|
}
|
|
|
|
#define ALLOC_ALIGNED(f, size, align) \
|
|
((align) <= 4 ? (int)(f)(size) : \
|
|
((align) * (((unsigned)(f)(size + (size ? (align) - 1 : 0)) + (align) - 1)/(align))))
|
|
|
|
void *
|
|
memalign(size_t align, size_t size)
|
|
{
|
|
return (void *)ALLOC_ALIGNED(GC_malloc, size, align);
|
|
}
|
|
|
|
# ifdef WANT_VALLOC
|
|
char *
|
|
valloc(size_t size)
|
|
{
|
|
return memalign(getpagesize(), size);
|
|
}
|
|
# endif WANT_VALLOC
|
|
#endif NEED_MALLOC
|
|
|
|
|
|
/**********************************************************
|
|
* GARBAGE COLLECTION *
|
|
**********************************************************/
|
|
|
|
cl_object @'si::*gc-verbose*';
|
|
cl_object @'si::*gc-message*';
|
|
|
|
void
|
|
register_root(cl_object *p)
|
|
{
|
|
GC_add_roots(p, p+1);
|
|
}
|
|
|
|
@(defun gc (area)
|
|
@
|
|
gc(0);
|
|
@(return)
|
|
@)
|
|
|
|
void
|
|
gc(enum type new_name)
|
|
{
|
|
start_critical_section();
|
|
GC_gcollect();
|
|
end_critical_section();
|
|
}
|