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"
/* Arbitrary block size */
#define HEADER_BLOCK_SIZE 4096
#define DATA_BLOCK_SIZE 4096
#define HEADER_SIZE 64
#define BLOCK_SIZE 4096
/* NOTE: Application will exit if arena fails to reserve or commit initial
* memory. */
struct arena *arena_alloc(u64 reserve)
{
__prof;
reserve += HEADER_SIZE;
/* Round up to nearest block size */
u64 block_remainder = reserve % DATA_BLOCK_SIZE;
u64 block_remainder = reserve % BLOCK_SIZE;
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) {
/* Hard fail on memory reserve failure for now */
sys_panic(LIT("Failed to reserve memory"));
}
u64 reserved = reserve;
gstat_add(GSTAT_MEMORY_RESERVED, reserve + HEADER_BLOCK_SIZE);
gstat_add(GSTAT_MEMORY_RESERVED, reserve + HEADER_SIZE);
/* Commit header block */
u8 *base = sys_memory_commit(reserve_base, HEADER_BLOCK_SIZE + DATA_BLOCK_SIZE);
/* Commit initial block */
u8 *base = sys_memory_commit(reserve_base, BLOCK_SIZE);
if (!base) {
/* Hard fail on commit failure */
sys_panic(LIT("Failed to commit initial memory block: System may be out of memory"));
}
base += HEADER_BLOCK_SIZE;
ASAN_POISON(base - HEADER_BLOCK_SIZE, HEADER_BLOCK_SIZE - sizeof(struct arena));
ASAN_POISON(base, DATA_BLOCK_SIZE);
ASAN_POISON(base + sizeof(struct arena), BLOCK_SIZE - sizeof(struct arena));
ASSERT(((u64)base & 0xFFF) == 0); /* Base should be 4k aligned */
CT_ASSERT(sizeof(struct arena) <= HEADER_BLOCK_SIZE); /* First block must fit arena */
gstat_add(GSTAT_MEMORY_COMMITTED, HEADER_BLOCK_SIZE + DATA_BLOCK_SIZE);
__profalloc(reserve_base, HEADER_BLOCK_SIZE + DATA_BLOCK_SIZE);
CT_ASSERT(HEADER_SIZE <= BLOCK_SIZE); /* Header must fit in first block */
CT_ASSERT(sizeof(struct arena) <= HEADER_SIZE); /* Arena struct must fit in header */
gstat_add(GSTAT_MEMORY_COMMITTED, BLOCK_SIZE);
__profalloc(reserve_base, BLOCK_SIZE);
/* 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);
base += HEADER_SIZE;
u64 committed = BLOCK_SIZE - HEADER_SIZE;
gstat_add(GSTAT_NUM_ARENAS, 1);
arena->committed = DATA_BLOCK_SIZE;
arena->committed = committed;
arena->reserve_base = reserve_base;
arena->base = base;
arena->reserved = reserved;
@ -57,7 +61,7 @@ struct arena *arena_alloc(u64 reserve)
void arena_release(struct arena *arena)
{
ASAN_UNPOISON(arena->reserve_, arena->committed + HEADER_BLOCK_SIZE);
ASAN_UNPOISON(arena->reserve_, arena->committed + HEADER_SIZE);
__prof;
__proffree(arena->reserve_base);
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) {
__profscope(_arena_push_bytes_COMMIT);
/* Commit new block(s) */
u64 blocks_needed = (new_pos - arena->committed + DATA_BLOCK_SIZE - 1) / DATA_BLOCK_SIZE;
u64 commit_bytes = blocks_needed * DATA_BLOCK_SIZE;
u64 blocks_needed = (new_pos - arena->committed + BLOCK_SIZE - 1) / BLOCK_SIZE;
u64 commit_bytes = blocks_needed * BLOCK_SIZE;
u64 new_capacity = arena->committed + commit_bytes;
if (new_capacity > arena->reserved) {
/* 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;
gstat_add(GSTAT_MEMORY_COMMITTED, commit_bytes);
__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);
}
start = arena->base + aligned_start_pos;
@ -126,7 +130,7 @@ void arena_decommit_unused_blocks(struct arena *arena)
{
#if 0
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) {
u8 *decommit_start = arena->base + next_block_pos;
u64 decommit_size = (arena->base + arena->committed) - decommit_start;
@ -146,12 +150,12 @@ void arena_set_readonly(struct arena *arena)
#if RTC
arena->readonly = true;
#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)
{
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
arena->readonly = false;
#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 string read_buff = ZI;
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;