diff --git a/src/base/base_arena.c b/src/base/base_arena.c index 51ff95f..57662f3 100644 --- a/src/base/base_arena.c +++ b/src/base/base_arena.c @@ -1,15 +1,16 @@ -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); + commit_size = AlignPow2(commit_size, os_get_system_info()->large_page_size); } else { reserve_size = AlignPow2(reserve_size, os_get_system_info()->page_size); - commit_size = AlignPow2(commit_size, os_get_system_info()->page_size); + 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) { @@ -29,28 +30,114 @@ internal *arena_alloc_(ArenaParams *params) { } #endif - Arena *arena = (Arena *)base; - arena->current = arena; // Current arena in the chain - arena->flags = params->flags; - arena->commit_size = (u32)params->commit_size; - arena->reserve_size = params->reserve_size; - arena->base_position 0; - arena->position = ARENA_HEADER_SIZE; - arena->commit = commit_size; - arena->reserve = reserve_size; + Arena *arena = (Arena *)base; + arena->current = arena; // Current arena in the chain + arena->flags = params->flags; + arena->commit_size = (u32)params->commit_size; + arena->reserve_size = params->reserve_size; + arena->base_position = 0; + arena->position = ARENA_HEADER_SIZE; + arena->commit = commit_size; + arena->reserve = reserve_size; return arena; } 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); } diff --git a/src/base/base_arena.h b/src/base/base_arena.h index c53590d..3e2df12 100644 --- a/src/base/base_arena.h +++ b/src/base/base_arena.h @@ -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))) diff --git a/src/base/base_core.h b/src/base/base_core.h index 606924c..5ba53ec 100644 --- a/src/base/base_core.h +++ b/src/base/base_core.h @@ -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 diff --git a/src/base/base_inc.c b/src/base/base_inc.c index 832b462..ebe70f2 100644 --- a/src/base/base_inc.c +++ b/src/base/base_inc.c @@ -1,6 +1,5 @@ // clang-format off -#include "base_core.c" #include "base_arena.c" #include "base_strings.c" diff --git a/src/base/base_stirngs.c b/src/base/base_strings.c similarity index 100% rename from src/base/base_stirngs.c rename to src/base/base_strings.c diff --git a/src/goff/goff_main.c b/src/goff/goff_main.c new file mode 100644 index 0000000..a42a733 --- /dev/null +++ b/src/goff/goff_main.c @@ -0,0 +1,6 @@ + +// [.h] includes +#include "base/base_inc.h" + +// [.c] includes +#include "base/base_inc.c" diff --git a/src/os/core/win32/os_core_win32.c b/src/os/core/win32/os_core_win32.c index 305d6d8..d271e43 100644 --- a/src/os/core/win32/os_core_win32.c +++ b/src/os/core/win32/os_core_win32.c @@ -3,7 +3,8 @@ 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; } -internal String8 os_get_current_path(Arena *arena) {} +// @nocheckin +internal String8 os_get_current_path(Arena *arena) {} // %os_hooks(implemented per-os) Memory allocation