store arena struct in first block

This commit is contained in:
jacob 2025-06-17 22:34:47 -05:00
parent cfd8fb5f21
commit 17a8284e6c
2 changed files with 28 additions and 24 deletions

View File

@ -6,49 +6,53 @@
#include "gstat.h" #include "gstat.h"
/* Arbitrary block size */ /* Arbitrary block size */
#define HEADER_BLOCK_SIZE 4096 #define HEADER_SIZE 64
#define DATA_BLOCK_SIZE 4096 #define BLOCK_SIZE 4096
/* NOTE: Application will exit if arena fails to reserve or commit initial /* NOTE: Application will exit if arena fails to reserve or commit initial
* memory. */ * memory. */
struct arena *arena_alloc(u64 reserve) struct arena *arena_alloc(u64 reserve)
{ {
__prof; __prof;
reserve += HEADER_SIZE;
/* Round up to nearest block size */ /* Round up to nearest block size */
u64 block_remainder = reserve % DATA_BLOCK_SIZE; u64 block_remainder = reserve % BLOCK_SIZE;
if (block_remainder > 0) { if (block_remainder > 0) {
reserve += DATA_BLOCK_SIZE - block_remainder; reserve += BLOCK_SIZE - block_remainder;
} }
u8 *reserve_base = sys_memory_reserve(reserve + HEADER_BLOCK_SIZE); u8 *reserve_base = sys_memory_reserve(reserve + HEADER_SIZE);
if (!reserve_base) { if (!reserve_base) {
/* Hard fail on memory reserve failure for now */ /* Hard fail on memory reserve failure for now */
sys_panic(LIT("Failed to reserve memory")); sys_panic(LIT("Failed to reserve memory"));
} }
u64 reserved = reserve; u64 reserved = reserve;
gstat_add(GSTAT_MEMORY_RESERVED, reserve + HEADER_BLOCK_SIZE); gstat_add(GSTAT_MEMORY_RESERVED, reserve + HEADER_SIZE);
/* Commit header block */ /* Commit initial block */
u8 *base = sys_memory_commit(reserve_base, HEADER_BLOCK_SIZE + DATA_BLOCK_SIZE); u8 *base = sys_memory_commit(reserve_base, BLOCK_SIZE);
if (!base) { if (!base) {
/* Hard fail on commit failure */ /* Hard fail on commit failure */
sys_panic(LIT("Failed to commit initial memory block: System may be out of memory")); sys_panic(LIT("Failed to commit initial memory block: System may be out of memory"));
} }
base += HEADER_BLOCK_SIZE; ASAN_POISON(base + sizeof(struct arena), BLOCK_SIZE - sizeof(struct arena));
ASAN_POISON(base - HEADER_BLOCK_SIZE, HEADER_BLOCK_SIZE - sizeof(struct arena));
ASAN_POISON(base, DATA_BLOCK_SIZE);
ASSERT(((u64)base & 0xFFF) == 0); /* Base should be 4k aligned */ ASSERT(((u64)base & 0xFFF) == 0); /* Base should be 4k aligned */
CT_ASSERT(sizeof(struct arena) <= HEADER_BLOCK_SIZE); /* First block must fit arena */ CT_ASSERT(HEADER_SIZE <= BLOCK_SIZE); /* Header must fit in first block */
gstat_add(GSTAT_MEMORY_COMMITTED, HEADER_BLOCK_SIZE + DATA_BLOCK_SIZE); CT_ASSERT(sizeof(struct arena) <= HEADER_SIZE); /* Arena struct must fit in header */
__profalloc(reserve_base, HEADER_BLOCK_SIZE + DATA_BLOCK_SIZE); gstat_add(GSTAT_MEMORY_COMMITTED, BLOCK_SIZE);
__profalloc(reserve_base, BLOCK_SIZE);
/* Create arena struct at end of header block */ /* Create arena struct at end of header block */
struct arena *arena = (struct arena *)(base - sizeof(struct arena)); struct arena *arena = (struct arena *)base;
MEMZERO_STRUCT(arena); MEMZERO_STRUCT(arena);
base += HEADER_SIZE;
u64 committed = BLOCK_SIZE - HEADER_SIZE;
gstat_add(GSTAT_NUM_ARENAS, 1); gstat_add(GSTAT_NUM_ARENAS, 1);
arena->committed = DATA_BLOCK_SIZE; arena->committed = committed;
arena->reserve_base = reserve_base; arena->reserve_base = reserve_base;
arena->base = base; arena->base = base;
arena->reserved = reserved; arena->reserved = reserved;
@ -57,7 +61,7 @@ struct arena *arena_alloc(u64 reserve)
void arena_release(struct arena *arena) void arena_release(struct arena *arena)
{ {
ASAN_UNPOISON(arena->reserve_, arena->committed + HEADER_BLOCK_SIZE); ASAN_UNPOISON(arena->reserve_, arena->committed + HEADER_SIZE);
__prof; __prof;
__proffree(arena->reserve_base); __proffree(arena->reserve_base);
gstat_sub(GSTAT_MEMORY_COMMITTED, arena->committed); gstat_sub(GSTAT_MEMORY_COMMITTED, arena->committed);
@ -83,8 +87,8 @@ void *arena_push_bytes_no_zero(struct arena *arena, u64 size, u64 align)
if (new_pos > arena->committed) { if (new_pos > arena->committed) {
__profscope(_arena_push_bytes_COMMIT); __profscope(_arena_push_bytes_COMMIT);
/* Commit new block(s) */ /* Commit new block(s) */
u64 blocks_needed = (new_pos - arena->committed + DATA_BLOCK_SIZE - 1) / DATA_BLOCK_SIZE; u64 blocks_needed = (new_pos - arena->committed + BLOCK_SIZE - 1) / BLOCK_SIZE;
u64 commit_bytes = blocks_needed * DATA_BLOCK_SIZE; u64 commit_bytes = blocks_needed * BLOCK_SIZE;
u64 new_capacity = arena->committed + commit_bytes; u64 new_capacity = arena->committed + commit_bytes;
if (new_capacity > arena->reserved) { if (new_capacity > arena->reserved) {
/* Hard fail if we overflow reserved memory for now */ /* Hard fail if we overflow reserved memory for now */
@ -98,7 +102,7 @@ void *arena_push_bytes_no_zero(struct arena *arena, u64 size, u64 align)
arena->committed += commit_bytes; arena->committed += commit_bytes;
gstat_add(GSTAT_MEMORY_COMMITTED, commit_bytes); gstat_add(GSTAT_MEMORY_COMMITTED, commit_bytes);
__proffree(arena->reserve_base); __proffree(arena->reserve_base);
__profalloc(arena->reserve_base, arena->committed + commit_bytes + HEADER_BLOCK_SIZE); __profalloc(arena->reserve_base, arena->committed + commit_bytes + HEADER_SIZE);
ASAN_POISON(commit_address, commit_bytes); ASAN_POISON(commit_address, commit_bytes);
} }
start = arena->base + aligned_start_pos; start = arena->base + aligned_start_pos;
@ -126,7 +130,7 @@ void arena_decommit_unused_blocks(struct arena *arena)
{ {
#if 0 #if 0
ASSERT(!arena->readonly); ASSERT(!arena->readonly);
u64 next_block_pos = DATA_BLOCK_SIZE * ((arena->pos + (DATA_BLOCK_SIZE - 1)) / DATA_BLOCK_SIZE); u64 next_block_pos = BLOCK_SIZE * ((arena->pos + (BLOCK_SIZE - 1)) / BLOCK_SIZE);
if (arena->committed > next_block_pos) { if (arena->committed > next_block_pos) {
u8 *decommit_start = arena->base + next_block_pos; u8 *decommit_start = arena->base + next_block_pos;
u64 decommit_size = (arena->base + arena->committed) - decommit_start; u64 decommit_size = (arena->base + arena->committed) - decommit_start;
@ -146,12 +150,12 @@ void arena_set_readonly(struct arena *arena)
#if RTC #if RTC
arena->readonly = true; arena->readonly = true;
#endif #endif
sys_memory_set_committed_readonly(arena->reserve_base, arena->committed + HEADER_BLOCK_SIZE); sys_memory_set_committed_readonly(arena->reserve_base, arena->committed + HEADER_SIZE);
} }
void arena_set_readwrite(struct arena *arena) void arena_set_readwrite(struct arena *arena)
{ {
sys_memory_set_committed_readwrite(arena->reserve_base, arena->committed + HEADER_BLOCK_SIZE); sys_memory_set_committed_readwrite(arena->reserve_base, arena->committed + HEADER_SIZE);
#if RTC #if RTC
arena->readonly = false; arena->readonly = false;
#endif #endif

View File

@ -1067,7 +1067,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(host_receiver_thread_entry_point, arg)
struct arena *read_buff_arena = arena_alloc(read_buff_size); struct arena *read_buff_arena = arena_alloc(read_buff_size);
struct string read_buff = ZI; struct string read_buff = ZI;
read_buff.len = read_buff_size; read_buff.len = read_buff_size;
read_buff.text = arena_push_array_no_zero(read_buff_arena, u8, KILOBYTE(64)); read_buff.text = arena_push_array_no_zero(read_buff_arena, u8, read_buff_size);
struct host *host = (struct host *)arg; struct host *host = (struct host *)arg;