sllibc/memory.c

87 lines
2.6 KiB
C

// Copyright (c) 2025, Zak Fenton
// Zak Fenton's libc is licensed under the Mulan PSL v2. You can use this
// software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN “AS IS” BASIS, WITHOUT warranties of
// any kind, either express or implied, including but not limited to
// non-infringement, merchantability or fit for a particular purpose.
// See the Mulan PSL v2 for more details.
#include <memory.h>
#include <stdlib.h>
#include <stdio.h>
#include <syscalls.h>
#include "elmalloc.h"
#include "internal.h"
elmm_t _libc_mm;
elmm_sbrk_data_t _libc_sbrkdata;
#define SIMGC_SYSMALLOC(x) elmm_malloc(&_libc_mm, x)
#define SIMGC_FREE(x) elmm_free(&_libc_mm, x)
#define SIMGC_IMPLEMENTATION
#include "simgc.h"
simgc_t _libc_gc;
simgc_thread_t* _libc_gcmainthread;
void _libc_malloc_init(void* stackptr) {
// Initialising the memory manager is currently a bit of work, but in
// theory should pay off as the memory manager code is easy to fine
// tune and adapt for more specialised allocators.
_libc_sbrkdata.func = (void*)(&sbrk); // Hooking it straight to the syscall should work, the userdata argument will be ignored
_libc_sbrkdata.max = 1024 * 1024 * 8;
_libc_sbrkdata.onlyChunk = NULL;
_libc_sbrkdata.udata = NULL;
_libc_mm.bigchunkMinimum = 1024 * 1024;
_libc_mm.bigchunkGranularity = 1024;
_libc_mm.initialised = false;
_libc_mm.lockFunction = NULL;
_libc_mm.bigchunkData = &_libc_sbrkdata;
_libc_mm.bigchunkFunction = &elmm_bigchunk_sbrk;
if (!elmm_init(&_libc_mm)) {
const char* err = "ERROR: Failed to initialise memory manager!\n";
write(2, err, strlen(err));
exit(-1);
}
if (!elmm_growheap(&_libc_mm, 1024*1024*4)) {
printf("Growheap failed.\n");
} else {
printf("Growheap success!\n");
}
simgc_init(&_libc_gc);
_libc_gcmainthread = simgc_begin_inner(&_libc_gc, stackptr);
}
void _libc_malloc_finish() {
simgc_end_inner(_libc_gcmainthread);
simgc_reclaim(&_libc_gc);
}
void* _libc_gcalloc(size_t sz) {
return simgc_alloc(&_libc_gc, sz);
}
void* malloc(size_t sz) {
return elmm_malloc(&_libc_mm, sz);
}
void free(void* mem) {
return elmm_free(&_libc_mm, mem);
}
void* calloc(size_t n, size_t sz) {
/* TODO: check for overflow of n * sz? Probably not a problem IRL (may
* have been more of a thing back in the 16-bit era but I guess math
* overflow is not an important issue on 64-bit or even 32-bit memory
* allocator calls)
*/
return elmm_calloc(&_libc_mm, n, sz);
}
void* realloc(void* mem, size_t sz) {
return elmm_realloc(&_libc_mm, mem, sz);
}