memory: make it possible to configure the allocator

This commit is contained in:
Daniel Kochmański 2024-12-09 12:10:54 +01:00
parent 24edc0a250
commit d58bab2a26
8 changed files with 117 additions and 13 deletions

View file

@ -206,7 +206,7 @@ _ecl_alloc_env(cl_env_ptr parent)
# endif
#endif
/* Initialize the structure with NULL data. */
memset(output, 0, sizeof(*output));
ecl_mset(output, 0, sizeof(*output));
#ifdef ECL_THREADS
add_env(output);
#endif
@ -247,6 +247,7 @@ struct ecl_core_struct ecl_core = {
.default_sigmask_bytes = 0,
.known_signals = ECL_NIL,
/* allocation */
.allocator = NULL,
.max_heap_size = 0,
.bytes_consed = ECL_NIL,
.gc_counter = ECL_NIL,
@ -277,6 +278,7 @@ ecl_boot(void)
}
return 1;
}
init_memory();
init_modules();
ecl_core.path_max = MAXPATHLEN;
return 0;

View file

@ -282,9 +282,9 @@ _ecl_dump_c_backtrace()
# endif
}
fflush(stderr);
free(pointers);
ecl_free(pointers);
# if defined(ECL_UNIX_BACKTRACE)
free(names);
ecl_free(names);
# elif defined(ECL_WINDOWS_BACKTRACE)
SymCleanup(process);
# endif

View file

@ -265,8 +265,8 @@ allocate_object_marked(struct ecl_type_information *type_info)
}
#endif
cl_object
ecl_alloc_object(cl_type t)
static cl_object
alloc_object(cl_type t)
{
#ifdef GBC_BOEHM_PRECISE
struct ecl_type_information *ti;
@ -1213,6 +1213,26 @@ si_gc_dump()
/* -- module definition ------------------------------------------------------ */
static void *
alloc_memory(cl_index size)
{
return GC_MALLOC(size);
}
static void
free_object(cl_object o)
{
standard_finalizer(o);
ecl_dealloc(o);
}
struct ecl_allocator_ops gc_ops = {
.allocate_memory = alloc_memory,
.allocate_object = alloc_object,
.free_memory = ecl_dealloc,
.free_object = free_object
};
static cl_object
create_gc()
{
@ -1277,6 +1297,8 @@ create_gc()
GC_set_oom_fn(out_of_memory);
GC_set_warn_proc(no_warnings);
ecl_core.allocator = &gc_ops;
return ECL_NIL;
}

View file

@ -2,7 +2,7 @@
/* vim: set filetype=c tabstop=2 shiftwidth=2 expandtab: */
/*
* memory.c - manual memory managament
* memory.c - memory managament
*
* Copyright (c) 2024 Daniel Kochmański
*
@ -32,13 +32,12 @@ out_of_memory()
goto AGAIN;
For now let's crash with an appropriate error. */
ecl_internal_error("*** manual memory allocator: out of memory\n");
ecl_internal_error("*** memory allocator: out of memory\n");
}
void *
ecl_malloc(cl_index n)
{
/* GC-free equivalent of ecl_alloc_atomic. */
const cl_env_ptr the_env = ecl_process_env_unsafe();
void *ptr;
if (!the_env) {
@ -68,10 +67,16 @@ ecl_free(void *ptr)
void *
ecl_realloc(void *ptr, cl_index osize, cl_index nsize)
{
void *p = ecl_malloc(nsize);
ecl_copy(p, ptr, (osize < nsize) ? osize : nsize);
ecl_free(ptr);
return p;
const cl_env_ptr the_env = ecl_process_env_unsafe();
if (!the_env) {
ptr = realloc(ptr, nsize);
} else {
ecl_disable_interrupts_env(the_env);
ptr = realloc(ptr, nsize);
ecl_enable_interrupts_env(the_env);
}
if (ptr == NULL) out_of_memory();
return ptr;
}
void
@ -79,3 +84,62 @@ ecl_copy(void *dst, void *src, cl_index ndx)
{
memcpy(dst, src, ndx);
}
void
ecl_mset(void *ptr, byte c, cl_index n)
{
memset(ptr, c, n);
}
/* -- Constructors ---------------------------------------------------------- */
cl_object
ecl_alloc_object(cl_type t)
{
return ecl_core.allocator->allocate_object(t);
}
void *
ecl_alloc_memory(cl_index n)
{
return ecl_core.allocator->allocate_memory(n);
}
void
ecl_free_object(cl_object ptr)
{
return ecl_core.allocator->free_object(ptr);
}
void
ecl_free_memory(void *ptr)
{
return ecl_core.allocator->free_memory(ptr);
}
/* -- Rudimentary manual memory allocator ----------------------------------- */
static cl_object
alloc_object(cl_type t)
{
ecl_internal_error("*** memory: alloc_object not implemented.\n");
}
static void
free_object(cl_object self)
{
ecl_internal_error("*** memory: free_object not implemented.\n");
}
struct ecl_allocator_ops manual_allocator = {
.allocate_memory = ecl_malloc,
.allocate_object = alloc_object,
.free_memory = ecl_free,
.free_object = free_object
};
void
init_memory ()
{
ecl_core.allocator = &manual_allocator;
}

View file

@ -219,6 +219,7 @@ extern ECL_API void *ecl_malloc(cl_index n);
extern ECL_API void *ecl_realloc(void *ptr, cl_index o, cl_index n);
extern ECL_API void ecl_free(void *ptr);
extern ECL_API void ecl_copy(void *dst, void *src, cl_index ndx);
extern ECL_API void ecl_mset(void *dst, byte val, cl_index ndx);
#define ecl_free_unsafe(x) ecl_free(x);
/* boot.c */

View file

@ -35,6 +35,7 @@ extern ECL_API cl_object ecl_module_bignum;
extern ECL_API cl_object ecl_module_ffi;
extern ECL_API cl_object ecl_module_aux;
extern void init_memory(void);
extern void init_all_symbols(void);
extern void init_backq(void);
extern void init_big();

View file

@ -17,6 +17,7 @@ struct ecl_core_struct {
cl_index last_var_index;
cl_object reused_indices;
#endif
struct ecl_allocator_ops *allocator;
size_t max_heap_size;
cl_object bytes_consed;
cl_object gc_counter;
@ -73,4 +74,10 @@ cl_object ecl_raise(ecl_ex_type t, bool ret,
#define ecl_cerror4(extype,a1,a2,a3) ecl_raise(extype, 1, a1, a2, a3, NULL)
#define ecl_cerror5(extype,a1,a2,a3,p4) ecl_raise(extype, 1, a1, a2, a3, p4)
/* memory.c */
void *ecl_alloc_memory(cl_index n);
cl_object ecl_alloc_object(cl_type t);
void ecl_free_memory(void *ptr);
void ecl_free_object(cl_object o);
#endif /* ECL_NUCLEUS_H */

View file

@ -96,7 +96,6 @@ typedef enum {
FREE = 127 /* free object */
} cl_type;
/*
Definition of the type of LISP objects.
*/
@ -108,6 +107,14 @@ typedef cl_object (*cl_objectfn)(cl_narg narg, ...);
typedef cl_object (*cl_objectfn_fixed)();
typedef cl_object (*cl_objectfn_envfn)(cl_env_ptr);
/* Allocator interface */
struct ecl_allocator_ops {
void *(*allocate_memory)(cl_index n); /* low-level alloc */
cl_object (*allocate_object)(cl_type t); /* high-level alloc */
void (*free_memory)(void*); /* low-level free */
void (*free_object)(cl_object); /* high-level free */
};
/*
OBJect NULL value.
It should not coincide with any legal object value.