#include #include #include #include #include #include #include #include #include #define ARENA_SIZE (1<<20) typedef struct UmArena { struct UmArena *next; uintptr_t mem; size_t cursor; int64_t balance; } UmArena; static UmArena *ARENAS = NULL; UmArena *um_newarena(void) { size_t arenasize = ARENA_SIZE; uint8_t *mem = NULL; int32_t err = mman_map(NULL, arenasize, MMAN_MAP_PF_RW, 0, &mem); if (mem == NULL || err != E_OK) { return NULL; } string_memset(mem, 0, arenasize); UmArena *arena = (UmArena *)mem; arena->mem = (uintptr_t)mem + sizeof(arena); arena->cursor = 0; LL_APPEND(ARENAS, arena); return arena; } void *umalloc(size_t size) { UmArena *usable = NULL; UmArena *arena, *arenatmp; LL_FOREACH_SAFE(ARENAS, arena, arenatmp) { if (arena->cursor + size < ARENA_SIZE) { usable = arena; break; } } if (usable == NULL) { usable = um_newarena(); } if (usable == NULL) { return NULL; } uintptr_t current = usable->mem + usable->cursor; usable->cursor += size; usable->balance += 1; return (void *)current; } void ufree(void *ptr_) { uintptr_t ptr = (uintptr_t)ptr_; UmArena *freeable = NULL; UmArena *arena, *arenatmp; LL_FOREACH_SAFE(ARENAS, arena, arenatmp) { if (ptr >= arena->mem && ptr < arena->mem + ARENA_SIZE) { freeable = arena; break; } } if (freeable == NULL) { return; } freeable->balance -= 1; if (freeable->balance <= 0) { uintptr_t origin = (uintptr_t)freeable - sizeof(UmArena); mman_unmap((void *)origin); } }