mirror of
https://gitlab.com/embeddable-common-lisp/ecl.git
synced 2025-12-15 15:21:03 -08:00
memory: make it possible to configure the allocator
This commit is contained in:
parent
24edc0a250
commit
d58bab2a26
8 changed files with 117 additions and 13 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue