mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-06 13:58:40 +00:00
update metagen base/os & entry point
This commit is contained in:
@@ -2,176 +2,135 @@
|
|||||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Implementation
|
//~ rjf: Arena Functions
|
||||||
|
|
||||||
|
//- rjf: arena creation/destruction
|
||||||
|
|
||||||
internal Arena *
|
internal Arena *
|
||||||
arena_alloc__sized(U64 init_res, U64 init_cmt)
|
arena_alloc_(ArenaParams *params)
|
||||||
{
|
{
|
||||||
ProfBeginFunction();
|
// rjf: round up reserve/commit sizes
|
||||||
Assert(ARENA_HEADER_SIZE < init_cmt && init_cmt <= init_res);
|
U64 reserve_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);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reserve_size = AlignPow2(reserve_size, os_get_system_info()->page_size);
|
||||||
|
commit_size = AlignPow2(commit_size, os_get_system_info()->page_size);
|
||||||
|
}
|
||||||
|
|
||||||
void *memory;
|
// rjf: reserve/commit initial block
|
||||||
U64 res;
|
void *base = params->optional_backing_buffer;
|
||||||
U64 cmt;
|
if(base == 0)
|
||||||
|
{
|
||||||
B32 large_pages = os_large_pages_enabled();
|
if(params->flags & ArenaFlag_LargePages)
|
||||||
if (large_pages) {
|
{
|
||||||
U64 page_size = os_large_page_size();
|
base = os_reserve_large(reserve_size);
|
||||||
res = AlignPow2(init_res, page_size);
|
os_commit_large(base, commit_size);
|
||||||
|
|
||||||
#if OS_WINDOWS
|
|
||||||
cmt = res;
|
|
||||||
#else
|
|
||||||
cmt AlignPow2(init_cmt, page_size);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
memory = os_reserve_large(res);
|
|
||||||
if (!os_commit_large(memory, cmt)) {
|
|
||||||
memory = 0;
|
|
||||||
os_release(memory, res);
|
|
||||||
}
|
}
|
||||||
} else {
|
else
|
||||||
U64 page_size = os_page_size();
|
{
|
||||||
res = AlignPow2(init_res, page_size);
|
base = os_reserve(reserve_size);
|
||||||
cmt = AlignPow2(init_cmt, page_size);
|
os_commit(base, commit_size);
|
||||||
|
|
||||||
memory = os_reserve(res);
|
|
||||||
if (!os_commit(memory, cmt)) {
|
|
||||||
memory = 0;
|
|
||||||
os_release(memory, res);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Assert(memory);
|
|
||||||
|
|
||||||
AsanPoisonMemoryRegion(memory, cmt);
|
// rjf: panic on arena creation failure
|
||||||
AsanUnpoisonMemoryRegion(memory, ARENA_HEADER_SIZE);
|
#if OS_FEATURE_GRAPHICAL
|
||||||
|
if(Unlikely(base == 0))
|
||||||
Arena *arena = (Arena*)memory;
|
{
|
||||||
if (arena) {
|
os_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure."));
|
||||||
arena->prev = 0;
|
os_abort(1);
|
||||||
arena->current = arena;
|
}
|
||||||
arena->base_pos = 0;
|
|
||||||
arena->pos = ARENA_HEADER_SIZE;
|
|
||||||
arena->cmt = cmt;
|
|
||||||
arena->res = res;
|
|
||||||
arena->align = 8;
|
|
||||||
#if ENABLE_DEV
|
|
||||||
arena->dev = 0;
|
|
||||||
#endif
|
#endif
|
||||||
arena->grow = 1;
|
|
||||||
arena->large_pages = large_pages;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProfEnd();
|
// rjf: extract arena header & fill
|
||||||
return arena;
|
Arena *arena = (Arena *)base;
|
||||||
}
|
arena->current = arena;
|
||||||
|
arena->flags = params->flags;
|
||||||
internal Arena *
|
arena->cmt_size = (U32)params->commit_size;
|
||||||
arena_alloc(void)
|
arena->res_size = params->reserve_size;
|
||||||
{
|
arena->base_pos = 0;
|
||||||
ProfBeginFunction();
|
arena->pos = ARENA_HEADER_SIZE;
|
||||||
|
arena->cmt = commit_size;
|
||||||
U64 init_res, init_cmt;
|
arena->res = reserve_size;
|
||||||
if (os_large_pages_enabled()) {
|
AsanPoisonMemoryRegion(base, commit_size);
|
||||||
init_res = ARENA_RESERVE_SIZE_LARGE_PAGES;
|
AsanUnpoisonMemoryRegion(base, ARENA_HEADER_SIZE);
|
||||||
init_cmt = ARENA_COMMIT_SIZE_LARGE_PAGES;
|
|
||||||
} else {
|
|
||||||
init_res = ARENA_RESERVE_SIZE;
|
|
||||||
init_cmt = ARENA_COMMIT_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
Arena *arena = arena_alloc__sized(init_res, init_cmt);
|
|
||||||
|
|
||||||
ProfEnd();
|
|
||||||
return arena;
|
return arena;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
arena_release(Arena *arena)
|
arena_release(Arena *arena)
|
||||||
{
|
{
|
||||||
for (Arena *node = arena->current, *prev = 0; node != 0; node = prev) {
|
for(Arena *n = arena->current, *prev = 0; n != 0; n = prev)
|
||||||
prev = node->prev;
|
{
|
||||||
os_release(node, node->res);
|
prev = n->prev;
|
||||||
|
os_release(n, n->res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal U64
|
//- rjf: arena push/pop core functions
|
||||||
arena_huge_push_threshold(void)
|
|
||||||
{
|
|
||||||
U64 reserve_size = os_large_pages_enabled() ? ARENA_RESERVE_SIZE_LARGE_PAGES : ARENA_RESERVE_SIZE;
|
|
||||||
U64 threshold = (reserve_size - ARENA_HEADER_SIZE) / 2 + 1;
|
|
||||||
return threshold;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void *
|
internal void *
|
||||||
arena_push__impl(Arena *arena, U64 size)
|
arena_push(Arena *arena, U64 size, U64 align)
|
||||||
{
|
{
|
||||||
Arena *current = arena->current;
|
Arena *current = arena->current;
|
||||||
U64 pos_mem = AlignPow2(current->pos, arena->align);
|
U64 pos_pre = AlignPow2(current->pos, align);
|
||||||
U64 pos_new = pos_mem + size;
|
U64 pos_pst = pos_pre + size;
|
||||||
|
|
||||||
if (current->res < pos_new && arena->grow) {
|
// rjf: chain, if needed
|
||||||
Arena *new_block;
|
if(current->res < pos_pst && !(arena->flags & ArenaFlag_NoChain))
|
||||||
|
{
|
||||||
// normal growth path
|
U64 res_size = current->res_size;
|
||||||
if (size < arena_huge_push_threshold()) {
|
U64 cmt_size = current->cmt_size;
|
||||||
new_block = arena_alloc();
|
if(size > cmt_size)
|
||||||
}
|
{
|
||||||
// huge growth path
|
res_size = size + ARENA_HEADER_SIZE;
|
||||||
else {
|
cmt_size = size + ARENA_HEADER_SIZE;
|
||||||
U64 new_block_size = size + ARENA_HEADER_SIZE;
|
|
||||||
new_block = arena_alloc__sized(new_block_size, new_block_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (new_block) {
|
|
||||||
new_block->base_pos = current->base_pos + current->res;
|
|
||||||
SLLStackPush_N(arena->current, new_block, prev);
|
|
||||||
|
|
||||||
current = new_block;
|
|
||||||
pos_mem = AlignPow2(current->pos, current->align);
|
|
||||||
pos_new = pos_mem + size;
|
|
||||||
}
|
}
|
||||||
|
Arena *new_block = arena_alloc(.reserve_size = res_size,
|
||||||
|
.commit_size = cmt_size,
|
||||||
|
.flags = current->flags);
|
||||||
|
new_block->base_pos = current->base_pos + current->res;
|
||||||
|
SLLStackPush_N(arena->current, new_block, prev);
|
||||||
|
current = new_block;
|
||||||
|
pos_pre = AlignPow2(current->pos, align);
|
||||||
|
pos_pst = pos_pst + size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current->cmt < pos_new) {
|
// rjf: commit new pages, if needed
|
||||||
U64 cmt_new_aligned, cmt_new_clamped, cmt_new_size;
|
if(current->cmt < pos_pst && !(current->flags & ArenaFlag_LargePages))
|
||||||
B32 is_cmt_ok;
|
{
|
||||||
|
U64 cmt_pst_aligned = AlignPow2(pos_pst, current->cmt_size);
|
||||||
if (current->large_pages) {
|
U64 cmt_pst_clamped = ClampTop(cmt_pst_aligned, current->res);
|
||||||
cmt_new_aligned = AlignPow2(pos_new, ARENA_COMMIT_SIZE_LARGE_PAGES);
|
U64 cmt_size = cmt_pst_clamped - current->cmt;
|
||||||
cmt_new_clamped = ClampTop(cmt_new_aligned, current->res);
|
os_commit((U8 *)current + current->cmt, cmt_size);
|
||||||
cmt_new_size = cmt_new_clamped - current->cmt;
|
current->cmt = cmt_pst_clamped;
|
||||||
is_cmt_ok = os_commit_large((U8*)current + current->cmt, cmt_new_size);
|
|
||||||
} else {
|
|
||||||
cmt_new_aligned = AlignPow2(pos_new, ARENA_COMMIT_SIZE);
|
|
||||||
cmt_new_clamped = ClampTop(cmt_new_aligned, current->res);
|
|
||||||
cmt_new_size = cmt_new_clamped - current->cmt;
|
|
||||||
is_cmt_ok = os_commit((U8*)current + current->cmt, cmt_new_size);
|
|
||||||
}
|
|
||||||
Assert(is_cmt_ok);
|
|
||||||
|
|
||||||
if (is_cmt_ok) {
|
|
||||||
current->cmt = cmt_new_clamped;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *memory = 0;
|
// rjf: push onto current block
|
||||||
|
void *result = 0;
|
||||||
if (current->cmt >= pos_new) {
|
if(current->cmt >= pos_pst)
|
||||||
memory = (U8*)current + pos_mem;
|
{
|
||||||
current->pos = pos_new;
|
result = (U8 *)current+pos_pre;
|
||||||
AsanUnpoisonMemoryRegion(memory, size);
|
current->pos = pos_pst;
|
||||||
|
AsanUnpoisonMemoryRegion(result, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rjf: panic on failure
|
||||||
#if OS_FEATURE_GRAPHICAL
|
#if OS_FEATURE_GRAPHICAL
|
||||||
if(Unlikely(memory == 0))
|
if(Unlikely(result == 0))
|
||||||
{
|
{
|
||||||
os_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure."));
|
os_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure."));
|
||||||
os_exit_process(1);
|
os_abort(1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return memory;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal U64
|
internal U64
|
||||||
@@ -183,95 +142,23 @@ arena_pos(Arena *arena)
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
arena_pop_to(Arena *arena, U64 big_pos_unclamped)
|
arena_pop_to(Arena *arena, U64 pos)
|
||||||
{
|
{
|
||||||
U64 big_pos = ClampBot(ARENA_HEADER_SIZE, big_pos_unclamped);
|
U64 big_pos = ClampBot(ARENA_HEADER_SIZE, pos);
|
||||||
|
|
||||||
// unroll the chain
|
|
||||||
Arena *current = arena->current;
|
Arena *current = arena->current;
|
||||||
for (Arena *prev = 0; current->base_pos >= big_pos; current = prev) {
|
for(Arena *prev = 0; current->base_pos >= big_pos; current = prev)
|
||||||
|
{
|
||||||
prev = current->prev;
|
prev = current->prev;
|
||||||
os_release(current, current->res);
|
os_release(current, current->res);
|
||||||
}
|
}
|
||||||
AssertAlways(current);
|
|
||||||
arena->current = current;
|
arena->current = current;
|
||||||
|
|
||||||
// compute arena-relative position
|
|
||||||
U64 new_pos = big_pos - current->base_pos;
|
U64 new_pos = big_pos - current->base_pos;
|
||||||
AssertAlways(new_pos <= current->pos);
|
AssertAlways(new_pos <= current->pos);
|
||||||
|
|
||||||
// poison popped memory block
|
|
||||||
AsanPoisonMemoryRegion((U8*)current + new_pos, (current->pos - new_pos));
|
AsanPoisonMemoryRegion((U8*)current + new_pos, (current->pos - new_pos));
|
||||||
|
|
||||||
// update position
|
|
||||||
current->pos = new_pos;
|
current->pos = new_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
//- rjf: arena push/pop helpers
|
||||||
arena_absorb(Arena *arena, Arena *sub)
|
|
||||||
{
|
|
||||||
#if ENABLE_DEV
|
|
||||||
arena_annotate_absorb__dev(arena, sub);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// base adjustment
|
|
||||||
Arena *current = arena->current;
|
|
||||||
U64 base_adjust = current->base_pos + current->res;
|
|
||||||
for (Arena *node = sub->current; node != 0; node = node->prev) {
|
|
||||||
node->base_pos += base_adjust;
|
|
||||||
}
|
|
||||||
|
|
||||||
// attach sub to arena
|
|
||||||
sub->prev = arena->current;
|
|
||||||
arena->current = sub->current;
|
|
||||||
sub->current = sub;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
// Wrappers
|
|
||||||
|
|
||||||
internal void *
|
|
||||||
arena_push(Arena *arena, U64 size)
|
|
||||||
{
|
|
||||||
void *memory = arena_push__impl(arena, size);
|
|
||||||
#if ENABLE_DEV
|
|
||||||
arena_annotate_push__dev(arena, size, memory);
|
|
||||||
#endif
|
|
||||||
return memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void *
|
|
||||||
arena_push_contiguous(Arena *arena, U64 size)
|
|
||||||
{
|
|
||||||
B32 restore = arena->grow;
|
|
||||||
arena->grow = 0;
|
|
||||||
void *memory = arena_push(arena, size);
|
|
||||||
arena->grow = restore;
|
|
||||||
#if ENABLE_DEV
|
|
||||||
arena_annotate_push__dev(arena, size, memory);
|
|
||||||
#endif
|
|
||||||
return memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void
|
|
||||||
arena_push_align(Arena *arena, U64 align)
|
|
||||||
{
|
|
||||||
Assert(IsPow2(align));
|
|
||||||
U64 amt = AlignPadPow2(arena->pos, align);
|
|
||||||
void *ptr = arena_push(arena, amt);
|
|
||||||
MemoryZero(ptr, amt);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void
|
|
||||||
arena_put_back(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);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
arena_clear(Arena *arena)
|
arena_clear(Arena *arena)
|
||||||
@@ -279,6 +166,20 @@ arena_clear(Arena *arena)
|
|||||||
arena_pop_to(arena, 0);
|
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
|
internal Temp
|
||||||
temp_begin(Arena *arena)
|
temp_begin(Arena *arena)
|
||||||
{
|
{
|
||||||
@@ -292,25 +193,3 @@ temp_end(Temp temp)
|
|||||||
{
|
{
|
||||||
arena_pop_to(temp.arena, temp.pos);
|
arena_pop_to(temp.arena, temp.pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ NOTE(allen): "Mini-Arena" Helper
|
|
||||||
|
|
||||||
internal B32
|
|
||||||
ensure_commit(void **cmtptr, void *pos, U64 cmt_block_size){
|
|
||||||
B32 result = 0;
|
|
||||||
U8 *cmt = (U8*)*cmtptr;
|
|
||||||
if (cmt < (U8*)pos){
|
|
||||||
U64 cmt_size_raw = (U8*)pos - cmt;
|
|
||||||
U64 cmt_size = AlignPow2(cmt_size_raw, cmt_block_size);
|
|
||||||
if (os_commit(cmt, cmt_size)){
|
|
||||||
*cmtptr = cmt + cmt_size;
|
|
||||||
result = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
result = 1;
|
|
||||||
}
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,39 +7,41 @@
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Constants
|
//~ rjf: Constants
|
||||||
|
|
||||||
#define ARENA_HEADER_SIZE 128
|
#define ARENA_HEADER_SIZE 64
|
||||||
|
|
||||||
#ifndef ARENA_RESERVE_SIZE
|
|
||||||
# define ARENA_RESERVE_SIZE MB(64)
|
|
||||||
#endif
|
|
||||||
#ifndef ARENA_COMMIT_SIZE
|
|
||||||
# define ARENA_COMMIT_SIZE KB(64)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ARENA_RESERVE_SIZE_LARGE_PAGES
|
|
||||||
# define ARENA_RESERVE_SIZE_LARGE_PAGES MB(8)
|
|
||||||
#endif
|
|
||||||
#ifndef ARENA_COMMIT_SIZE_LARGE_PAGES
|
|
||||||
# define ARENA_COMMIT_SIZE_LARGE_PAGES MB(2)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Arena Types
|
//~ rjf: Types
|
||||||
|
|
||||||
|
typedef U32 ArenaFlags;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
ArenaFlag_NoChain = (1<<0),
|
||||||
|
ArenaFlag_LargePages = (1<<1),
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct ArenaParams ArenaParams;
|
||||||
|
struct ArenaParams
|
||||||
|
{
|
||||||
|
ArenaFlags flags;
|
||||||
|
U64 reserve_size;
|
||||||
|
U64 commit_size;
|
||||||
|
void *optional_backing_buffer;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct Arena Arena;
|
typedef struct Arena Arena;
|
||||||
struct Arena
|
struct Arena
|
||||||
{
|
{
|
||||||
struct Arena *prev;
|
Arena *prev; // previous arena in chain
|
||||||
struct Arena *current;
|
Arena *current; // current arena in chain
|
||||||
|
ArenaFlags flags;
|
||||||
|
U32 cmt_size;
|
||||||
|
U64 res_size;
|
||||||
U64 base_pos;
|
U64 base_pos;
|
||||||
U64 pos;
|
U64 pos;
|
||||||
U64 cmt;
|
U64 cmt;
|
||||||
U64 res;
|
U64 res;
|
||||||
U64 align;
|
|
||||||
struct ArenaDev *dev;
|
|
||||||
B8 grow;
|
|
||||||
B8 large_pages;
|
|
||||||
};
|
};
|
||||||
|
StaticAssert(sizeof(Arena) <= ARENA_HEADER_SIZE, arena_header_size_check);
|
||||||
|
|
||||||
typedef struct Temp Temp;
|
typedef struct Temp Temp;
|
||||||
struct Temp
|
struct Temp
|
||||||
@@ -49,46 +51,30 @@ struct Temp
|
|||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Implementation
|
//~ rjf: Arena Functions
|
||||||
|
|
||||||
internal Arena* arena_alloc__sized(U64 init_res, U64 init_cmt);
|
//- rjf: arena creation/destruction
|
||||||
|
internal Arena *arena_alloc_(ArenaParams *params);
|
||||||
|
#define arena_alloc(...) arena_alloc_(&(ArenaParams){.reserve_size = MB(64), .commit_size = KB(64), __VA_ARGS__})
|
||||||
|
internal void arena_release(Arena *arena);
|
||||||
|
|
||||||
internal Arena* arena_alloc(void);
|
//- rjf: arena push/pop/pos core functions
|
||||||
internal void arena_release(Arena *arena);
|
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);
|
||||||
|
|
||||||
internal void* arena_push__impl(Arena *arena, U64 size);
|
//- rjf: arena push/pop helpers
|
||||||
internal U64 arena_pos(Arena *arena);
|
internal void arena_clear(Arena *arena);
|
||||||
internal void arena_pop_to(Arena *arena, U64 pos);
|
internal void arena_pop(Arena *arena, U64 amt);
|
||||||
|
|
||||||
internal void arena_absorb(Arena *arena, Arena *sub);
|
//- rjf: temporary arena scopes
|
||||||
|
internal Temp temp_begin(Arena *arena);
|
||||||
|
internal void temp_end(Temp temp);
|
||||||
|
|
||||||
////////////////////////////////
|
//- rjf: push helper macros
|
||||||
// Wrappers
|
#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))
|
||||||
internal void* arena_push(Arena *arena, U64 size);
|
#define push_array_no_zero(a, T, c) push_array_no_zero_aligned(a, T, c, Max(8, AlignOf(T)))
|
||||||
internal void* arena_push_contiguous(Arena *arena, U64 size);
|
#define push_array(a, T, c) push_array_aligned(a, T, c, Max(8, AlignOf(T)))
|
||||||
internal void arena_clear(Arena *arena);
|
|
||||||
internal void arena_push_align(Arena *arena, U64 align);
|
|
||||||
internal void arena_put_back(Arena *arena, U64 amt);
|
|
||||||
|
|
||||||
internal Temp temp_begin(Arena *arena);
|
|
||||||
internal void temp_end(Temp temp);
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ NOTE(allen): "Mini-Arena" Helper
|
|
||||||
|
|
||||||
internal B32 ensure_commit(void **cmt, void *pos, U64 cmt_block_size);
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ NOTE(allen): Main API Macros
|
|
||||||
|
|
||||||
#if !ENABLE_DEV
|
|
||||||
# define push_array_no_zero(a,T,c) (T*)arena_push((a), sizeof(T)*(c))
|
|
||||||
#else
|
|
||||||
# define push_array_no_zero(a,T,c) (tctx_write_this_srcloc(), (T*)arena_push((a), sizeof(T)*(c)))
|
|
||||||
#endif
|
|
||||||
#define push_array_no_zero__no_annotation(a,T,c) (T*)arena_push__impl((a), sizeof(T)*(c))
|
|
||||||
|
|
||||||
#define push_array(a,T,c) (T*)MemoryZero(push_array_no_zero(a,T,c), sizeof(T)*(c))
|
|
||||||
|
|
||||||
#endif // BASE_ARENA_H
|
#endif // BASE_ARENA_H
|
||||||
|
|||||||
@@ -1,197 +0,0 @@
|
|||||||
// Copyright (c) 2024 Epic Games Tools
|
|
||||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
// NOTE(allen): Dev Arena
|
|
||||||
|
|
||||||
#if ENABLE_DEV
|
|
||||||
|
|
||||||
internal void
|
|
||||||
arena_annotate_push__dev(Arena *arena, U64 size, void *ptr){
|
|
||||||
ArenaDev *dev = arena->dev;
|
|
||||||
if (dev != 0 && ptr != 0){
|
|
||||||
//- read location
|
|
||||||
char *file_name = 0;
|
|
||||||
U64 line_number = 0;
|
|
||||||
tctx_read_srcloc(&file_name, &line_number);
|
|
||||||
tctx_write_srcloc(0, 0);
|
|
||||||
|
|
||||||
//- profile
|
|
||||||
ArenaProf *prof = dev->prof;
|
|
||||||
if (prof != 0){
|
|
||||||
// c string -> string
|
|
||||||
String8 file_name_str = str8_lit("(null)");
|
|
||||||
if (file_name != 0){
|
|
||||||
file_name_str = str8_cstring(file_name);
|
|
||||||
}
|
|
||||||
// record
|
|
||||||
arena_prof_inc_counters__dev(dev->arena, prof, file_name_str, line_number, size, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void
|
|
||||||
arena_annotate_absorb__dev(Arena *arena, Arena *sub){
|
|
||||||
ArenaDev *dev = arena->dev;
|
|
||||||
ArenaDev *sub_dev = sub->dev;
|
|
||||||
if (dev != 0 && sub_dev != 0){
|
|
||||||
//- merge profiles
|
|
||||||
ArenaProf *prof = dev->prof;
|
|
||||||
ArenaProf *sub_prof = sub_dev->prof;
|
|
||||||
if (prof != 0 && sub_prof != 0){
|
|
||||||
for (ArenaProfNode *sub_node = sub_prof->first;
|
|
||||||
sub_node != 0;
|
|
||||||
sub_node = sub_node->next){
|
|
||||||
arena_prof_inc_counters__dev(dev->arena, prof, sub_node->file_name, sub_node->line,
|
|
||||||
sub_node->size, sub_node->count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//- release the sub dev memory
|
|
||||||
if (sub_dev != 0){
|
|
||||||
arena_release(sub_dev->arena);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal ArenaDev*
|
|
||||||
arena_equip__dev(Arena *arena){
|
|
||||||
ArenaDev *result = arena->dev;
|
|
||||||
if (result == 0){
|
|
||||||
Arena *dev_arena = arena_alloc();
|
|
||||||
ArenaDev *dev = (ArenaDev*)arena_push__impl(dev_arena, sizeof(ArenaDev));
|
|
||||||
MemoryZeroStruct(dev);
|
|
||||||
dev->arena = dev_arena;
|
|
||||||
arena->dev = dev;
|
|
||||||
result = dev;
|
|
||||||
}
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void
|
|
||||||
arena_equip_profile__dev(Arena *arena){
|
|
||||||
ArenaDev *dev = arena_equip__dev(arena);
|
|
||||||
if (dev->prof == 0){
|
|
||||||
dev->prof = (ArenaProf*)arena_push__impl(dev->arena, sizeof(ArenaProf));
|
|
||||||
MemoryZeroStruct(dev->prof);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void
|
|
||||||
arena_print_profile__dev(Arena *arena, Arena *out_arena, String8List *out){
|
|
||||||
Assert(arena != out_arena);
|
|
||||||
|
|
||||||
//- get dev & disable
|
|
||||||
ArenaDev *dev = arena->dev;
|
|
||||||
arena->dev = 0;
|
|
||||||
|
|
||||||
//- get prof
|
|
||||||
ArenaProf *prof = (dev != 0)?dev->prof:0;
|
|
||||||
|
|
||||||
//- not equipped with prof
|
|
||||||
if (prof == 0){
|
|
||||||
str8_list_push(out_arena, out, str8_lit("not equipped with a memory profile\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
//- print prof
|
|
||||||
if (prof != 0){
|
|
||||||
Temp scratch = temp_begin(dev->arena);
|
|
||||||
|
|
||||||
//- make flat array
|
|
||||||
U64 note_count = prof->count;
|
|
||||||
ArenaProfNode **notes = push_array_no_zero__no_annotation(scratch.arena, ArenaProfNode*, note_count);
|
|
||||||
{
|
|
||||||
ArenaProfNode **note_ptr = notes;
|
|
||||||
for (ArenaProfNode *node = prof->first;
|
|
||||||
node != 0;
|
|
||||||
node = node->next, note_ptr += 1){
|
|
||||||
*note_ptr = node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//- file name size
|
|
||||||
U64 max_file_name_size = 0;
|
|
||||||
{
|
|
||||||
ArenaProfNode **note_ptr = notes;
|
|
||||||
for (U64 i = 0; i < note_count; i += 1, note_ptr += 1){
|
|
||||||
max_file_name_size = Max(max_file_name_size, (**note_ptr).file_name.size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//- sort (> size, < [address])
|
|
||||||
for (U64 i = 0; i < note_count; i += 1){
|
|
||||||
ArenaProfNode **i_note = notes + i;
|
|
||||||
ArenaProfNode **min_note = i_note;
|
|
||||||
for (U64 j = i + 1; j < note_count; j += 1){
|
|
||||||
ArenaProfNode **j_note = notes + j;
|
|
||||||
if ((**j_note).size > (**min_note).size ||
|
|
||||||
((**j_note).size == (**min_note).size && *j_note < *min_note)){
|
|
||||||
min_note = j_note;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (min_note != i_note){
|
|
||||||
ArenaProfNode *t = *i_note;
|
|
||||||
*i_note = *min_note;
|
|
||||||
*min_note = t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//- total size
|
|
||||||
U64 total_size = 0;
|
|
||||||
{
|
|
||||||
ArenaProfNode **note_ptr = notes;
|
|
||||||
for (U64 i = 0; i < note_count; i += 1, note_ptr += 1){
|
|
||||||
ArenaProfNode *note = *note_ptr;
|
|
||||||
total_size += note->size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//- print
|
|
||||||
{
|
|
||||||
str8_list_pushf(out_arena, out, "memory total: %llu\n", total_size);
|
|
||||||
|
|
||||||
ArenaProfNode **note_ptr = notes;
|
|
||||||
for (U64 i = 0; i < note_count; i += 1, note_ptr += 1){
|
|
||||||
ArenaProfNode *note = *note_ptr;
|
|
||||||
String8 location = push_str8f(scratch.arena, "%S:%5llu:",
|
|
||||||
note->file_name, note->line);
|
|
||||||
F32 percent = 100.f*((F32)note->size)/total_size;
|
|
||||||
str8_list_pushf(out_arena, out, "%*.*s %12llu %5.2f%% [%5llu]\n",
|
|
||||||
max_file_name_size + 7, str8_varg(location),
|
|
||||||
note->size, percent, note->count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
temp_end(scratch);
|
|
||||||
}
|
|
||||||
|
|
||||||
//- restore dev
|
|
||||||
arena->dev = dev;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void
|
|
||||||
arena_prof_inc_counters__dev(Arena *dev_arena, ArenaProf *prof, String8 file_name, U64 line,
|
|
||||||
U64 size, U64 count){
|
|
||||||
// find existing profile node
|
|
||||||
ArenaProfNode *prof_node = 0;
|
|
||||||
for (ArenaProfNode *node = prof->first;
|
|
||||||
node != 0;
|
|
||||||
node = node->next){
|
|
||||||
if (node->line == line && str8_match(file_name, node->file_name, 0)){
|
|
||||||
prof_node = node;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// make new histogram node if necessary
|
|
||||||
if (prof_node == 0){
|
|
||||||
prof_node = (ArenaProfNode*)arena_push(dev_arena, sizeof(*prof_node));
|
|
||||||
SLLQueuePush(prof->first, prof->last, prof_node);
|
|
||||||
prof->count += 1;
|
|
||||||
prof_node->file_name = file_name;
|
|
||||||
prof_node->line = line;
|
|
||||||
}
|
|
||||||
// record this allocation
|
|
||||||
prof_node->size += size;
|
|
||||||
prof_node->count += count;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
// Copyright (c) 2024 Epic Games Tools
|
|
||||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
|
||||||
|
|
||||||
#ifndef BASE_ARENA_DEV_H
|
|
||||||
#define BASE_ARENA_DEV_H
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ NOTE(allen): Dev Arena Types
|
|
||||||
|
|
||||||
typedef struct ArenaDev ArenaDev;
|
|
||||||
struct ArenaDev
|
|
||||||
{
|
|
||||||
Arena *arena;
|
|
||||||
struct ArenaProf *prof;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct ArenaProf ArenaProf;
|
|
||||||
struct ArenaProf
|
|
||||||
{
|
|
||||||
struct ArenaProfNode *first;
|
|
||||||
struct ArenaProfNode *last;
|
|
||||||
U64 count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct ArenaProfNode ArenaProfNode;
|
|
||||||
struct ArenaProfNode
|
|
||||||
{
|
|
||||||
ArenaProfNode *next;
|
|
||||||
String8 file_name;
|
|
||||||
U64 line;
|
|
||||||
U64 size;
|
|
||||||
U64 count;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ NOTE(allen): Dev Arena Functions
|
|
||||||
|
|
||||||
#if ENABLE_DEV
|
|
||||||
internal void arena_annotate_push__dev(Arena *arena, U64 size, void *ptr);
|
|
||||||
internal void arena_annotate_absorb__dev(Arena *arena, Arena *sub);
|
|
||||||
internal ArenaDev* arena_equip__dev(Arena *arena);
|
|
||||||
internal void arena_equip_profile__dev(Arena *arena);
|
|
||||||
internal void arena_print_profile__dev(Arena *arena, Arena *out_arena, String8List *out);
|
|
||||||
internal void arena_prof_inc_counters__dev(Arena *dev_arena, ArenaProf *prof, String8 file_name, U64 line, U64 size, U64 count);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // BASE_ARENA_DEV_H
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
// Copyright (c) 2024 Epic Games Tools
|
|
||||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
|
||||||
|
|
||||||
#if COMPILER_CL || (COMPILER_CLANG && OS_WINDOWS)
|
|
||||||
|
|
||||||
internal U64
|
|
||||||
count_bits_set16(U16 val)
|
|
||||||
{
|
|
||||||
return __popcnt16(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal U64
|
|
||||||
count_bits_set32(U32 val)
|
|
||||||
{
|
|
||||||
return __popcnt(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal U64
|
|
||||||
count_bits_set64(U64 val)
|
|
||||||
{
|
|
||||||
return __popcnt64(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal U64
|
|
||||||
ctz32(U32 mask)
|
|
||||||
{
|
|
||||||
unsigned long idx;
|
|
||||||
_BitScanForward(&idx, mask);
|
|
||||||
return idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal U64
|
|
||||||
ctz64(U64 mask)
|
|
||||||
{
|
|
||||||
unsigned long idx;
|
|
||||||
_BitScanForward64(&idx, mask);
|
|
||||||
return idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal U64
|
|
||||||
clz32(U32 mask)
|
|
||||||
{
|
|
||||||
unsigned long idx;
|
|
||||||
_BitScanReverse(&idx, mask);
|
|
||||||
return 31 - idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal U64
|
|
||||||
clz64(U64 mask)
|
|
||||||
{
|
|
||||||
unsigned long idx;
|
|
||||||
_BitScanReverse64(&idx, mask);
|
|
||||||
return 63 - idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif COMPILER_CLANG || COMPILER_GCC
|
|
||||||
|
|
||||||
internal U64
|
|
||||||
count_bits_set16(U16 val)
|
|
||||||
{
|
|
||||||
NotImplemented;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal U64
|
|
||||||
count_bits_set32(U32 val)
|
|
||||||
{
|
|
||||||
NotImplemented;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal U64
|
|
||||||
count_bits_set64(U64 val)
|
|
||||||
{
|
|
||||||
NotImplemented;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal U64
|
|
||||||
ctz32(U32 val)
|
|
||||||
{
|
|
||||||
NotImplemented;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal U64
|
|
||||||
clz32(U32 val)
|
|
||||||
{
|
|
||||||
NotImplemented;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal U64
|
|
||||||
clz64(U64 val)
|
|
||||||
{
|
|
||||||
NotImplemented;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
# error "bits not defined for this target"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
// Copyright (c) 2024 Epic Games Tools
|
|
||||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
|
||||||
|
|
||||||
#ifndef BASE_BITS_H
|
|
||||||
#define BASE_BITS_H
|
|
||||||
|
|
||||||
#define ExtractBit(word, idx) (((word) >> (idx)) & 1)
|
|
||||||
|
|
||||||
internal U64 count_bits_set16(U16 val);
|
|
||||||
internal U64 count_bits_set32(U32 val);
|
|
||||||
internal U64 count_bits_set64(U64 val);
|
|
||||||
|
|
||||||
internal U64 ctz32(U32 val);
|
|
||||||
internal U64 ctz64(U64 val);
|
|
||||||
internal U64 clz32(U32 val);
|
|
||||||
internal U64 clz64(U64 val);
|
|
||||||
|
|
||||||
#endif // BASE_BITS_H
|
|
||||||
@@ -82,6 +82,7 @@ internal CmdLine
|
|||||||
cmd_line_from_string_list(Arena *arena, String8List command_line)
|
cmd_line_from_string_list(Arena *arena, String8List command_line)
|
||||||
{
|
{
|
||||||
CmdLine parsed = {0};
|
CmdLine parsed = {0};
|
||||||
|
parsed.exe_name = command_line.first->string;
|
||||||
|
|
||||||
// NOTE(rjf): Set up config option table.
|
// NOTE(rjf): Set up config option table.
|
||||||
{
|
{
|
||||||
@@ -91,6 +92,7 @@ cmd_line_from_string_list(Arena *arena, String8List command_line)
|
|||||||
|
|
||||||
// NOTE(rjf): Parse command line.
|
// NOTE(rjf): Parse command line.
|
||||||
B32 after_passthrough_option = 0;
|
B32 after_passthrough_option = 0;
|
||||||
|
B32 first_passthrough = 1;
|
||||||
for(String8Node *node = command_line.first->next, *next = 0; node != 0; node = next)
|
for(String8Node *node = command_line.first->next, *next = 0; node != 0; node = next)
|
||||||
{
|
{
|
||||||
next = node->next;
|
next = node->next;
|
||||||
@@ -174,10 +176,11 @@ cmd_line_from_string_list(Arena *arena, String8List command_line)
|
|||||||
|
|
||||||
// NOTE(rjf): Default path, treat as a passthrough config option to be
|
// NOTE(rjf): Default path, treat as a passthrough config option to be
|
||||||
// handled by tool-specific code.
|
// handled by tool-specific code.
|
||||||
else if(!str8_match(node->string, str8_lit("--"), 0))
|
else if(!str8_match(node->string, str8_lit("--"), 0) || !first_passthrough)
|
||||||
{
|
{
|
||||||
str8_list_push(arena, &parsed.inputs, node->string);
|
str8_list_push(arena, &parsed.inputs, node->string);
|
||||||
after_passthrough_option = 1;
|
after_passthrough_option = 1;
|
||||||
|
first_passthrough = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ struct CmdLineOptList
|
|||||||
typedef struct CmdLine CmdLine;
|
typedef struct CmdLine CmdLine;
|
||||||
struct CmdLine
|
struct CmdLine
|
||||||
{
|
{
|
||||||
|
String8 exe_name;
|
||||||
CmdLineOptList options;
|
CmdLineOptList options;
|
||||||
String8List inputs;
|
String8List inputs;
|
||||||
U64 option_table_size;
|
U64 option_table_size;
|
||||||
|
|||||||
@@ -4,6 +4,9 @@
|
|||||||
#ifndef BASE_CONTEXT_CRACKING_H
|
#ifndef BASE_CONTEXT_CRACKING_H
|
||||||
#define BASE_CONTEXT_CRACKING_H
|
#define BASE_CONTEXT_CRACKING_H
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Clang OS/Arch Cracking
|
||||||
|
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
|
|
||||||
# define COMPILER_CLANG 1
|
# define COMPILER_CLANG 1
|
||||||
@@ -15,7 +18,7 @@
|
|||||||
# elif defined(__APPLE__) && defined(__MACH__)
|
# elif defined(__APPLE__) && defined(__MACH__)
|
||||||
# define OS_MAC 1
|
# define OS_MAC 1
|
||||||
# else
|
# else
|
||||||
# error This compiler/platform combo is not supported yet
|
# error This compiler/OS combo is not supported.
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
|
# if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
|
||||||
@@ -27,17 +30,40 @@
|
|||||||
# elif defined(__arm__)
|
# elif defined(__arm__)
|
||||||
# define ARCH_ARM32 1
|
# define ARCH_ARM32 1
|
||||||
# else
|
# else
|
||||||
# error architecture not supported yet
|
# error Architecture not supported.
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: MSVC OS/Arch Cracking
|
||||||
|
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
|
|
||||||
# define COMPILER_CL 1
|
# define COMPILER_MSVC 1
|
||||||
|
|
||||||
|
# if _MSC_VER >= 1920
|
||||||
|
# define COMPILER_MSVC_YEAR 2019
|
||||||
|
# elif _MSC_VER >= 1910
|
||||||
|
# define COMPILER_MSVC_YEAR 2017
|
||||||
|
# elif _MSC_VER >= 1900
|
||||||
|
# define COMPILER_MSVC_YEAR 2015
|
||||||
|
# elif _MSC_VER >= 1800
|
||||||
|
# define COMPILER_MSVC_YEAR 2013
|
||||||
|
# elif _MSC_VER >= 1700
|
||||||
|
# define COMPILER_MSVC_YEAR 2012
|
||||||
|
# elif _MSC_VER >= 1600
|
||||||
|
# define COMPILER_MSVC_YEAR 2010
|
||||||
|
# elif _MSC_VER >= 1500
|
||||||
|
# define COMPILER_MSVC_YEAR 2008
|
||||||
|
# elif _MSC_VER >= 1400
|
||||||
|
# define COMPILER_MSVC_YEAR 2005
|
||||||
|
# else
|
||||||
|
# define COMPILER_MSVC_YEAR 0
|
||||||
|
# endif
|
||||||
|
|
||||||
# if defined(_WIN32)
|
# if defined(_WIN32)
|
||||||
# define OS_WINDOWS 1
|
# define OS_WINDOWS 1
|
||||||
# else
|
# else
|
||||||
# error This compiler/platform combo is not supported yet
|
# error This compiler/OS combo is not supported.
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# if defined(_M_AMD64)
|
# if defined(_M_AMD64)
|
||||||
@@ -49,9 +75,12 @@
|
|||||||
# elif defined(_M_ARM)
|
# elif defined(_M_ARM)
|
||||||
# define ARCH_ARM32 1
|
# define ARCH_ARM32 1
|
||||||
# else
|
# else
|
||||||
# error architecture not supported yet
|
# error Architecture not supported.
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: GCC OS/Arch Cracking
|
||||||
|
|
||||||
#elif defined(__GNUC__) || defined(__GNUG__)
|
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||||
|
|
||||||
# define COMPILER_GCC 1
|
# define COMPILER_GCC 1
|
||||||
@@ -59,7 +88,7 @@
|
|||||||
# if defined(__gnu_linux__) || defined(__linux__)
|
# if defined(__gnu_linux__) || defined(__linux__)
|
||||||
# define OS_LINUX 1
|
# define OS_LINUX 1
|
||||||
# else
|
# else
|
||||||
# error This compiler/platform combo is not supported yet
|
# error This compiler/OS combo is not supported.
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
|
# if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
|
||||||
@@ -71,26 +100,96 @@
|
|||||||
# elif defined(__arm__)
|
# elif defined(__arm__)
|
||||||
# define ARCH_ARM32 1
|
# define ARCH_ARM32 1
|
||||||
# else
|
# else
|
||||||
# error architecture not supported yet
|
# error Architecture not supported.
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
# error This compiler is not supported yet
|
# error Compiler not supported.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Arch Cracking
|
||||||
|
|
||||||
#if defined(ARCH_X64)
|
#if defined(ARCH_X64)
|
||||||
# define ARCH_64BIT 1
|
# define ARCH_64BIT 1
|
||||||
#elif defined(ARCH_X86)
|
#elif defined(ARCH_X86)
|
||||||
# define ARCH_32BIT 1
|
# define ARCH_32BIT 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ARCH_ARM32 || ARCH_ARM64 || ARCH_X64 || ARCH_X86
|
||||||
|
# define ARCH_LITTLE_ENDIAN 1
|
||||||
|
#else
|
||||||
|
# error Endianness of this architecture not understood by context cracker.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Language Cracking
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
# define LANG_CPP 1
|
# define LANG_CPP 1
|
||||||
#else
|
#else
|
||||||
# define LANG_C 1
|
# define LANG_C 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// zeroify
|
////////////////////////////////
|
||||||
|
//~ rjf: Build Option Cracking
|
||||||
|
|
||||||
|
#if !defined(BUILD_DEBUG)
|
||||||
|
# define BUILD_DEBUG 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(BUILD_SUPPLEMENTARY_UNIT)
|
||||||
|
# define BUILD_SUPPLEMENTARY_UNIT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(BUILD_ENTRY_DEFINING_UNIT)
|
||||||
|
# define BUILD_ENTRY_DEFINING_UNIT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(BUILD_CONSOLE_INTERFACE)
|
||||||
|
# define BUILD_CONSOLE_INTERFACE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(BUILD_VERSION_MAJOR)
|
||||||
|
# define BUILD_VERSION_MAJOR 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(BUILD_VERSION_MINOR)
|
||||||
|
# define BUILD_VERSION_MINOR 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(BUILD_VERSION_PATCH)
|
||||||
|
# define BUILD_VERSION_PATCH 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BUILD_VERSION_STRING_LITERAL Stringify(BUILD_VERSION_MAJOR) "." Stringify(BUILD_VERSION_MINOR) "." Stringify(BUILD_VERSION_PATCH)
|
||||||
|
#if BUILD_DEBUG
|
||||||
|
# define BUILD_MODE_STRING_LITERAL_APPEND " [Debug]"
|
||||||
|
#else
|
||||||
|
# define BUILD_MODE_STRING_LITERAL_APPEND ""
|
||||||
|
#endif
|
||||||
|
#if defined(BUILD_GIT_HASH)
|
||||||
|
# define BUILD_GIT_HASH_STRING_LITERAL_APPEND " [" BUILD_GIT_HASH "]"
|
||||||
|
#else
|
||||||
|
# define BUILD_GIT_HASH_STRING_LITERAL_APPEND ""
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(BUILD_TITLE)
|
||||||
|
# define BUILD_TITLE "Untitled"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(BUILD_RELEASE_PHASE_STRING_LITERAL)
|
||||||
|
# define BUILD_RELEASE_PHASE_STRING_LITERAL "ALPHA"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(BUILD_ISSUES_LINK_STRING_LITERAL)
|
||||||
|
# define BUILD_ISSUES_LINK_STRING_LITERAL "https://github.com/EpicGames/raddebugger/issues"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BUILD_TITLE_STRING_LITERAL BUILD_TITLE " (" BUILD_VERSION_STRING_LITERAL " " BUILD_RELEASE_PHASE_STRING_LITERAL ") - " __DATE__ "" BUILD_GIT_HASH_STRING_LITERAL_APPEND BUILD_MODE_STRING_LITERAL_APPEND
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Zero All Undefined Options
|
||||||
|
|
||||||
#if !defined(ARCH_32BIT)
|
#if !defined(ARCH_32BIT)
|
||||||
# define ARCH_32BIT 0
|
# define ARCH_32BIT 0
|
||||||
@@ -110,8 +209,8 @@
|
|||||||
#if !defined(ARCH_ARM32)
|
#if !defined(ARCH_ARM32)
|
||||||
# define ARCH_ARM32 0
|
# define ARCH_ARM32 0
|
||||||
#endif
|
#endif
|
||||||
#if !defined(COMPILER_CL)
|
#if !defined(COMPILER_MSVC)
|
||||||
# define COMPILER_CL 0
|
# define COMPILER_MSVC 0
|
||||||
#endif
|
#endif
|
||||||
#if !defined(COMPILER_GCC)
|
#if !defined(COMPILER_GCC)
|
||||||
# define COMPILER_GCC 0
|
# define COMPILER_GCC 0
|
||||||
@@ -135,12 +234,6 @@
|
|||||||
# define LANG_C 0
|
# define LANG_C 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ARCH_ARM32 || ARCH_ARM64 || ARCH_X64 || ARCH_X86
|
|
||||||
# define ARCH_LITTLE_ENDIAN 1
|
|
||||||
#else
|
|
||||||
# error Endianness of this architecture not understood by context cracker
|
|
||||||
#endif
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Unsupported Errors
|
//~ rjf: Unsupported Errors
|
||||||
|
|
||||||
|
|||||||
+111
-3
@@ -2,7 +2,7 @@
|
|||||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Safe Casts
|
//~ rjf: Safe Casts
|
||||||
|
|
||||||
internal U16
|
internal U16
|
||||||
safe_cast_u16(U32 x)
|
safe_cast_u16(U32 x)
|
||||||
@@ -141,6 +141,106 @@ bswap_u64(U64 x)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if COMPILER_MSVC || (COMPILER_CLANG && OS_WINDOWS)
|
||||||
|
|
||||||
|
internal U64
|
||||||
|
count_bits_set16(U16 val)
|
||||||
|
{
|
||||||
|
return __popcnt16(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal U64
|
||||||
|
count_bits_set32(U32 val)
|
||||||
|
{
|
||||||
|
return __popcnt(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal U64
|
||||||
|
count_bits_set64(U64 val)
|
||||||
|
{
|
||||||
|
return __popcnt64(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal U64
|
||||||
|
ctz32(U32 mask)
|
||||||
|
{
|
||||||
|
unsigned long idx;
|
||||||
|
_BitScanForward(&idx, mask);
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal U64
|
||||||
|
ctz64(U64 mask)
|
||||||
|
{
|
||||||
|
unsigned long idx;
|
||||||
|
_BitScanForward64(&idx, mask);
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal U64
|
||||||
|
clz32(U32 mask)
|
||||||
|
{
|
||||||
|
unsigned long idx;
|
||||||
|
_BitScanReverse(&idx, mask);
|
||||||
|
return 31 - idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal U64
|
||||||
|
clz64(U64 mask)
|
||||||
|
{
|
||||||
|
unsigned long idx;
|
||||||
|
_BitScanReverse64(&idx, mask);
|
||||||
|
return 63 - idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif COMPILER_CLANG || COMPILER_GCC
|
||||||
|
|
||||||
|
internal U64
|
||||||
|
count_bits_set16(U16 val)
|
||||||
|
{
|
||||||
|
NotImplemented;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal U64
|
||||||
|
count_bits_set32(U32 val)
|
||||||
|
{
|
||||||
|
NotImplemented;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal U64
|
||||||
|
count_bits_set64(U64 val)
|
||||||
|
{
|
||||||
|
NotImplemented;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal U64
|
||||||
|
ctz32(U32 val)
|
||||||
|
{
|
||||||
|
NotImplemented;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal U64
|
||||||
|
clz32(U32 val)
|
||||||
|
{
|
||||||
|
NotImplemented;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal U64
|
||||||
|
clz64(U64 val)
|
||||||
|
{
|
||||||
|
NotImplemented;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
# error "Bit intrinsic functions not defined for this compiler."
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Enum -> Sign
|
//~ rjf: Enum -> Sign
|
||||||
|
|
||||||
@@ -287,6 +387,14 @@ txt_rng_union(TxtRng a, TxtRng b)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal B32
|
||||||
|
txt_rng_contains(TxtRng r, TxtPt pt)
|
||||||
|
{
|
||||||
|
B32 result = ((txt_pt_less_than(r.min, pt) || txt_pt_match(r.min, pt)) &&
|
||||||
|
txt_pt_less_than(pt, r.max));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Toolchain/Environment Enum Functions
|
//~ rjf: Toolchain/Environment Enum Functions
|
||||||
|
|
||||||
@@ -344,8 +452,8 @@ architecture_from_context(void){
|
|||||||
internal Compiler
|
internal Compiler
|
||||||
compiler_from_context(void){
|
compiler_from_context(void){
|
||||||
Compiler compiler = Compiler_Null;
|
Compiler compiler = Compiler_Null;
|
||||||
#if COMPILER_CL
|
#if COMPILER_MSVC
|
||||||
compiler = Compiler_cl;
|
compiler = Compiler_msvc;
|
||||||
#elif COMPILER_GCC
|
#elif COMPILER_GCC
|
||||||
compiler = Compiler_gcc;
|
compiler = Compiler_gcc;
|
||||||
#elif COMPILER_CLANG
|
#elif COMPILER_CLANG
|
||||||
+256
-137
@@ -1,8 +1,8 @@
|
|||||||
// Copyright (c) 2024 Epic Games Tools
|
// Copyright (c) 2024 Epic Games Tools
|
||||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
#ifndef BASE_TYPES_H
|
#ifndef BASE_CORE_H
|
||||||
#define BASE_TYPES_H
|
#define BASE_CORE_H
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Foreign Includes
|
//~ rjf: Foreign Includes
|
||||||
@@ -13,17 +13,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ rjf: Build Configuration
|
|
||||||
|
|
||||||
#if !defined(ENABLE_DEV)
|
|
||||||
# define ENABLE_DEV 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(SUPPLEMENT_UNIT)
|
|
||||||
# define SUPPLEMENT_UNIT 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Codebase Keywords
|
//~ rjf: Codebase Keywords
|
||||||
|
|
||||||
@@ -31,7 +20,7 @@
|
|||||||
#define global static
|
#define global static
|
||||||
#define local_persist static
|
#define local_persist static
|
||||||
|
|
||||||
#if COMPILER_CL || (COMPILER_CLANG && OS_WINDOWS)
|
#if COMPILER_MSVC || (COMPILER_CLANG && OS_WINDOWS)
|
||||||
# pragma section(".rdata$", read)
|
# pragma section(".rdata$", read)
|
||||||
# define read_only __declspec(allocate(".rdata$"))
|
# define read_only __declspec(allocate(".rdata$"))
|
||||||
#elif (COMPILER_CLANG && OS_LINUX)
|
#elif (COMPILER_CLANG && OS_LINUX)
|
||||||
@@ -45,6 +34,93 @@
|
|||||||
# define read_only
|
# define read_only
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if COMPILER_MSVC
|
||||||
|
# define thread_static __declspec(thread)
|
||||||
|
#elif COMPILER_CLANG || COMPILER_GCC
|
||||||
|
# define thread_static __thread
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Linkage Keyword Macros
|
||||||
|
|
||||||
|
#if OS_WINDOWS
|
||||||
|
# define shared_function C_LINKAGE __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
# define shared_function C_LINKAGE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LANG_CPP
|
||||||
|
# define C_LINKAGE_BEGIN extern "C"{
|
||||||
|
# define C_LINKAGE_END }
|
||||||
|
# define C_LINKAGE extern "C"
|
||||||
|
#else
|
||||||
|
# define C_LINKAGE_BEGIN
|
||||||
|
# define C_LINKAGE_END
|
||||||
|
# define C_LINKAGE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Units
|
||||||
|
|
||||||
|
#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)
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Branch Predictor Hints
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
# define Expect(expr, val) __builtin_expect((expr), (val))
|
||||||
|
#else
|
||||||
|
# define Expect(expr, val) (expr)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define Likely(expr) Expect(expr,1)
|
||||||
|
#define Unlikely(expr) Expect(expr,0)
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Clamps, Mins, Maxes
|
||||||
|
|
||||||
|
#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))
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Type -> Alignment
|
||||||
|
|
||||||
|
#if COMPILER_MSVC
|
||||||
|
# define AlignOf(T) __alignof(T)
|
||||||
|
#elif COMPILER_CLANG
|
||||||
|
# define AlignOf(T) __alignof(T)
|
||||||
|
#elif COMPILER_GCC
|
||||||
|
# define AlignOf(T) __alignof__(T)
|
||||||
|
#else
|
||||||
|
# error AlignOf not defined for this compiler.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Member Offsets
|
||||||
|
|
||||||
|
#define Member(T,m) (((T*)0)->m)
|
||||||
|
#define OffsetOf(T,m) IntFromPtr(&Member(T,m))
|
||||||
|
#define MemberFromOffset(T,ptr,off) (T)((((U8 *)ptr)+(off)))
|
||||||
|
#define CastFromMember(T,m,ptr) (T*)(((U8*)ptr) - OffsetOf(T,m))
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: For-Loop Construct Macros
|
||||||
|
|
||||||
|
#define DeferLoop(begin, end) for(int _i_ = ((begin), 0); !_i_; _i_ += 1, (end))
|
||||||
|
#define DeferLoopChecked(begin, end) for(int _i_ = 2 * !(begin); (_i_ == 2 ? ((end), 0) : !_i_); _i_ += 1, (end))
|
||||||
|
|
||||||
|
#define EachEnumVal(type, it) type it = (type)0; it < type##_COUNT; it = (type)(it+1)
|
||||||
|
#define EachNonZeroEnumVal(type, it) type it = (type)1; it < type##_COUNT; it = (type)(it+1)
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Memory Operation Macros
|
//~ rjf: Memory Operation Macros
|
||||||
|
|
||||||
@@ -67,99 +143,179 @@
|
|||||||
#define MemoryMatchArray(a,b) MemoryMatch((a),(b),sizeof(a))
|
#define MemoryMatchArray(a,b) MemoryMatch((a),(b),sizeof(a))
|
||||||
|
|
||||||
#define MemoryRead(T,p,e) ( ((p)+sizeof(T)<=(e))?(*(T*)(p)):(0) )
|
#define MemoryRead(T,p,e) ( ((p)+sizeof(T)<=(e))?(*(T*)(p)):(0) )
|
||||||
#define MemoryConsume(T,p,e) \
|
#define MemoryConsume(T,p,e) ( ((p)+sizeof(T)<=(e))?((p)+=sizeof(T),*(T*)((p)-sizeof(T))):((p)=(e),0) )
|
||||||
( ((p)+sizeof(T)<=(e))?((p)+=sizeof(T),*(T*)((p)-sizeof(T))):((p)=(e),0) )
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ rjf: Units
|
|
||||||
|
|
||||||
#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)
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Asserts
|
//~ rjf: Asserts
|
||||||
|
|
||||||
#if COMPILER_CL
|
#if COMPILER_MSVC
|
||||||
# define Trap() __debugbreak()
|
# define Trap() __debugbreak()
|
||||||
#elif COMPILER_CLANG || COMPILER_GCC
|
#elif COMPILER_CLANG || COMPILER_GCC
|
||||||
# define Trap() __builtin_trap()
|
# define Trap() __builtin_trap()
|
||||||
# else
|
#else
|
||||||
# error "undefined trap"
|
# error Unknown trap intrinsic for this compiler.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define AssertAlways(x) do{if(!(x)) {Trap();}}while(0)
|
#define AssertAlways(x) do{if(!(x)) {Trap();}}while(0)
|
||||||
#if !defined(NDEBUG)
|
#if BUILD_DEBUG
|
||||||
# define Assert(x) AssertAlways(x)
|
# define Assert(x) AssertAlways(x)
|
||||||
#else
|
#else
|
||||||
# define Assert(x) (void)(x)
|
# define Assert(x) (void)(x)
|
||||||
#endif
|
#endif
|
||||||
#define AssertImplies(a,b) Assert(!(a) || b)
|
|
||||||
#define AssertIff(a,b) Assert(!!(a) == !!(b))
|
|
||||||
#define InvalidPath Assert(!"Invalid Path!")
|
#define InvalidPath Assert(!"Invalid Path!")
|
||||||
#define NotImplemented Assert(!"Not Implemented!")
|
#define NotImplemented Assert(!"Not Implemented!")
|
||||||
|
#define NoOp ((void)0)
|
||||||
#define StaticAssert(C,ID) global U8 Glue(ID,__LINE__)[(C)?1:-1]
|
#define StaticAssert(C, ID) global U8 Glue(ID, __LINE__)[(C)?1:-1]
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Branch Predictor Hints
|
//~ rjf: Atomic Operations
|
||||||
|
|
||||||
#if defined(__clang__)
|
#if OS_WINDOWS
|
||||||
# define Expect(expr, val) __builtin_expect((expr), (val))
|
# include <windows.h>
|
||||||
|
# include <tmmintrin.h>
|
||||||
|
# include <wmmintrin.h>
|
||||||
|
# include <intrin.h>
|
||||||
|
# if ARCH_X64
|
||||||
|
# define ins_atomic_u64_eval(x) InterlockedAdd64((volatile __int64 *)(x), 0)
|
||||||
|
# define ins_atomic_u64_inc_eval(x) InterlockedIncrement64((volatile __int64 *)(x))
|
||||||
|
# define ins_atomic_u64_dec_eval(x) InterlockedDecrement64((volatile __int64 *)(x))
|
||||||
|
# define ins_atomic_u64_eval_assign(x,c) InterlockedExchange64((volatile __int64 *)(x),(c))
|
||||||
|
# define ins_atomic_u64_add_eval(x,c) InterlockedAdd64((volatile __int64 *)(x), c)
|
||||||
|
# define ins_atomic_u64_eval_cond_assign(x,k,c) InterlockedCompareExchange64((volatile __int64 *)(x),(k),(c))
|
||||||
|
# define ins_atomic_u32_eval(x,c) InterlockedAdd((volatile LONG *)(x), 0)
|
||||||
|
# define ins_atomic_u32_eval_assign(x,c) InterlockedExchange((volatile LONG *)(x),(c))
|
||||||
|
# define ins_atomic_u32_eval_cond_assign(x,k,c) InterlockedCompareExchange((volatile LONG *)(x),(k),(c))
|
||||||
|
# define ins_atomic_ptr_eval_assign(x,c) (void*)ins_atomic_u64_eval_assign((volatile __int64 *)(x), (__int64)(c))
|
||||||
|
# else
|
||||||
|
# error Atomic intrinsics not defined for this operating system / architecture combination.
|
||||||
|
# endif
|
||||||
|
#elif OS_LINUX
|
||||||
|
# if ARCH_X64
|
||||||
|
# define ins_atomic_u64_inc_eval(x) __sync_fetch_and_add((volatile U64 *)(x), 1)
|
||||||
|
# else
|
||||||
|
# error Atomic intrinsics not defined for this operating system / architecture combination.
|
||||||
|
# endif
|
||||||
#else
|
#else
|
||||||
# define Expect(expr, val) (expr)
|
# error Atomic intrinsics not defined for this operating system.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define Likely(expr) Expect(expr,1)
|
////////////////////////////////
|
||||||
#define Unlikely(expr) Expect(expr,0)
|
//~ rjf: Linked List Building Macros
|
||||||
|
|
||||||
|
//- rjf: linked list macro helpers
|
||||||
|
#define CheckNil(nil,p) ((p) == 0 || (p) == nil)
|
||||||
|
#define SetNil(nil,p) ((p) = nil)
|
||||||
|
|
||||||
|
//- rjf: doubly-linked-lists
|
||||||
|
#define DLLInsert_NPZ(nil,f,l,p,n,next,prev) (CheckNil(nil,f) ? \
|
||||||
|
((f) = (l) = (n), SetNil(nil,(n)->next), SetNil(nil,(n)->prev)) :\
|
||||||
|
CheckNil(nil,p) ? \
|
||||||
|
((n)->next = (f), (f)->prev = (n), (f) = (n), SetNil(nil,(n)->prev)) :\
|
||||||
|
((p)==(l)) ? \
|
||||||
|
((l)->next = (n), (n)->prev = (l), (l) = (n), SetNil(nil, (n)->next)) :\
|
||||||
|
(((!CheckNil(nil,p) && CheckNil(nil,(p)->next)) ? (0) : ((p)->next->prev = (n))), ((n)->next = (p)->next), ((p)->next = (n)), ((n)->prev = (p))))
|
||||||
|
#define DLLPushBack_NPZ(nil,f,l,n,next,prev) DLLInsert_NPZ(nil,f,l,l,n,next,prev)
|
||||||
|
#define DLLPushFront_NPZ(nil,f,l,n,next,prev) DLLInsert_NPZ(nil,l,f,f,n,prev,next)
|
||||||
|
#define DLLRemove_NPZ(nil,f,l,n,next,prev) (((n) == (f) ? (f) = (n)->next : (0)),\
|
||||||
|
((n) == (l) ? (l) = (l)->prev : (0)),\
|
||||||
|
(CheckNil(nil,(n)->prev) ? (0) :\
|
||||||
|
((n)->prev->next = (n)->next)),\
|
||||||
|
(CheckNil(nil,(n)->next) ? (0) :\
|
||||||
|
((n)->next->prev = (n)->prev)))
|
||||||
|
|
||||||
|
//- rjf: singly-linked, doubly-headed lists (queues)
|
||||||
|
#define SLLQueuePush_NZ(nil,f,l,n,next) (CheckNil(nil,f)?\
|
||||||
|
((f)=(l)=(n),SetNil(nil,(n)->next)):\
|
||||||
|
((l)->next=(n),(l)=(n),SetNil(nil,(n)->next)))
|
||||||
|
#define SLLQueuePushFront_NZ(nil,f,l,n,next) (CheckNil(nil,f)?\
|
||||||
|
((f)=(l)=(n),SetNil(nil,(n)->next)):\
|
||||||
|
((n)->next=(f),(f)=(n)))
|
||||||
|
#define SLLQueuePop_NZ(nil,f,l,next) ((f)==(l)?\
|
||||||
|
(SetNil(nil,f),SetNil(nil,l)):\
|
||||||
|
((f)=(f)->next))
|
||||||
|
|
||||||
|
//- rjf: singly-linked, singly-headed lists (stacks)
|
||||||
|
#define SLLStackPush_N(f,n,next) ((n)->next=(f), (f)=(n))
|
||||||
|
#define SLLStackPop_N(f,next) ((f)=(f)->next)
|
||||||
|
|
||||||
|
//- rjf: doubly-linked-list helpers
|
||||||
|
#define DLLInsert_NP(f,l,p,n,next,prev) DLLInsert_NPZ(0,f,l,p,n,next,prev)
|
||||||
|
#define DLLPushBack_NP(f,l,n,next,prev) DLLPushBack_NPZ(0,f,l,n,next,prev)
|
||||||
|
#define DLLPushFront_NP(f,l,n,next,prev) DLLPushFront_NPZ(0,f,l,n,next,prev)
|
||||||
|
#define DLLRemove_NP(f,l,n,next,prev) DLLRemove_NPZ(0,f,l,n,next,prev)
|
||||||
|
#define DLLInsert(f,l,p,n) DLLInsert_NPZ(0,f,l,p,n,next,prev)
|
||||||
|
#define DLLPushBack(f,l,n) DLLPushBack_NPZ(0,f,l,n,next,prev)
|
||||||
|
#define DLLPushFront(f,l,n) DLLPushFront_NPZ(0,f,l,n,next,prev)
|
||||||
|
#define DLLRemove(f,l,n) DLLRemove_NPZ(0,f,l,n,next,prev)
|
||||||
|
|
||||||
|
//- rjf: singly-linked, doubly-headed list helpers
|
||||||
|
#define SLLQueuePush_N(f,l,n,next) SLLQueuePush_NZ(0,f,l,n,next)
|
||||||
|
#define SLLQueuePushFront_N(f,l,n,next) SLLQueuePushFront_NZ(0,f,l,n,next)
|
||||||
|
#define SLLQueuePop_N(f,l,next) SLLQueuePop_NZ(0,f,l,next)
|
||||||
|
#define SLLQueuePush(f,l,n) SLLQueuePush_NZ(0,f,l,n,next)
|
||||||
|
#define SLLQueuePushFront(f,l,n) SLLQueuePushFront_NZ(0,f,l,n,next)
|
||||||
|
#define SLLQueuePop(f,l) SLLQueuePop_NZ(0,f,l,next)
|
||||||
|
|
||||||
|
//- rjf: singly-linked, singly-headed list helpers
|
||||||
|
#define SLLStackPush(f,n) SLLStackPush_N(f,n,next)
|
||||||
|
#define SLLStackPop(f) SLLStackPop_N(f,next)
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Address Sanitizer Markup
|
||||||
|
|
||||||
|
#if COMPILER_MSVC
|
||||||
|
# if defined(__SANITIZE_ADDRESS__)
|
||||||
|
# define ASAN_ENABLED 1
|
||||||
|
# define NO_ASAN __declspec(no_sanitize_address)
|
||||||
|
# else
|
||||||
|
# define NO_ASAN
|
||||||
|
# endif
|
||||||
|
#elif COMPILER_CLANG
|
||||||
|
# if defined(__has_feature)
|
||||||
|
# if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
||||||
|
# define ASAN_ENABLED 1
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# define NO_ASAN __attribute__((no_sanitize("address")))
|
||||||
|
#else
|
||||||
|
# error "NO_ASAN is not defined for this compiler."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ASAN_ENABLED
|
||||||
|
#pragma comment(lib, "clang_rt.asan-x86_64.lib")
|
||||||
|
C_LINKAGE void __asan_poison_memory_region(void const volatile *addr, size_t size);
|
||||||
|
C_LINKAGE void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
|
||||||
|
# define AsanPoisonMemoryRegion(addr, size) __asan_poison_memory_region((addr), (size))
|
||||||
|
# define AsanUnpoisonMemoryRegion(addr, size) __asan_unpoison_memory_region((addr), (size))
|
||||||
|
#else
|
||||||
|
# define AsanPoisonMemoryRegion(addr, size) ((void)(addr), (void)(size))
|
||||||
|
# define AsanUnpoisonMemoryRegion(addr, size) ((void)(addr), (void)(size))
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Misc. Helper Macros
|
//~ rjf: Misc. Helper Macros
|
||||||
|
|
||||||
#define ArrayCount(a) (sizeof(a) / sizeof((a)[0]))
|
|
||||||
|
|
||||||
#define Stmnt(S) do{ S }while(0)
|
|
||||||
|
|
||||||
#define Stringify_(S) #S
|
#define Stringify_(S) #S
|
||||||
#define Stringify(S) Stringify_(S)
|
#define Stringify(S) Stringify_(S)
|
||||||
|
|
||||||
#define Glue_(A,B) A##B
|
#define Glue_(A,B) A##B
|
||||||
#define Glue(A,B) Glue_(A,B)
|
#define Glue(A,B) Glue_(A,B)
|
||||||
|
|
||||||
#define Min(A,B) ( ((A)<(B))?(A):(B) )
|
#define ArrayCount(a) (sizeof(a) / sizeof((a)[0]))
|
||||||
#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 PtrClampTop(A,X) ClampTop(A,X)
|
|
||||||
#define PtrClampBot(X,B) ClampBot(X,B)
|
|
||||||
#define PtrClamp(A,X,B) Clamp(A,X,B)
|
|
||||||
|
|
||||||
#define CeilIntegerDiv(a,b) (((a) + (b) - 1)/(b))
|
#define CeilIntegerDiv(a,b) (((a) + (b) - 1)/(b))
|
||||||
|
|
||||||
#define Swap(T,a,b) Stmnt( T t__ = a; a = b; b = t__; )
|
#define Swap(T,a,b) do{T t__ = a; a = b; b = t__;}while(0)
|
||||||
|
|
||||||
#if ARCH_64BIT
|
#if ARCH_64BIT
|
||||||
# define IntFromPtr(ptr) ((U64)(ptr))
|
# define IntFromPtr(ptr) ((U64)(ptr))
|
||||||
#elif ARCH_32BIT
|
#elif ARCH_32BIT
|
||||||
# define IntFromPtr(ptr) ((U32)(ptr))
|
# define IntFromPtr(ptr) ((U32)(ptr))
|
||||||
#else
|
#else
|
||||||
# error missing ptr cast for this architecture
|
# error Missing pointer-to-integer cast for this architecture.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PtrFromInt(i) (void*)((U8*)0 + (i))
|
#define PtrFromInt(i) (void*)((U8*)0 + (i))
|
||||||
|
|
||||||
#define Member(T,m) (((T*)0)->m)
|
|
||||||
#define OffsetOf(T,m) IntFromPtr(&Member(T,m))
|
|
||||||
#define MemberFromOffset(T,ptr,off) (T)((((U8 *)ptr)+(off)))
|
|
||||||
#define CastFromMember(T,m,ptr) (T*)(((U8*)ptr) - OffsetOf(T,m))
|
|
||||||
|
|
||||||
#define Compose64Bit(a,b) ((((U64)a) << 32) | ((U64)b));
|
#define Compose64Bit(a,b) ((((U64)a) << 32) | ((U64)b));
|
||||||
#define AlignPow2(x,b) (((x) + (b) - 1)&(~((b) - 1)))
|
#define AlignPow2(x,b) (((x) + (b) - 1)&(~((b) - 1)))
|
||||||
#define AlignDownPow2(x,b) ((x)&(~((b) - 1)))
|
#define AlignDownPow2(x,b) ((x)&(~((b) - 1)))
|
||||||
@@ -167,11 +323,7 @@
|
|||||||
#define IsPow2(x) ((x)!=0 && ((x)&((x)-1))==0)
|
#define IsPow2(x) ((x)!=0 && ((x)&((x)-1))==0)
|
||||||
#define IsPow2OrZero(x) ((((x) - 1)&(x)) == 0)
|
#define IsPow2OrZero(x) ((((x) - 1)&(x)) == 0)
|
||||||
|
|
||||||
#define DeferLoop(begin, end) for(int _i_ = ((begin), 0); !_i_; _i_ += 1, (end))
|
#define ExtractBit(word, idx) (((word) >> (idx)) & 1)
|
||||||
#define DeferLoopChecked(begin, end) for(int _i_ = 2 * !(begin); (_i_ == 2 ? ((end), 0) : !_i_); _i_ += 1, (end))
|
|
||||||
|
|
||||||
#define B8 S8
|
|
||||||
#define B32 rrbool
|
|
||||||
|
|
||||||
#if LANG_CPP
|
#if LANG_CPP
|
||||||
# define zero_struct {}
|
# define zero_struct {}
|
||||||
@@ -185,64 +337,6 @@
|
|||||||
# define this_function_name __func__
|
# define this_function_name __func__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LANG_CPP
|
|
||||||
# define C_LINKAGE_BEGIN extern "C"{
|
|
||||||
# define C_LINKAGE_END }
|
|
||||||
# define C_LINKAGE extern "C"
|
|
||||||
#else
|
|
||||||
# define C_LINKAGE_BEGIN
|
|
||||||
# define C_LINKAGE_END
|
|
||||||
# define C_LINKAGE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if COMPILER_CL
|
|
||||||
# define thread_static __declspec(thread)
|
|
||||||
#elif COMPILER_CLANG || COMPILER_GCC
|
|
||||||
# define thread_static __thread
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if OS_WINDOWS
|
|
||||||
# define shared_function C_LINKAGE __declspec(dllexport)
|
|
||||||
#else
|
|
||||||
# define shared_function C_LINKAGE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ ASAN
|
|
||||||
|
|
||||||
#if COMPILER_CL
|
|
||||||
# if defined(__SANITIZE_ADDRESS__)
|
|
||||||
# define ASAN_ENABLED 1
|
|
||||||
# endif
|
|
||||||
# define NO_ASAN __declspec(no_sanitize_address)
|
|
||||||
#elif COMPILER_CLANG
|
|
||||||
# if defined(__has_feature)
|
|
||||||
# if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
|
||||||
# define ASAN_ENABLED 1
|
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
# define NO_ASAN __attribute__((no_sanitize("address")))
|
|
||||||
#else
|
|
||||||
# error "NO_ASAN is not defined"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ASAN_ENABLED
|
|
||||||
|
|
||||||
#pragma comment(lib, "clang_rt.asan-x86_64.lib")
|
|
||||||
|
|
||||||
C_LINKAGE_BEGIN
|
|
||||||
void __asan_poison_memory_region(void const volatile *addr, size_t size);
|
|
||||||
void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
|
|
||||||
C_LINKAGE_END
|
|
||||||
|
|
||||||
# define AsanPoisonMemoryRegion(addr, size) __asan_poison_memory_region((addr), (size))
|
|
||||||
# define AsanUnpoisonMemoryRegion(addr, size) __asan_unpoison_memory_region((addr), (size))
|
|
||||||
#else
|
|
||||||
# define AsanPoisonMemoryRegion(addr, size) ((void)(addr), (void)(size))
|
|
||||||
# define AsanUnpoisonMemoryRegion(addr, size) ((void)(addr), (void)(size))
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Base Types
|
//~ rjf: Base Types
|
||||||
|
|
||||||
@@ -260,10 +354,7 @@ typedef S32 B32;
|
|||||||
typedef S64 B64;
|
typedef S64 B64;
|
||||||
typedef float F32;
|
typedef float F32;
|
||||||
typedef double F64;
|
typedef double F64;
|
||||||
|
typedef void VoidProc(void);
|
||||||
////////////////////////////////
|
|
||||||
//~ rjf: Large Base Types
|
|
||||||
|
|
||||||
typedef struct U128 U128;
|
typedef struct U128 U128;
|
||||||
struct U128
|
struct U128
|
||||||
{
|
{
|
||||||
@@ -273,8 +364,6 @@ struct U128
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Basic Types & Spaces
|
//~ rjf: Basic Types & Spaces
|
||||||
|
|
||||||
typedef void VoidProc(void);
|
|
||||||
|
|
||||||
typedef enum Dimension
|
typedef enum Dimension
|
||||||
{
|
{
|
||||||
Dimension_X,
|
Dimension_X,
|
||||||
@@ -315,6 +404,19 @@ typedef enum Corner
|
|||||||
}
|
}
|
||||||
Corner;
|
Corner;
|
||||||
|
|
||||||
|
typedef enum Dir2
|
||||||
|
{
|
||||||
|
Dir2_Invalid = -1,
|
||||||
|
Dir2_Left,
|
||||||
|
Dir2_Up,
|
||||||
|
Dir2_Right,
|
||||||
|
Dir2_Down,
|
||||||
|
Dir2_COUNT
|
||||||
|
}
|
||||||
|
Dir2;
|
||||||
|
#define axis2_from_dir2(d) (((d) & 1) ? Axis2_Y : Axis2_X)
|
||||||
|
#define side_from_dir2(d) (((d) < Dir2_Right) ? Side_Min : Side_Max)
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Toolchain/Environment Enums
|
//~ rjf: Toolchain/Environment Enums
|
||||||
|
|
||||||
@@ -342,7 +444,7 @@ Architecture;
|
|||||||
typedef enum Compiler
|
typedef enum Compiler
|
||||||
{
|
{
|
||||||
Compiler_Null,
|
Compiler_Null,
|
||||||
Compiler_cl,
|
Compiler_msvc,
|
||||||
Compiler_gcc,
|
Compiler_gcc,
|
||||||
Compiler_clang,
|
Compiler_clang,
|
||||||
Compiler_COUNT,
|
Compiler_COUNT,
|
||||||
@@ -570,11 +672,13 @@ struct DateTime
|
|||||||
U16 min; // [0,59]
|
U16 min; // [0,59]
|
||||||
U16 hour; // [0,24]
|
U16 hour; // [0,24]
|
||||||
U16 day; // [0,30]
|
U16 day; // [0,30]
|
||||||
union{
|
union
|
||||||
|
{
|
||||||
WeekDay week_day;
|
WeekDay week_day;
|
||||||
U32 wday;
|
U32 wday;
|
||||||
};
|
};
|
||||||
union{
|
union
|
||||||
|
{
|
||||||
Month month;
|
Month month;
|
||||||
U32 mon;
|
U32 mon;
|
||||||
};
|
};
|
||||||
@@ -602,7 +706,7 @@ struct FileProperties
|
|||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Safe Casts
|
//~ rjf: Safe Casts
|
||||||
|
|
||||||
internal U16 safe_cast_u16(U32 x);
|
internal U16 safe_cast_u16(U32 x);
|
||||||
internal U32 safe_cast_u32(U64 x);
|
internal U32 safe_cast_u32(U64 x);
|
||||||
@@ -630,6 +734,15 @@ internal U16 bswap_u16(U16 x);
|
|||||||
internal U32 bswap_u32(U32 x);
|
internal U32 bswap_u32(U32 x);
|
||||||
internal U64 bswap_u64(U64 x);
|
internal U64 bswap_u64(U64 x);
|
||||||
|
|
||||||
|
internal U64 count_bits_set16(U16 val);
|
||||||
|
internal U64 count_bits_set32(U32 val);
|
||||||
|
internal U64 count_bits_set64(U64 val);
|
||||||
|
|
||||||
|
internal U64 ctz32(U32 val);
|
||||||
|
internal U64 ctz64(U64 val);
|
||||||
|
internal U64 clz32(U32 val);
|
||||||
|
internal U64 clz64(U64 val);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Enum -> Sign
|
//~ rjf: Enum -> Sign
|
||||||
|
|
||||||
@@ -652,6 +765,7 @@ internal TxtPt txt_pt_max(TxtPt a, TxtPt b);
|
|||||||
internal TxtRng txt_rng(TxtPt min, TxtPt max);
|
internal TxtRng txt_rng(TxtPt min, TxtPt max);
|
||||||
internal TxtRng txt_rng_intersect(TxtRng a, TxtRng b);
|
internal TxtRng txt_rng_intersect(TxtRng a, TxtRng b);
|
||||||
internal TxtRng txt_rng_union(TxtRng a, TxtRng b);
|
internal TxtRng txt_rng_union(TxtRng a, TxtRng b);
|
||||||
|
internal B32 txt_rng_contains(TxtRng r, TxtPt pt);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Toolchain/Environment Enum Functions
|
//~ rjf: Toolchain/Environment Enum Functions
|
||||||
@@ -678,4 +792,9 @@ internal U64 ring_read(U8 *ring_base, U64 ring_size, U64 ring_pos, void *dst_dat
|
|||||||
#define ring_write_struct(ring_base, ring_size, ring_pos, ptr) ring_write((ring_base), (ring_size), (ring_pos), (ptr), sizeof(*(ptr)))
|
#define ring_write_struct(ring_base, ring_size, ring_pos, ptr) ring_write((ring_base), (ring_size), (ring_pos), (ptr), sizeof(*(ptr)))
|
||||||
#define ring_read_struct(ring_base, ring_size, ring_pos, ptr) ring_read((ring_base), (ring_size), (ring_pos), (ptr), sizeof(*(ptr)))
|
#define ring_read_struct(ring_base, ring_size, ring_pos, ptr) ring_read((ring_base), (ring_size), (ring_pos), (ptr), sizeof(*(ptr)))
|
||||||
|
|
||||||
#endif // BASE_TYPES_H
|
////////////////////////////////
|
||||||
|
//~ rjf: Sorts
|
||||||
|
|
||||||
|
#define quick_sort(ptr, count, element_size, cmp_function) qsort((ptr), (count), (element_size), (int (*)(const void *, const void *))(cmp_function))
|
||||||
|
|
||||||
|
#endif // BASE_CORE_H
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
// Copyright (c) 2024 Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
internal void
|
||||||
|
main_thread_base_entry_point(void (*entry_point)(CmdLine *cmdline), char **arguments, U64 arguments_count)
|
||||||
|
{
|
||||||
|
#if PROFILE_TELEMETRY
|
||||||
|
local_persist U8 tm_data[MB(64)];
|
||||||
|
tmLoadLibrary(TM_RELEASE);
|
||||||
|
tmSetMaxThreadCount(256);
|
||||||
|
tmInitialize(sizeof(tm_data), (char *)tm_data);
|
||||||
|
#endif
|
||||||
|
ThreadNameF("[main thread]");
|
||||||
|
Temp scratch = scratch_begin(0, 0);
|
||||||
|
String8List command_line_argument_strings = os_string_list_from_argcv(scratch.arena, (int)arguments_count, arguments);
|
||||||
|
CmdLine cmdline = cmd_line_from_string_list(scratch.arena, command_line_argument_strings);
|
||||||
|
B32 capture = cmd_line_has_flag(&cmdline, str8_lit("capture"));
|
||||||
|
if(capture)
|
||||||
|
{
|
||||||
|
ProfBeginCapture(arguments[0]);
|
||||||
|
}
|
||||||
|
#if defined(TASK_SYSTEM_H) && !defined(TS_INIT_MANUAL)
|
||||||
|
ts_init();
|
||||||
|
#endif
|
||||||
|
#if defined(HASH_STORE_H) && !defined(HS_INIT_MANUAL)
|
||||||
|
hs_init();
|
||||||
|
#endif
|
||||||
|
#if defined(FILE_STREAM_H) && !defined(FS_INIT_MANUAL)
|
||||||
|
fs_init();
|
||||||
|
#endif
|
||||||
|
#if defined(TEXT_CACHE_H) && !defined(TXT_INIT_MANUAL)
|
||||||
|
txt_init();
|
||||||
|
#endif
|
||||||
|
#if defined(MUTABLE_TEXT_H) && !defined(MTX_INIT_MANUAL)
|
||||||
|
mtx_init();
|
||||||
|
#endif
|
||||||
|
#if defined(DASM_CACHE_H) && !defined(DASM_INIT_MANUAL)
|
||||||
|
dasm_init();
|
||||||
|
#endif
|
||||||
|
#if defined(DI_H) && !defined(DI_INIT_MANUAL)
|
||||||
|
di_init();
|
||||||
|
#endif
|
||||||
|
#if defined(FUZZY_SEARCH_H) && !defined(FZY_INIT_MANUAL)
|
||||||
|
fzy_init();
|
||||||
|
#endif
|
||||||
|
#if defined(DEMON_CORE_H) && !defined(DMN_INIT_MANUAL)
|
||||||
|
dmn_init();
|
||||||
|
#endif
|
||||||
|
#if defined(CTRL_CORE_H) && !defined(CTRL_INIT_MANUAL)
|
||||||
|
ctrl_init();
|
||||||
|
#endif
|
||||||
|
#if defined(OS_GRAPHICAL_H) && !defined(OS_GFX_INIT_MANUAL)
|
||||||
|
os_gfx_init();
|
||||||
|
#endif
|
||||||
|
#if defined(FONT_PROVIDER_H) && !defined(FP_INIT_MANUAL)
|
||||||
|
fp_init();
|
||||||
|
#endif
|
||||||
|
#if defined(RENDER_CORE_H) && !defined(R_INIT_MANUAL)
|
||||||
|
r_init(&cmdline);
|
||||||
|
#endif
|
||||||
|
#if defined(TEXTURE_CACHE_H) && !defined(TEX_INIT_MANUAL)
|
||||||
|
tex_init();
|
||||||
|
#endif
|
||||||
|
#if defined(GEO_CACHE_H) && !defined(GEO_INIT_MANUAL)
|
||||||
|
geo_init();
|
||||||
|
#endif
|
||||||
|
#if defined(FONT_CACHE_H) && !defined(F_INIT_MANUAL)
|
||||||
|
f_init();
|
||||||
|
#endif
|
||||||
|
#if defined(DF_CORE_H) && !defined(DF_INIT_MANUAL)
|
||||||
|
DF_StateDeltaHistory *hist = df_state_delta_history_alloc();
|
||||||
|
df_core_init(&cmdline, hist);
|
||||||
|
#endif
|
||||||
|
#if defined(DF_GFX_H) && !defined(DF_GFX_INIT_MANUAL)
|
||||||
|
df_gfx_init(update_and_render, df_state_delta_history());
|
||||||
|
#endif
|
||||||
|
entry_point(&cmdline);
|
||||||
|
if(capture)
|
||||||
|
{
|
||||||
|
ProfEndCapture();
|
||||||
|
}
|
||||||
|
scratch_end(scratch);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
supplement_thread_base_entry_point(void (*entry_point)(void *params), void *params)
|
||||||
|
{
|
||||||
|
TCTX tctx;
|
||||||
|
tctx_init_and_equip(&tctx);
|
||||||
|
entry_point(params);
|
||||||
|
tctx_release();
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// Copyright (c) 2024 Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
#ifndef BASE_ENTRY_POINT_H
|
||||||
|
#define BASE_ENTRY_POINT_H
|
||||||
|
|
||||||
|
internal void main_thread_base_entry_point(void (*entry_point)(CmdLine *cmdline), char **arguments, U64 arguments_count);
|
||||||
|
internal void supplement_thread_base_entry_point(void (*entry_point)(void *params), void *params);
|
||||||
|
|
||||||
|
#endif // BASE_ENTRY_POINT_H
|
||||||
@@ -7,12 +7,13 @@
|
|||||||
#undef RADDBG_LAYER_COLOR
|
#undef RADDBG_LAYER_COLOR
|
||||||
#define RADDBG_LAYER_COLOR 0.20f, 0.60f, 0.80f
|
#define RADDBG_LAYER_COLOR 0.20f, 0.60f, 0.80f
|
||||||
|
|
||||||
#include "metagen_base_types.c"
|
#include "metagen_base_core.c"
|
||||||
#include "metagen_base_markup.c"
|
#include "metagen_base_profile.c"
|
||||||
#include "metagen_base_arena.c"
|
#include "metagen_base_arena.c"
|
||||||
#include "metagen_base_math.c"
|
#include "metagen_base_math.c"
|
||||||
#include "metagen_base_string.c"
|
#include "metagen_base_strings.c"
|
||||||
#include "metagen_base_thread_context.c"
|
#include "metagen_base_thread_context.c"
|
||||||
#include "metagen_base_command_line.c"
|
#include "metagen_base_command_line.c"
|
||||||
#include "metagen_base_arena_dev.c"
|
#include "metagen_base_markup.c"
|
||||||
#include "metagen_base_bits.c"
|
#include "metagen_base_log.c"
|
||||||
|
#include "metagen_base_entry_point.c"
|
||||||
|
|||||||
@@ -8,16 +8,16 @@
|
|||||||
//~ rjf: Base Includes
|
//~ rjf: Base Includes
|
||||||
|
|
||||||
#include "metagen_base_context_cracking.h"
|
#include "metagen_base_context_cracking.h"
|
||||||
#include "metagen_base_types.h"
|
|
||||||
#include "metagen_base_markup.h"
|
#include "metagen_base_core.h"
|
||||||
#include "metagen_base_ins.h"
|
#include "metagen_base_profile.h"
|
||||||
#include "metagen_base_linked_lists.h"
|
|
||||||
#include "metagen_base_arena.h"
|
#include "metagen_base_arena.h"
|
||||||
#include "metagen_base_math.h"
|
#include "metagen_base_math.h"
|
||||||
#include "metagen_base_string.h"
|
#include "metagen_base_strings.h"
|
||||||
#include "metagen_base_thread_context.h"
|
#include "metagen_base_thread_context.h"
|
||||||
#include "metagen_base_command_line.h"
|
#include "metagen_base_command_line.h"
|
||||||
#include "metagen_base_arena_dev.h"
|
#include "metagen_base_markup.h"
|
||||||
#include "metagen_base_bits.h"
|
#include "metagen_base_log.h"
|
||||||
|
#include "metagen_base_entry_point.h"
|
||||||
|
|
||||||
#endif // BASE_INC_H
|
#endif // BASE_INC_H
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
// Copyright (c) 2024 Epic Games Tools
|
|
||||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
|
||||||
|
|
||||||
#ifndef BASE_INS_H
|
|
||||||
#define BASE_INS_H
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
// NOTE(allen): Implementations of Intrinsics
|
|
||||||
|
|
||||||
#if OS_WINDOWS
|
|
||||||
|
|
||||||
# include <windows.h>
|
|
||||||
# include <tmmintrin.h>
|
|
||||||
# include <wmmintrin.h>
|
|
||||||
# include <intrin.h>
|
|
||||||
|
|
||||||
# if ARCH_X64
|
|
||||||
# define ins_atomic_u64_eval(x) InterlockedAdd((volatile LONG *)(x), 0)
|
|
||||||
# define ins_atomic_u64_inc_eval(x) InterlockedIncrement64((volatile __int64 *)(x))
|
|
||||||
# define ins_atomic_u64_dec_eval(x) InterlockedDecrement64((volatile __int64 *)(x))
|
|
||||||
# define ins_atomic_u64_eval_assign(x,c) InterlockedExchange64((volatile __int64 *)(x),(c))
|
|
||||||
# define ins_atomic_u64_add_eval(x,c) InterlockedAdd((volatile LONG *)(x), c)
|
|
||||||
# define ins_atomic_u32_eval_assign(x,c) InterlockedExchange((volatile LONG *)(x),(c))
|
|
||||||
# define ins_atomic_u32_eval_cond_assign(x,k,c) InterlockedCompareExchange((volatile LONG *)(x),(k),(c))
|
|
||||||
# define ins_atomic_ptr_eval_assign(x,c) (void*)ins_atomic_u64_eval_assign((volatile __int64 *)(x), (__int64)(c))
|
|
||||||
# endif
|
|
||||||
|
|
||||||
#elif OS_LINUX
|
|
||||||
|
|
||||||
# if ARCH_X64
|
|
||||||
# define ins_atomic_u64_inc_eval(x) __sync_fetch_and_add((volatile U64 *)(x), 1)
|
|
||||||
# endif
|
|
||||||
|
|
||||||
#else
|
|
||||||
// TODO(allen):
|
|
||||||
#endif
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
// NOTE(allen): Intrinsic Checks
|
|
||||||
|
|
||||||
#if ARCH_X64
|
|
||||||
|
|
||||||
# if !defined(ins_atomic_u64_inc_eval)
|
|
||||||
# error missing: ins_atomic_u64_inc_eval
|
|
||||||
# endif
|
|
||||||
|
|
||||||
#else
|
|
||||||
# error the intrinsic set for this arch is not developed
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif //BASE_INS_H
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
// Copyright (c) 2024 Epic Games Tools
|
|
||||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
|
||||||
|
|
||||||
#ifndef BASE_LINKED_LIST_H
|
|
||||||
#define BASE_LINKED_LIST_H
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ rjf: Helpers
|
|
||||||
|
|
||||||
#define CheckNil(nil,p) ((p) == 0 || (p) == nil)
|
|
||||||
#define SetNil(nil,p) ((p) = nil)
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ rjf: Base Macros
|
|
||||||
|
|
||||||
//- rjf: Base Doubly-Linked-List Macros
|
|
||||||
#define DLLInsert_NPZ(nil,f,l,p,n,next,prev) (CheckNil(nil,f) ? \
|
|
||||||
((f) = (l) = (n), SetNil(nil,(n)->next), SetNil(nil,(n)->prev)) :\
|
|
||||||
CheckNil(nil,p) ? \
|
|
||||||
((n)->next = (f), (f)->prev = (n), (f) = (n), SetNil(nil,(n)->prev)) :\
|
|
||||||
((p)==(l)) ? \
|
|
||||||
((l)->next = (n), (n)->prev = (l), (l) = (n), SetNil(nil, (n)->next)) :\
|
|
||||||
(((!CheckNil(nil,p) && CheckNil(nil,(p)->next)) ? (0) : ((p)->next->prev = (n))), ((n)->next = (p)->next), ((p)->next = (n)), ((n)->prev = (p))))
|
|
||||||
#define DLLPushBack_NPZ(nil,f,l,n,next,prev) DLLInsert_NPZ(nil,f,l,l,n,next,prev)
|
|
||||||
#define DLLPushFront_NPZ(nil,f,l,n,next,prev) DLLInsert_NPZ(nil,l,f,f,n,prev,next)
|
|
||||||
#define DLLRemove_NPZ(nil,f,l,n,next,prev) (((n) == (f) ? (f) = (n)->next : (0)),\
|
|
||||||
((n) == (l) ? (l) = (l)->prev : (0)),\
|
|
||||||
(CheckNil(nil,(n)->prev) ? (0) :\
|
|
||||||
((n)->prev->next = (n)->next)),\
|
|
||||||
(CheckNil(nil,(n)->next) ? (0) :\
|
|
||||||
((n)->next->prev = (n)->prev)))
|
|
||||||
|
|
||||||
//- rjf: Base Singly-Linked-List Queue Macros
|
|
||||||
#define SLLQueuePush_NZ(nil,f,l,n,next) (CheckNil(nil,f)?\
|
|
||||||
((f)=(l)=(n),SetNil(nil,(n)->next)):\
|
|
||||||
((l)->next=(n),(l)=(n),SetNil(nil,(n)->next)))
|
|
||||||
#define SLLQueuePushFront_NZ(nil,f,l,n,next) (CheckNil(nil,f)?\
|
|
||||||
((f)=(l)=(n),SetNil(nil,(n)->next)):\
|
|
||||||
((n)->next=(f),(f)=(n)))
|
|
||||||
#define SLLQueuePop_NZ(nil,f,l,next) ((f)==(l)?\
|
|
||||||
(SetNil(nil,f),SetNil(nil,l)):\
|
|
||||||
((f)=(f)->next))
|
|
||||||
|
|
||||||
//- rjf: Base Singly-Linked-List Stack Macros
|
|
||||||
#define SLLStackPush_N(f,n,next) ((n)->next=(f), (f)=(n))
|
|
||||||
#define SLLStackPop_N(f,next) ((f)=(f)->next)
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ rjf: Convenience Wrappers
|
|
||||||
|
|
||||||
//- rjf: Doubly-Linked-List Wrappers
|
|
||||||
#define DLLInsert_NP(f,l,p,n,next,prev) DLLInsert_NPZ(0,f,l,p,n,next,prev)
|
|
||||||
#define DLLPushBack_NP(f,l,n,next,prev) DLLPushBack_NPZ(0,f,l,n,next,prev)
|
|
||||||
#define DLLPushFront_NP(f,l,n,next,prev) DLLPushFront_NPZ(0,f,l,n,next,prev)
|
|
||||||
#define DLLRemove_NP(f,l,n,next,prev) DLLRemove_NPZ(0,f,l,n,next,prev)
|
|
||||||
#define DLLInsert(f,l,p,n) DLLInsert_NPZ(0,f,l,p,n,next,prev)
|
|
||||||
#define DLLPushBack(f,l,n) DLLPushBack_NPZ(0,f,l,n,next,prev)
|
|
||||||
#define DLLPushFront(f,l,n) DLLPushFront_NPZ(0,f,l,n,next,prev)
|
|
||||||
#define DLLRemove(f,l,n) DLLRemove_NPZ(0,f,l,n,next,prev)
|
|
||||||
|
|
||||||
//- rjf: Singly-Linked-List Queue Wrappers
|
|
||||||
#define SLLQueuePush_N(f,l,n,next) SLLQueuePush_NZ(0,f,l,n,next)
|
|
||||||
#define SLLQueuePushFront_N(f,l,n,next) SLLQueuePushFront_NZ(0,f,l,n,next)
|
|
||||||
#define SLLQueuePop_N(f,l,next) SLLQueuePop_NZ(0,f,l,next)
|
|
||||||
#define SLLQueuePush(f,l,n) SLLQueuePush_NZ(0,f,l,n,next)
|
|
||||||
#define SLLQueuePushFront(f,l,n) SLLQueuePushFront_NZ(0,f,l,n,next)
|
|
||||||
#define SLLQueuePop(f,l) SLLQueuePop_NZ(0,f,l,next)
|
|
||||||
|
|
||||||
//- rjf: Singly-Linked-List Stack Wrappers
|
|
||||||
#define SLLStackPush(f,n) SLLStackPush_N(f,n,next)
|
|
||||||
#define SLLStackPop(f) SLLStackPop_N(f,next)
|
|
||||||
|
|
||||||
#endif //BASE_LINKED_LIST_H
|
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
// Copyright (c) 2024 Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Globals/Thread-Locals
|
||||||
|
|
||||||
|
C_LINKAGE thread_static Log *log_active;
|
||||||
|
#if !BUILD_SUPPLEMENTARY_UNIT
|
||||||
|
C_LINKAGE thread_static Log *log_active = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Log Creation/Selection
|
||||||
|
|
||||||
|
internal Log *
|
||||||
|
log_alloc(void)
|
||||||
|
{
|
||||||
|
Arena *arena = arena_alloc();
|
||||||
|
Log *log = push_array(arena, Log, 1);
|
||||||
|
log->arena = arena;
|
||||||
|
return log;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
log_release(Log *log)
|
||||||
|
{
|
||||||
|
arena_release(log->arena);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
log_select(Log *log)
|
||||||
|
{
|
||||||
|
log_active = log;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Log Building/Clearing
|
||||||
|
|
||||||
|
internal void
|
||||||
|
log_msg(LogMsgKind kind, String8 string)
|
||||||
|
{
|
||||||
|
if(log_active != 0 && log_active->top_scope != 0)
|
||||||
|
{
|
||||||
|
String8 string_copy = push_str8_copy(log_active->arena, string);
|
||||||
|
str8_list_push(log_active->arena, &log_active->top_scope->strings[kind], string_copy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
log_msgf(LogMsgKind kind, char *fmt, ...)
|
||||||
|
{
|
||||||
|
if(log_active != 0)
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(0, 0);
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
String8 string = push_str8fv(scratch.arena, fmt, args);
|
||||||
|
log_msg(kind, string);
|
||||||
|
va_end(args);
|
||||||
|
scratch_end(scratch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Log Scopes
|
||||||
|
|
||||||
|
internal void
|
||||||
|
log_scope_begin(void)
|
||||||
|
{
|
||||||
|
if(log_active != 0)
|
||||||
|
{
|
||||||
|
U64 pos = arena_pos(log_active->arena);
|
||||||
|
LogScope *scope = push_array(log_active->arena, LogScope, 1);
|
||||||
|
scope->pos = pos;
|
||||||
|
SLLStackPush(log_active->top_scope, scope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal LogScopeResult
|
||||||
|
log_scope_end(Arena *arena)
|
||||||
|
{
|
||||||
|
LogScopeResult result = {0};
|
||||||
|
if(log_active != 0)
|
||||||
|
{
|
||||||
|
LogScope *scope = log_active->top_scope;
|
||||||
|
if(scope != 0)
|
||||||
|
{
|
||||||
|
SLLStackPop(log_active->top_scope);
|
||||||
|
if(arena != 0)
|
||||||
|
{
|
||||||
|
for(EachEnumVal(LogMsgKind, kind))
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(&arena, 1);
|
||||||
|
String8 result_unindented = str8_list_join(scratch.arena, &scope->strings[kind], 0);
|
||||||
|
result.strings[kind] = indented_from_string(arena, result_unindented);
|
||||||
|
scratch_end(scratch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arena_pop_to(log_active->arena, scope->pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
// Copyright (c) 2024 Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
#ifndef BASE_LOG_H
|
||||||
|
#define BASE_LOG_H
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Log Types
|
||||||
|
|
||||||
|
typedef enum LogMsgKind
|
||||||
|
{
|
||||||
|
LogMsgKind_Info,
|
||||||
|
LogMsgKind_UserError,
|
||||||
|
LogMsgKind_COUNT
|
||||||
|
}
|
||||||
|
LogMsgKind;
|
||||||
|
|
||||||
|
typedef struct LogScope LogScope;
|
||||||
|
struct LogScope
|
||||||
|
{
|
||||||
|
LogScope *next;
|
||||||
|
U64 pos;
|
||||||
|
String8List strings[LogMsgKind_COUNT];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct LogScopeResult LogScopeResult;
|
||||||
|
struct LogScopeResult
|
||||||
|
{
|
||||||
|
String8 strings[LogMsgKind_COUNT];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Log Log;
|
||||||
|
struct Log
|
||||||
|
{
|
||||||
|
Arena *arena;
|
||||||
|
LogScope *top_scope;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Log Creation/Selection
|
||||||
|
|
||||||
|
internal Log *log_alloc(void);
|
||||||
|
internal void log_release(Log *log);
|
||||||
|
internal void log_select(Log *log);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Log Building
|
||||||
|
|
||||||
|
internal void log_msg(LogMsgKind kind, String8 string);
|
||||||
|
internal void log_msgf(LogMsgKind kind, char *fmt, ...);
|
||||||
|
#define log_info(s) log_msg(LogMsgKind_Info, (s))
|
||||||
|
#define log_infof(fmt, ...) log_msgf(LogMsgKind_Info, (fmt), __VA_ARGS__)
|
||||||
|
#define log_user_error(s) log_msg(LogMsgKind_UserError, (s))
|
||||||
|
#define log_user_errorf(fmt, ...) log_msgf(LogMsgKind_UserError, (fmt), __VA_ARGS__)
|
||||||
|
|
||||||
|
#define LogInfoNamedBlock(s) DeferLoop(log_infof("%S:\n{\n", (s)), log_infof("}\n"))
|
||||||
|
#define LogInfoNamedBlockF(fmt, ...) DeferLoop((log_infof(fmt, __VA_ARGS__), log_infof(":\n{\n")), log_infof("}\n"))
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Log Scopes
|
||||||
|
|
||||||
|
internal void log_scope_begin(void);
|
||||||
|
internal LogScopeResult log_scope_end(Arena *arena);
|
||||||
|
|
||||||
|
#endif // BASE_LOG_H
|
||||||
@@ -1,2 +1,21 @@
|
|||||||
// Copyright (c) 2024 Epic Games Tools
|
// Copyright (c) 2024 Epic Games Tools
|
||||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
internal void
|
||||||
|
set_thread_name(String8 string)
|
||||||
|
{
|
||||||
|
ProfThreadName("%.*s", str8_varg(string));
|
||||||
|
os_set_thread_name(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
set_thread_namef(char *fmt, ...)
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(0, 0);
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
String8 string = push_str8fv(scratch.arena, fmt, args);
|
||||||
|
set_thread_name(string);
|
||||||
|
va_end(args);
|
||||||
|
scratch_end(scratch);
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,76 +4,9 @@
|
|||||||
#ifndef BASE_MARKUP_H
|
#ifndef BASE_MARKUP_H
|
||||||
#define BASE_MARKUP_H
|
#define BASE_MARKUP_H
|
||||||
|
|
||||||
////////////////////////////////
|
internal void set_thread_name(String8 string);
|
||||||
//~ rjf: Zero Settings
|
internal void set_thread_namef(char *fmt, ...);
|
||||||
|
#define ThreadNameF(...) (set_thread_namef(__VA_ARGS__))
|
||||||
#if !defined(PROFILE_TELEMETRY)
|
#define ThreadName(str) (set_thread_name(str))
|
||||||
# define PROFILE_TELEMETRY 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(MARKUP_LAYER_COLOR)
|
|
||||||
# define MARKUP_LAYER_COLOR 1.00f, 0.00f, 1.00f
|
|
||||||
#endif
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ rjf: Third Party Includes
|
|
||||||
|
|
||||||
#if PROFILE_TELEMETRY
|
|
||||||
# include "rad_tm.h"
|
|
||||||
# if OS_WINDOWS
|
|
||||||
# pragma comment(lib, "rad_tm_win64.lib")
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ rjf: Telemetry Profile Defines
|
|
||||||
|
|
||||||
#if PROFILE_TELEMETRY
|
|
||||||
# define ProfBegin(...) tmEnter(0, 0, __VA_ARGS__)
|
|
||||||
# define ProfBeginDynamic(...) (TM_API_PTR ? TM_API_PTR->_tmEnterZoneV_Core(0, 0, __FILE__, &g_telemetry_filename_id, __LINE__, __VA_ARGS__) : (void)0)
|
|
||||||
# define ProfEnd(...) (TM_API_PTR ? TM_API_PTR->_tmLeaveZone(0) : (void)0)
|
|
||||||
# define ProfTick(...) tmTick(0)
|
|
||||||
# define ProfIsCapturing(...) tmRunning()
|
|
||||||
# define ProfBeginCapture(...) tmOpen(0, __VA_ARGS__, __DATE__, "localhost", TMCT_TCP, TELEMETRY_DEFAULT_PORT, TMOF_INIT_NETWORKING|TMOF_CAPTURE_CONTEXT_SWITCHES, 100)
|
|
||||||
# define ProfEndCapture(...) tmClose(0)
|
|
||||||
# define ProfThreadName(...) (TM_API_PTR ? TM_API_PTR->_tmThreadName(0, 0, __VA_ARGS__) : (void)0)
|
|
||||||
# define ProfMsg(...) (TM_API_PTR ? TM_API_PTR->_tmMessageV_Core(0, TMMF_ICON_NOTE, __FILE__, &g_telemetry_filename_id, __LINE__, __VA_ARGS__) : (void)0)
|
|
||||||
# define ProfBeginLockWait(...) tmStartWaitForLock(0, 0, __VA_ARGS__)
|
|
||||||
# define ProfEndLockWait(...) tmEndWaitForLock(0)
|
|
||||||
# define ProfLockTake(...) tmAcquiredLock(0, 0, __VA_ARGS__)
|
|
||||||
# define ProfLockDrop(...) tmReleasedLock(0, __VA_ARGS__)
|
|
||||||
# define ProfColor(color) tmZoneColorSticky(color)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ rjf: Zeroify Undefined Defines
|
|
||||||
|
|
||||||
#if !defined(ProfBegin)
|
|
||||||
# define ProfBegin(...) (0)
|
|
||||||
# define ProfBeginDynamic(...) (0)
|
|
||||||
# define ProfEnd(...) (0)
|
|
||||||
# define ProfTick(...) (0)
|
|
||||||
# define ProfIsCapturing(...) (0)
|
|
||||||
# define ProfBeginCapture(...) (0)
|
|
||||||
# define ProfEndCapture(...) (0)
|
|
||||||
# define ProfThreadName(...) (0)
|
|
||||||
# define ProfMsg(...) (0)
|
|
||||||
# define ProfBeginLockWait(...) (0)
|
|
||||||
# define ProfEndLockWait(...) (0)
|
|
||||||
# define ProfLockTake(...) (0)
|
|
||||||
# define ProfLockDrop(...) (0)
|
|
||||||
# define ProfColor(...) (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ rjf: Helper Wrappers
|
|
||||||
|
|
||||||
#define ProfBeginFunction(...) ProfBegin(this_function_name)
|
|
||||||
#define ProfScope(...) DeferLoop(ProfBeginDynamic(__VA_ARGS__), ProfEnd())
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ rjf: General Markup
|
|
||||||
|
|
||||||
#define ThreadName(...) (ProfThreadName(__VA_ARGS__))
|
|
||||||
|
|
||||||
#endif // BASE_MARKUP_H
|
#endif // BASE_MARKUP_H
|
||||||
|
|||||||
@@ -141,6 +141,15 @@ make_translate_3x3f32(Vec2F32 delta)
|
|||||||
return mat;
|
return mat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal Mat3x3F32
|
||||||
|
make_scale_3x3f32(Vec2F32 scale)
|
||||||
|
{
|
||||||
|
Mat3x3F32 mat = mat_3x3f32(1.f);
|
||||||
|
mat.v[0][0] = scale.x;
|
||||||
|
mat.v[1][1] = scale.y;
|
||||||
|
return mat;
|
||||||
|
}
|
||||||
|
|
||||||
internal Mat3x3F32
|
internal Mat3x3F32
|
||||||
mul_3x3f32(Mat3x3F32 a, Mat3x3F32 b)
|
mul_3x3f32(Mat3x3F32 a, Mat3x3F32 b)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -507,6 +507,7 @@ internal Vec4S32 mix_4s32(Vec4S32 a, Vec4S32 b, F32 t);
|
|||||||
|
|
||||||
internal Mat3x3F32 mat_3x3f32(F32 diagonal);
|
internal Mat3x3F32 mat_3x3f32(F32 diagonal);
|
||||||
internal Mat3x3F32 make_translate_3x3f32(Vec2F32 delta);
|
internal Mat3x3F32 make_translate_3x3f32(Vec2F32 delta);
|
||||||
|
internal Mat3x3F32 make_scale_3x3f32(Vec2F32 scale);
|
||||||
internal Mat3x3F32 mul_3x3f32(Mat3x3F32 a, Mat3x3F32 b);
|
internal Mat3x3F32 mul_3x3f32(Mat3x3F32 a, Mat3x3F32 b);
|
||||||
|
|
||||||
internal Mat4x4F32 mat_4x4f32(F32 diagonal);
|
internal Mat4x4F32 mat_4x4f32(F32 diagonal);
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
// Copyright (c) 2024 Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
// Copyright (c) 2024 Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
#ifndef BASE_PROFILE_H
|
||||||
|
#define BASE_PROFILE_H
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Zero Settings
|
||||||
|
|
||||||
|
#if !defined(PROFILE_TELEMETRY)
|
||||||
|
# define PROFILE_TELEMETRY 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(MARKUP_LAYER_COLOR)
|
||||||
|
# define MARKUP_LAYER_COLOR 1.00f, 0.00f, 1.00f
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Third Party Includes
|
||||||
|
|
||||||
|
#if PROFILE_TELEMETRY
|
||||||
|
# include "rad_tm.h"
|
||||||
|
# if OS_WINDOWS
|
||||||
|
# pragma comment(lib, "rad_tm_win64.lib")
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Telemetry Profile Defines
|
||||||
|
|
||||||
|
#if PROFILE_TELEMETRY
|
||||||
|
# define ProfBegin(...) tmEnter(0, 0, __VA_ARGS__)
|
||||||
|
# define ProfBeginDynamic(...) (TM_API_PTR ? TM_API_PTR->_tmEnterZoneV_Core(0, 0, __FILE__, &g_telemetry_filename_id, __LINE__, __VA_ARGS__) : (void)0)
|
||||||
|
# define ProfEnd(...) (TM_API_PTR ? TM_API_PTR->_tmLeaveZone(0) : (void)0)
|
||||||
|
# define ProfTick(...) tmTick(0)
|
||||||
|
# define ProfIsCapturing(...) tmRunning()
|
||||||
|
# define ProfBeginCapture(...) tmOpen(0, __VA_ARGS__, __DATE__, "localhost", TMCT_TCP, TELEMETRY_DEFAULT_PORT, TMOF_INIT_NETWORKING|TMOF_CAPTURE_CONTEXT_SWITCHES, 100)
|
||||||
|
# define ProfEndCapture(...) tmClose(0)
|
||||||
|
# define ProfThreadName(...) (TM_API_PTR ? TM_API_PTR->_tmThreadName(0, 0, __VA_ARGS__) : (void)0)
|
||||||
|
# define ProfMsg(...) (TM_API_PTR ? TM_API_PTR->_tmMessageV_Core(0, TMMF_ICON_NOTE, __FILE__, &g_telemetry_filename_id, __LINE__, __VA_ARGS__) : (void)0)
|
||||||
|
# define ProfBeginLockWait(...) tmStartWaitForLock(0, 0, __VA_ARGS__)
|
||||||
|
# define ProfEndLockWait(...) tmEndWaitForLock(0)
|
||||||
|
# define ProfLockTake(...) tmAcquiredLock(0, 0, __VA_ARGS__)
|
||||||
|
# define ProfLockDrop(...) tmReleasedLock(0, __VA_ARGS__)
|
||||||
|
# define ProfColor(color) tmZoneColorSticky(color)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Zeroify Undefined Defines
|
||||||
|
|
||||||
|
#if !defined(ProfBegin)
|
||||||
|
# define ProfBegin(...) (0)
|
||||||
|
# define ProfBeginDynamic(...) (0)
|
||||||
|
# define ProfEnd(...) (0)
|
||||||
|
# define ProfTick(...) (0)
|
||||||
|
# define ProfIsCapturing(...) (0)
|
||||||
|
# define ProfBeginCapture(...) (0)
|
||||||
|
# define ProfEndCapture(...) (0)
|
||||||
|
# define ProfThreadName(...) (0)
|
||||||
|
# define ProfMsg(...) (0)
|
||||||
|
# define ProfBeginLockWait(...) (0)
|
||||||
|
# define ProfEndLockWait(...) (0)
|
||||||
|
# define ProfLockTake(...) (0)
|
||||||
|
# define ProfLockDrop(...) (0)
|
||||||
|
# define ProfColor(...) (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Helper Wrappers
|
||||||
|
|
||||||
|
#define ProfBeginFunction(...) ProfBegin(this_function_name)
|
||||||
|
#define ProfScope(...) DeferLoop(ProfBeginDynamic(__VA_ARGS__), ProfEnd())
|
||||||
|
|
||||||
|
#endif // BASE_PROFILE_H
|
||||||
+167
-70
@@ -4,7 +4,7 @@
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Third Party Includes
|
//~ rjf: Third Party Includes
|
||||||
|
|
||||||
#if !SUPPLEMENT_UNIT
|
#if !BUILD_SUPPLEMENTARY_UNIT
|
||||||
# define STB_SPRINTF_IMPLEMENTATION
|
# define STB_SPRINTF_IMPLEMENTATION
|
||||||
# define STB_SPRINTF_STATIC
|
# define STB_SPRINTF_STATIC
|
||||||
# include "third_party/stb/stb_sprintf.h"
|
# include "third_party/stb/stb_sprintf.h"
|
||||||
@@ -406,13 +406,11 @@ push_str8_cat(Arena *arena, String8 s1, String8 s2){
|
|||||||
|
|
||||||
internal String8
|
internal String8
|
||||||
push_str8_copy(Arena *arena, String8 s){
|
push_str8_copy(Arena *arena, String8 s){
|
||||||
//ProfBeginFunction();
|
|
||||||
String8 str;
|
String8 str;
|
||||||
str.size = s.size;
|
str.size = s.size;
|
||||||
str.str = push_array_no_zero(arena, U8, str.size + 1);
|
str.str = push_array_no_zero(arena, U8, str.size + 1);
|
||||||
MemoryCopy(str.str, s.str, s.size);
|
MemoryCopy(str.str, s.str, s.size);
|
||||||
str.str[str.size] = 0;
|
str.str[str.size] = 0;
|
||||||
//ProfEnd();
|
|
||||||
return(str);
|
return(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -543,64 +541,6 @@ try_s64_from_str8_c_rules(String8 string, S64 *x){
|
|||||||
return(is_integer);
|
return(is_integer);
|
||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: string -> integer (base64 & base16)
|
|
||||||
|
|
||||||
internal U64
|
|
||||||
base64_size_from_data_size(U64 size_in_bytes){
|
|
||||||
U64 bits = size_in_bytes*8;
|
|
||||||
U64 base64_size = (bits + 5)/6;
|
|
||||||
return(base64_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal U64
|
|
||||||
base64_from_data(U8 *dst, U8 *src, U64 src_size){
|
|
||||||
U8 *dst_base = dst;
|
|
||||||
U8 *opl = src + src_size;
|
|
||||||
U32 bit_num = 0;
|
|
||||||
if (src < opl){
|
|
||||||
U8 byte = *src;
|
|
||||||
for (;;){
|
|
||||||
U32 x = 0;
|
|
||||||
for (U32 i = 0; i < 6; i += 1){
|
|
||||||
x |= ((byte >> bit_num) & 1) << i;
|
|
||||||
bit_num += 1;
|
|
||||||
if (bit_num == 8){
|
|
||||||
bit_num = 0;
|
|
||||||
src += 1;
|
|
||||||
byte = (src < opl)?(*src):0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*dst = base64[x];
|
|
||||||
dst += 1;
|
|
||||||
if (src >= opl){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return(dst - dst_base);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal U64
|
|
||||||
base16_size_from_data_size(U64 size_in_bytes){
|
|
||||||
U64 base16_size = size_in_bytes*2;
|
|
||||||
return(base16_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal U64
|
|
||||||
base16_from_data(U8 *dst, U8 *src, U64 src_size){
|
|
||||||
U8 *dst_base = dst;
|
|
||||||
U8 *opl = src + src_size;
|
|
||||||
for (;src < opl;){
|
|
||||||
U8 byte = *src;
|
|
||||||
*dst = integer_symbols[byte & 0xF];
|
|
||||||
dst += 1;
|
|
||||||
*dst = integer_symbols[byte >> 4];
|
|
||||||
dst += 1;
|
|
||||||
src += 1;
|
|
||||||
}
|
|
||||||
return(dst - dst_base);
|
|
||||||
}
|
|
||||||
|
|
||||||
//- rjf: integer -> string
|
//- rjf: integer -> string
|
||||||
|
|
||||||
internal String8
|
internal String8
|
||||||
@@ -1006,11 +946,11 @@ str8_array_from_list(Arena *arena, String8List *list)
|
|||||||
{
|
{
|
||||||
String8Array array;
|
String8Array array;
|
||||||
array.count = list->node_count;
|
array.count = list->node_count;
|
||||||
array.strings = push_array_no_zero(arena, String8, array.count);
|
array.v = push_array_no_zero(arena, String8, array.count);
|
||||||
U64 idx = 0;
|
U64 idx = 0;
|
||||||
for(String8Node *n = list->first; n != 0; n = n->next, idx += 1)
|
for(String8Node *n = list->first; n != 0; n = n->next, idx += 1)
|
||||||
{
|
{
|
||||||
array.strings[idx] = n->string;
|
array.v[idx] = n->string;
|
||||||
}
|
}
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
@@ -1020,7 +960,7 @@ str8_array_reserve(Arena *arena, U64 count)
|
|||||||
{
|
{
|
||||||
String8Array arr;
|
String8Array arr;
|
||||||
arr.count = 0;
|
arr.count = 0;
|
||||||
arr.strings = push_array(arena, String8, count);
|
arr.v = push_array(arena, String8, count);
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1341,7 +1281,7 @@ utf16_decode(U16 *str, U64 max){
|
|||||||
result.codepoint = str[0];
|
result.codepoint = str[0];
|
||||||
result.inc = 1;
|
result.inc = 1;
|
||||||
if (max > 1 && 0xD800 <= str[0] && str[0] < 0xDC00 && 0xDC00 <= str[1] && str[1] < 0xE000){
|
if (max > 1 && 0xD800 <= str[0] && str[0] < 0xDC00 && 0xDC00 <= str[1] && str[1] < 0xE000){
|
||||||
result.codepoint = ((str[0] - 0xD800) << 10) | (str[1] - 0xDC00);
|
result.codepoint = ((str[0] - 0xD800) << 10) | (str[1] - 0xDC00) + 0x10000;
|
||||||
result.inc = 2;
|
result.inc = 2;
|
||||||
}
|
}
|
||||||
return(result);
|
return(result);
|
||||||
@@ -1366,7 +1306,7 @@ utf8_encode(U8 *str, U32 codepoint){
|
|||||||
inc = 3;
|
inc = 3;
|
||||||
}
|
}
|
||||||
else if (codepoint <= 0x10FFFF){
|
else if (codepoint <= 0x10FFFF){
|
||||||
str[0] = (bitmask4 << 3) | ((codepoint >> 18) & bitmask3);
|
str[0] = (bitmask4 << 4) | ((codepoint >> 18) & bitmask3);
|
||||||
str[1] = bit8 | ((codepoint >> 12) & bitmask6);
|
str[1] = bit8 | ((codepoint >> 12) & bitmask6);
|
||||||
str[2] = bit8 | ((codepoint >> 6) & bitmask6);
|
str[2] = bit8 | ((codepoint >> 6) & bitmask6);
|
||||||
str[3] = bit8 | ( codepoint & bitmask6);
|
str[3] = bit8 | ( codepoint & bitmask6);
|
||||||
@@ -1418,7 +1358,7 @@ str8_from_16(Arena *arena, String16 in){
|
|||||||
size += utf8_encode(str + size, consume.codepoint);
|
size += utf8_encode(str + size, consume.codepoint);
|
||||||
}
|
}
|
||||||
str[size] = 0;
|
str[size] = 0;
|
||||||
arena_put_back(arena, (cap - size));
|
arena_pop(arena, (cap - size));
|
||||||
return(str8(str, size));
|
return(str8(str, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1435,7 +1375,7 @@ str16_from_8(Arena *arena, String8 in){
|
|||||||
size += utf16_encode(str + size, consume.codepoint);
|
size += utf16_encode(str + size, consume.codepoint);
|
||||||
}
|
}
|
||||||
str[size] = 0;
|
str[size] = 0;
|
||||||
arena_put_back(arena, (cap - size)*2);
|
arena_pop(arena, (cap - size)*2);
|
||||||
return(str16(str, size));
|
return(str16(str, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1450,7 +1390,7 @@ str8_from_32(Arena *arena, String32 in){
|
|||||||
size += utf8_encode(str + size, *ptr);
|
size += utf8_encode(str + size, *ptr);
|
||||||
}
|
}
|
||||||
str[size] = 0;
|
str[size] = 0;
|
||||||
arena_put_back(arena, (cap - size));
|
arena_pop(arena, (cap - size));
|
||||||
return(str8(str, size));
|
return(str8(str, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1468,7 +1408,7 @@ str32_from_8(Arena *arena, String8 in){
|
|||||||
size += 1;
|
size += 1;
|
||||||
}
|
}
|
||||||
str[size] = 0;
|
str[size] = 0;
|
||||||
arena_put_back(arena, (cap - size)*4);
|
arena_pop(arena, (cap - size)*4);
|
||||||
return(str32(str, size));
|
return(str32(str, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1625,6 +1565,102 @@ string_from_elapsed_time(Arena *arena, DateTime dt){
|
|||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Basic Text Indentation
|
||||||
|
|
||||||
|
internal String8
|
||||||
|
indented_from_string(Arena *arena, String8 string)
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(&arena, 1);
|
||||||
|
read_only local_persist U8 indentation_bytes[] = " ";
|
||||||
|
String8List indented_strings = {0};
|
||||||
|
S64 depth = 0;
|
||||||
|
S64 next_depth = 0;
|
||||||
|
U64 line_begin_off = 0;
|
||||||
|
for(U64 off = 0; off <= string.size; off += 1)
|
||||||
|
{
|
||||||
|
U8 byte = off<string.size ? string.str[off] : 0;
|
||||||
|
switch(byte)
|
||||||
|
{
|
||||||
|
default:{}break;
|
||||||
|
case '{':case '[':case '(':{next_depth += 1; next_depth = Max(0, next_depth);}break;
|
||||||
|
case '}':case ']':case ')':{next_depth -= 1; next_depth = Max(0, next_depth); depth = next_depth;}break;
|
||||||
|
case '\n':
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
String8 line = str8_skip_chop_whitespace(str8_substr(string, r1u64(line_begin_off, off)));
|
||||||
|
if(line.size != 0)
|
||||||
|
{
|
||||||
|
str8_list_pushf(scratch.arena, &indented_strings, "%.*s%S\n", (int)depth*2, indentation_bytes, line);
|
||||||
|
}
|
||||||
|
line_begin_off = off+1;
|
||||||
|
depth = next_depth;
|
||||||
|
}break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String8 result = str8_list_join(arena, &indented_strings, 0);
|
||||||
|
scratch_end(scratch);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Text Wrapping
|
||||||
|
|
||||||
|
internal String8List
|
||||||
|
wrapped_lines_from_string(Arena *arena, String8 string, U64 first_line_max_width, U64 max_width, U64 wrap_indent)
|
||||||
|
{
|
||||||
|
String8List list = {0};
|
||||||
|
Rng1U64 line_range = r1u64(0, 0);
|
||||||
|
U64 wrapped_indent_level = 0;
|
||||||
|
static char *spaces = " ";
|
||||||
|
for (U64 idx = 0; idx <= string.size; idx += 1){
|
||||||
|
U8 chr = idx < string.size ? string.str[idx] : 0;
|
||||||
|
if (chr == '\n'){
|
||||||
|
Rng1U64 candidate_line_range = line_range;
|
||||||
|
candidate_line_range.max = idx;
|
||||||
|
// NOTE(nick): when wrapping is interrupted with \n we emit a string without including \n
|
||||||
|
// because later tool_fprint_list inserts separator after each node
|
||||||
|
// except for last node, so don't strip last \n.
|
||||||
|
if (idx + 1 == string.size){
|
||||||
|
candidate_line_range.max += 1;
|
||||||
|
}
|
||||||
|
String8 substr = str8_substr(string, candidate_line_range);
|
||||||
|
str8_list_push(arena, &list, substr);
|
||||||
|
line_range = r1u64(idx+1,idx+1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (char_is_space(chr) || chr == 0){
|
||||||
|
Rng1U64 candidate_line_range = line_range;
|
||||||
|
candidate_line_range.max = idx;
|
||||||
|
String8 substr = str8_substr(string, candidate_line_range);
|
||||||
|
U64 width_this_line = max_width-wrapped_indent_level;
|
||||||
|
if (list.node_count == 0){
|
||||||
|
width_this_line = first_line_max_width;
|
||||||
|
}
|
||||||
|
if (substr.size > width_this_line){
|
||||||
|
String8 line = str8_substr(string, line_range);
|
||||||
|
if (wrapped_indent_level > 0){
|
||||||
|
line = push_str8f(arena, "%.*s%S", wrapped_indent_level, spaces, line);
|
||||||
|
}
|
||||||
|
str8_list_push(arena, &list, line);
|
||||||
|
line_range = r1u64(line_range.max+1, candidate_line_range.max);
|
||||||
|
wrapped_indent_level = ClampTop(64, wrap_indent);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
line_range = candidate_line_range;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (line_range.min < string.size && line_range.max > line_range.min){
|
||||||
|
String8 line = str8_substr(string, line_range);
|
||||||
|
if (wrapped_indent_level > 0){
|
||||||
|
line = push_str8f(arena, "%.*s%S", wrapped_indent_level, spaces, line);
|
||||||
|
}
|
||||||
|
str8_list_push(arena, &list, line);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: String <-> Color
|
//~ rjf: String <-> Color
|
||||||
|
|
||||||
@@ -1657,6 +1693,67 @@ rgba_from_hex_string_4f32(String8 hex_string)
|
|||||||
return rgba;
|
return rgba;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: String Fuzzy Matching
|
||||||
|
|
||||||
|
internal FuzzyMatchRangeList
|
||||||
|
fuzzy_match_find(Arena *arena, String8 needle, String8 haystack)
|
||||||
|
{
|
||||||
|
FuzzyMatchRangeList result = {0};
|
||||||
|
Temp scratch = scratch_begin(&arena, 1);
|
||||||
|
String8List needles = str8_split(scratch.arena, needle, (U8*)" ", 1, 0);
|
||||||
|
result.needle_part_count = needles.node_count;
|
||||||
|
for(String8Node *needle_n = needles.first; needle_n != 0; needle_n = needle_n->next)
|
||||||
|
{
|
||||||
|
U64 find_pos = 0;
|
||||||
|
for(;find_pos < haystack.size;)
|
||||||
|
{
|
||||||
|
find_pos = str8_find_needle(haystack, find_pos, needle_n->string, StringMatchFlag_CaseInsensitive);
|
||||||
|
B32 is_in_gathered_ranges = 0;
|
||||||
|
for(FuzzyMatchRangeNode *n = result.first; n != 0; n = n->next)
|
||||||
|
{
|
||||||
|
if(n->range.min <= find_pos && find_pos < n->range.max)
|
||||||
|
{
|
||||||
|
is_in_gathered_ranges = 1;
|
||||||
|
find_pos = n->range.max;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!is_in_gathered_ranges)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(find_pos < haystack.size)
|
||||||
|
{
|
||||||
|
Rng1U64 range = r1u64(find_pos, find_pos+needle_n->string.size);
|
||||||
|
FuzzyMatchRangeNode *n = push_array(arena, FuzzyMatchRangeNode, 1);
|
||||||
|
n->range = range;
|
||||||
|
SLLQueuePush(result.first, result.last, n);
|
||||||
|
result.count += 1;
|
||||||
|
result.total_dim += dim_1u64(range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scratch_end(scratch);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal FuzzyMatchRangeList
|
||||||
|
fuzzy_match_range_list_copy(Arena *arena, FuzzyMatchRangeList *src)
|
||||||
|
{
|
||||||
|
FuzzyMatchRangeList dst = {0};
|
||||||
|
for(FuzzyMatchRangeNode *src_n = src->first; src_n != 0; src_n = src_n->next)
|
||||||
|
{
|
||||||
|
FuzzyMatchRangeNode *dst_n = push_array(arena, FuzzyMatchRangeNode, 1);
|
||||||
|
SLLQueuePush(dst.first, dst.last, dst_n);
|
||||||
|
dst_n->range = src_n->range;
|
||||||
|
}
|
||||||
|
dst.count = src->count;
|
||||||
|
dst.needle_part_count = src->needle_part_count;
|
||||||
|
dst.total_dim = src->total_dim;
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ NOTE(allen): Serialization Helpers
|
//~ NOTE(allen): Serialization Helpers
|
||||||
|
|
||||||
+40
-10
@@ -1,8 +1,8 @@
|
|||||||
// Copyright (c) 2024 Epic Games Tools
|
// Copyright (c) 2024 Epic Games Tools
|
||||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
#ifndef BASE_STRING_H
|
#ifndef BASE_STRINGS_H
|
||||||
#define BASE_STRING_H
|
#define BASE_STRINGS_H
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Third Party Includes
|
//~ rjf: Third Party Includes
|
||||||
@@ -63,7 +63,7 @@ struct String8List
|
|||||||
typedef struct String8Array String8Array;
|
typedef struct String8Array String8Array;
|
||||||
struct String8Array
|
struct String8Array
|
||||||
{
|
{
|
||||||
String8 *strings;
|
String8 *v;
|
||||||
U64 count;
|
U64 count;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -128,6 +128,26 @@ struct UnicodeDecode
|
|||||||
U32 codepoint;
|
U32 codepoint;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: String Fuzzy Matching Types
|
||||||
|
|
||||||
|
typedef struct FuzzyMatchRangeNode FuzzyMatchRangeNode;
|
||||||
|
struct FuzzyMatchRangeNode
|
||||||
|
{
|
||||||
|
FuzzyMatchRangeNode *next;
|
||||||
|
Rng1U64 range;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct FuzzyMatchRangeList FuzzyMatchRangeList;
|
||||||
|
struct FuzzyMatchRangeList
|
||||||
|
{
|
||||||
|
FuzzyMatchRangeNode *first;
|
||||||
|
FuzzyMatchRangeNode *last;
|
||||||
|
U64 count;
|
||||||
|
U64 needle_part_count;
|
||||||
|
U64 total_dim;
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Character Classification & Conversion Functions
|
//~ rjf: Character Classification & Conversion Functions
|
||||||
|
|
||||||
@@ -216,12 +236,6 @@ internal S64 s64_from_str8(String8 string, U32 radix);
|
|||||||
internal B32 try_u64_from_str8_c_rules(String8 string, U64 *x);
|
internal B32 try_u64_from_str8_c_rules(String8 string, U64 *x);
|
||||||
internal B32 try_s64_from_str8_c_rules(String8 string, S64 *x);
|
internal B32 try_s64_from_str8_c_rules(String8 string, S64 *x);
|
||||||
|
|
||||||
//- rjf: string -> integer (base64 & base16)
|
|
||||||
internal U64 base64_size_from_data_size(U64 size_in_bytes);
|
|
||||||
internal U64 base64_from_data(U8 *dst, U8 *src, U64 src_size);
|
|
||||||
internal U64 base16_size_from_data_size(U64 size_in_bytes);
|
|
||||||
internal U64 base16_from_data(U8 *dst, U8 *src, U64 src_size);
|
|
||||||
|
|
||||||
//- rjf: integer -> string
|
//- rjf: integer -> string
|
||||||
internal String8 str8_from_memory_size(Arena *arena, U64 z);
|
internal String8 str8_from_memory_size(Arena *arena, U64 z);
|
||||||
internal String8 str8_from_u64(Arena *arena, U64 u64, U32 radix, U8 min_digits, U8 digit_group_separator);
|
internal String8 str8_from_u64(Arena *arena, U64 u64, U32 radix, U8 min_digits, U8 digit_group_separator);
|
||||||
@@ -312,12 +326,28 @@ internal String8 push_date_time_string(Arena *arena, DateTime *date_time);
|
|||||||
internal String8 push_file_name_date_time_string(Arena *arena, DateTime *date_time);
|
internal String8 push_file_name_date_time_string(Arena *arena, DateTime *date_time);
|
||||||
internal String8 string_from_elapsed_time(Arena *arena, DateTime dt);
|
internal String8 string_from_elapsed_time(Arena *arena, DateTime dt);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Basic Text Indentation
|
||||||
|
|
||||||
|
internal String8 indented_from_string(Arena *arena, String8 string);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Text Wrapping
|
||||||
|
|
||||||
|
internal String8List wrapped_lines_from_string(Arena *arena, String8 string, U64 first_line_max_width, U64 max_width, U64 wrap_indent);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: String <-> Color
|
//~ rjf: String <-> Color
|
||||||
|
|
||||||
internal String8 hex_string_from_rgba_4f32(Arena *arena, Vec4F32 rgba);
|
internal String8 hex_string_from_rgba_4f32(Arena *arena, Vec4F32 rgba);
|
||||||
internal Vec4F32 rgba_from_hex_string_4f32(String8 hex_string);
|
internal Vec4F32 rgba_from_hex_string_4f32(String8 hex_string);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: String Fuzzy Matching
|
||||||
|
|
||||||
|
internal FuzzyMatchRangeList fuzzy_match_find(Arena *arena, String8 needle, String8 haystack);
|
||||||
|
internal FuzzyMatchRangeList fuzzy_match_range_list_copy(Arena *arena, FuzzyMatchRangeList *src);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ NOTE(allen): Serialization Helpers
|
//~ NOTE(allen): Serialization Helpers
|
||||||
|
|
||||||
@@ -348,4 +378,4 @@ internal U64 str8_deserial_read_block(String8 string, U64 off, U64 size, Stri
|
|||||||
#define str8_deserial_read_array(string, off, ptr, count) str8_deserial_read((string), (off), (ptr), sizeof(*(ptr))*(count), sizeof(*(ptr)))
|
#define str8_deserial_read_array(string, off, ptr, count) str8_deserial_read((string), (off), (ptr), sizeof(*(ptr))*(count), sizeof(*(ptr)))
|
||||||
#define str8_deserial_read_struct(string, off, ptr) str8_deserial_read((string), (off), (ptr), sizeof(*(ptr)), sizeof(*(ptr)))
|
#define str8_deserial_read_struct(string, off, ptr) str8_deserial_read((string), (off), (ptr), sizeof(*(ptr)), sizeof(*(ptr)))
|
||||||
|
|
||||||
#endif // BASE_STRING_H
|
#endif // BASE_STRINGS_H
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
// NOTE(allen): Thread Context Functions
|
// NOTE(allen): Thread Context Functions
|
||||||
|
|
||||||
C_LINKAGE thread_static TCTX* tctx_thread_local;
|
C_LINKAGE thread_static TCTX* tctx_thread_local;
|
||||||
#if !SUPPLEMENT_UNIT
|
#if !BUILD_SUPPLEMENTARY_UNIT
|
||||||
C_LINKAGE thread_static TCTX* tctx_thread_local = 0;
|
C_LINKAGE thread_static TCTX* tctx_thread_local = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -19,6 +19,15 @@ tctx_init_and_equip(TCTX *tctx){
|
|||||||
tctx_thread_local = tctx;
|
tctx_thread_local = tctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
tctx_release(void)
|
||||||
|
{
|
||||||
|
for(U64 i = 0; i < ArrayCount(tctx_thread_local->arenas); i += 1)
|
||||||
|
{
|
||||||
|
arena_release(tctx_thread_local->arenas[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal TCTX*
|
internal TCTX*
|
||||||
tctx_get_equipped(void){
|
tctx_get_equipped(void){
|
||||||
return(tctx_thread_local);
|
return(tctx_thread_local);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ struct TCTX
|
|||||||
// NOTE(allen): Thread Context Functions
|
// NOTE(allen): Thread Context Functions
|
||||||
|
|
||||||
internal void tctx_init_and_equip(TCTX *tctx);
|
internal void tctx_init_and_equip(TCTX *tctx);
|
||||||
|
internal void tctx_release(void);
|
||||||
internal TCTX* tctx_get_equipped(void);
|
internal TCTX* tctx_get_equipped(void);
|
||||||
|
|
||||||
internal Arena* tctx_get_scratch(Arena **conflicts, U64 count);
|
internal Arena* tctx_get_scratch(Arena **conflicts, U64 count);
|
||||||
@@ -37,4 +38,4 @@ internal void tctx_read_srcloc(char **file_name, U64 *line_number);
|
|||||||
#define scratch_begin(conflicts, count) temp_begin(tctx_get_scratch((conflicts), (count)))
|
#define scratch_begin(conflicts, count) temp_begin(tctx_get_scratch((conflicts), (count)))
|
||||||
#define scratch_end(scratch) temp_end(scratch)
|
#define scratch_end(scratch) temp_end(scratch)
|
||||||
|
|
||||||
#endif //BASE_THREAD_CONTEXT_H
|
#endif // BASE_THREAD_CONTEXT_H
|
||||||
|
|||||||
@@ -24,17 +24,14 @@
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Entry Point
|
//~ rjf: Entry Point
|
||||||
|
|
||||||
int main(int argument_count, char **arguments)
|
internal void
|
||||||
|
entry_point(CmdLine *cmdline)
|
||||||
{
|
{
|
||||||
local_persist TCTX main_tctx = {0};
|
|
||||||
tctx_init_and_equip(&main_tctx);
|
|
||||||
os_init(argument_count, arguments);
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- rjf: set up state
|
//- rjf: set up state
|
||||||
//
|
//
|
||||||
MG_MsgList msgs = {0};
|
MG_MsgList msgs = {0};
|
||||||
mg_arena = arena_alloc__sized(GB(64), MB(64));
|
mg_arena = arena_alloc(.reserve_size = GB(64), .commit_size = MB(64));
|
||||||
mg_state = push_array(mg_arena, MG_State, 1);
|
mg_state = push_array(mg_arena, MG_State, 1);
|
||||||
mg_state->slots_count = 256;
|
mg_state->slots_count = 256;
|
||||||
mg_state->slots = push_array(mg_arena, MG_LayerSlot, mg_state->slots_count);
|
mg_state->slots = push_array(mg_arena, MG_LayerSlot, mg_state->slots_count);
|
||||||
@@ -42,7 +39,7 @@ int main(int argument_count, char **arguments)
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- rjf: extract paths
|
//- rjf: extract paths
|
||||||
//
|
//
|
||||||
String8 build_dir_path = os_string_from_system_path(mg_arena, OS_SystemPath_Binary);
|
String8 build_dir_path = os_get_process_info()->binary_path;
|
||||||
String8 project_dir_path = str8_chop_last_slash(build_dir_path);
|
String8 project_dir_path = str8_chop_last_slash(build_dir_path);
|
||||||
String8 code_dir_path = push_str8f(mg_arena, "%S/src", project_dir_path);
|
String8 code_dir_path = push_str8f(mg_arena, "%S/src", project_dir_path);
|
||||||
|
|
||||||
@@ -656,6 +653,4 @@ int main(int argument_count, char **arguments)
|
|||||||
MG_Msg *msg = &n->v;
|
MG_Msg *msg = &n->v;
|
||||||
fprintf(stderr, "%.*s: %.*s: %.*s\n", str8_varg(msg->location), str8_varg(msg->kind), str8_varg(msg->msg));
|
fprintf(stderr, "%.*s: %.*s: %.*s\n", str8_varg(msg->location), str8_varg(msg->kind), str8_varg(msg->msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,14 @@
|
|||||||
// Copyright (c) 2024 Epic Games Tools
|
// Copyright (c) 2024 Epic Games Tools
|
||||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
#ifndef LINUX_H
|
#ifndef OS_CORE_LINUX_H
|
||||||
#define LINUX_H
|
#define OS_CORE_LINUX_H
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ NOTE(allen): Get all these linux includes
|
//~ rjf: Includes
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <features.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@@ -22,67 +24,111 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <sys/sysinfo.h>
|
#include <sys/sysinfo.h>
|
||||||
|
#include <sys/random.h>
|
||||||
|
|
||||||
|
int pthread_setname_np(pthread_t thread, const char *name);
|
||||||
|
int pthread_getname_np(pthread_t thread, char *name, size_t size);
|
||||||
|
|
||||||
|
typedef struct tm tm;
|
||||||
|
typedef struct timespec timespec;
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ NOTE(allen): File Iterator
|
//~ rjf: File Iterator
|
||||||
|
|
||||||
struct LNX_FileIter{
|
typedef struct OS_LNX_FileIter OS_LNX_FileIter;
|
||||||
int fd;
|
struct OS_LNX_FileIter
|
||||||
|
{
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
|
struct dirent *dp;
|
||||||
|
String8 path;
|
||||||
};
|
};
|
||||||
StaticAssert(sizeof(Member(OS_FileIter, memory)) >= sizeof(LNX_FileIter), file_iter_memory_size);
|
StaticAssert(sizeof(Member(OS_FileIter, memory)) >= sizeof(OS_LNX_FileIter), os_lnx_file_iter_size_check);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ NOTE(allen): Threading Entities
|
//~ rjf: Safe Call Handler Chain
|
||||||
|
|
||||||
enum LNX_EntityKind{
|
typedef struct OS_LNX_SafeCallChain OS_LNX_SafeCallChain;
|
||||||
LNX_EntityKind_Null,
|
struct OS_LNX_SafeCallChain
|
||||||
LNX_EntityKind_Thread,
|
{
|
||||||
LNX_EntityKind_Mutex,
|
OS_LNX_SafeCallChain *next;
|
||||||
LNX_EntityKind_ConditionVariable,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LNX_Entity{
|
|
||||||
LNX_Entity *next;
|
|
||||||
LNX_EntityKind kind;
|
|
||||||
volatile U32 reference_mask;
|
|
||||||
union{
|
|
||||||
struct{
|
|
||||||
OS_ThreadFunctionType *func;
|
|
||||||
void *ptr;
|
|
||||||
pthread_t handle;
|
|
||||||
} thread;
|
|
||||||
pthread_mutex_t mutex;
|
|
||||||
pthread_cond_t cond;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ NOTE(allen): Safe Call Chain
|
|
||||||
|
|
||||||
struct LNX_SafeCallChain{
|
|
||||||
LNX_SafeCallChain *next;
|
|
||||||
OS_ThreadFunctionType *fail_handler;
|
OS_ThreadFunctionType *fail_handler;
|
||||||
void *ptr;
|
void *ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ NOTE(allen): Helpers
|
//~ rjf: Entities
|
||||||
|
|
||||||
internal B32 lnx_write_list_to_file_descriptor(int fd, String8List list);
|
typedef enum OS_LNX_EntityKind
|
||||||
|
{
|
||||||
|
OS_LNX_EntityKind_Thread,
|
||||||
|
OS_LNX_EntityKind_Mutex,
|
||||||
|
OS_LNX_EntityKind_RWMutex,
|
||||||
|
OS_LNX_EntityKind_ConditionVariable,
|
||||||
|
}
|
||||||
|
OS_LNX_EntityKind;
|
||||||
|
|
||||||
internal void lnx_date_time_from_tm(DateTime *out, struct tm *in, U32 msec);
|
typedef struct OS_LNX_Entity OS_LNX_Entity;
|
||||||
internal void lnx_tm_from_date_time(struct tm *out, DateTime *in);
|
struct OS_LNX_Entity
|
||||||
internal void lnx_dense_time_from_timespec(DenseTime *out, struct timespec *in);
|
{
|
||||||
internal void lnx_file_properties_from_stat(FileProperties *out, struct stat *in);
|
OS_LNX_Entity *next;
|
||||||
|
OS_LNX_EntityKind kind;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
pthread_t handle;
|
||||||
|
OS_ThreadFunctionType *func;
|
||||||
|
void *ptr;
|
||||||
|
} thread;
|
||||||
|
pthread_mutex_t mutex_handle;
|
||||||
|
pthread_rwlock_t rwmutex_handle;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
pthread_cond_t cond_handle;
|
||||||
|
pthread_mutex_t rwlock_mutex_handle;
|
||||||
|
} cv;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
internal String8 lnx_string_from_signal(int signum);
|
////////////////////////////////
|
||||||
internal String8 lnx_string_from_errno(int error_number);
|
//~ rjf: State
|
||||||
|
|
||||||
internal LNX_Entity* lnx_alloc_entity(LNX_EntityKind kind);
|
typedef struct OS_LNX_State OS_LNX_State;
|
||||||
internal void lnx_free_entity(LNX_Entity *entity);
|
struct OS_LNX_State
|
||||||
internal void* lnx_thread_base(void *ptr);
|
{
|
||||||
|
Arena *arena;
|
||||||
|
OS_SystemInfo system_info;
|
||||||
|
OS_ProcessInfo process_info;
|
||||||
|
pthread_mutex_t entity_mutex;
|
||||||
|
Arena *entity_arena;
|
||||||
|
OS_LNX_Entity *entity_free;
|
||||||
|
};
|
||||||
|
|
||||||
internal void lnx_safe_call_sig_handler(int);
|
////////////////////////////////
|
||||||
|
//~ rjf: Globals
|
||||||
|
|
||||||
#endif //LINUX_H
|
global OS_LNX_State os_lnx_state = {0};
|
||||||
|
thread_static OS_LNX_SafeCallChain *os_lnx_safe_call_chain = 0;
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Helpers
|
||||||
|
|
||||||
|
internal DateTime os_lnx_date_time_from_tm(tm in, U32 msec);
|
||||||
|
internal tm os_lnx_tm_from_date_time(DateTime dt);
|
||||||
|
internal timespec os_lnx_timespec_from_date_time(DateTime dt);
|
||||||
|
internal DenseTime os_lnx_dense_time_from_timespec(timespec in);
|
||||||
|
internal FileProperties os_lnx_file_properties_from_stat(struct stat *s);
|
||||||
|
internal void os_lnx_safe_call_sig_handler(int x);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Entities
|
||||||
|
|
||||||
|
internal OS_LNX_Entity *os_lnx_entity_alloc(OS_LNX_EntityKind kind);
|
||||||
|
internal void os_lnx_entity_release(OS_LNX_Entity *entity);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Thread Entry Point
|
||||||
|
|
||||||
|
internal void *os_lnx_thread_entry_point(void *ptr);
|
||||||
|
|
||||||
|
#endif // OS_CORE_LINUX_H
|
||||||
|
|||||||
@@ -40,18 +40,6 @@ os_handle_array_from_list(Arena *arena, OS_HandleList *list)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ rjf: System Path Helper (Helper, Implemented Once)
|
|
||||||
|
|
||||||
internal String8
|
|
||||||
os_string_from_system_path(Arena *arena, OS_SystemPath path)
|
|
||||||
{
|
|
||||||
String8List strs = {0};
|
|
||||||
os_string_list_from_system_path(arena, path, &strs);
|
|
||||||
String8 result = str8_list_first(&strs);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Command Line Argc/Argv Helper (Helper, Implemented Once)
|
//~ rjf: Command Line Argc/Argv Helper (Helper, Implemented Once)
|
||||||
|
|
||||||
@@ -67,26 +55,13 @@ os_string_list_from_argcv(Arena *arena, int argc, char **argv)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ rjf: Process Helpers (Helper, Implemented Once)
|
|
||||||
|
|
||||||
internal void
|
|
||||||
os_relaunch_self(void){
|
|
||||||
Temp scratch = scratch_begin(0, 0);
|
|
||||||
OS_LaunchOptions opts = {0};
|
|
||||||
opts.cmd_line = os_get_command_line_arguments();
|
|
||||||
opts.path = os_string_from_system_path(scratch.arena, OS_SystemPath_Initial);
|
|
||||||
os_launch_process(&opts, 0);
|
|
||||||
scratch_end(scratch);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Filesystem Helpers (Helpers, Implemented Once)
|
//~ rjf: Filesystem Helpers (Helpers, Implemented Once)
|
||||||
|
|
||||||
internal String8
|
internal String8
|
||||||
os_data_from_file_path(Arena *arena, String8 path)
|
os_data_from_file_path(Arena *arena, String8 path)
|
||||||
{
|
{
|
||||||
OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_Shared, path);
|
OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead, path);
|
||||||
FileProperties props = os_properties_from_file(file);
|
FileProperties props = os_properties_from_file(file);
|
||||||
String8 data = os_string_from_file_range(arena, file, r1u64(0, props.size));
|
String8 data = os_string_from_file_range(arena, file, r1u64(0, props.size));
|
||||||
os_file_close(file);
|
os_file_close(file);
|
||||||
@@ -126,19 +101,28 @@ os_write_data_list_to_file_path(String8 path, String8List list)
|
|||||||
return good;
|
return good;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal FileProperties
|
internal B32
|
||||||
os_properties_from_file_path(String8 path)
|
os_append_data_to_file_path(String8 path, String8 data)
|
||||||
{
|
{
|
||||||
OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_Shared, path);
|
B32 good = 0;
|
||||||
FileProperties props = os_properties_from_file(file);
|
if(data.size != 0)
|
||||||
os_file_close(file);
|
{
|
||||||
return props;
|
OS_Handle file = os_file_open(OS_AccessFlag_Write|OS_AccessFlag_Append, path);
|
||||||
|
if(!os_handle_match(file, os_handle_zero()))
|
||||||
|
{
|
||||||
|
good = 1;
|
||||||
|
U64 pos = os_properties_from_file(file).size;
|
||||||
|
os_file_write(file, r1u64(pos, pos+data.size), data.str);
|
||||||
|
os_file_close(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return good;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal OS_FileID
|
internal OS_FileID
|
||||||
os_id_from_file_path(String8 path)
|
os_id_from_file_path(String8 path)
|
||||||
{
|
{
|
||||||
OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_Shared, path);
|
OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead, path);
|
||||||
OS_FileID id = os_id_from_file(file);
|
OS_FileID id = os_id_from_file(file);
|
||||||
os_file_close(file);
|
os_file_close(file);
|
||||||
return id;
|
return id;
|
||||||
@@ -168,83 +152,7 @@ os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range)
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Synchronization Primitive Helpers (Helpers, Implemented Once)
|
//~ rjf: GUID Helpers (Helpers, Implemented Once)
|
||||||
|
|
||||||
internal void
|
|
||||||
os_mutex_take(OS_Handle mutex){
|
|
||||||
ProfBeginLockWait((void *)(mutex.u64[0]), "take mutex");
|
|
||||||
os_mutex_take_(mutex);
|
|
||||||
ProfEndLockWait();
|
|
||||||
ProfLockTake((void *)(mutex.u64[0]), "take mutex");
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void
|
|
||||||
os_mutex_drop(OS_Handle mutex){
|
|
||||||
os_mutex_drop_(mutex);
|
|
||||||
ProfLockDrop((void *)(mutex.u64[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void
|
|
||||||
os_rw_mutex_take_r(OS_Handle rw_mutex){
|
|
||||||
ProfBeginLockWait((void *)(rw_mutex.u64[0]), "rw mutex take r");
|
|
||||||
os_rw_mutex_take_r_(rw_mutex);
|
|
||||||
ProfEndLockWait();
|
|
||||||
ProfLockTake((void *)(rw_mutex.u64[0]), "rw mutex take r");
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void
|
|
||||||
os_rw_mutex_drop_r(OS_Handle rw_mutex){
|
|
||||||
os_rw_mutex_drop_r_(rw_mutex);
|
|
||||||
ProfLockDrop((void *)(rw_mutex.u64[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void
|
|
||||||
os_rw_mutex_take_w(OS_Handle rw_mutex){
|
|
||||||
ProfBeginLockWait((void *)(rw_mutex.u64[0]), "rw mutex take rw");
|
|
||||||
os_rw_mutex_take_w_(rw_mutex);
|
|
||||||
ProfEndLockWait();
|
|
||||||
ProfLockTake((void *)(rw_mutex.u64[0]), "rw mutex take rw");
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void
|
|
||||||
os_rw_mutex_drop_w(OS_Handle rw_mutex){
|
|
||||||
os_rw_mutex_drop_w_(rw_mutex);
|
|
||||||
ProfLockDrop((void *)(rw_mutex.u64[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
internal B32
|
|
||||||
os_condition_variable_wait(OS_Handle cv, OS_Handle mutex, U64 endt_us){
|
|
||||||
ProfLockDrop((void *)(mutex.u64[0]));
|
|
||||||
B32 result = os_condition_variable_wait_(cv, mutex, endt_us);
|
|
||||||
ProfLockTake((void *)(mutex.u64[0]), "wait cv");
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal B32
|
|
||||||
os_condition_variable_wait_rw_r(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us){
|
|
||||||
ProfLockDrop((void *)(mutex_rw.u64[0]));
|
|
||||||
B32 result = os_condition_variable_wait_rw_r_(cv, mutex_rw, endt_us);
|
|
||||||
ProfLockTake((void *)(mutex_rw.u64[0]), "wait cv rw r");
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal B32
|
|
||||||
os_condition_variable_wait_rw_w(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us){
|
|
||||||
ProfLockDrop((void *)(mutex_rw.u64[0]));
|
|
||||||
B32 result = os_condition_variable_wait_rw_w_(cv, mutex_rw, endt_us);
|
|
||||||
ProfLockTake((void *)(mutex_rw.u64[0]), "wait cv rw w");
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void
|
|
||||||
os_condition_variable_signal(OS_Handle cv){
|
|
||||||
os_condition_variable_signal_(cv);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void
|
|
||||||
os_condition_variable_broadcast(OS_Handle cv){
|
|
||||||
os_condition_variable_broadcast_(cv);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal String8
|
internal String8
|
||||||
os_string_from_guid(Arena *arena, OS_Guid guid)
|
os_string_from_guid(Arena *arena, OS_Guid guid)
|
||||||
|
|||||||
@@ -4,20 +4,49 @@
|
|||||||
#ifndef OS_CORE_H
|
#ifndef OS_CORE_H
|
||||||
#define OS_CORE_H
|
#define OS_CORE_H
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: System Info
|
||||||
|
|
||||||
|
typedef struct OS_SystemInfo OS_SystemInfo;
|
||||||
|
struct OS_SystemInfo
|
||||||
|
{
|
||||||
|
U32 logical_processor_count;
|
||||||
|
U64 page_size;
|
||||||
|
U64 large_page_size;
|
||||||
|
U64 allocation_granularity;
|
||||||
|
String8 machine_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Process Info
|
||||||
|
|
||||||
|
typedef struct OS_ProcessInfo OS_ProcessInfo;
|
||||||
|
struct OS_ProcessInfo
|
||||||
|
{
|
||||||
|
U32 pid;
|
||||||
|
String8 binary_path;
|
||||||
|
String8 initial_path;
|
||||||
|
String8 user_program_data_path;
|
||||||
|
String8List module_load_paths;
|
||||||
|
String8List environment;
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Access Flags
|
//~ rjf: Access Flags
|
||||||
|
|
||||||
typedef U32 OS_AccessFlags;
|
typedef U32 OS_AccessFlags;
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
OS_AccessFlag_Read = (1<<0),
|
OS_AccessFlag_Read = (1<<0),
|
||||||
OS_AccessFlag_Write = (1<<1),
|
OS_AccessFlag_Write = (1<<1),
|
||||||
OS_AccessFlag_Execute = (1<<2),
|
OS_AccessFlag_Execute = (1<<2),
|
||||||
OS_AccessFlag_Shared = (1<<3),
|
OS_AccessFlag_Append = (1<<3),
|
||||||
|
OS_AccessFlag_ShareRead = (1<<4),
|
||||||
|
OS_AccessFlag_ShareWrite = (1<<5),
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ allen: Files
|
//~ rjf: Files
|
||||||
|
|
||||||
typedef U32 OS_FileIterFlags;
|
typedef U32 OS_FileIterFlags;
|
||||||
enum
|
enum
|
||||||
@@ -32,7 +61,7 @@ typedef struct OS_FileIter OS_FileIter;
|
|||||||
struct OS_FileIter
|
struct OS_FileIter
|
||||||
{
|
{
|
||||||
OS_FileIterFlags flags;
|
OS_FileIterFlags flags;
|
||||||
U8 memory[600];
|
U8 memory[800];
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct OS_FileInfo OS_FileInfo;
|
typedef struct OS_FileInfo OS_FileInfo;
|
||||||
@@ -50,40 +79,10 @@ struct OS_FileID
|
|||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: System Paths
|
//~ rjf: Process Launch Parameters
|
||||||
|
|
||||||
typedef enum OS_SystemPath
|
typedef struct OS_ProcessLaunchParams OS_ProcessLaunchParams;
|
||||||
{
|
struct OS_ProcessLaunchParams
|
||||||
OS_SystemPath_Binary,
|
|
||||||
OS_SystemPath_Initial,
|
|
||||||
OS_SystemPath_Current,
|
|
||||||
OS_SystemPath_UserProgramData,
|
|
||||||
OS_SystemPath_ModuleLoad,
|
|
||||||
}
|
|
||||||
OS_SystemPath;
|
|
||||||
|
|
||||||
typedef enum OS_PathFromUserKind
|
|
||||||
{
|
|
||||||
OS_PathFromUserKind_Save,
|
|
||||||
OS_PathFromUserKind_Load,
|
|
||||||
}
|
|
||||||
OS_PathFromUserKind;
|
|
||||||
|
|
||||||
typedef struct OS_PathFromUser OS_PathFromUser;
|
|
||||||
struct OS_PathFromUser
|
|
||||||
{
|
|
||||||
OS_PathFromUserKind kind;
|
|
||||||
String8 path;
|
|
||||||
U64 filter_count;
|
|
||||||
String8 *filter_extensions;
|
|
||||||
String8 *filter_names;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ allen: Launch Input
|
|
||||||
|
|
||||||
typedef struct OS_LaunchOptions OS_LaunchOptions;
|
|
||||||
struct OS_LaunchOptions
|
|
||||||
{
|
{
|
||||||
String8List cmd_line;
|
String8List cmd_line;
|
||||||
String8 path;
|
String8 path;
|
||||||
@@ -124,21 +123,16 @@ struct OS_HandleArray
|
|||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Time
|
//~ rjf: Globally Unique IDs
|
||||||
|
|
||||||
#define OS_UNIX_TIME_MAX max_U32
|
typedef struct OS_Guid OS_Guid;
|
||||||
typedef U32 OS_UnixTime;
|
struct OS_Guid
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
// Global Unique ID
|
|
||||||
|
|
||||||
typedef struct OS_Guid
|
|
||||||
{
|
{
|
||||||
U32 data1;
|
U32 data1;
|
||||||
U16 data2;
|
U16 data2;
|
||||||
U16 data3;
|
U16 data3;
|
||||||
U8 data4[8];
|
U8 data4[8];
|
||||||
} OS_Guid;
|
};
|
||||||
StaticAssert(sizeof(OS_Guid) == 16, os_guid_check);
|
StaticAssert(sizeof(OS_Guid) == 16, os_guid_check);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
@@ -154,95 +148,57 @@ internal B32 os_handle_match(OS_Handle a, OS_Handle b);
|
|||||||
internal void os_handle_list_push(Arena *arena, OS_HandleList *handles, OS_Handle handle);
|
internal void os_handle_list_push(Arena *arena, OS_HandleList *handles, OS_Handle handle);
|
||||||
internal OS_HandleArray os_handle_array_from_list(Arena *arena, OS_HandleList *list);
|
internal OS_HandleArray os_handle_array_from_list(Arena *arena, OS_HandleList *list);
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ rjf: System Path Helper (Helper, Implemented Once)
|
|
||||||
|
|
||||||
internal String8 os_string_from_system_path(Arena *arena, OS_SystemPath path);
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Command Line Argc/Argv Helper (Helper, Implemented Once)
|
//~ rjf: Command Line Argc/Argv Helper (Helper, Implemented Once)
|
||||||
|
|
||||||
internal String8List os_string_list_from_argcv(Arena *arena, int argc, char **argv);
|
internal String8List os_string_list_from_argcv(Arena *arena, int argc, char **argv);
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ rjf: Process Helpers (Helper, Implemented Once)
|
|
||||||
|
|
||||||
internal void os_relaunch_self(void);
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Filesystem Helpers (Helpers, Implemented Once)
|
//~ rjf: Filesystem Helpers (Helpers, Implemented Once)
|
||||||
|
|
||||||
internal String8 os_data_from_file_path(Arena *arena, String8 path);
|
internal String8 os_data_from_file_path(Arena *arena, String8 path);
|
||||||
internal B32 os_write_data_to_file_path(String8 path, String8 data);
|
internal B32 os_write_data_to_file_path(String8 path, String8 data);
|
||||||
internal B32 os_write_data_list_to_file_path(String8 path, String8List list);
|
internal B32 os_write_data_list_to_file_path(String8 path, String8List list);
|
||||||
internal FileProperties os_properties_from_file_path(String8 path);
|
internal B32 os_append_data_to_file_path(String8 path, String8 data);
|
||||||
internal OS_FileID os_id_from_file_path(String8 path);
|
internal OS_FileID os_id_from_file_path(String8 path);
|
||||||
internal S64 os_file_id_compare(OS_FileID a, OS_FileID b);
|
internal S64 os_file_id_compare(OS_FileID a, OS_FileID b);
|
||||||
internal String8 os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range);
|
internal String8 os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Synchronization Primitive Helpers (Helpers, Implemented Once)
|
//~ rjf: GUID Helpers (Helpers, Implemented Once)
|
||||||
|
|
||||||
internal void os_mutex_take(OS_Handle mutex);
|
internal String8 os_string_from_guid(Arena *arena, OS_Guid guid);
|
||||||
internal void os_mutex_drop(OS_Handle mutex);
|
|
||||||
internal void os_rw_mutex_take_r(OS_Handle rw_mutex);
|
|
||||||
internal void os_rw_mutex_drop_r(OS_Handle rw_mutex);
|
|
||||||
internal void os_rw_mutex_take_w(OS_Handle rw_mutex);
|
|
||||||
internal void os_rw_mutex_drop_w(OS_Handle rw_mutex);
|
|
||||||
// returns false on timeout, true on signal, (max_wait_ms = max_U64) -> no timeout
|
|
||||||
internal B32 os_condition_variable_wait(OS_Handle cv, OS_Handle mutex, U64 endt_us);
|
|
||||||
internal B32 os_condition_variable_wait_rw_r(OS_Handle cv, OS_Handle rw_mutex, U64 endt_us);
|
|
||||||
internal B32 os_condition_variable_wait_rw_w(OS_Handle cv, OS_Handle rw_mutex, U64 endt_us);
|
|
||||||
internal void os_condition_variable_signal(OS_Handle cv);
|
|
||||||
internal void os_condition_variable_broadcast(OS_Handle cv);
|
|
||||||
|
|
||||||
#define OS_MutexScope(mutex) DeferLoop(os_mutex_take(mutex), os_mutex_drop(mutex))
|
|
||||||
#define OS_MutexScopeR(mutex) DeferLoop(os_rw_mutex_take_r(mutex), os_rw_mutex_drop_r(mutex))
|
|
||||||
#define OS_MutexScopeW(mutex) DeferLoop(os_rw_mutex_take_w(mutex), os_rw_mutex_drop_w(mutex))
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: @os_hooks Main Initialization API (Implemented Per-OS)
|
//~ rjf: @os_hooks System/Process Info (Implemented Per-OS)
|
||||||
|
|
||||||
internal void os_init(int argc, char **argv);
|
internal OS_SystemInfo *os_get_system_info(void);
|
||||||
|
internal OS_ProcessInfo *os_get_process_info(void);
|
||||||
|
internal String8 os_get_current_path(Arena *arena);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: @os_hooks Memory Allocation (Implemented Per-OS)
|
//~ rjf: @os_hooks Memory Allocation (Implemented Per-OS)
|
||||||
|
|
||||||
internal void* os_reserve(U64 size);
|
//- rjf: basic
|
||||||
|
internal void *os_reserve(U64 size);
|
||||||
internal B32 os_commit(void *ptr, U64 size);
|
internal B32 os_commit(void *ptr, U64 size);
|
||||||
internal void* os_reserve_large(U64 size);
|
|
||||||
internal B32 os_commit_large(void *ptr, U64 size);
|
|
||||||
internal void os_decommit(void *ptr, U64 size);
|
internal void os_decommit(void *ptr, U64 size);
|
||||||
internal void os_release(void *ptr, U64 size);
|
internal void os_release(void *ptr, U64 size);
|
||||||
|
|
||||||
internal B32 os_set_large_pages(B32 flag);
|
//- rjf: large pages
|
||||||
internal B32 os_large_pages_enabled(void);
|
internal void *os_reserve_large(U64 size);
|
||||||
internal U64 os_large_page_size(void);
|
internal B32 os_commit_large(void *ptr, U64 size);
|
||||||
|
|
||||||
internal void* os_alloc_ring_buffer(U64 size, U64 *actual_size_out);
|
|
||||||
internal void os_free_ring_buffer(void *ring_buffer, U64 actual_size);
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: @os_hooks System Info (Implemented Per-OS)
|
//~ rjf: @os_hooks Thread Info (Implemented Per-OS)
|
||||||
|
|
||||||
internal String8 os_machine_name(void);
|
internal U32 os_tid(void);
|
||||||
internal U64 os_page_size(void);
|
internal void os_set_thread_name(String8 string);
|
||||||
internal U64 os_allocation_granularity(void);
|
|
||||||
internal U64 os_logical_core_count(void);
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: @os_hooks Process Info (Implemented Per-OS)
|
//~ rjf: @os_hooks Aborting (Implemented Per-OS)
|
||||||
|
|
||||||
internal String8List os_get_command_line_arguments(void);
|
internal void os_abort(S32 exit_code);
|
||||||
internal S32 os_get_pid(void);
|
|
||||||
internal S32 os_get_tid(void);
|
|
||||||
internal String8List os_get_environment(void);
|
|
||||||
internal U64 os_string_list_from_system_path(Arena *arena, OS_SystemPath path, String8List *out);
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ rjf: @os_hooks Process Control (Implemented Per-OS)
|
|
||||||
|
|
||||||
internal void os_exit_process(S32 exit_code);
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: @os_hooks File System (Implemented Per-OS)
|
//~ rjf: @os_hooks File System (Implemented Per-OS)
|
||||||
@@ -251,7 +207,7 @@ internal void os_exit_process(S32 exit_code);
|
|||||||
internal OS_Handle os_file_open(OS_AccessFlags flags, String8 path);
|
internal OS_Handle os_file_open(OS_AccessFlags flags, String8 path);
|
||||||
internal void os_file_close(OS_Handle file);
|
internal void os_file_close(OS_Handle file);
|
||||||
internal U64 os_file_read(OS_Handle file, Rng1U64 rng, void *out_data);
|
internal U64 os_file_read(OS_Handle file, Rng1U64 rng, void *out_data);
|
||||||
internal void os_file_write(OS_Handle file, Rng1U64 rng, void *data);
|
internal U64 os_file_write(OS_Handle file, Rng1U64 rng, void *data);
|
||||||
internal B32 os_file_set_times(OS_Handle file, DateTime time);
|
internal B32 os_file_set_times(OS_Handle file, DateTime time);
|
||||||
internal FileProperties os_properties_from_file(OS_Handle file);
|
internal FileProperties os_properties_from_file(OS_Handle file);
|
||||||
internal OS_FileID os_id_from_file(OS_Handle file);
|
internal OS_FileID os_id_from_file(OS_Handle file);
|
||||||
@@ -259,12 +215,13 @@ internal B32 os_delete_file_at_path(String8 path);
|
|||||||
internal B32 os_copy_file_path(String8 dst, String8 src);
|
internal B32 os_copy_file_path(String8 dst, String8 src);
|
||||||
internal String8 os_full_path_from_path(Arena *arena, String8 path);
|
internal String8 os_full_path_from_path(Arena *arena, String8 path);
|
||||||
internal B32 os_file_path_exists(String8 path);
|
internal B32 os_file_path_exists(String8 path);
|
||||||
|
internal FileProperties os_properties_from_file_path(String8 path);
|
||||||
|
|
||||||
//- rjf: file maps
|
//- rjf: file maps
|
||||||
internal OS_Handle os_file_map_open(OS_AccessFlags flags, OS_Handle file);
|
internal OS_Handle os_file_map_open(OS_AccessFlags flags, OS_Handle file);
|
||||||
internal void os_file_map_close(OS_Handle map);
|
internal void os_file_map_close(OS_Handle map);
|
||||||
internal void * os_file_map_view_open(OS_Handle map, OS_AccessFlags flags, Rng1U64 range);
|
internal void * os_file_map_view_open(OS_Handle map, OS_AccessFlags flags, Rng1U64 range);
|
||||||
internal void os_file_map_view_close(OS_Handle map, void *ptr);
|
internal void os_file_map_view_close(OS_Handle map, void *ptr, Rng1U64 range);
|
||||||
|
|
||||||
//- rjf: directory iteration
|
//- rjf: directory iteration
|
||||||
internal OS_FileIter *os_file_iter_begin(Arena *arena, String8 path, OS_FileIterFlags flags);
|
internal OS_FileIter *os_file_iter_begin(Arena *arena, String8 path, OS_FileIterFlags flags);
|
||||||
@@ -281,60 +238,58 @@ internal OS_Handle os_shared_memory_alloc(U64 size, String8 name);
|
|||||||
internal OS_Handle os_shared_memory_open(String8 name);
|
internal OS_Handle os_shared_memory_open(String8 name);
|
||||||
internal void os_shared_memory_close(OS_Handle handle);
|
internal void os_shared_memory_close(OS_Handle handle);
|
||||||
internal void * os_shared_memory_view_open(OS_Handle handle, Rng1U64 range);
|
internal void * os_shared_memory_view_open(OS_Handle handle, Rng1U64 range);
|
||||||
internal void os_shared_memory_view_close(OS_Handle handle, void *ptr);
|
internal void os_shared_memory_view_close(OS_Handle handle, void *ptr, Rng1U64 range);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: @os_hooks Time (Implemented Per-OS)
|
//~ rjf: @os_hooks Time (Implemented Per-OS)
|
||||||
|
|
||||||
internal OS_UnixTime os_now_unix(void);
|
|
||||||
internal DateTime os_now_universal_time(void);
|
|
||||||
internal DateTime os_universal_time_from_local_time(DateTime *local_time);
|
|
||||||
internal DateTime os_local_time_from_universal_time(DateTime *universal_time);
|
|
||||||
internal U64 os_now_microseconds(void);
|
internal U64 os_now_microseconds(void);
|
||||||
|
internal U32 os_now_unix(void);
|
||||||
|
internal DateTime os_now_universal_time(void);
|
||||||
|
internal DateTime os_universal_time_from_local(DateTime *local_time);
|
||||||
|
internal DateTime os_local_time_from_universal(DateTime *universal_time);
|
||||||
internal void os_sleep_milliseconds(U32 msec);
|
internal void os_sleep_milliseconds(U32 msec);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: @os_hooks Child Processes (Implemented Per-OS)
|
//~ rjf: @os_hooks Child Processes (Implemented Per-OS)
|
||||||
|
|
||||||
internal B32 os_launch_process(OS_LaunchOptions *options, OS_Handle *handle_out);
|
internal OS_Handle os_process_launch(OS_ProcessLaunchParams *params);
|
||||||
internal B32 os_process_wait(OS_Handle handle, U64 endt_us);
|
internal B32 os_process_join(OS_Handle handle, U64 endt_us);
|
||||||
internal void os_process_release_handle(OS_Handle handle);
|
internal void os_process_detach(OS_Handle handle);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: @os_hooks Threads (Implemented Per-OS)
|
//~ rjf: @os_hooks Threads (Implemented Per-OS)
|
||||||
|
|
||||||
internal OS_Handle os_launch_thread(OS_ThreadFunctionType *func, void *ptr, void *params);
|
internal OS_Handle os_thread_launch(OS_ThreadFunctionType *func, void *ptr, void *params);
|
||||||
internal void os_release_thread_handle(OS_Handle thread);
|
internal B32 os_thread_join(OS_Handle handle, U64 endt_us);
|
||||||
|
internal void os_thread_detach(OS_Handle handle);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: @os_hooks Synchronization Primitives (Implemented Per-OS)
|
//~ rjf: @os_hooks Synchronization Primitives (Implemented Per-OS)
|
||||||
|
|
||||||
// NOTE(allen): Mutexes are recursive - support counted acquire/release nesting
|
|
||||||
// on a single thread
|
|
||||||
|
|
||||||
//- rjf: recursive mutexes
|
//- rjf: recursive mutexes
|
||||||
internal OS_Handle os_mutex_alloc(void);
|
internal OS_Handle os_mutex_alloc(void);
|
||||||
internal void os_mutex_release(OS_Handle mutex);
|
internal void os_mutex_release(OS_Handle mutex);
|
||||||
internal void os_mutex_take_(OS_Handle mutex);
|
internal void os_mutex_take(OS_Handle mutex);
|
||||||
internal void os_mutex_drop_(OS_Handle mutex);
|
internal void os_mutex_drop(OS_Handle mutex);
|
||||||
|
|
||||||
//- rjf: reader/writer mutexes
|
//- rjf: reader/writer mutexes
|
||||||
internal OS_Handle os_rw_mutex_alloc(void);
|
internal OS_Handle os_rw_mutex_alloc(void);
|
||||||
internal void os_rw_mutex_release(OS_Handle rw_mutex);
|
internal void os_rw_mutex_release(OS_Handle rw_mutex);
|
||||||
internal void os_rw_mutex_take_r_(OS_Handle mutex);
|
internal void os_rw_mutex_take_r(OS_Handle mutex);
|
||||||
internal void os_rw_mutex_drop_r_(OS_Handle mutex);
|
internal void os_rw_mutex_drop_r(OS_Handle mutex);
|
||||||
internal void os_rw_mutex_take_w_(OS_Handle mutex);
|
internal void os_rw_mutex_take_w(OS_Handle mutex);
|
||||||
internal void os_rw_mutex_drop_w_(OS_Handle mutex);
|
internal void os_rw_mutex_drop_w(OS_Handle mutex);
|
||||||
|
|
||||||
//- rjf: condition variables
|
//- rjf: condition variables
|
||||||
internal OS_Handle os_condition_variable_alloc(void);
|
internal OS_Handle os_condition_variable_alloc(void);
|
||||||
internal void os_condition_variable_release(OS_Handle cv);
|
internal void os_condition_variable_release(OS_Handle cv);
|
||||||
// returns false on timeout, true on signal, (max_wait_ms = max_U64) -> no timeout
|
// returns false on timeout, true on signal, (max_wait_ms = max_U64) -> no timeout
|
||||||
internal B32 os_condition_variable_wait_(OS_Handle cv, OS_Handle mutex, U64 endt_us);
|
internal B32 os_condition_variable_wait(OS_Handle cv, OS_Handle mutex, U64 endt_us);
|
||||||
internal B32 os_condition_variable_wait_rw_r_(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us);
|
internal B32 os_condition_variable_wait_rw_r(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us);
|
||||||
internal B32 os_condition_variable_wait_rw_w_(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us);
|
internal B32 os_condition_variable_wait_rw_w(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us);
|
||||||
internal void os_condition_variable_signal_(OS_Handle cv);
|
internal void os_condition_variable_signal(OS_Handle cv);
|
||||||
internal void os_condition_variable_broadcast_(OS_Handle cv);
|
internal void os_condition_variable_broadcast(OS_Handle cv);
|
||||||
|
|
||||||
//- rjf: cross-process semaphores
|
//- rjf: cross-process semaphores
|
||||||
internal OS_Handle os_semaphore_alloc(U32 initial_count, U32 max_count, String8 name);
|
internal OS_Handle os_semaphore_alloc(U32 initial_count, U32 max_count, String8 name);
|
||||||
@@ -344,12 +299,18 @@ internal void os_semaphore_close(OS_Handle semaphore);
|
|||||||
internal B32 os_semaphore_take(OS_Handle semaphore, U64 endt_us);
|
internal B32 os_semaphore_take(OS_Handle semaphore, U64 endt_us);
|
||||||
internal void os_semaphore_drop(OS_Handle semaphore);
|
internal void os_semaphore_drop(OS_Handle semaphore);
|
||||||
|
|
||||||
|
//- rjf: scope macros
|
||||||
|
#define OS_MutexScope(mutex) DeferLoop(os_mutex_take(mutex), os_mutex_drop(mutex))
|
||||||
|
#define OS_MutexScopeR(mutex) DeferLoop(os_rw_mutex_take_r(mutex), os_rw_mutex_drop_r(mutex))
|
||||||
|
#define OS_MutexScopeW(mutex) DeferLoop(os_rw_mutex_take_w(mutex), os_rw_mutex_drop_w(mutex))
|
||||||
|
#define OS_MutexScopeRWPromote(mutex) DeferLoop((os_rw_mutex_drop_r(mutex), os_rw_mutex_take_w(mutex)), (os_rw_mutex_drop_w(mutex), os_rw_mutex_take_r(mutex)))
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: @os_hooks Dynamically-Loaded Libraries (Implemented Per-OS)
|
//~ rjf: @os_hooks Dynamically-Loaded Libraries (Implemented Per-OS)
|
||||||
|
|
||||||
internal OS_Handle os_library_open(String8 path);
|
internal OS_Handle os_library_open(String8 path);
|
||||||
internal VoidProc *os_library_load_proc(OS_Handle lib, String8 name);
|
|
||||||
internal void os_library_close(OS_Handle lib);
|
internal void os_library_close(OS_Handle lib);
|
||||||
|
internal VoidProc *os_library_load_proc(OS_Handle lib, String8 name);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: @os_hooks Safe Calls (Implemented Per-OS)
|
//~ rjf: @os_hooks Safe Calls (Implemented Per-OS)
|
||||||
@@ -360,6 +321,16 @@ internal void os_safe_call(OS_ThreadFunctionType *func, OS_ThreadFunctionType *f
|
|||||||
//~ rjf: @os_hooks GUIDs (Implemented Per-OS)
|
//~ rjf: @os_hooks GUIDs (Implemented Per-OS)
|
||||||
|
|
||||||
internal OS_Guid os_make_guid(void);
|
internal OS_Guid os_make_guid(void);
|
||||||
internal String8 os_string_from_guid(Arena *arena, OS_Guid guid);
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: @os_hooks Entry Points (Implemented Per-OS)
|
||||||
|
|
||||||
|
// NOTE(rjf): The implementation of `os_core` will define low-level entry
|
||||||
|
// points if BUILD_ENTRY_DEFINING_UNIT is defined to 1. These will call
|
||||||
|
// into the standard codebase program entry points, named "entry_point".
|
||||||
|
|
||||||
|
#if BUILD_ENTRY_DEFINING_UNIT
|
||||||
|
internal void entry_point(CmdLine *cmdline);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // OS_CORE_H
|
#endif // OS_CORE_H
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,62 +1,64 @@
|
|||||||
// Copyright (c) 2024 Epic Games Tools
|
// Copyright (c) 2024 Epic Games Tools
|
||||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
#ifndef WIN32_H
|
#ifndef OS_CORE_WIN32_H
|
||||||
#define WIN32_H
|
#define OS_CORE_WIN32_H
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ NOTE(allen): Negotiate the windows header include order
|
//~ rjf: Includes / Libraries
|
||||||
|
|
||||||
#if OS_FEATURE_SOCKET
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <WinSock2.h>
|
#include <windows.h>
|
||||||
#endif
|
#include <windowsx.h>
|
||||||
|
#include <timeapi.h>
|
||||||
#include <Windows.h>
|
#include <tlhelp32.h>
|
||||||
#include <Shlobj.h>
|
#include <Shlobj.h>
|
||||||
|
|
||||||
#if OS_FEATURE_GRAPHICAL
|
|
||||||
#include <shellscalingapi.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if OS_FEATURE_SOCKET
|
|
||||||
#include <WS2tcpip.h>
|
|
||||||
#include <Mswsock.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <processthreadsapi.h>
|
#include <processthreadsapi.h>
|
||||||
|
#pragma comment(lib, "user32")
|
||||||
|
#pragma comment(lib, "winmm")
|
||||||
|
#pragma comment(lib, "shell32")
|
||||||
|
#pragma comment(lib, "advapi32")
|
||||||
|
#pragma comment(lib, "rpcrt4")
|
||||||
|
#pragma comment(lib, "shlwapi")
|
||||||
|
#pragma comment(lib, "comctl32")
|
||||||
|
#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") // this is required for loading correct comctl32 dll file
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ NOTE(allen): File Iterator
|
//~ rjf: File Iterator Types
|
||||||
|
|
||||||
typedef struct W32_FileIter W32_FileIter;
|
typedef struct OS_W32_FileIter OS_W32_FileIter;
|
||||||
struct W32_FileIter
|
struct OS_W32_FileIter
|
||||||
{
|
{
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
WIN32_FIND_DATAW find_data;
|
WIN32_FIND_DATAW find_data;
|
||||||
|
B32 is_volume_iter;
|
||||||
|
String8Array drive_strings;
|
||||||
|
U64 drive_strings_iter_idx;
|
||||||
};
|
};
|
||||||
StaticAssert(sizeof(Member(OS_FileIter, memory)) >= sizeof(W32_FileIter), file_iter_memory_size);
|
StaticAssert(sizeof(Member(OS_FileIter, memory)) >= sizeof(OS_W32_FileIter), file_iter_memory_size);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ NOTE(allen): Threading Entities
|
//~ rjf: Entity Types
|
||||||
|
|
||||||
typedef enum W32_EntityKind
|
typedef enum OS_W32_EntityKind
|
||||||
{
|
{
|
||||||
W32_EntityKind_Null,
|
OS_W32_EntityKind_Null,
|
||||||
W32_EntityKind_Thread,
|
OS_W32_EntityKind_Thread,
|
||||||
W32_EntityKind_Mutex,
|
OS_W32_EntityKind_Mutex,
|
||||||
W32_EntityKind_RWMutex,
|
OS_W32_EntityKind_RWMutex,
|
||||||
W32_EntityKind_ConditionVariable,
|
OS_W32_EntityKind_ConditionVariable,
|
||||||
}
|
}
|
||||||
W32_EntityKind;
|
OS_W32_EntityKind;
|
||||||
|
|
||||||
typedef struct W32_Entity W32_Entity;
|
typedef struct OS_W32_Entity OS_W32_Entity;
|
||||||
struct W32_Entity
|
struct OS_W32_Entity
|
||||||
{
|
{
|
||||||
W32_Entity *next;
|
OS_W32_Entity *next;
|
||||||
W32_EntityKind kind;
|
OS_W32_EntityKind kind;
|
||||||
volatile U32 reference_mask;
|
union
|
||||||
union{
|
{
|
||||||
struct{
|
struct
|
||||||
|
{
|
||||||
OS_ThreadFunctionType *func;
|
OS_ThreadFunctionType *func;
|
||||||
void *ptr;
|
void *ptr;
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
@@ -69,23 +71,52 @@ struct W32_Entity
|
|||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Helpers
|
//~ rjf: State
|
||||||
|
|
||||||
//- rjf: files
|
typedef struct OS_W32_State OS_W32_State;
|
||||||
internal FilePropertyFlags w32_file_property_flags_from_dwFileAttributes(DWORD dwFileAttributes);
|
struct OS_W32_State
|
||||||
internal void w32_file_properties_from_attributes(FileProperties *properties, WIN32_FILE_ATTRIBUTE_DATA *attributes);
|
{
|
||||||
|
Arena *arena;
|
||||||
|
|
||||||
//- rjf: time
|
// rjf: info
|
||||||
internal void w32_date_time_from_system_time(DateTime *out, SYSTEMTIME *in);
|
OS_SystemInfo system_info;
|
||||||
internal void w32_system_time_from_date_time(SYSTEMTIME *out, DateTime *in);
|
OS_ProcessInfo process_info;
|
||||||
internal void w32_dense_time_from_file_time(DenseTime *out, FILETIME *in);
|
U64 microsecond_resolution;
|
||||||
internal U32 w32_sleep_ms_from_endt_us(U64 endt_us);
|
|
||||||
|
|
||||||
//- rjf: entities
|
// rjf: entity storage
|
||||||
internal W32_Entity* w32_alloc_entity(W32_EntityKind kind);
|
CRITICAL_SECTION entity_mutex;
|
||||||
internal void w32_free_entity(W32_Entity *entity);
|
Arena *entity_arena;
|
||||||
|
OS_W32_Entity *entity_free;
|
||||||
|
};
|
||||||
|
|
||||||
//- rjf: threads
|
////////////////////////////////
|
||||||
internal DWORD w32_thread_base(void *ptr);
|
//~ rjf: Globals
|
||||||
|
|
||||||
#endif //WIN32_H
|
global OS_W32_State os_w32_state = {0};
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: File Info Conversion Helpers
|
||||||
|
|
||||||
|
internal FilePropertyFlags os_w32_file_property_flags_from_dwFileAttributes(DWORD dwFileAttributes);
|
||||||
|
internal void os_w32_file_properties_from_attribute_data(FileProperties *properties, WIN32_FILE_ATTRIBUTE_DATA *attributes);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Time Conversion Helpers
|
||||||
|
|
||||||
|
internal void os_w32_date_time_from_system_time(DateTime *out, SYSTEMTIME *in);
|
||||||
|
internal void os_w32_system_time_from_date_time(SYSTEMTIME *out, DateTime *in);
|
||||||
|
internal void os_w32_dense_time_from_file_time(DenseTime *out, FILETIME *in);
|
||||||
|
internal U32 os_w32_sleep_ms_from_endt_us(U64 endt_us);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Entity Functions
|
||||||
|
|
||||||
|
internal OS_W32_Entity *os_w32_entity_alloc(OS_W32_EntityKind kind);
|
||||||
|
internal void os_w32_entity_release(OS_W32_Entity *entity);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Thread Entry Point
|
||||||
|
|
||||||
|
internal DWORD os_w32_thread_entry_point(void *ptr);
|
||||||
|
|
||||||
|
#endif // OS_CORE_WIN32_H
|
||||||
|
|||||||
@@ -1,29 +1,12 @@
|
|||||||
// Copyright (c) 2024 Epic Games Tools
|
// Copyright (c) 2024 Epic Games Tools
|
||||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
////////////////////////////////
|
#include "metagen/metagen_os/core/metagen_os_core.c"
|
||||||
// NOTE(allen): Include OS features for extra features and target OS
|
|
||||||
|
|
||||||
#include "core/metagen_os_core.c"
|
|
||||||
|
|
||||||
#if OS_FEATURE_SOCKET
|
|
||||||
#include "socket/metagen_os_socket.c"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if OS_FEATURE_GRAPHICAL
|
|
||||||
#include "gfx/metagen_os_gfx.c"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
# include "core/win32/metagen_os_core_win32.c"
|
# include "metagen/metagen_os/core/win32/metagen_os_core_win32.c"
|
||||||
# if OS_FEATURE_SOCKET
|
|
||||||
# include "socket/win32/metagen_os_socket_win32.c"
|
|
||||||
# endif
|
|
||||||
# if OS_FEATURE_GRAPHICAL
|
|
||||||
# include "gfx/win32/metagen_os_gfx_win32.c"
|
|
||||||
# endif
|
|
||||||
#elif OS_LINUX
|
#elif OS_LINUX
|
||||||
# include "core/linux/metagen_os_core_linux.c"
|
# include "metagen/metagen_os/core/linux/metagen_os_core_linux.c"
|
||||||
#else
|
#else
|
||||||
# error no OS layer setup
|
# error OS core layer not implemented for this operating system.
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -4,36 +4,22 @@
|
|||||||
#ifndef OS_INC_H
|
#ifndef OS_INC_H
|
||||||
#define OS_INC_H
|
#define OS_INC_H
|
||||||
|
|
||||||
#if !defined(OS_FEATURE_SOCKET)
|
|
||||||
# define OS_FEATURE_SOCKET 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(OS_FEATURE_GRAPHICAL)
|
#if !defined(OS_FEATURE_GRAPHICAL)
|
||||||
# define OS_FEATURE_GRAPHICAL 0
|
# define OS_FEATURE_GRAPHICAL 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "core/metagen_os_core.h"
|
#if !defined(OS_GFX_STUB)
|
||||||
|
# define OS_GFX_STUB 0
|
||||||
#if OS_FEATURE_SOCKET
|
|
||||||
#include "socket/metagen_os_socket.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if OS_FEATURE_GRAPHICAL
|
#include "metagen/metagen_os/core/metagen_os_core.h"
|
||||||
#include "gfx/metagen_os_gfx.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
# include "core/win32/metagen_os_core_win32.h"
|
# include "metagen/metagen_os/core/win32/metagen_os_core_win32.h"
|
||||||
# if OS_FEATURE_SOCKET
|
|
||||||
# include "socket/win32/metagen_os_socket_win32.h"
|
|
||||||
# endif
|
|
||||||
# if OS_FEATURE_GRAPHICAL
|
|
||||||
# include "gfx/win32/metagen_os_gfx_win32.h"
|
|
||||||
# endif
|
|
||||||
#elif OS_LINUX
|
#elif OS_LINUX
|
||||||
# include "core/linux/metagen_os_core_linux.h"
|
# include "metagen/metagen_os/core/linux/metagen_os_core_linux.h"
|
||||||
#else
|
#else
|
||||||
# error no OS layer setup
|
# error OS core layer not implemented for this operating system.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // OS_INC_H
|
#endif // OS_INC_H
|
||||||
|
|||||||
Reference in New Issue
Block a user