SharedScratchCtx shared_scratch_ctx = ZI; /* NOTE: Application will exit if arena fails to reserve or commit initial memory. */ Arena *AllocArena(u64 reserve) { __prof; reserve += ArenaHeaderSize; /* Round up to nearest block size */ u64 block_remainder = reserve % ArenaBlockSize; if (block_remainder > 0) { reserve += ArenaBlockSize - block_remainder; } u8 *base = ReserveMemory(reserve); if (!base) { /* Hard fail on memory reserve failure for now */ /* FIXME: Enable this */ //P_Panic(Lit("Failed to reserve memory")); (*(volatile int *)0) = 0; } u64 reserved = reserve; AddGstat(GSTAT_MEMORY_RESERVED, reserve); /* Commit initial block */ base = CommitMemory(base, ArenaBlockSize); if (!base) { /* Hard fail on commit failure */ /* FIXME: Enable this */ //P_Panic(Lit("Failed to commit initial memory block: System may be out of memory")); (*(volatile int *)0) = 0; } Assert(((u64)base & 0xFFF) == 0); /* Base should be 4k aligned */ StaticAssert(ArenaHeaderSize <= ArenaBlockSize); /* Header must fit in first block */ StaticAssert(sizeof(Arena) <= ArenaHeaderSize); /* Arena struct must fit in header */ __profalloc(base, ArenaBlockSize); AsanPoison(base + sizeof(Arena), ArenaBlockSize - sizeof(Arena)); AddGstat(GSTAT_MEMORY_COMMITTED, ArenaBlockSize); AddGstat(GSTAT_NUM_ARENAS, 1); /* Create & return arena header at beginning of block */ Arena *arena = (Arena *)base; ZeroStruct(arena); arena->committed = ArenaBlockSize - ArenaHeaderSize; arena->reserved = reserved; return arena; } void ReleaseArena(Arena *arena) { AsanUnpoison(arena, arena->committed + ArenaHeaderSize); __prof; __proffree(arena); AddGstat(GSTAT_MEMORY_COMMITTED, -(i64)(arena->committed - ArenaHeaderSize)); AddGstat(GSTAT_MEMORY_RESERVED, -(i64)(arena->reserved)); AddGstat(GSTAT_NUM_ARENAS, -1); ReleaseMemory(arena); } /* NOTE: Application will exit if arena fails to commit memory */ void *PushBytesNoZero(Arena *arena, u64 size, u64 align) { Assert(align > 0); Assert(!arena->readonly); void *ptr = 0; u8 *base = ArenaBase(arena); /* Check to avoid aligning when size = 0 */ if (size > 0) { u64 aligned_start_pos = (arena->pos + (align - 1)); aligned_start_pos -= aligned_start_pos % align; u64 new_pos = aligned_start_pos + size; if (new_pos > arena->committed) { __profn("Arena commit"); /* Commit new block(s) */ u64 blocks_needed = (new_pos - arena->committed + ArenaBlockSize - 1) / ArenaBlockSize; u64 commit_bytes = blocks_needed * ArenaBlockSize; u64 new_capacity = arena->committed + commit_bytes; if (new_capacity > arena->reserved) { /* Hard fail if we overflow reserved memory for now */ /* FIXME: Enable this */ //P_Panic(Lit("Failed to commit new memory block: Overflow of reserved memory")); (*(volatile int *)0) = 0; } void *commit_address = base + arena->committed; if (!CommitMemory(commit_address, commit_bytes)) { /* Hard fail on memory allocation failure for now */ /* FIXME: Enable this */ //P_Panic(Lit("Failed to commit new memory block: System may be out of memory")); (*(volatile int *)0) = 0; } arena->committed += commit_bytes; AddGstat(GSTAT_MEMORY_COMMITTED, commit_bytes); __proffree(arena); __profalloc(arena, arena->committed + ArenaHeaderSize); AsanPoison(commit_address, commit_bytes); } ptr = base + aligned_start_pos; AsanUnpoison(ptr, new_pos - aligned_start_pos); arena->pos = new_pos; } else { ptr = base + arena->pos; } return ptr; } /* Copies the memory from the source arena into the destination arena, * replacing old contents. Destination arena will be expanded if necessary. */ void CopyArena(Arena *dst, Arena *src) { ResetArena(dst); u64 data_size = src->pos; u8 *data_src = ArenaBase(src); u8 *data_dst = PushBytesNoZero(dst, data_size, 1); CopyBytes(data_dst, data_src, data_size); } void ShrinkArena(Arena *arena) { /* Not implemented */ Assert(0); LAX arena; } void SetArenaReadonly(Arena *arena) { #if RtcIsEnabled arena->readonly = 1; #endif SetMemoryReadonly(arena, arena->committed + ArenaHeaderSize); } void SetArenaReadWrite(Arena *arena) { SetMemoryReadWrite(arena, arena->committed + ArenaHeaderSize); #if RtcIsEnabled arena->readonly = 0; #endif }