You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

65 lines
2.3 KiB
C

#include "../kernel.h"
#include "ktypes.h"
#include "malloc.h"
#include "ecall.h"
#include "io.h"
// information about the systems memory layout is stored here
static struct malloc_info global_malloc_info = { 0 };
// this pointer points to the end of unused memory
static void* allocate_memory_end;
// this stack holds currently unused program stacks
// it is a stack in the sense that you can push and pop variables
static struct voidptr_stack unused_stacks;
void stash_stack(void* stack_top)
{
if (voidptr_stack_push(&unused_stacks, stack_top) == 0) {
// if this happens, we know we messed up and created more stacks than we
// could ever have processes running simultaneously!
// we probably have an erro in retrieving stashed stacks?
dbgln("cannot stash stack, no space left! This should never ever happen!", 65);
}
}
// this function is called by the kernels init() function after it parsed the
// list of loaded binaries and calculated the available memory for general allocation
void malloc_init(struct malloc_info* given_info)
{
// save the passed info
global_malloc_info = *given_info;
allocate_memory_end = given_info->allocate_memory_end;
allocate_memory_end = (void*) (((int) allocate_memory_end) - PROCESS_COUNT);
voidptr_stack_new(&unused_stacks, (void**) allocate_memory_end, PROCESS_COUNT);
}
// allocate stack and return a pointer to the *end* of the allocated region
// this doesn't reuse stack from functions which exited
optional_voidptr malloc_stack()
{
// try to reuse a stack top
void* stack_top = voidptr_stack_pop(&unused_stacks);
if (stack_top != NULL) {
return (optional_voidptr) { .value = stack_top };
}
// otherwise allocate a new stack at the end of available memory
void* new_alloc_end = (void*) (((int) allocate_memory_end) - USER_STACK_SIZE);
// check if we ran out of space
if (new_alloc_end < global_malloc_info.allocate_memory_start)
return (optional_voidptr) { .error = ENOMEM };
stack_top = allocate_memory_end;
allocate_memory_end = new_alloc_end;
return (optional_voidptr) { .value = stack_top };
}
// a stack is not returned to the general memory pool (since EMBARK has no such
// pool) but rather just added to the pool of free process stacks.
void free_stack(void* stack_top)
{
stash_stack(stack_top);
}