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:
parent
b4cfc14d3b
commit
ab89c03813
@ -1,6 +1,7 @@
|
|||||||
internal *arena_alloc_(ArenaParams *params) {
|
internal Arena *arena_alloc_(ArenaParams *params) {
|
||||||
u64 reserve_size = params->reserve_size;
|
u64 reserve_size = params->reserve_size;
|
||||||
u64 commit_size = params->reserve_size;
|
u64 commit_size = params->commit_size;
|
||||||
|
|
||||||
if (params->flags & ArenaFlag_LargePages) {
|
if (params->flags & ArenaFlag_LargePages) {
|
||||||
reserve_size = AlignPow2(reserve_size, os_get_system_info()->large_page_size);
|
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);
|
||||||
@ -9,7 +10,7 @@ internal *arena_alloc_(ArenaParams *params) {
|
|||||||
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;
|
void *base = params->optional_backing_buffer;
|
||||||
if (base == 0) {
|
if (base == 0) {
|
||||||
if (params->flags & ArenaFlag_LargePages) {
|
if (params->flags & ArenaFlag_LargePages) {
|
||||||
@ -34,7 +35,7 @@ internal *arena_alloc_(ArenaParams *params) {
|
|||||||
arena->flags = params->flags;
|
arena->flags = params->flags;
|
||||||
arena->commit_size = (u32)params->commit_size;
|
arena->commit_size = (u32)params->commit_size;
|
||||||
arena->reserve_size = params->reserve_size;
|
arena->reserve_size = params->reserve_size;
|
||||||
arena->base_position 0;
|
arena->base_position = 0;
|
||||||
arena->position = ARENA_HEADER_SIZE;
|
arena->position = ARENA_HEADER_SIZE;
|
||||||
arena->commit = commit_size;
|
arena->commit = commit_size;
|
||||||
arena->reserve = reserve_size;
|
arena->reserve = reserve_size;
|
||||||
@ -42,15 +43,101 @@ internal *arena_alloc_(ArenaParams *params) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal void arena_release(Arena *arena) {
|
internal void arena_release(Arena *arena) {
|
||||||
for (Arena *n = arena->current; *l_previous = 0; n != 0; n = l_previous) {
|
for (Arena *current_arena = arena->current, *previous_arena = 0; current_arena != 0; current_arena = previous_arena) {
|
||||||
l_previous = n->previous;
|
previous_arena = current_arena->previous;
|
||||||
os_release(n, n->reserve);
|
os_release(current_arena, current_arena->reserve);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @nocheckin
|
internal void *arena_push(Arena *arena, u64 size_to_push, u64 align) {
|
||||||
internal void *arena_push(Arena *arena, u64 size, u64 align) {
|
Arena *current_arena = arena->current;
|
||||||
Arena *current = arena->current;
|
u64 position_pre_push = AlignPow2(current_arena->position, align); // position of arena before push
|
||||||
u64 position_pre = AlignPow2(current->position);
|
u64 position_post_push = position_pre_push + size_to_push; // position of arena after push
|
||||||
u64 position_past = position_pre + size;
|
|
||||||
|
// ??(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); }
|
||||||
|
@ -19,15 +19,20 @@
|
|||||||
// Constants
|
// Constants
|
||||||
#define ARENA_HEADER_SIZE 64
|
#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;
|
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;
|
typedef struct ArenaParams ArenaParams;
|
||||||
struct ArenaParams {
|
struct ArenaParams {
|
||||||
ArenaFlags flags;
|
ArenaFlags flags;
|
||||||
u64 reserve_size;
|
u64 reserve_size;
|
||||||
u64 commite_size;
|
u64 commit_size;
|
||||||
void *optional_backing_buffer; // NOTE(tijani): ??
|
void *optional_backing_buffer; // NOTE(tijani): ??
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -56,11 +61,11 @@ internal Arena *arena_alloc_(ArenaParams *params);
|
|||||||
internal void arena_releas(Arena *arena);
|
internal void arena_releas(Arena *arena);
|
||||||
|
|
||||||
// push, pop operations
|
// 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 u64 arena_position(Arena *arena);
|
||||||
internal void arena_pop_to(Arena *arena, u64 position);
|
internal void arena_pop_to(Arena *arena, u64 position);
|
||||||
internal void arena_clear(Arena *arena);
|
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_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_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)))
|
#define push_array_no_zero(a, T, c) push_array_no_zero_aligned(a, T, c, Max(8, Align_Of(T)))
|
||||||
|
@ -41,9 +41,20 @@ typedef double f64;
|
|||||||
// Memory operations
|
// Memory operations
|
||||||
#define MemoryZero(dest, count) memset((dest), 0, (count))
|
#define MemoryZero(dest, count) memset((dest), 0, (count))
|
||||||
|
|
||||||
// Max, Min
|
// Max, Min, Clamps
|
||||||
#define Max(A, B) (((A) > (B)) ? (A) : (B))
|
#define Max(A, B) (((A) > (B)) ? (A) : (B))
|
||||||
#define Min(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
|
// Type Alignment
|
||||||
#if COMPILER_MSVC
|
#if COMPILER_MSVC
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
// clang-format off
|
// clang-format off
|
||||||
|
|
||||||
#include "base_core.c"
|
|
||||||
#include "base_arena.c"
|
#include "base_arena.c"
|
||||||
#include "base_strings.c"
|
#include "base_strings.c"
|
||||||
|
|
||||||
|
6
src/goff/goff_main.c
Normal file
6
src/goff/goff_main.c
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
// [.h] includes
|
||||||
|
#include "base/base_inc.h"
|
||||||
|
|
||||||
|
// [.c] includes
|
||||||
|
#include "base/base_inc.c"
|
@ -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; }
|
internal OS_ProcessInfo *os_get_process_info(void) { return &os_w32_state.process_info; }
|
||||||
|
|
||||||
|
// @nocheckin
|
||||||
internal String8 os_get_current_path(Arena *arena) {}
|
internal String8 os_get_current_path(Arena *arena) {}
|
||||||
|
|
||||||
// %os_hooks(implemented per-os) Memory allocation
|
// %os_hooks(implemented per-os) Memory allocation
|
||||||
|
Loading…
Reference in New Issue
Block a user