basic arena with a test

This commit is contained in:
Anton Ljungdahl 2025-05-17 21:45:29 +02:00
parent 0c2f8bdbd5
commit 8c26c11e0d
12 changed files with 708 additions and 14 deletions

View File

@ -15,14 +15,24 @@ set LastError=%ERRORLEVEL%
ctime -end timeBuild.ctm %LastError%
popd
echo --- Codegen:
IF NOT %LastError%==0 GOTO :end
ctime -begin timeBuild.ctm
pushd src
pushd gen_test
..\..\build\codegen.exe ./
popd
pushd os
..\..\build\codegen.exe ./
popd
popd
echo Codegen time:
set LastError=%ERRORLEVEL%
ctime -end timeBuild.ctm %LastError%
echo --- Main

151
src/base/base_arena.c Normal file
View File

@ -0,0 +1,151 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//~ Base arena implementation
internal Arena *
arena_alloc_()
{
U64 reserve_size = g_arena_default_reserve_size;
U64 commit_size = g_arena_default_commit_size;
// TODO align to page sizes
// Reserve/commit initial block
void *base = 0;
if(base == 0) // TODO(anton): can have optional backing buffer
{
base = os_reserve(reserve_size);
os_commit(base, commit_size);
}
// Extract arena header and fill it
Arena *arena = (Arena *)base;
arena->current = arena;
arena->commit_size = commit_size;
arena->reserve_size = reserve_size;
arena->base_pos = 0;
arena->pos = ARENA_HEADER_SIZE;
arena->commit = commit_size;
arena->reserve = reserve_size;
return arena;
}
internal void
arena_release(Arena *arena)
{
// Go back in chain and release
for(Arena *n = arena->current, *prev = 0; n != 0; n = prev)
{
prev = n->prev;
os_release(n, n->reserve);
}
}
internal void *
arena_push(Arena *arena, U64 size, U64 align)
{
Arena *current = arena->current;
U64 pos_pre = AlignPow2(current->pos, align);
U64 pos_post = pos_pre + size;
// TODO(anton): Add chaining etc. Now we always just put up a new block.
// Commit new pages if needed, that is if the new position of the arena pointer
// is larger than the current commit adress.
if(current->commit < pos_post)
{
U64 commit_post_aligned = pos_post + current->commit_size - 1;
commit_post_aligned -= commit_post_aligned % current->commit_size;
// Now commit_post_aligned is aligned
U64 commit_post_clamped = ClampTop(commit_post_aligned, current->reserve);
U64 commit_size = commit_post_clamped - current->commit;
U8 *commit_ptr = (U8 *)current + current->commit;
os_commit(commit_ptr, commit_size);
current->commit = commit_post_clamped;
}
// Push to current block
void *result = 0;
if(current->commit >= pos_post)
{
result = (U8 *)current+pos_pre;
current->pos = pos_post;
}
if(result == 0)
{
LOG("FATAL ERROR IN ARENA ALLOC");
ExitProcess(0);
}
return result;
}
internal U64
arena_pos(Arena *arena)
{
Arena *current = arena->current;
U64 pos = current->base_pos + current->pos;
return pos;
}
internal void
arena_pop_to(Arena *arena, U64 pos)
{
U64 big_pos = ClampBot(ARENA_HEADER_SIZE, pos);
Arena *current = arena->current;
for(Arena *prev = 0; current->base_pos >= big_pos; current = prev)
{
prev = current->prev;
os_release(current, current->reserve);
}
arena->current = current;
U64 new_pos = big_pos - current->base_pos;
AssertAlways(new_pos <= current->pos);
current->pos = new_pos;
}
internal void
arena_clear(Arena *arena)
{
arena_pop_to(arena, 0);
}
internal void
arena_pop(Arena *arena, U64 amt)
{
U64 pos_old = arena_pos(arena);
U64 pos_new = pos_old;
if(amt < pos_old)
{
pos_new = pos_old - amt;
}
arena_pop_to(arena, pos_new);
}
//- rjf: temporary arena scopes
internal Temp
temp_begin(Arena *arena)
{
U64 pos = arena_pos(arena);
Temp temp = {arena, pos};
return temp;
}
internal void
temp_end(Temp temp)
{
arena_pop_to(temp.arena, temp.pos);
}

64
src/base/base_arena.h Normal file
View File

@ -0,0 +1,64 @@
#ifndef BASE_ARENA_H
#define BASE_ARENA_H
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//~
#define ARENA_HEADER_SIZE 128
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//~
typedef struct Arena Arena;
struct Arena
{
// If we have chains of arenas we have linked list links here
Arena *prev;
Arena *current;
U64 commit_size;
U64 reserve_size;
U64 base_pos;
U64 pos;
U64 commit;
U64 reserve;
};
typedef struct Temp Temp;
struct Temp
{
Arena *arena;
U64 pos;
};
global U64 g_arena_default_reserve_size = MB(64);
global U64 g_arena_default_commit_size = MB(64);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//~
internal Arena *arena_alloc_(/* TODO arena params */);
// Macro for arena alloc with default params:
#define arena_alloc(...) arena_alloc_()
internal void arena_release(Arena *arena);
//- arena push/pop/pos core functions
internal void *arena_push(Arena *arena, U64 size, U64 align);
internal U64 arena_pos(Arena *arena);
internal void arena_pop_to(Arena *arena, U64 pos);
//- arena push/pop helpers
internal void arena_clear(Arena *arena);
internal void arena_pop(Arena *arena, U64 amt);
//- temporary arena scopes
internal Temp temp_begin(Arena *arena);
internal void temp_end(Temp temp);
//- push helper macros
#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, AlignOf(T)))
#define push_array(a, T, c) push_array_aligned(a, T, c, Max(8, AlignOf(T)))
#endif /* BASE_ARENA_H */

View File

@ -1,19 +1,120 @@
#ifndef BASE_CORE_H
#define BASE_CORE_H
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//~
#include <stdint.h>
#include <stdarg.h>
typedef int32_t S32;
typedef uint32_t U32;
typedef int64_t S64;
typedef uint64_t U64;
typedef float F32;
typedef double F64;
// TODO(anton): Move to context cracking
#if defined(_MSC_VER)
#define COMPILER_MSVC 1
#endif
////////////////////////////////
//~ Asserts
#if COMPILER_MSVC
# define Trap() __debugbreak()
#elif COMPILER_CLANG || COMPILER_GCC
# define Trap() __builtin_trap()
#else
# error Unknown trap intrinsic for this compiler.
#endif
#if COMPILER_MSVC
# define AlignOf(T) __alignof(T)
#else
# error Need MSVC for now!
#endif
#define AssertAlways(x) do{if(!(x)) {Trap();}}while(0)
#if BUILD_DEBUG
# define Assert(x) AssertAlways(x)
#else
# define Assert(x) (void)(x)
#endif
#define InvalidPath Assert(!"Invalid Path!")
#define NotImplemented Assert(!"Not Implemented!")
#define NoOp ((void)0)
#define StaticAssert(C, ID) global U8 Glue(ID, __LINE__)[(C)?1:-1]
#define global static
#define function static
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//~
typedef uint8_t U8;
typedef uint16_t U16;
typedef uint32_t U32;
typedef uint64_t U64;
typedef int8_t S8;
typedef int16_t S16;
typedef int32_t S32;
typedef int64_t S64;
typedef S8 B8;
typedef S16 B16;
typedef S32 B32;
typedef S64 B64;
typedef float F32;
typedef double F64;
typedef void VoidProc(void);
typedef union U128 U128;
union U128
{
U8 u8[16];
U16 u16[8];
U32 u32[4];
U64 u64[2];
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//~
#define global static
#define internal static
#define local_persist static
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//~
#define Min(A,B) (((A)<(B))?(A):(B))
#define Max(A,B) (((A)>(B))?(A):(B))
#define ClampTop(A,X) Min(A,X)
#define ClampBot(X,B) Max(X,B)
#define Clamp(A,X,B) (((X)<(A))?(A):((X)>(B))?(B):(X))
#define MemoryCopy(dst, src, size) memmove((dst), (src), (size))
#define MemorySet(dst, byte, size) memset((dst), (byte), (size))
#define MemoryCopyStruct(d,s) MemoryCopy((d),(s),sizeof(*(d)))
#define MemoryCopyArray(d,s) MemoryCopy((d),(s),sizeof(d))
#define MemoryZero(s,z) memset((s),0,(z))
#define MemoryZeroStruct(s) MemoryZero((s),sizeof(*(s)))
#define MemoryZeroArray(a) MemoryZero((a),sizeof(a))
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//~
#define KB(n) (((U64)(n)) << 10)
#define MB(n) (((U64)(n)) << 20)
#define GB(n) (((U64)(n)) << 30)
#define TB(n) (((U64)(n)) << 40)
#define Thousand(n) ((n)*1000)
#define Million(n) ((n)*1000000)
#define Billion(n) ((n)*1000000000)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//~ Helper macros
#define ArrayCount(a) (sizeof(a) / sizeof((a)[0]))
#define AlignPow2(x,b) (((x) + (b) - 1)&(~((b) - 1)))
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//~
#define LOG OS_W32_log_debug
#endif /* BASE_CORE_H */

View File

@ -1,2 +1,4 @@
//////////////////////////////////////////////////////////////////////////////////////////////
//~
//~
#include "base_arena.c"

View File

@ -4,7 +4,7 @@
//////////////////////////////////////////////////////////////////////////////////////////////
//~
#include "base_core.h"
// #include "base_arena.h"
#include "base_arena.h"
// #include "base_math.h"
// #include "base_entry_point.h"

View File

@ -16,15 +16,83 @@ static void entry_point();
#include "os/os_inc.c"
#include "render/render_inc.c"
#include "gen_test/generated/test.meta.h"
#include "gen_test/generated/test.meta.c"
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//~
internal void
test_arena(Arena *arena)
{
LOG("Testing arena with filled entries with A prefix.\n");
U64 count = 0;
U64 N1 = 32;
U64 *arr = push_array(arena, U64, N1);
for(U64 i = 0; i < N1; i += 1)
{
arr[i] = i;
count += 1;
}
for(U64 i = 0; i < count; i += 1)
{
U64 value = arr[i];
LOG("arr[%i] = %i \n", i, value);
}
arena_pop(arena, sizeof(U64)*N1);
U64 N2 = 8;
count = 0;
for(U64 i = 0; i < N2; i += 1)
{
arr[i] = 100 + i;
count += 1;
}
LOG("After pop: \n");
for(U64 i = 0; i < count; i += 1)
{
U64 value = arr[i];
LOG("arr[%i] = %i \n", i, value);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//~ Main entry
function void
internal void
entry_point()
{
printf("HELLO MAIN");
LOG("HELLO MAIN \n");
// Init systems
Arena *arena = arena_alloc();
//test_arena(arena);
// Main program loop
U32 do_exit = 0;
for(;;)
{
MSG Message;
while(PeekMessage(&Message, 0, 0, 0, PM_REMOVE))
{
switch(Message.message)
{
case WM_CLOSE:
{
SendMessageW(g_service_window_handle, OS_W32_MSG_DESTROY_WINDOW, Message.wParam, 0);
do_exit = 1;
} break;
}
}
if(do_exit)
{
break;
}
}
arena_release(arena);
}

View File

View File

@ -0,0 +1,119 @@
typedef enum OS_Key
{
OS_Key_Null,
OS_Key_Esc,
OS_Key_F1,
OS_Key_F2,
OS_Key_F3,
OS_Key_F4,
OS_Key_F5,
OS_Key_F6,
OS_Key_F7,
OS_Key_F8,
OS_Key_F9,
OS_Key_F10,
OS_Key_F11,
OS_Key_F12,
OS_Key_F13,
OS_Key_F14,
OS_Key_F15,
OS_Key_F16,
OS_Key_F17,
OS_Key_F18,
OS_Key_F19,
OS_Key_F20,
OS_Key_F21,
OS_Key_F22,
OS_Key_F23,
OS_Key_F24,
OS_Key_Tick,
OS_Key_0,
OS_Key_1,
OS_Key_2,
OS_Key_3,
OS_Key_4,
OS_Key_5,
OS_Key_6,
OS_Key_7,
OS_Key_8,
OS_Key_9,
OS_Key_Minus,
OS_Key_Equal,
OS_Key_Backspace,
OS_Key_Tab,
OS_Key_Q,
OS_Key_W,
OS_Key_E,
OS_Key_R,
OS_Key_T,
OS_Key_Y,
OS_Key_U,
OS_Key_I,
OS_Key_O,
OS_Key_P,
OS_Key_LeftBracket,
OS_Key_RightBracket,
OS_Key_BackSlash,
OS_Key_CapsLock,
OS_Key_A,
OS_Key_S,
OS_Key_D,
OS_Key_F,
OS_Key_G,
OS_Key_H,
OS_Key_J,
OS_Key_K,
OS_Key_L,
OS_Key_Semicolon,
OS_Key_Quote,
OS_Key_Return,
OS_Key_Shift,
OS_Key_Z,
OS_Key_X,
OS_Key_C,
OS_Key_V,
OS_Key_B,
OS_Key_N,
OS_Key_M,
OS_Key_Comma,
OS_Key_Period,
OS_Key_Slash,
OS_Key_Ctrl,
OS_Key_Alt,
OS_Key_Space,
OS_Key_Menu,
OS_Key_ScrollLock,
OS_Key_Pause,
OS_Key_Insert,
OS_Key_Home,
OS_Key_PageUp,
OS_Key_Delete,
OS_Key_End,
OS_Key_PageDown,
OS_Key_Up,
OS_Key_Left,
OS_Key_Down,
OS_Key_Right,
OS_Key_NumLock,
OS_Key_NumSlash,
OS_Key_NumStar,
OS_Key_NumMinus,
OS_Key_NumPlus,
OS_Key_NumPeriod,
OS_Key_Num0,
OS_Key_Num1,
OS_Key_Num2,
OS_Key_Num3,
OS_Key_Num4,
OS_Key_Num5,
OS_Key_Num6,
OS_Key_Num7,
OS_Key_Num8,
OS_Key_Num9,
OS_Key_LeftMouseButton,
OS_Key_MiddleMouseButton,
OS_Key_RightMouseButton,
OS_Key_COUNT
}
OS_Key;

View File

@ -3,5 +3,51 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//~
#include "os/generated/os_core.meta.h"
typedef struct OS_Handle OS_Handle;
struct OS_Handle
{
U64 handle[1];
};
typedef enum OS_EventKind
{
OS_EventKind_Null,
OS_EventKind_Press,
OS_EventKind_Release,
OS_EventKind_MouseMove,
OS_EventKind_COUNT
}
OS_EventKind;
typedef struct OS_Event OS_Event;
struct OS_Event
{
OS_Event *next;
OS_Event *prev;
OS_Handle window;
OS_EventKind kind;
OS_Key key;
};
typedef struct OS_EventList OS_EventList;
struct OS_EventList
{
U64 count;
OS_Event *first;
OS_Event *last;
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//~
// OS memory
internal void *os_reserve(U64 size);
internal B32 os_commit(void *ptr, U64 size);
internal void os_decommit(void *ptr, U64 size);
internal void os_release(void *ptr, U64 size);
#endif /* OS_CORE_H */

133
src/os/os_core.mdesk Normal file
View File

@ -0,0 +1,133 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//~ Table with key enums.
// TODO(anton): Extend this table to include description strings etc when necessary.
@table(name)
OS_KeyTable:
{
{Null }
{Esc }
{F1 }
{F2 }
{F3 }
{F4 }
{F5 }
{F6 }
{F7 }
{F8 }
{F9 }
{F10 }
{F11 }
{F12 }
{F13 }
{F14 }
{F15 }
{F16 }
{F17 }
{F18 }
{F19 }
{F20 }
{F21 }
{F22 }
{F23 }
{F24 }
{Tick }
{0 }
{1 }
{2 }
{3 }
{4 }
{5 }
{6 }
{7 }
{8 }
{9 }
{Minus }
{Equal }
{Backspace }
{Tab }
{Q }
{W }
{E }
{R }
{T }
{Y }
{U }
{I }
{O }
{P }
{LeftBracket }
{RightBracket }
{BackSlash }
{CapsLock }
{A }
{S }
{D }
{F }
{G }
{H }
{J }
{K }
{L }
{Semicolon }
{Quote }
{Return }
{Shift }
{Z }
{X }
{C }
{V }
{B }
{N }
{M }
{Comma }
{Period }
{Slash }
{Ctrl }
{Alt }
{Space }
{Menu }
{ScrollLock }
{Pause }
{Insert }
{Home }
{PageUp }
{Delete }
{End }
{PageDown }
{Up }
{Left }
{Down }
{Right }
{NumLock }
{NumSlash }
{NumStar }
{NumMinus }
{NumPlus }
{NumPeriod }
{Num0 }
{Num1 }
{Num2 }
{Num3 }
{Num4 }
{Num5 }
{Num6 }
{Num7 }
{Num8 }
{Num9 }
{LeftMouseButton }
{MiddleMouseButton }
{RightMouseButton }
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//~ Generators
@table_gen_enum OS_Key:
{
@expand(OS_KeyTable a)
` OS_Key_$(a.name),`;
` OS_Key_COUNT`
}

BIN
timeBuild.ctm Normal file

Binary file not shown.