arena operations: push, position, pop_to, clear, pop_off, temporary memory. clamps for memory alignment. unity build not setup although it does not work.

This commit is contained in:
Tijani Lawal 2024-08-07 00:02:35 -05:00
parent b4cfc14d3b
commit ab89c03813
7 changed files with 139 additions and 30 deletions

View File

@ -1,6 +1,7 @@
internal *arena_alloc_(ArenaParams *params) {
internal Arena *arena_alloc_(ArenaParams *params) {
u64 reserve_size = params->reserve_size;
u64 commit_size = params->reserve_size;
u64 commit_size = params->commit_size;
if (params->flags & ArenaFlag_LargePages) {
reserve_size = AlignPow2(reserve_size, os_get_system_info()->large_page_size);
commit_size = AlignPow2(commit_size, os_get_system_info()->large_page_size);
@ -9,7 +10,7 @@ internal *arena_alloc_(ArenaParams *params) {
commit_size = AlignPow2(commit_size, os_get_system_info()->page_size);
}
// reserve/commit initial block
// reserve/commit initial block of memory
void *base = params->optional_backing_buffer;
if (base == 0) {
if (params->flags & ArenaFlag_LargePages) {
@ -34,7 +35,7 @@ internal *arena_alloc_(ArenaParams *params) {
arena->flags = params->flags;
arena->commit_size = (u32)params->commit_size;
arena->reserve_size = params->reserve_size;
arena->base_position 0;
arena->base_position = 0;
arena->position = ARENA_HEADER_SIZE;
arena->commit = commit_size;
arena->reserve = reserve_size;
@ -42,15 +43,101 @@ internal *arena_alloc_(ArenaParams *params) {
}
internal void arena_release(Arena *arena) {
for (Arena *n = arena->current; *l_previous = 0; n != 0; n = l_previous) {
l_previous = n->previous;
os_release(n, n->reserve);
for (Arena *current_arena = arena->current, *previous_arena = 0; current_arena != 0; current_arena = previous_arena) {
previous_arena = current_arena->previous;
os_release(current_arena, current_arena->reserve);
}
}
// @nocheckin
internal void *arena_push(Arena *arena, u64 size, u64 align) {
Arena *current = arena->current;
u64 position_pre = AlignPow2(current->position);
u64 position_past = position_pre + size;
internal void *arena_push(Arena *arena, u64 size_to_push, u64 align) {
Arena *current_arena = arena->current;
u64 position_pre_push = AlignPow2(current_arena->position, align); // position of arena before push
u64 position_post_push = position_pre_push + size_to_push; // position of arena after push
// ??(tijani): chain, if needed
if (current_arena->reserve < position_post_push && !(arena->flags & ArenaFlag_NoChain)) {
u64 new_reserve_size = current_arena->reserve_size;
u64 new_commit_size = current_arena->commit_size;
if (size_to_push > new_reserve_size) {
new_reserve_size = size_to_push + ARENA_HEADER_SIZE;
new_commit_size = size_to_push + ARENA_HEADER_SIZE;
}
Arena *new_memory_block =
arena_alloc(.reserve_size = new_reserve_size, .commit_size = new_commit_size, .flags = current_arena->flags);
new_memory_block->base_position = current_arena->base_position + current_arena->reserve;
SLLStackPush_N(arena->current, new_memory_block, previous); // `previous` refers to `previous` in `Arena` struct
current_arena = new_memory_block;
position_pre_push = AlignPow2(current_arena->position, align);
position_post_push = position_pre_push + size_to_push;
}
// ??(tijani): commit new page, if needed
if (current_arena->commit < position_post_push && !(current_arena->flags & ArenaFlag_LargePages)) {
u64 commit_post_aligned = AlignPow2(position_post_push, current_arena->commit_size);
u64 commit_post_clamped = ClampTop(commit_post_aligned, current_arena->reserve);
u64 new_commit_size = commit_post_clamped - current_arena->commit;
os_commit((u8 *)current_arena + current_arena->commit, new_commit_size);
}
// push onto the current block
void *memory = 0;
if (current_arena->commit >= position_post_push) {
memory = (u8 *)current_arena + position_pre_push;
current_arena->position = position_post_push;
// ??(tijani): why need to Asan Unpoision memory
}
// panic when fail
#if OS_FEATURE_GRAPHICAL
if (memory == 0) {
os_graphical_message(1, str8_lit("Fatal allocation failure"), str8_lit("Unexpected memory allocation failure"));
os_abort(1);
}
#endif
return memory;
}
internal u64 arena_position(Arena *arena) {
Arena *current_arena = arena->current;
u64 current_position = current_arena->base_position + current_arena->position;
return current_position;
}
internal void arena_pop_to(Arena *arena, u64 position) {
u64 big_position = ClampBot(ARENA_HEADER_SIZE, position);
Arena *current_arena = arena->current;
for (Arena *previous_arena = 0; current_arena->base_position >= big_position; current_arena = previous_arena) {
previous_arena = current_arena->previous;
os_release(current_arena, current_arena->reserve);
}
arena->current = current_arena;
u64 new_position = big_position - current_arena->base_position;
// ??(tijani): why need to ASSERT and AsanPoision memory region.
current_arena->position = new_position;
}
internal void arena_clear(Arena *arena) { arena_pop_to(arena, 0); }
// Pops the amount of memory passed off the passed in arena.
// The new position of the passed in arena will be the same
// memory block minus the amount passed in.
internal void arena_pop_off(Arena *arena, u64 amount) {
u64 old_position = arena_position(arena);
u64 new_position = old_position;
if (amount < old_position) {
new_position = old_position - amount;
}
arena_pop_to(arena, new_position);
}
// Temporary memory
internal Temp temp_begin(Arena *arena) {
u64 position = arena_position(arena);
Temp temp = {arena, position};
return temp;
}
internal void temp_end(Temp temp) { arena_pop_to(temp.arena, temp.position); }

View File

@ -19,15 +19,20 @@
// Constants
#define ARENA_HEADER_SIZE 64
// Types
// Flags
// ArenaFlag_NoChain - Arenas are chained by default, this flag tells it otherwise.
// ArenaFlag_LargePages - Use large pages.
typedef u32 ArenaFlags;
enum { ArenaFlag_NoChain = (1 << 0); ArenaFlag_LargePages = (1 << 1); };
enum {
ArenaFlag_NoChain = (1 << 0),
ArenaFlag_LargePages = (1 << 1),
};
typedef struct ArenaParams ArenaParams;
struct ArenaParams {
ArenaFlags flags;
u64 reserve_size;
u64 commite_size;
u64 commit_size;
void *optional_backing_buffer; // NOTE(tijani): ??
};
@ -56,11 +61,11 @@ internal Arena *arena_alloc_(ArenaParams *params);
internal void arena_releas(Arena *arena);
// push, pop operations
internal void *arena_psuh(Arena *arena, u64 size, u64 align);
internal void *arena_push(Arena *arena, u64 size_to_push, u64 align);
internal u64 arena_position(Arena *arena);
internal void arena_pop_to(Arena *arena, u64 position);
internal void arena_clear(Arena *arena);
internal void arena_pop(Arena *arena, u64 amount);
internal void arena_pop_off(Arena *arena, u64 amount);
#define push_array_no_zero_aligned(a, T, c, align) (T *)arena_push((a), sizeof(T) * (c), (align))
#define push_array_aligned(a, T, c, align) (T *)MemoryZero(push_array_no_zero_aligned(a, T, c, align), sizeof(T) * (c))
#define push_array_no_zero(a, T, c) push_array_no_zero_aligned(a, T, c, Max(8, Align_Of(T)))

View File

@ -41,9 +41,20 @@ typedef double f64;
// Memory operations
#define MemoryZero(dest, count) memset((dest), 0, (count))
// Max, Min
// Max, Min, Clamps
#define Max(A, B) (((A) > (B)) ? (A) : (B))
#define Min(A, B) (((A) < (B)) ? (A) : (B))
// NOTE(tijani):
// if X < A:
// return A
// else
// if X > B
// return B
// else
// return X
#define Clamp(A, X, B) (((X) < (A)) ? (A) : ((X) > (B) ? (B) : (X)))
#define ClampTop(A, X) Min(A, X)
#define ClampBot(X, B) Max(X, B)
// Type Alignment
#if COMPILER_MSVC

View File

@ -1,6 +1,5 @@
// clang-format off
#include "base_core.c"
#include "base_arena.c"
#include "base_strings.c"

6
src/goff/goff_main.c Normal file
View File

@ -0,0 +1,6 @@
// [.h] includes
#include "base/base_inc.h"
// [.c] includes
#include "base/base_inc.c"

View File

@ -3,6 +3,7 @@ internal OS_SystemInfo *os_get_system_info(void) { return &os_w32_state.system_
internal OS_ProcessInfo *os_get_process_info(void) { return &os_w32_state.process_info; }
// @nocheckin
internal String8 os_get_current_path(Arena *arena) {}
// %os_hooks(implemented per-os) Memory allocation