ecl/src/c/memory.d
Daniel Kochmański 09ebfb47dd core: add wrapper for manual memory managament
We will use this operators to allocate the first environment and stacks so that
there is no circularity between ecl_boot and starting the garbage collector.
2025-03-31 20:44:46 +02:00

81 lines
1.7 KiB
C

/* -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/* vim: set filetype=c tabstop=2 shiftwidth=2 expandtab: */
/*
* memory.c - manual memory managament
*
* Copyright (c) 2024 Daniel Kochmański
*
* See file 'LICENSE' for the copyright details.
*
*/
/* -- imports --------------------------------------------------------------- */
#include <ecl/ecl.h>
#include <ecl/ecl-inl.h>
#include <ecl/internal.h>
#include <ecl/external.h>
#include <stdlib.h>
#include <string.h>
/* -- implementation -------------------------------------------------------- */
static void
out_of_memory()
{
/* FIXME we should signal the STORAGE-EXHAUSTED and allow a potential handler
an attempt to release some memory:
ecl_cerror(ecl_ct_oom_tag);
goto AGAIN;
For now let's crash with an appropriate error. */
ecl_internal_error("*** manual 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) {
ptr = malloc(n);
} else {
ecl_disable_interrupts_env(the_env);
ptr = malloc(n);
ecl_enable_interrupts_env(the_env);
}
if (ptr == NULL) out_of_memory();
return ptr;
}
void
ecl_free(void *ptr)
{
const cl_env_ptr the_env = ecl_process_env_unsafe();
if (!the_env) {
free(ptr);
} else {
ecl_disable_interrupts_env(the_env);
free(ptr);
ecl_enable_interrupts_env(the_env);
}
}
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;
}
void
ecl_copy(void *dst, void *src, cl_index ndx)
{
memcpy(dst, src, ndx);
}