update metagen base/os & entry point

This commit is contained in:
Ryan Fleury
2024-07-16 16:09:53 -07:00
parent d82b54597f
commit d0d9327236
38 changed files with 10683 additions and 10870 deletions
+195 -316
View File
@@ -1,316 +1,195 @@
// 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/)
//////////////////////////////// ////////////////////////////////
// Implementation //~ rjf: Arena Functions
internal Arena * //- rjf: arena creation/destruction
arena_alloc__sized(U64 init_res, U64 init_cmt)
{ internal Arena *
ProfBeginFunction(); arena_alloc_(ArenaParams *params)
Assert(ARENA_HEADER_SIZE < init_cmt && init_cmt <= init_res); {
// rjf: round up reserve/commit sizes
void *memory; U64 reserve_size = params->reserve_size;
U64 res; U64 commit_size = params->commit_size;
U64 cmt; if(params->flags & ArenaFlag_LargePages)
{
B32 large_pages = os_large_pages_enabled(); reserve_size = AlignPow2(reserve_size, os_get_system_info()->large_page_size);
if (large_pages) { commit_size = AlignPow2(commit_size, os_get_system_info()->large_page_size);
U64 page_size = os_large_page_size(); }
res = AlignPow2(init_res, page_size); else
{
#if OS_WINDOWS reserve_size = AlignPow2(reserve_size, os_get_system_info()->page_size);
cmt = res; commit_size = AlignPow2(commit_size, os_get_system_info()->page_size);
#else }
cmt AlignPow2(init_cmt, page_size);
#endif // rjf: reserve/commit initial block
void *base = params->optional_backing_buffer;
memory = os_reserve_large(res); if(base == 0)
if (!os_commit_large(memory, cmt)) { {
memory = 0; if(params->flags & ArenaFlag_LargePages)
os_release(memory, res); {
} base = os_reserve_large(reserve_size);
} else { os_commit_large(base, commit_size);
U64 page_size = os_page_size(); }
res = AlignPow2(init_res, page_size); else
cmt = AlignPow2(init_cmt, page_size); {
base = os_reserve(reserve_size);
memory = os_reserve(res); os_commit(base, commit_size);
if (!os_commit(memory, cmt)) { }
memory = 0; }
os_release(memory, res);
} // rjf: panic on arena creation failure
} #if OS_FEATURE_GRAPHICAL
Assert(memory); if(Unlikely(base == 0))
{
AsanPoisonMemoryRegion(memory, cmt); os_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure."));
AsanUnpoisonMemoryRegion(memory, ARENA_HEADER_SIZE); os_abort(1);
}
Arena *arena = (Arena*)memory; #endif
if (arena) {
arena->prev = 0; // rjf: extract arena header & fill
arena->current = arena; Arena *arena = (Arena *)base;
arena->base_pos = 0; arena->current = arena;
arena->pos = ARENA_HEADER_SIZE; arena->flags = params->flags;
arena->cmt = cmt; arena->cmt_size = (U32)params->commit_size;
arena->res = res; arena->res_size = params->reserve_size;
arena->align = 8; arena->base_pos = 0;
#if ENABLE_DEV arena->pos = ARENA_HEADER_SIZE;
arena->dev = 0; arena->cmt = commit_size;
#endif arena->res = reserve_size;
arena->grow = 1; AsanPoisonMemoryRegion(base, commit_size);
arena->large_pages = large_pages; AsanUnpoisonMemoryRegion(base, ARENA_HEADER_SIZE);
} return arena;
}
ProfEnd();
return arena; internal void
} arena_release(Arena *arena)
{
internal Arena * for(Arena *n = arena->current, *prev = 0; n != 0; n = prev)
arena_alloc(void) {
{ prev = n->prev;
ProfBeginFunction(); os_release(n, n->res);
}
U64 init_res, init_cmt; }
if (os_large_pages_enabled()) {
init_res = ARENA_RESERVE_SIZE_LARGE_PAGES; //- rjf: arena push/pop core functions
init_cmt = ARENA_COMMIT_SIZE_LARGE_PAGES;
} else { internal void *
init_res = ARENA_RESERVE_SIZE; arena_push(Arena *arena, U64 size, U64 align)
init_cmt = ARENA_COMMIT_SIZE; {
} Arena *current = arena->current;
U64 pos_pre = AlignPow2(current->pos, align);
Arena *arena = arena_alloc__sized(init_res, init_cmt); U64 pos_pst = pos_pre + size;
ProfEnd(); // rjf: chain, if needed
return arena; if(current->res < pos_pst && !(arena->flags & ArenaFlag_NoChain))
} {
U64 res_size = current->res_size;
internal void U64 cmt_size = current->cmt_size;
arena_release(Arena *arena) if(size > cmt_size)
{ {
for (Arena *node = arena->current, *prev = 0; node != 0; node = prev) { res_size = size + ARENA_HEADER_SIZE;
prev = node->prev; cmt_size = size + ARENA_HEADER_SIZE;
os_release(node, node->res); }
} Arena *new_block = arena_alloc(.reserve_size = res_size,
} .commit_size = cmt_size,
.flags = current->flags);
internal U64 new_block->base_pos = current->base_pos + current->res;
arena_huge_push_threshold(void) SLLStackPush_N(arena->current, new_block, prev);
{ current = new_block;
U64 reserve_size = os_large_pages_enabled() ? ARENA_RESERVE_SIZE_LARGE_PAGES : ARENA_RESERVE_SIZE; pos_pre = AlignPow2(current->pos, align);
U64 threshold = (reserve_size - ARENA_HEADER_SIZE) / 2 + 1; pos_pst = pos_pst + size;
return threshold; }
}
// rjf: commit new pages, if needed
internal void * if(current->cmt < pos_pst && !(current->flags & ArenaFlag_LargePages))
arena_push__impl(Arena *arena, U64 size) {
{ U64 cmt_pst_aligned = AlignPow2(pos_pst, current->cmt_size);
Arena *current = arena->current; U64 cmt_pst_clamped = ClampTop(cmt_pst_aligned, current->res);
U64 pos_mem = AlignPow2(current->pos, arena->align); U64 cmt_size = cmt_pst_clamped - current->cmt;
U64 pos_new = pos_mem + size; os_commit((U8 *)current + current->cmt, cmt_size);
current->cmt = cmt_pst_clamped;
if (current->res < pos_new && arena->grow) { }
Arena *new_block;
// rjf: push onto current block
// normal growth path void *result = 0;
if (size < arena_huge_push_threshold()) { if(current->cmt >= pos_pst)
new_block = arena_alloc(); {
} result = (U8 *)current+pos_pre;
// huge growth path current->pos = pos_pst;
else { AsanUnpoisonMemoryRegion(result, size);
U64 new_block_size = size + ARENA_HEADER_SIZE; }
new_block = arena_alloc__sized(new_block_size, new_block_size);
} // rjf: panic on failure
#if OS_FEATURE_GRAPHICAL
if (new_block) { if(Unlikely(result == 0))
new_block->base_pos = current->base_pos + current->res; {
SLLStackPush_N(arena->current, new_block, prev); os_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure."));
os_abort(1);
current = new_block; }
pos_mem = AlignPow2(current->pos, current->align); #endif
pos_new = pos_mem + size;
} return result;
} }
if (current->cmt < pos_new) { internal U64
U64 cmt_new_aligned, cmt_new_clamped, cmt_new_size; arena_pos(Arena *arena)
B32 is_cmt_ok; {
Arena *current = arena->current;
if (current->large_pages) { U64 pos = current->base_pos + current->pos;
cmt_new_aligned = AlignPow2(pos_new, ARENA_COMMIT_SIZE_LARGE_PAGES); return pos;
cmt_new_clamped = ClampTop(cmt_new_aligned, current->res); }
cmt_new_size = cmt_new_clamped - current->cmt;
is_cmt_ok = os_commit_large((U8*)current + current->cmt, cmt_new_size); internal void
} else { arena_pop_to(Arena *arena, U64 pos)
cmt_new_aligned = AlignPow2(pos_new, ARENA_COMMIT_SIZE); {
cmt_new_clamped = ClampTop(cmt_new_aligned, current->res); U64 big_pos = ClampBot(ARENA_HEADER_SIZE, pos);
cmt_new_size = cmt_new_clamped - current->cmt; Arena *current = arena->current;
is_cmt_ok = os_commit((U8*)current + current->cmt, cmt_new_size); for(Arena *prev = 0; current->base_pos >= big_pos; current = prev)
} {
Assert(is_cmt_ok); prev = current->prev;
os_release(current, current->res);
if (is_cmt_ok) { }
current->cmt = cmt_new_clamped; arena->current = current;
} U64 new_pos = big_pos - current->base_pos;
} AssertAlways(new_pos <= current->pos);
AsanPoisonMemoryRegion((U8*)current + new_pos, (current->pos - new_pos));
void *memory = 0; current->pos = new_pos;
}
if (current->cmt >= pos_new) {
memory = (U8*)current + pos_mem; //- rjf: arena push/pop helpers
current->pos = pos_new;
AsanUnpoisonMemoryRegion(memory, size); internal void
} arena_clear(Arena *arena)
{
#if OS_FEATURE_GRAPHICAL arena_pop_to(arena, 0);
if(Unlikely(memory == 0)) }
{
os_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure.")); internal void
os_exit_process(1); arena_pop(Arena *arena, U64 amt)
} {
#endif U64 pos_old = arena_pos(arena);
U64 pos_new = pos_old;
return memory; if(amt < pos_old)
} {
pos_new = pos_old - amt;
internal U64 }
arena_pos(Arena *arena) arena_pop_to(arena, pos_new);
{ }
Arena *current = arena->current;
U64 pos = current->base_pos + current->pos; //- rjf: temporary arena scopes
return pos;
} internal Temp
temp_begin(Arena *arena)
internal void {
arena_pop_to(Arena *arena, U64 big_pos_unclamped) U64 pos = arena_pos(arena);
{ Temp temp = {arena, pos};
U64 big_pos = ClampBot(ARENA_HEADER_SIZE, big_pos_unclamped); return temp;
}
// unroll the chain
Arena *current = arena->current; internal void
for (Arena *prev = 0; current->base_pos >= big_pos; current = prev) { temp_end(Temp temp)
prev = current->prev; {
os_release(current, current->res); arena_pop_to(temp.arena, temp.pos);
} }
AssertAlways(current);
arena->current = current;
// compute arena-relative position
U64 new_pos = big_pos - current->base_pos;
AssertAlways(new_pos <= current->pos);
// poison popped memory block
AsanPoisonMemoryRegion((U8*)current + new_pos, (current->pos - new_pos));
// update position
current->pos = new_pos;
}
internal void
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
arena_clear(Arena *arena)
{
arena_pop_to(arena, 0);
}
internal Temp
temp_begin(Arena *arena)
{
U64 pos = arena_pos(arena);
Temp temp = {arena, pos};
return temp;
}
internal void
temp_end(Temp temp)
{
arena_pop_to(temp.arena, temp.pos);
}
////////////////////////////////
//~ 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);
}
+80 -94
View File
@@ -1,94 +1,80 @@
// 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_ARENA_H #ifndef BASE_ARENA_H
#define BASE_ARENA_H #define BASE_ARENA_H
//////////////////////////////// ////////////////////////////////
//~ rjf: Constants //~ rjf: Constants
#define ARENA_HEADER_SIZE 128 #define ARENA_HEADER_SIZE 64
#ifndef ARENA_RESERVE_SIZE ////////////////////////////////
# define ARENA_RESERVE_SIZE MB(64) //~ rjf: Types
#endif
#ifndef ARENA_COMMIT_SIZE typedef U32 ArenaFlags;
# define ARENA_COMMIT_SIZE KB(64) enum
#endif {
ArenaFlag_NoChain = (1<<0),
#ifndef ARENA_RESERVE_SIZE_LARGE_PAGES ArenaFlag_LargePages = (1<<1),
# define ARENA_RESERVE_SIZE_LARGE_PAGES MB(8) };
#endif
#ifndef ARENA_COMMIT_SIZE_LARGE_PAGES typedef struct ArenaParams ArenaParams;
# define ARENA_COMMIT_SIZE_LARGE_PAGES MB(2) struct ArenaParams
#endif {
ArenaFlags flags;
//////////////////////////////// U64 reserve_size;
//~ rjf: Arena Types U64 commit_size;
void *optional_backing_buffer;
typedef struct Arena Arena; };
struct Arena
{ typedef struct Arena Arena;
struct Arena *prev; struct Arena
struct Arena *current; {
U64 base_pos; Arena *prev; // previous arena in chain
U64 pos; Arena *current; // current arena in chain
U64 cmt; ArenaFlags flags;
U64 res; U32 cmt_size;
U64 align; U64 res_size;
struct ArenaDev *dev; U64 base_pos;
B8 grow; U64 pos;
B8 large_pages; U64 cmt;
}; U64 res;
};
typedef struct Temp Temp; StaticAssert(sizeof(Arena) <= ARENA_HEADER_SIZE, arena_header_size_check);
struct Temp
{ typedef struct Temp Temp;
Arena *arena; struct Temp
U64 pos; {
}; Arena *arena;
U64 pos;
//////////////////////////////// };
// Implementation
////////////////////////////////
internal Arena* arena_alloc__sized(U64 init_res, U64 init_cmt); //~ rjf: Arena Functions
internal Arena* arena_alloc(void); //- rjf: arena creation/destruction
internal void arena_release(Arena *arena); 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_push__impl(Arena *arena, U64 size); internal void arena_release(Arena *arena);
internal U64 arena_pos(Arena *arena);
internal void arena_pop_to(Arena *arena, U64 pos); //- rjf: arena push/pop/pos core functions
internal void *arena_push(Arena *arena, U64 size, U64 align);
internal void arena_absorb(Arena *arena, Arena *sub); internal U64 arena_pos(Arena *arena);
internal void arena_pop_to(Arena *arena, U64 pos);
////////////////////////////////
// Wrappers //- rjf: arena push/pop helpers
internal void arena_clear(Arena *arena);
internal void* arena_push(Arena *arena, U64 size); internal void arena_pop(Arena *arena, U64 amt);
internal void* arena_push_contiguous(Arena *arena, U64 size);
internal void arena_clear(Arena *arena); //- rjf: temporary arena scopes
internal void arena_push_align(Arena *arena, U64 align); internal Temp temp_begin(Arena *arena);
internal void arena_put_back(Arena *arena, U64 amt); internal void temp_end(Temp temp);
internal Temp temp_begin(Arena *arena); //- rjf: push helper macros
internal void temp_end(Temp temp); #define push_array_no_zero_aligned(a, T, c, align) (T *)arena_push((a), sizeof(T)*(c), (align))
#define push_array_aligned(a, T, c, align) (T *)MemoryZero(push_array_no_zero_aligned(a, T, c, align), sizeof(T)*(c))
//////////////////////////////// #define push_array_no_zero(a, T, c) push_array_no_zero_aligned(a, T, c, Max(8, AlignOf(T)))
//~ NOTE(allen): "Mini-Arena" Helper #define push_array(a, T, c) push_array_aligned(a, T, c, Max(8, AlignOf(T)))
internal B32 ensure_commit(void **cmt, void *pos, U64 cmt_block_size); #endif // BASE_ARENA_H
////////////////////////////////
//~ 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
@@ -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
@@ -1,229 +1,232 @@
// 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/)
//////////////////////////////// ////////////////////////////////
//~ NOTE(rjf): Command Line Option Parsing //~ NOTE(rjf): Command Line Option Parsing
internal U64 internal U64
cmd_line_hash_from_string(String8 string) cmd_line_hash_from_string(String8 string)
{ {
U64 result = 5381; U64 result = 5381;
for(U64 i = 0; i < string.size; i += 1) for(U64 i = 0; i < string.size; i += 1)
{ {
result = ((result << 5) + result) + string.str[i]; result = ((result << 5) + result) + string.str[i];
} }
return result; return result;
} }
internal CmdLineOpt ** internal CmdLineOpt **
cmd_line_slot_from_string(CmdLine *cmd_line, String8 string) cmd_line_slot_from_string(CmdLine *cmd_line, String8 string)
{ {
CmdLineOpt **slot = 0; CmdLineOpt **slot = 0;
if(cmd_line->option_table_size != 0) if(cmd_line->option_table_size != 0)
{ {
U64 hash = cmd_line_hash_from_string(string); U64 hash = cmd_line_hash_from_string(string);
U64 bucket = hash % cmd_line->option_table_size; U64 bucket = hash % cmd_line->option_table_size;
slot = &cmd_line->option_table[bucket]; slot = &cmd_line->option_table[bucket];
} }
return slot; return slot;
} }
internal CmdLineOpt * internal CmdLineOpt *
cmd_line_opt_from_slot(CmdLineOpt **slot, String8 string) cmd_line_opt_from_slot(CmdLineOpt **slot, String8 string)
{ {
CmdLineOpt *result = 0; CmdLineOpt *result = 0;
for(CmdLineOpt *var = *slot; var; var = var->hash_next) for(CmdLineOpt *var = *slot; var; var = var->hash_next)
{ {
if(str8_match(string, var->string, 0)) if(str8_match(string, var->string, 0))
{ {
result = var; result = var;
break; break;
} }
} }
return result; return result;
} }
internal void internal void
cmd_line_push_opt(CmdLineOptList *list, CmdLineOpt *var) cmd_line_push_opt(CmdLineOptList *list, CmdLineOpt *var)
{ {
SLLQueuePush(list->first, list->last, var); SLLQueuePush(list->first, list->last, var);
list->count += 1; list->count += 1;
} }
internal CmdLineOpt * internal CmdLineOpt *
cmd_line_insert_opt(Arena *arena, CmdLine *cmd_line, String8 string, String8List values) cmd_line_insert_opt(Arena *arena, CmdLine *cmd_line, String8 string, String8List values)
{ {
CmdLineOpt *var = 0; CmdLineOpt *var = 0;
CmdLineOpt **slot = cmd_line_slot_from_string(cmd_line, string); CmdLineOpt **slot = cmd_line_slot_from_string(cmd_line, string);
CmdLineOpt *existing_var = cmd_line_opt_from_slot(slot, string); CmdLineOpt *existing_var = cmd_line_opt_from_slot(slot, string);
if(existing_var != 0) if(existing_var != 0)
{ {
var = existing_var; var = existing_var;
} }
else else
{ {
var = push_array(arena, CmdLineOpt, 1); var = push_array(arena, CmdLineOpt, 1);
var->hash_next = *slot; var->hash_next = *slot;
var->hash = cmd_line_hash_from_string(string); var->hash = cmd_line_hash_from_string(string);
var->string = push_str8_copy(arena, string); var->string = push_str8_copy(arena, string);
var->value_strings = values; var->value_strings = values;
StringJoin join = {0}; StringJoin join = {0};
join.pre = str8_lit(""); join.pre = str8_lit("");
join.sep = str8_lit(","); join.sep = str8_lit(",");
join.post = str8_lit(""); join.post = str8_lit("");
var->value_string = str8_list_join(arena, &var->value_strings, &join); var->value_string = str8_list_join(arena, &var->value_strings, &join);
*slot = var; *slot = var;
cmd_line_push_opt(&cmd_line->options, var); cmd_line_push_opt(&cmd_line->options, var);
} }
return var; return var;
} }
internal CmdLine 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.
parsed.option_table_size = 4096; {
parsed.option_table = push_array(arena, CmdLineOpt *, parsed.option_table_size); parsed.option_table_size = 4096;
} parsed.option_table = push_array(arena, CmdLineOpt *, parsed.option_table_size);
}
// NOTE(rjf): Parse command line.
B32 after_passthrough_option = 0; // NOTE(rjf): Parse command line.
for(String8Node *node = command_line.first->next, *next = 0; node != 0; node = next) B32 after_passthrough_option = 0;
{ B32 first_passthrough = 1;
next = node->next; for(String8Node *node = command_line.first->next, *next = 0; node != 0; node = next)
String8 option_name = node->string; {
next = node->next;
// NOTE(rjf): Look at -- or - at the start of an argument to determine if it's String8 option_name = node->string;
// a flag option. All arguments after a single "--" (with no trailing string
// on the command line will be considered as input files. // NOTE(rjf): Look at -- or - at the start of an argument to determine if it's
B32 is_option = 1; // a flag option. All arguments after a single "--" (with no trailing string
if(after_passthrough_option == 0) // on the command line will be considered as input files.
{ B32 is_option = 1;
if(str8_match(node->string, str8_lit("--"), 0)) if(after_passthrough_option == 0)
{ {
after_passthrough_option = 1; if(str8_match(node->string, str8_lit("--"), 0))
is_option = 0; {
} after_passthrough_option = 1;
else if(str8_match(str8_prefix(node->string, 2), str8_lit("--"), 0)) is_option = 0;
{ }
option_name = str8_skip(option_name, 2); else if(str8_match(str8_prefix(node->string, 2), str8_lit("--"), 0))
} {
else if(str8_match(str8_prefix(node->string, 1), str8_lit("-"), 0)) option_name = str8_skip(option_name, 2);
{ }
option_name = str8_skip(option_name, 1); else if(str8_match(str8_prefix(node->string, 1), str8_lit("-"), 0))
} {
else option_name = str8_skip(option_name, 1);
{ }
is_option = 0; else
} {
} is_option = 0;
else }
{ }
is_option = 0; else
} {
is_option = 0;
// NOTE(rjf): This string is an option. }
if(is_option)
{ // NOTE(rjf): This string is an option.
B32 has_arguments = 0; if(is_option)
U64 arg_signifier_position1 = str8_find_needle(option_name, 0, str8_lit(":"), 0); {
U64 arg_signifier_position2 = str8_find_needle(option_name, 0, str8_lit("="), 0); B32 has_arguments = 0;
U64 arg_signifier_position = Min(arg_signifier_position1, arg_signifier_position2); U64 arg_signifier_position1 = str8_find_needle(option_name, 0, str8_lit(":"), 0);
String8 arg_portion_this_string = str8_skip(option_name, arg_signifier_position+1); U64 arg_signifier_position2 = str8_find_needle(option_name, 0, str8_lit("="), 0);
if(arg_signifier_position < option_name.size) U64 arg_signifier_position = Min(arg_signifier_position1, arg_signifier_position2);
{ String8 arg_portion_this_string = str8_skip(option_name, arg_signifier_position+1);
has_arguments = 1; if(arg_signifier_position < option_name.size)
} {
option_name = str8_prefix(option_name, arg_signifier_position); has_arguments = 1;
}
String8List arguments = {0}; option_name = str8_prefix(option_name, arg_signifier_position);
// NOTE(rjf): Parse arguments. String8List arguments = {0};
if(has_arguments)
{ // NOTE(rjf): Parse arguments.
for(String8Node *n = node; n; n = n->next) if(has_arguments)
{ {
next = n->next; for(String8Node *n = node; n; n = n->next)
{
String8 string = n->string; next = n->next;
if(n == node)
{ String8 string = n->string;
string = arg_portion_this_string; if(n == node)
} {
string = arg_portion_this_string;
U8 splits[] = { ',' }; }
String8List args_in_this_string = str8_split(arena, string, splits, ArrayCount(splits), 0);
for(String8Node *sub_arg = args_in_this_string.first; sub_arg; sub_arg = sub_arg->next) U8 splits[] = { ',' };
{ String8List args_in_this_string = str8_split(arena, string, splits, ArrayCount(splits), 0);
str8_list_push(arena, &arguments, sub_arg->string); for(String8Node *sub_arg = args_in_this_string.first; sub_arg; sub_arg = sub_arg->next)
} {
if(!str8_match(str8_postfix(n->string, 1), str8_lit(","), 0) && str8_list_push(arena, &arguments, sub_arg->string);
(n != node || arg_portion_this_string.size != 0)) }
{ if(!str8_match(str8_postfix(n->string, 1), str8_lit(","), 0) &&
break; (n != node || arg_portion_this_string.size != 0))
} {
} break;
} }
}
// NOTE(rjf): Register config variable. }
cmd_line_insert_opt(arena, &parsed, option_name, arguments);
} // NOTE(rjf): Register config variable.
cmd_line_insert_opt(arena, &parsed, option_name, arguments);
// NOTE(rjf): Default path, treat as a passthrough config option to be }
// handled by tool-specific code.
else if(!str8_match(node->string, str8_lit("--"), 0)) // NOTE(rjf): Default path, treat as a passthrough config option to be
{ // handled by tool-specific code.
str8_list_push(arena, &parsed.inputs, node->string); else if(!str8_match(node->string, str8_lit("--"), 0) || !first_passthrough)
after_passthrough_option = 1; {
} str8_list_push(arena, &parsed.inputs, node->string);
} after_passthrough_option = 1;
first_passthrough = 0;
return parsed; }
} }
internal CmdLineOpt * return parsed;
cmd_line_opt_from_string(CmdLine *cmd_line, String8 name) }
{
return cmd_line_opt_from_slot(cmd_line_slot_from_string(cmd_line, name), name); internal CmdLineOpt *
} cmd_line_opt_from_string(CmdLine *cmd_line, String8 name)
{
internal String8List return cmd_line_opt_from_slot(cmd_line_slot_from_string(cmd_line, name), name);
cmd_line_strings(CmdLine *cmd_line, String8 name) }
{
String8List result = {0}; internal String8List
CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name); cmd_line_strings(CmdLine *cmd_line, String8 name)
if(var != 0) {
{ String8List result = {0};
result = var->value_strings; CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name);
} if(var != 0)
return result; {
} result = var->value_strings;
}
internal String8 return result;
cmd_line_string(CmdLine *cmd_line, String8 name) }
{
String8 result = {0}; internal String8
CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name); cmd_line_string(CmdLine *cmd_line, String8 name)
if(var != 0) {
{ String8 result = {0};
result = var->value_string; CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name);
} if(var != 0)
return result; {
} result = var->value_string;
}
internal B32 return result;
cmd_line_has_flag(CmdLine *cmd_line, String8 name) }
{
CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name); internal B32
return(var != 0); cmd_line_has_flag(CmdLine *cmd_line, String8 name)
} {
CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name);
internal B32 return(var != 0);
cmd_line_has_argument(CmdLine *cmd_line, String8 name) }
{
CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name); internal B32
return(var != 0 && var->value_strings.node_count > 0); cmd_line_has_argument(CmdLine *cmd_line, String8 name)
} {
CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name);
return(var != 0 && var->value_strings.node_count > 0);
}
@@ -1,53 +1,54 @@
// 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_COMMAND_LINE_H #ifndef BASE_COMMAND_LINE_H
#define BASE_COMMAND_LINE_H #define BASE_COMMAND_LINE_H
//////////////////////////////// ////////////////////////////////
//~ rjf: Parsed Command Line Types //~ rjf: Parsed Command Line Types
typedef struct CmdLineOpt CmdLineOpt; typedef struct CmdLineOpt CmdLineOpt;
struct CmdLineOpt struct CmdLineOpt
{ {
CmdLineOpt *next; CmdLineOpt *next;
CmdLineOpt *hash_next; CmdLineOpt *hash_next;
U64 hash; U64 hash;
String8 string; String8 string;
String8List value_strings; String8List value_strings;
String8 value_string; String8 value_string;
}; };
typedef struct CmdLineOptList CmdLineOptList; typedef struct CmdLineOptList CmdLineOptList;
struct CmdLineOptList struct CmdLineOptList
{ {
U64 count; U64 count;
CmdLineOpt *first; CmdLineOpt *first;
CmdLineOpt *last; CmdLineOpt *last;
}; };
typedef struct CmdLine CmdLine; typedef struct CmdLine CmdLine;
struct CmdLine struct CmdLine
{ {
CmdLineOptList options; String8 exe_name;
String8List inputs; CmdLineOptList options;
U64 option_table_size; String8List inputs;
CmdLineOpt **option_table; U64 option_table_size;
}; CmdLineOpt **option_table;
};
////////////////////////////////
//~ NOTE(rjf): Command Line Option Parsing ////////////////////////////////
//~ NOTE(rjf): Command Line Option Parsing
internal U64 cmd_line_hash_from_string(String8 string);
internal CmdLineOpt** cmd_line_slot_from_string(CmdLine *cmd_line, String8 string); internal U64 cmd_line_hash_from_string(String8 string);
internal CmdLineOpt* cmd_line_opt_from_slot(CmdLineOpt **slot, String8 string); internal CmdLineOpt** cmd_line_slot_from_string(CmdLine *cmd_line, String8 string);
internal void cmd_line_push_opt(CmdLineOptList *list, CmdLineOpt *var); internal CmdLineOpt* cmd_line_opt_from_slot(CmdLineOpt **slot, String8 string);
internal CmdLineOpt* cmd_line_insert_opt(Arena *arena, CmdLine *cmd_line, String8 string, String8List values); internal void cmd_line_push_opt(CmdLineOptList *list, CmdLineOpt *var);
internal CmdLine cmd_line_from_string_list(Arena *arena, String8List arguments); internal CmdLineOpt* cmd_line_insert_opt(Arena *arena, CmdLine *cmd_line, String8 string, String8List values);
internal CmdLineOpt* cmd_line_opt_from_string(CmdLine *cmd_line, String8 name); internal CmdLine cmd_line_from_string_list(Arena *arena, String8List arguments);
internal String8List cmd_line_strings(CmdLine *cmd_line, String8 name); internal CmdLineOpt* cmd_line_opt_from_string(CmdLine *cmd_line, String8 name);
internal String8 cmd_line_string(CmdLine *cmd_line, String8 name); internal String8List cmd_line_strings(CmdLine *cmd_line, String8 name);
internal B32 cmd_line_has_flag(CmdLine *cmd_line, String8 name); internal String8 cmd_line_string(CmdLine *cmd_line, String8 name);
internal B32 cmd_line_has_argument(CmdLine *cmd_line, String8 name); internal B32 cmd_line_has_flag(CmdLine *cmd_line, String8 name);
internal B32 cmd_line_has_argument(CmdLine *cmd_line, String8 name);
#endif // BASE_COMMAND_LINE_H
#endif // BASE_COMMAND_LINE_H
@@ -1,154 +1,247 @@
// 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_CONTEXT_CRACKING_H #ifndef BASE_CONTEXT_CRACKING_H
#define BASE_CONTEXT_CRACKING_H #define BASE_CONTEXT_CRACKING_H
#if defined(__clang__) ////////////////////////////////
//~ rjf: Clang OS/Arch Cracking
# define COMPILER_CLANG 1
#if defined(__clang__)
# if defined(_WIN32)
# define OS_WINDOWS 1 # define COMPILER_CLANG 1
# elif defined(__gnu_linux__) || defined(__linux__)
# define OS_LINUX 1 # if defined(_WIN32)
# elif defined(__APPLE__) && defined(__MACH__) # define OS_WINDOWS 1
# define OS_MAC 1 # elif defined(__gnu_linux__) || defined(__linux__)
# else # define OS_LINUX 1
# error This compiler/platform combo is not supported yet # elif defined(__APPLE__) && defined(__MACH__)
# endif # define OS_MAC 1
# else
# if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) # error This compiler/OS combo is not supported.
# define ARCH_X64 1 # endif
# elif defined(i386) || defined(__i386) || defined(__i386__)
# define ARCH_X86 1 # if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
# elif defined(__aarch64__) # define ARCH_X64 1
# define ARCH_ARM64 1 # elif defined(i386) || defined(__i386) || defined(__i386__)
# elif defined(__arm__) # define ARCH_X86 1
# define ARCH_ARM32 1 # elif defined(__aarch64__)
# else # define ARCH_ARM64 1
# error architecture not supported yet # elif defined(__arm__)
# endif # define ARCH_ARM32 1
# else
#elif defined(_MSC_VER) # error Architecture not supported.
# endif
# define COMPILER_CL 1
////////////////////////////////
# if defined(_WIN32) //~ rjf: MSVC OS/Arch Cracking
# define OS_WINDOWS 1
# else #elif defined(_MSC_VER)
# error This compiler/platform combo is not supported yet
# endif # define COMPILER_MSVC 1
# if defined(_M_AMD64) # if _MSC_VER >= 1920
# define ARCH_X64 1 # define COMPILER_MSVC_YEAR 2019
# elif defined(_M_IX86) # elif _MSC_VER >= 1910
# define ARCH_X86 1 # define COMPILER_MSVC_YEAR 2017
# elif defined(_M_ARM64) # elif _MSC_VER >= 1900
# define ARCH_ARM64 1 # define COMPILER_MSVC_YEAR 2015
# elif defined(_M_ARM) # elif _MSC_VER >= 1800
# define ARCH_ARM32 1 # define COMPILER_MSVC_YEAR 2013
# else # elif _MSC_VER >= 1700
# error architecture not supported yet # define COMPILER_MSVC_YEAR 2012
# endif # elif _MSC_VER >= 1600
# define COMPILER_MSVC_YEAR 2010
#elif defined(__GNUC__) || defined(__GNUG__) # elif _MSC_VER >= 1500
# define COMPILER_MSVC_YEAR 2008
# define COMPILER_GCC 1 # elif _MSC_VER >= 1400
# define COMPILER_MSVC_YEAR 2005
# if defined(__gnu_linux__) || defined(__linux__) # else
# define OS_LINUX 1 # define COMPILER_MSVC_YEAR 0
# else # endif
# error This compiler/platform combo is not supported yet
# endif # if defined(_WIN32)
# define OS_WINDOWS 1
# if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) # else
# define ARCH_X64 1 # error This compiler/OS combo is not supported.
# elif defined(i386) || defined(__i386) || defined(__i386__) # endif
# define ARCH_X86 1
# elif defined(__aarch64__) # if defined(_M_AMD64)
# define ARCH_ARM64 1 # define ARCH_X64 1
# elif defined(__arm__) # elif defined(_M_IX86)
# define ARCH_ARM32 1 # define ARCH_X86 1
# else # elif defined(_M_ARM64)
# error architecture not supported yet # define ARCH_ARM64 1
# endif # elif defined(_M_ARM)
# define ARCH_ARM32 1
#else # else
# error This compiler is not supported yet # error Architecture not supported.
#endif # endif
#if defined(ARCH_X64) ////////////////////////////////
# define ARCH_64BIT 1 //~ rjf: GCC OS/Arch Cracking
#elif defined(ARCH_X86)
# define ARCH_32BIT 1 #elif defined(__GNUC__) || defined(__GNUG__)
#endif
# define COMPILER_GCC 1
#if defined(__cplusplus)
# define LANG_CPP 1 # if defined(__gnu_linux__) || defined(__linux__)
#else # define OS_LINUX 1
# define LANG_C 1 # else
#endif # error This compiler/OS combo is not supported.
# endif
// zeroify
# if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
#if !defined(ARCH_32BIT) # define ARCH_X64 1
# define ARCH_32BIT 0 # elif defined(i386) || defined(__i386) || defined(__i386__)
#endif # define ARCH_X86 1
#if !defined(ARCH_64BIT) # elif defined(__aarch64__)
# define ARCH_64BIT 0 # define ARCH_ARM64 1
#endif # elif defined(__arm__)
#if !defined(ARCH_X64) # define ARCH_ARM32 1
# define ARCH_X64 0 # else
#endif # error Architecture not supported.
#if !defined(ARCH_X86) # endif
# define ARCH_X86 0
#endif #else
#if !defined(ARCH_ARM64) # error Compiler not supported.
# define ARCH_ARM64 0 #endif
#endif
#if !defined(ARCH_ARM32) ////////////////////////////////
# define ARCH_ARM32 0 //~ rjf: Arch Cracking
#endif
#if !defined(COMPILER_CL) #if defined(ARCH_X64)
# define COMPILER_CL 0 # define ARCH_64BIT 1
#endif #elif defined(ARCH_X86)
#if !defined(COMPILER_GCC) # define ARCH_32BIT 1
# define COMPILER_GCC 0 #endif
#endif
#if !defined(COMPILER_CLANG) #if ARCH_ARM32 || ARCH_ARM64 || ARCH_X64 || ARCH_X86
# define COMPILER_CLANG 0 # define ARCH_LITTLE_ENDIAN 1
#endif #else
#if !defined(OS_WINDOWS) # error Endianness of this architecture not understood by context cracker.
# define OS_WINDOWS 0 #endif
#endif
#if !defined(OS_LINUX) ////////////////////////////////
# define OS_LINUX 0 //~ rjf: Language Cracking
#endif
#if !defined(OS_MAC) #if defined(__cplusplus)
# define OS_MAC 0 # define LANG_CPP 1
#endif #else
#if !defined(LANG_CPP) # define LANG_C 1
# define LANG_CPP 0 #endif
#endif
#if !defined(LANG_C) ////////////////////////////////
# define LANG_C 0 //~ rjf: Build Option Cracking
#endif
#if !defined(BUILD_DEBUG)
#if ARCH_ARM32 || ARCH_ARM64 || ARCH_X64 || ARCH_X86 # define BUILD_DEBUG 1
# define ARCH_LITTLE_ENDIAN 1 #endif
#else
# error Endianness of this architecture not understood by context cracker #if !defined(BUILD_SUPPLEMENTARY_UNIT)
#endif # define BUILD_SUPPLEMENTARY_UNIT 0
#endif
////////////////////////////////
//~ rjf: Unsupported Errors #if !defined(BUILD_ENTRY_DEFINING_UNIT)
# define BUILD_ENTRY_DEFINING_UNIT 1
#if ARCH_X86 #endif
# error You tried to build in x86 (32 bit) mode, but currently, only building in x64 (64 bit) mode is supported.
#endif #if !defined(BUILD_CONSOLE_INTERFACE)
#if !ARCH_X64 # define BUILD_CONSOLE_INTERFACE 0
# error You tried to build with an unsupported architecture. Currently, only building in x64 mode is supported. #endif
#endif
#if !defined(BUILD_VERSION_MAJOR)
#endif // BASE_CONTEXT_CRACKING_H # 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)
# define ARCH_32BIT 0
#endif
#if !defined(ARCH_64BIT)
# define ARCH_64BIT 0
#endif
#if !defined(ARCH_X64)
# define ARCH_X64 0
#endif
#if !defined(ARCH_X86)
# define ARCH_X86 0
#endif
#if !defined(ARCH_ARM64)
# define ARCH_ARM64 0
#endif
#if !defined(ARCH_ARM32)
# define ARCH_ARM32 0
#endif
#if !defined(COMPILER_MSVC)
# define COMPILER_MSVC 0
#endif
#if !defined(COMPILER_GCC)
# define COMPILER_GCC 0
#endif
#if !defined(COMPILER_CLANG)
# define COMPILER_CLANG 0
#endif
#if !defined(OS_WINDOWS)
# define OS_WINDOWS 0
#endif
#if !defined(OS_LINUX)
# define OS_LINUX 0
#endif
#if !defined(OS_MAC)
# define OS_MAC 0
#endif
#if !defined(LANG_CPP)
# define LANG_CPP 0
#endif
#if !defined(LANG_C)
# define LANG_C 0
#endif
////////////////////////////////
//~ rjf: Unsupported Errors
#if ARCH_X86
# error You tried to build in x86 (32 bit) mode, but currently, only building in x64 (64 bit) mode is supported.
#endif
#if !ARCH_X64
# error You tried to build with an unsupported architecture. Currently, only building in x64 mode is supported.
#endif
#endif // BASE_CONTEXT_CRACKING_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
+19 -18
View File
@@ -1,18 +1,19 @@
// 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/)
//////////////////////////////// ////////////////////////////////
//~ rjf: Base Includes //~ rjf: Base Includes
#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"
+23 -23
View File
@@ -1,23 +1,23 @@
// 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_INC_H #ifndef BASE_INC_H
#define BASE_INC_H #define BASE_INC_H
//////////////////////////////// ////////////////////////////////
//~ 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_strings.h"
#include "metagen_base_string.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_markup.h"
#include "metagen_base_arena_dev.h" #include "metagen_base_log.h"
#include "metagen_base_bits.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
+103
View File
@@ -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
+21 -2
View File
@@ -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);
}
+12 -79
View File
@@ -1,79 +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/)
#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 #endif // BASE_MARKUP_H
#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
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -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
@@ -1,351 +1,381 @@
// 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
#define STB_SPRINTF_DECORATE(name) raddbg_##name #define STB_SPRINTF_DECORATE(name) raddbg_##name
#include "third_party/stb/stb_sprintf.h" #include "third_party/stb/stb_sprintf.h"
//////////////////////////////// ////////////////////////////////
//~ rjf: String Types //~ rjf: String Types
typedef struct String8 String8; typedef struct String8 String8;
struct String8 struct String8
{ {
U8 *str; U8 *str;
U64 size; U64 size;
}; };
typedef struct String16 String16; typedef struct String16 String16;
struct String16 struct String16
{ {
U16 *str; U16 *str;
U64 size; U64 size;
}; };
typedef struct String32 String32; typedef struct String32 String32;
struct String32 struct String32
{ {
U32 *str; U32 *str;
U64 size; U64 size;
}; };
//////////////////////////////// ////////////////////////////////
//~ rjf: String List & Array Types //~ rjf: String List & Array Types
typedef struct String8Node String8Node; typedef struct String8Node String8Node;
struct String8Node struct String8Node
{ {
String8Node *next; String8Node *next;
String8 string; String8 string;
}; };
typedef struct String8MetaNode String8MetaNode; typedef struct String8MetaNode String8MetaNode;
struct String8MetaNode struct String8MetaNode
{ {
String8MetaNode *next; String8MetaNode *next;
String8Node *node; String8Node *node;
}; };
typedef struct String8List String8List; typedef struct String8List String8List;
struct String8List struct String8List
{ {
String8Node *first; String8Node *first;
String8Node *last; String8Node *last;
U64 node_count; U64 node_count;
U64 total_size; U64 total_size;
}; };
typedef struct String8Array String8Array; typedef struct String8Array String8Array;
struct String8Array struct String8Array
{ {
String8 *strings; String8 *v;
U64 count; U64 count;
}; };
//////////////////////////////// ////////////////////////////////
//~ rjf: String Matching, Splitting, & Joining Types //~ rjf: String Matching, Splitting, & Joining Types
typedef U32 StringMatchFlags; typedef U32 StringMatchFlags;
enum enum
{ {
StringMatchFlag_CaseInsensitive = (1 << 0), StringMatchFlag_CaseInsensitive = (1 << 0),
StringMatchFlag_RightSideSloppy = (1 << 1), StringMatchFlag_RightSideSloppy = (1 << 1),
StringMatchFlag_SlashInsensitive = (1 << 2), StringMatchFlag_SlashInsensitive = (1 << 2),
}; };
typedef U32 StringSplitFlags; typedef U32 StringSplitFlags;
enum enum
{ {
StringSplitFlag_KeepEmpties = (1 << 0), StringSplitFlag_KeepEmpties = (1 << 0),
}; };
typedef enum PathStyle typedef enum PathStyle
{ {
PathStyle_Relative, PathStyle_Relative,
PathStyle_WindowsAbsolute, PathStyle_WindowsAbsolute,
PathStyle_UnixAbsolute, PathStyle_UnixAbsolute,
#if OS_WINDOWS #if OS_WINDOWS
PathStyle_SystemAbsolute = PathStyle_WindowsAbsolute PathStyle_SystemAbsolute = PathStyle_WindowsAbsolute
#elif OS_LINUX #elif OS_LINUX
PathStyle_SystemAbsolute = PathStyle_UnixAbsolute PathStyle_SystemAbsolute = PathStyle_UnixAbsolute
#else #else
# error "absolute path style is undefined for this OS" # error "absolute path style is undefined for this OS"
#endif #endif
} }
PathStyle; PathStyle;
typedef struct StringJoin StringJoin; typedef struct StringJoin StringJoin;
struct StringJoin struct StringJoin
{ {
String8 pre; String8 pre;
String8 sep; String8 sep;
String8 post; String8 post;
}; };
//////////////////////////////// ////////////////////////////////
//~ rjf: String Pair Types //~ rjf: String Pair Types
typedef struct String8TxtPtPair String8TxtPtPair; typedef struct String8TxtPtPair String8TxtPtPair;
struct String8TxtPtPair struct String8TxtPtPair
{ {
String8 string; String8 string;
TxtPt pt; TxtPt pt;
}; };
//////////////////////////////// ////////////////////////////////
//~ rjf: UTF Decoding Types //~ rjf: UTF Decoding Types
typedef struct UnicodeDecode UnicodeDecode; typedef struct UnicodeDecode UnicodeDecode;
struct UnicodeDecode struct UnicodeDecode
{ {
U32 inc; U32 inc;
U32 codepoint; U32 codepoint;
}; };
//////////////////////////////// ////////////////////////////////
//~ rjf: Character Classification & Conversion Functions //~ rjf: String Fuzzy Matching Types
internal B32 char_is_space(U8 c); typedef struct FuzzyMatchRangeNode FuzzyMatchRangeNode;
internal B32 char_is_upper(U8 c); struct FuzzyMatchRangeNode
internal B32 char_is_lower(U8 c); {
internal B32 char_is_alpha(U8 c); FuzzyMatchRangeNode *next;
internal B32 char_is_slash(U8 c); Rng1U64 range;
internal B32 char_is_digit(U8 c, U32 base); };
internal U8 char_to_lower(U8 c);
internal U8 char_to_upper(U8 c); typedef struct FuzzyMatchRangeList FuzzyMatchRangeList;
internal U8 char_to_correct_slash(U8 c); struct FuzzyMatchRangeList
{
//////////////////////////////// FuzzyMatchRangeNode *first;
//~ rjf: C-String Measurement FuzzyMatchRangeNode *last;
U64 count;
internal U64 cstring8_length(U8 *c); U64 needle_part_count;
internal U64 cstring16_length(U16 *c); U64 total_dim;
internal U64 cstring32_length(U32 *c); };
//////////////////////////////// ////////////////////////////////
//~ rjf: String Constructors //~ rjf: Character Classification & Conversion Functions
#define str8_lit(S) str8((U8*)(S), sizeof(S) - 1) internal B32 char_is_space(U8 c);
#define str8_lit_comp(S) {(U8*)(S), sizeof(S) - 1,} internal B32 char_is_upper(U8 c);
#define str8_varg(S) (int)((S).size), ((S).str) internal B32 char_is_lower(U8 c);
internal B32 char_is_alpha(U8 c);
#define str8_array(S,C) str8((U8*)(S), sizeof(*(S))*(C)) internal B32 char_is_slash(U8 c);
#define str8_array_fixed(S) str8((U8*)(S), sizeof(S)) internal B32 char_is_digit(U8 c, U32 base);
#define str8_struct(S) str8((U8*)(S), sizeof(*(S))) internal U8 char_to_lower(U8 c);
internal U8 char_to_upper(U8 c);
internal String8 str8(U8 *str, U64 size); internal U8 char_to_correct_slash(U8 c);
internal String8 str8_range(U8 *first, U8 *one_past_last);
internal String8 str8_zero(void); ////////////////////////////////
internal String16 str16(U16 *str, U64 size); //~ rjf: C-String Measurement
internal String16 str16_range(U16 *first, U16 *one_past_last);
internal String16 str16_zero(void); internal U64 cstring8_length(U8 *c);
internal String32 str32(U32 *str, U64 size); internal U64 cstring16_length(U16 *c);
internal String32 str32_range(U32 *first, U32 *one_past_last); internal U64 cstring32_length(U32 *c);
internal String32 str32_zero(void);
internal String8 str8_cstring(char *c); ////////////////////////////////
internal String16 str16_cstring(U16 *c); //~ rjf: String Constructors
internal String32 str32_cstring(U32 *c);
internal String8 str8_cstring_capped(void *cstr, void *cap); #define str8_lit(S) str8((U8*)(S), sizeof(S) - 1)
#define str8_lit_comp(S) {(U8*)(S), sizeof(S) - 1,}
//////////////////////////////// #define str8_varg(S) (int)((S).size), ((S).str)
//~ rjf: String Stylization
#define str8_array(S,C) str8((U8*)(S), sizeof(*(S))*(C))
internal String8 upper_from_str8(Arena *arena, String8 string); #define str8_array_fixed(S) str8((U8*)(S), sizeof(S))
internal String8 lower_from_str8(Arena *arena, String8 string); #define str8_struct(S) str8((U8*)(S), sizeof(*(S)))
internal String8 backslashed_from_str8(Arena *arena, String8 string);
internal String8 str8(U8 *str, U64 size);
//////////////////////////////// internal String8 str8_range(U8 *first, U8 *one_past_last);
//~ rjf: String Matching internal String8 str8_zero(void);
internal String16 str16(U16 *str, U64 size);
internal B32 str8_match(String8 a, String8 b, StringMatchFlags flags); internal String16 str16_range(U16 *first, U16 *one_past_last);
internal U64 str8_find_needle(String8 string, U64 start_pos, String8 needle, StringMatchFlags flags); internal String16 str16_zero(void);
internal B32 str8_ends_with(String8 string, String8 end, StringMatchFlags flags); internal String32 str32(U32 *str, U64 size);
internal String32 str32_range(U32 *first, U32 *one_past_last);
//////////////////////////////// internal String32 str32_zero(void);
//~ rjf: String Slicing internal String8 str8_cstring(char *c);
internal String16 str16_cstring(U16 *c);
internal String8 str8_substr(String8 str, Rng1U64 range); internal String32 str32_cstring(U32 *c);
internal String8 str8_prefix(String8 str, U64 size); internal String8 str8_cstring_capped(void *cstr, void *cap);
internal String8 str8_skip(String8 str, U64 amt);
internal String8 str8_postfix(String8 str, U64 size); ////////////////////////////////
internal String8 str8_chop(String8 str, U64 amt); //~ rjf: String Stylization
internal String8 str8_skip_chop_whitespace(String8 string);
internal String8 upper_from_str8(Arena *arena, String8 string);
//////////////////////////////// internal String8 lower_from_str8(Arena *arena, String8 string);
//~ rjf: String Formatting & Copying internal String8 backslashed_from_str8(Arena *arena, String8 string);
internal String8 push_str8_cat(Arena *arena, String8 s1, String8 s2); ////////////////////////////////
internal String8 push_str8_copy(Arena *arena, String8 s); //~ rjf: String Matching
internal String8 push_str8fv(Arena *arena, char *fmt, va_list args);
internal String8 push_str8f(Arena *arena, char *fmt, ...); internal B32 str8_match(String8 a, String8 b, StringMatchFlags flags);
internal U64 str8_find_needle(String8 string, U64 start_pos, String8 needle, StringMatchFlags flags);
//////////////////////////////// internal B32 str8_ends_with(String8 string, String8 end, StringMatchFlags flags);
//~ rjf: String <=> Integer Conversions
////////////////////////////////
//- rjf: string -> integer //~ rjf: String Slicing
internal S64 sign_from_str8(String8 string, String8 *string_tail);
internal B32 str8_is_integer(String8 string, U32 radix); internal String8 str8_substr(String8 str, Rng1U64 range);
internal U64 u64_from_str8(String8 string, U32 radix); internal String8 str8_prefix(String8 str, U64 size);
internal S64 s64_from_str8(String8 string, U32 radix); internal String8 str8_skip(String8 str, U64 amt);
internal B32 try_u64_from_str8_c_rules(String8 string, U64 *x); internal String8 str8_postfix(String8 str, U64 size);
internal B32 try_s64_from_str8_c_rules(String8 string, S64 *x); internal String8 str8_chop(String8 str, U64 amt);
internal String8 str8_skip_chop_whitespace(String8 string);
//- 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); //~ rjf: String Formatting & Copying
internal U64 base16_size_from_data_size(U64 size_in_bytes);
internal U64 base16_from_data(U8 *dst, U8 *src, U64 src_size); internal String8 push_str8_cat(Arena *arena, String8 s1, String8 s2);
internal String8 push_str8_copy(Arena *arena, String8 s);
//- rjf: integer -> string internal String8 push_str8fv(Arena *arena, char *fmt, va_list args);
internal String8 str8_from_memory_size(Arena *arena, U64 z); internal String8 push_str8f(Arena *arena, char *fmt, ...);
internal String8 str8_from_u64(Arena *arena, U64 u64, U32 radix, U8 min_digits, U8 digit_group_separator);
internal String8 str8_from_s64(Arena *arena, S64 s64, U32 radix, U8 min_digits, U8 digit_group_separator); ////////////////////////////////
//~ rjf: String <=> Integer Conversions
////////////////////////////////
//~ rjf: String <=> Float Conversions //- rjf: string -> integer
internal S64 sign_from_str8(String8 string, String8 *string_tail);
internal F64 f64_from_str8(String8 string); internal B32 str8_is_integer(String8 string, U32 radix);
internal U64 u64_from_str8(String8 string, U32 radix);
//////////////////////////////// internal S64 s64_from_str8(String8 string, U32 radix);
//~ rjf: String List Construction Functions 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 String8Node* str8_list_push_node(String8List *list, String8Node *node);
internal String8Node* str8_list_push_node_set_string(String8List *list, String8Node *node, String8 string); //- rjf: integer -> string
internal String8Node* str8_list_push_node_front(String8List *list, String8Node *node); internal String8 str8_from_memory_size(Arena *arena, U64 z);
internal String8Node* str8_list_push_node_front_set_string(String8List *list, String8Node *node, String8 string); internal String8 str8_from_u64(Arena *arena, U64 u64, U32 radix, U8 min_digits, U8 digit_group_separator);
internal String8Node* str8_list_push(Arena *arena, String8List *list, String8 string); internal String8 str8_from_s64(Arena *arena, S64 s64, U32 radix, U8 min_digits, U8 digit_group_separator);
internal String8Node* str8_list_push_front(Arena *arena, String8List *list, String8 string);
internal void str8_list_concat_in_place(String8List *list, String8List *to_push); ////////////////////////////////
internal String8Node* str8_list_push_aligner(Arena *arena, String8List *list, U64 min, U64 align); //~ rjf: String <=> Float Conversions
internal String8Node* str8_list_pushf(Arena *arena, String8List *list, char *fmt, ...);
internal String8Node* str8_list_push_frontf(Arena *arena, String8List *list, char *fmt, ...); internal F64 f64_from_str8(String8 string);
internal String8List str8_list_copy(Arena *arena, String8List *list);
#define str8_list_first(list) ((list)->first ? (list)->first->string : str8_zero()) ////////////////////////////////
//~ rjf: String List Construction Functions
////////////////////////////////
//~ rjf: String Splitting & Joining internal String8Node* str8_list_push_node(String8List *list, String8Node *node);
internal String8Node* str8_list_push_node_set_string(String8List *list, String8Node *node, String8 string);
internal String8List str8_split(Arena *arena, String8 string, U8 *split_chars, U64 split_char_count, StringSplitFlags flags); internal String8Node* str8_list_push_node_front(String8List *list, String8Node *node);
internal String8List str8_split_by_string_chars(Arena *arena, String8 string, String8 split_chars, StringSplitFlags flags); internal String8Node* str8_list_push_node_front_set_string(String8List *list, String8Node *node, String8 string);
internal String8List str8_list_split_by_string_chars(Arena *arena, String8List list, String8 split_chars, StringSplitFlags flags); internal String8Node* str8_list_push(Arena *arena, String8List *list, String8 string);
internal String8 str8_list_join(Arena *arena, String8List *list, StringJoin *optional_params); internal String8Node* str8_list_push_front(Arena *arena, String8List *list, String8 string);
internal void str8_list_from_flags(Arena *arena, String8List *list, U32 flags, String8 *flag_string_table, U32 flag_string_count); internal void str8_list_concat_in_place(String8List *list, String8List *to_push);
internal String8Node* str8_list_push_aligner(Arena *arena, String8List *list, U64 min, U64 align);
//////////////////////////////// internal String8Node* str8_list_pushf(Arena *arena, String8List *list, char *fmt, ...);
//~ rjf; String Arrays internal String8Node* str8_list_push_frontf(Arena *arena, String8List *list, char *fmt, ...);
internal String8List str8_list_copy(Arena *arena, String8List *list);
internal String8Array str8_array_from_list(Arena *arena, String8List *list); #define str8_list_first(list) ((list)->first ? (list)->first->string : str8_zero())
internal String8Array str8_array_reserve(Arena *arena, U64 count);
////////////////////////////////
//////////////////////////////// //~ rjf: String Splitting & Joining
//~ rjf: String Path Helpers
internal String8List str8_split(Arena *arena, String8 string, U8 *split_chars, U64 split_char_count, StringSplitFlags flags);
internal String8 str8_chop_last_slash(String8 string); internal String8List str8_split_by_string_chars(Arena *arena, String8 string, String8 split_chars, StringSplitFlags flags);
internal String8 str8_skip_last_slash(String8 string); internal String8List str8_list_split_by_string_chars(Arena *arena, String8List list, String8 split_chars, StringSplitFlags flags);
internal String8 str8_chop_last_dot(String8 string); internal String8 str8_list_join(Arena *arena, String8List *list, StringJoin *optional_params);
internal String8 str8_skip_last_dot(String8 string); internal void str8_list_from_flags(Arena *arena, String8List *list, U32 flags, String8 *flag_string_table, U32 flag_string_count);
internal PathStyle path_style_from_str8(String8 string); ////////////////////////////////
internal String8List str8_split_path(Arena *arena, String8 string); //~ rjf; String Arrays
internal void str8_path_list_resolve_dots_in_place(String8List *path, PathStyle style);
internal String8 str8_path_list_join_by_style(Arena *arena, String8List *path, PathStyle style); internal String8Array str8_array_from_list(Arena *arena, String8List *list);
internal String8Array str8_array_reserve(Arena *arena, U64 count);
internal String8TxtPtPair str8_txt_pt_pair_from_string(String8 string);
////////////////////////////////
//////////////////////////////// //~ rjf: String Path Helpers
//~ rjf: UTF-8 & UTF-16 Decoding/Encoding
internal String8 str8_chop_last_slash(String8 string);
internal UnicodeDecode utf8_decode(U8 *str, U64 max); internal String8 str8_skip_last_slash(String8 string);
internal UnicodeDecode utf16_decode(U16 *str, U64 max); internal String8 str8_chop_last_dot(String8 string);
internal U32 utf8_encode(U8 *str, U32 codepoint); internal String8 str8_skip_last_dot(String8 string);
internal U32 utf16_encode(U16 *str, U32 codepoint);
internal U32 utf8_from_utf32_single(U8 *buffer, U32 character); internal PathStyle path_style_from_str8(String8 string);
internal String8List str8_split_path(Arena *arena, String8 string);
//////////////////////////////// internal void str8_path_list_resolve_dots_in_place(String8List *path, PathStyle style);
//~ rjf: Unicode String Conversions internal String8 str8_path_list_join_by_style(Arena *arena, String8List *path, PathStyle style);
internal String8 str8_from_16(Arena *arena, String16 in); internal String8TxtPtPair str8_txt_pt_pair_from_string(String8 string);
internal String16 str16_from_8(Arena *arena, String8 in);
internal String8 str8_from_32(Arena *arena, String32 in); ////////////////////////////////
internal String32 str32_from_8(Arena *arena, String8 in); //~ rjf: UTF-8 & UTF-16 Decoding/Encoding
//////////////////////////////// internal UnicodeDecode utf8_decode(U8 *str, U64 max);
//~ rjf: Basic Types & Space Enum -> String Conversions internal UnicodeDecode utf16_decode(U16 *str, U64 max);
internal U32 utf8_encode(U8 *str, U32 codepoint);
internal String8 string_from_dimension(Dimension dimension); internal U32 utf16_encode(U16 *str, U32 codepoint);
internal String8 string_from_side(Side side); internal U32 utf8_from_utf32_single(U8 *buffer, U32 character);
internal String8 string_from_operating_system(OperatingSystem os);
internal String8 string_from_architecture(Architecture arch); ////////////////////////////////
//~ rjf: Unicode String Conversions
////////////////////////////////
//~ rjf: Time Types -> String internal String8 str8_from_16(Arena *arena, String16 in);
internal String16 str16_from_8(Arena *arena, String8 in);
internal String8 string_from_week_day(WeekDay week_day); internal String8 str8_from_32(Arena *arena, String32 in);
internal String8 string_from_month(Month month); internal String32 str32_from_8(Arena *arena, String8 in);
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 string_from_elapsed_time(Arena *arena, DateTime dt); //~ rjf: Basic Types & Space Enum -> String Conversions
//////////////////////////////// internal String8 string_from_dimension(Dimension dimension);
//~ rjf: String <-> Color internal String8 string_from_side(Side side);
internal String8 string_from_operating_system(OperatingSystem os);
internal String8 hex_string_from_rgba_4f32(Arena *arena, Vec4F32 rgba); internal String8 string_from_architecture(Architecture arch);
internal Vec4F32 rgba_from_hex_string_4f32(String8 hex_string);
////////////////////////////////
//////////////////////////////// //~ rjf: Time Types -> String
//~ NOTE(allen): Serialization Helpers
internal String8 string_from_week_day(WeekDay week_day);
internal void str8_serial_begin(Arena *arena, String8List *srl); internal String8 string_from_month(Month month);
internal String8 str8_serial_end(Arena *arena, String8List *srl); internal String8 push_date_time_string(Arena *arena, DateTime *date_time);
internal void str8_serial_write_to_dst(String8List *srl, void *out); internal String8 push_file_name_date_time_string(Arena *arena, DateTime *date_time);
internal U64 str8_serial_push_align(Arena *arena, String8List *srl, U64 align); internal String8 string_from_elapsed_time(Arena *arena, DateTime dt);
internal void * str8_serial_push_size(Arena *arena, String8List *srl, U64 size);
internal void * str8_serial_push_data(Arena *arena, String8List *srl, void *data, U64 size); ////////////////////////////////
internal void str8_serial_push_data_list(Arena *arena, String8List *srl, String8Node *first); //~ rjf: Basic Text Indentation
internal void str8_serial_push_u64(Arena *arena, String8List *srl, U64 x);
internal void str8_serial_push_u32(Arena *arena, String8List *srl, U32 x); internal String8 indented_from_string(Arena *arena, String8 string);
internal void str8_serial_push_u16(Arena *arena, String8List *srl, U16 x);
internal void str8_serial_push_u8(Arena *arena, String8List *srl, U8 x); ////////////////////////////////
internal void str8_serial_push_cstr(Arena *arena, String8List *srl, String8 str); //~ rjf: Text Wrapping
internal void str8_serial_push_string(Arena *arena, String8List *srl, String8 str);
#define str8_serial_push_array(arena, srl, ptr, count) str8_serial_push_data(arena, srl, ptr, sizeof(*(ptr)) * (count)) internal String8List wrapped_lines_from_string(Arena *arena, String8 string, U64 first_line_max_width, U64 max_width, U64 wrap_indent);
#define str8_serial_push_struct(arena, srl, ptr) str8_serial_push_array(arena, srl, ptr, 1)
////////////////////////////////
//////////////////////////////// //~ rjf: String <-> Color
//~ rjf: Deserialization Helpers
internal String8 hex_string_from_rgba_4f32(Arena *arena, Vec4F32 rgba);
internal U64 str8_deserial_read(String8 string, U64 off, void *read_dst, U64 read_size, U64 granularity); internal Vec4F32 rgba_from_hex_string_4f32(String8 hex_string);
internal U64 str8_deserial_find_first_match(String8 string, U64 off, U16 scan_val);
internal void * str8_deserial_get_raw_ptr(String8 string, U64 off, U64 size);internal U64 str8_deserial_read_cstr(String8 string, U64 off, String8 *cstr_out); ////////////////////////////////
internal U64 str8_deserial_read_windows_utf16_string16(String8 string, U64 off, String16 *str_out); //~ rjf: String Fuzzy Matching
internal U64 str8_deserial_read_block(String8 string, U64 off, U64 size, String8 *block_out);
#define str8_deserial_read_array(string, off, ptr, count) str8_deserial_read((string), (off), (ptr), sizeof(*(ptr))*(count), sizeof(*(ptr))) internal FuzzyMatchRangeList fuzzy_match_find(Arena *arena, String8 needle, String8 haystack);
#define str8_deserial_read_struct(string, off, ptr) str8_deserial_read((string), (off), (ptr), sizeof(*(ptr)), sizeof(*(ptr))) internal FuzzyMatchRangeList fuzzy_match_range_list_copy(Arena *arena, FuzzyMatchRangeList *src);
#endif // BASE_STRING_H ////////////////////////////////
//~ NOTE(allen): Serialization Helpers
internal void str8_serial_begin(Arena *arena, String8List *srl);
internal String8 str8_serial_end(Arena *arena, String8List *srl);
internal void str8_serial_write_to_dst(String8List *srl, void *out);
internal U64 str8_serial_push_align(Arena *arena, String8List *srl, U64 align);
internal void * str8_serial_push_size(Arena *arena, String8List *srl, U64 size);
internal void * str8_serial_push_data(Arena *arena, String8List *srl, void *data, U64 size);
internal void str8_serial_push_data_list(Arena *arena, String8List *srl, String8Node *first);
internal void str8_serial_push_u64(Arena *arena, String8List *srl, U64 x);
internal void str8_serial_push_u32(Arena *arena, String8List *srl, U32 x);
internal void str8_serial_push_u16(Arena *arena, String8List *srl, U16 x);
internal void str8_serial_push_u8(Arena *arena, String8List *srl, U8 x);
internal void str8_serial_push_cstr(Arena *arena, String8List *srl, String8 str);
internal void str8_serial_push_string(Arena *arena, String8List *srl, String8 str);
#define str8_serial_push_array(arena, srl, ptr, count) str8_serial_push_data(arena, srl, ptr, sizeof(*(ptr)) * (count))
#define str8_serial_push_struct(arena, srl, ptr) str8_serial_push_array(arena, srl, ptr, 1)
////////////////////////////////
//~ rjf: Deserialization Helpers
internal U64 str8_deserial_read(String8 string, U64 off, void *read_dst, U64 read_size, U64 granularity);
internal U64 str8_deserial_find_first_match(String8 string, U64 off, U16 scan_val);
internal void * str8_deserial_get_raw_ptr(String8 string, U64 off, U64 size);internal U64 str8_deserial_read_cstr(String8 string, U64 off, String8 *cstr_out);
internal U64 str8_deserial_read_windows_utf16_string16(String8 string, U64 off, String16 *str_out);
internal U64 str8_deserial_read_block(String8 string, U64 off, U64 size, String8 *block_out);
#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)))
#endif // BASE_STRINGS_H
@@ -1,78 +1,87 @@
// 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/)
//////////////////////////////// ////////////////////////////////
// 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
internal void internal void
tctx_init_and_equip(TCTX *tctx){ tctx_init_and_equip(TCTX *tctx){
MemoryZeroStruct(tctx); MemoryZeroStruct(tctx);
Arena **arena_ptr = tctx->arenas; Arena **arena_ptr = tctx->arenas;
for (U64 i = 0; i < ArrayCount(tctx->arenas); i += 1, arena_ptr += 1){ for (U64 i = 0; i < ArrayCount(tctx->arenas); i += 1, arena_ptr += 1){
*arena_ptr = arena_alloc(); *arena_ptr = arena_alloc();
} }
tctx_thread_local = tctx; tctx_thread_local = tctx;
} }
internal TCTX* internal void
tctx_get_equipped(void){ tctx_release(void)
return(tctx_thread_local); {
} for(U64 i = 0; i < ArrayCount(tctx_thread_local->arenas); i += 1)
{
internal Arena* arena_release(tctx_thread_local->arenas[i]);
tctx_get_scratch(Arena **conflicts, U64 count){ }
TCTX *tctx = tctx_get_equipped(); }
Arena *result = 0; internal TCTX*
Arena **arena_ptr = tctx->arenas; tctx_get_equipped(void){
for (U64 i = 0; i < ArrayCount(tctx->arenas); i += 1, arena_ptr += 1){ return(tctx_thread_local);
Arena **conflict_ptr = conflicts; }
B32 has_conflict = 0;
for (U64 j = 0; j < count; j += 1, conflict_ptr += 1){ internal Arena*
if (*arena_ptr == *conflict_ptr){ tctx_get_scratch(Arena **conflicts, U64 count){
has_conflict = 1; TCTX *tctx = tctx_get_equipped();
break;
} Arena *result = 0;
} Arena **arena_ptr = tctx->arenas;
if (!has_conflict){ for (U64 i = 0; i < ArrayCount(tctx->arenas); i += 1, arena_ptr += 1){
result = *arena_ptr; Arena **conflict_ptr = conflicts;
break; B32 has_conflict = 0;
} for (U64 j = 0; j < count; j += 1, conflict_ptr += 1){
} if (*arena_ptr == *conflict_ptr){
has_conflict = 1;
return(result); break;
} }
}
internal void if (!has_conflict){
tctx_set_thread_name(String8 string){ result = *arena_ptr;
TCTX *tctx = tctx_get_equipped(); break;
U64 size = ClampTop(string.size, sizeof(tctx->thread_name)); }
MemoryCopy(tctx->thread_name, string.str, size); }
tctx->thread_name_size = size;
} return(result);
}
internal String8
tctx_get_thread_name(void){ internal void
TCTX *tctx = tctx_get_equipped(); tctx_set_thread_name(String8 string){
String8 result = str8(tctx->thread_name, tctx->thread_name_size); TCTX *tctx = tctx_get_equipped();
return(result); U64 size = ClampTop(string.size, sizeof(tctx->thread_name));
} MemoryCopy(tctx->thread_name, string.str, size);
tctx->thread_name_size = size;
internal void }
tctx_write_srcloc(char *file_name, U64 line_number){
TCTX *tctx = tctx_get_equipped(); internal String8
tctx->file_name = file_name; tctx_get_thread_name(void){
tctx->line_number = line_number; TCTX *tctx = tctx_get_equipped();
} String8 result = str8(tctx->thread_name, tctx->thread_name_size);
return(result);
internal void }
tctx_read_srcloc(char **file_name, U64 *line_number){
TCTX *tctx = tctx_get_equipped(); internal void
*file_name = tctx->file_name; tctx_write_srcloc(char *file_name, U64 line_number){
*line_number = tctx->line_number; TCTX *tctx = tctx_get_equipped();
} tctx->file_name = file_name;
tctx->line_number = line_number;
}
internal void
tctx_read_srcloc(char **file_name, U64 *line_number){
TCTX *tctx = tctx_get_equipped();
*file_name = tctx->file_name;
*line_number = tctx->line_number;
}
@@ -1,40 +1,41 @@
// 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_THREAD_CONTEXT_H #ifndef BASE_THREAD_CONTEXT_H
#define BASE_THREAD_CONTEXT_H #define BASE_THREAD_CONTEXT_H
//////////////////////////////// ////////////////////////////////
// NOTE(allen): Thread Context // NOTE(allen): Thread Context
typedef struct TCTX TCTX; typedef struct TCTX TCTX;
struct TCTX struct TCTX
{ {
Arena *arenas[2]; Arena *arenas[2];
U8 thread_name[32]; U8 thread_name[32];
U64 thread_name_size; U64 thread_name_size;
char *file_name; char *file_name;
U64 line_number; U64 line_number;
}; };
//////////////////////////////// ////////////////////////////////
// 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 TCTX* tctx_get_equipped(void); internal void tctx_release(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);
internal void tctx_set_thread_name(String8 name);
internal String8 tctx_get_thread_name(void); internal void tctx_set_thread_name(String8 name);
internal String8 tctx_get_thread_name(void);
internal void tctx_write_srcloc(char *file_name, U64 line_number);
internal void tctx_read_srcloc(char **file_name, U64 *line_number); internal void tctx_write_srcloc(char *file_name, U64 line_number);
#define tctx_write_this_srcloc() tctx_write_srcloc(__FILE__, __LINE__) internal void tctx_read_srcloc(char **file_name, U64 *line_number);
#define tctx_write_this_srcloc() tctx_write_srcloc(__FILE__, __LINE__)
#define scratch_begin(conflicts, count) temp_begin(tctx_get_scratch((conflicts), (count)))
#define scratch_end(scratch) temp_end(scratch) #define scratch_begin(conflicts, count) temp_begin(tctx_get_scratch((conflicts), (count)))
#define scratch_end(scratch) temp_end(scratch)
#endif //BASE_THREAD_CONTEXT_H
#endif // BASE_THREAD_CONTEXT_H
+656 -661
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,88 +1,134 @@
// 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
#include <stdlib.h> #define _GNU_SOURCE
#include <sys/mman.h> #include <features.h>
#include <sys/types.h> #include <stdlib.h>
#include <sys/stat.h> #include <sys/mman.h>
#include <unistd.h> #include <sys/types.h>
#include <fcntl.h> #include <sys/stat.h>
#include <linux/limits.h> #include <unistd.h>
#include <time.h> #include <fcntl.h>
#include <dirent.h> #include <linux/limits.h>
#include <pthread.h> #include <time.h>
#include <sys/syscall.h> #include <dirent.h>
#include <signal.h> #include <pthread.h>
#include <errno.h> #include <sys/syscall.h>
#include <dlfcn.h> #include <signal.h>
#include <sys/sysinfo.h> #include <errno.h>
#include <dlfcn.h>
//////////////////////////////// #include <sys/sysinfo.h>
//~ NOTE(allen): File Iterator #include <sys/random.h>
struct LNX_FileIter{ int pthread_setname_np(pthread_t thread, const char *name);
int fd; int pthread_getname_np(pthread_t thread, char *name, size_t size);
DIR *dir;
}; typedef struct tm tm;
StaticAssert(sizeof(Member(OS_FileIter, memory)) >= sizeof(LNX_FileIter), file_iter_memory_size); typedef struct timespec timespec;
//////////////////////////////// ////////////////////////////////
//~ NOTE(allen): Threading Entities //~ rjf: File Iterator
enum LNX_EntityKind{ typedef struct OS_LNX_FileIter OS_LNX_FileIter;
LNX_EntityKind_Null, struct OS_LNX_FileIter
LNX_EntityKind_Thread, {
LNX_EntityKind_Mutex, DIR *dir;
LNX_EntityKind_ConditionVariable, struct dirent *dp;
}; String8 path;
};
struct LNX_Entity{ StaticAssert(sizeof(Member(OS_FileIter, memory)) >= sizeof(OS_LNX_FileIter), os_lnx_file_iter_size_check);
LNX_Entity *next;
LNX_EntityKind kind; ////////////////////////////////
volatile U32 reference_mask; //~ rjf: Safe Call Handler Chain
union{
struct{ typedef struct OS_LNX_SafeCallChain OS_LNX_SafeCallChain;
OS_ThreadFunctionType *func; struct OS_LNX_SafeCallChain
void *ptr; {
pthread_t handle; OS_LNX_SafeCallChain *next;
} thread; OS_ThreadFunctionType *fail_handler;
pthread_mutex_t mutex; void *ptr;
pthread_cond_t cond; };
};
}; ////////////////////////////////
//~ rjf: Entities
////////////////////////////////
//~ NOTE(allen): Safe Call Chain typedef enum OS_LNX_EntityKind
{
struct LNX_SafeCallChain{ OS_LNX_EntityKind_Thread,
LNX_SafeCallChain *next; OS_LNX_EntityKind_Mutex,
OS_ThreadFunctionType *fail_handler; OS_LNX_EntityKind_RWMutex,
void *ptr; OS_LNX_EntityKind_ConditionVariable,
}; }
OS_LNX_EntityKind;
////////////////////////////////
//~ NOTE(allen): Helpers typedef struct OS_LNX_Entity OS_LNX_Entity;
struct OS_LNX_Entity
internal B32 lnx_write_list_to_file_descriptor(int fd, String8List list); {
OS_LNX_Entity *next;
internal void lnx_date_time_from_tm(DateTime *out, struct tm *in, U32 msec); OS_LNX_EntityKind kind;
internal void lnx_tm_from_date_time(struct tm *out, DateTime *in); union
internal void lnx_dense_time_from_timespec(DenseTime *out, struct timespec *in); {
internal void lnx_file_properties_from_stat(FileProperties *out, struct stat *in); struct
{
internal String8 lnx_string_from_signal(int signum); pthread_t handle;
internal String8 lnx_string_from_errno(int error_number); OS_ThreadFunctionType *func;
void *ptr;
internal LNX_Entity* lnx_alloc_entity(LNX_EntityKind kind); } thread;
internal void lnx_free_entity(LNX_Entity *entity); pthread_mutex_t mutex_handle;
internal void* lnx_thread_base(void *ptr); pthread_rwlock_t rwmutex_handle;
struct
internal void lnx_safe_call_sig_handler(int); {
pthread_cond_t cond_handle;
#endif //LINUX_H pthread_mutex_t rwlock_mutex_handle;
} cv;
};
};
////////////////////////////////
//~ rjf: State
typedef struct OS_LNX_State OS_LNX_State;
struct OS_LNX_State
{
Arena *arena;
OS_SystemInfo system_info;
OS_ProcessInfo process_info;
pthread_mutex_t entity_mutex;
Arena *entity_arena;
OS_LNX_Entity *entity_free;
};
////////////////////////////////
//~ rjf: Globals
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
+173 -265
View File
@@ -1,265 +1,173 @@
// 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/)
//////////////////////////////// ////////////////////////////////
//~ rjf: Handle Type Functions (Helpers, Implemented Once) //~ rjf: Handle Type Functions (Helpers, Implemented Once)
internal OS_Handle internal OS_Handle
os_handle_zero(void) os_handle_zero(void)
{ {
OS_Handle handle = {0}; OS_Handle handle = {0};
return handle; return handle;
} }
internal B32 internal B32
os_handle_match(OS_Handle a, OS_Handle b) os_handle_match(OS_Handle a, OS_Handle b)
{ {
return a.u64[0] == b.u64[0]; return a.u64[0] == b.u64[0];
} }
internal void internal void
os_handle_list_push(Arena *arena, OS_HandleList *handles, OS_Handle handle) os_handle_list_push(Arena *arena, OS_HandleList *handles, OS_Handle handle)
{ {
OS_HandleNode *n = push_array(arena, OS_HandleNode, 1); OS_HandleNode *n = push_array(arena, OS_HandleNode, 1);
n->v = handle; n->v = handle;
SLLQueuePush(handles->first, handles->last, n); SLLQueuePush(handles->first, handles->last, n);
handles->count += 1; handles->count += 1;
} }
internal OS_HandleArray internal OS_HandleArray
os_handle_array_from_list(Arena *arena, OS_HandleList *list) os_handle_array_from_list(Arena *arena, OS_HandleList *list)
{ {
OS_HandleArray result = {0}; OS_HandleArray result = {0};
result.count = list->count; result.count = list->count;
result.v = push_array_no_zero(arena, OS_Handle, result.count); result.v = push_array_no_zero(arena, OS_Handle, result.count);
U64 idx = 0; U64 idx = 0;
for(OS_HandleNode *n = list->first; n != 0; n = n->next, idx += 1) for(OS_HandleNode *n = list->first; n != 0; n = n->next, idx += 1)
{ {
result.v[idx] = n->v; result.v[idx] = n->v;
} }
return result; return result;
} }
//////////////////////////////// ////////////////////////////////
//~ rjf: System Path Helper (Helper, Implemented Once) //~ rjf: Command Line Argc/Argv Helper (Helper, Implemented Once)
internal String8 internal String8List
os_string_from_system_path(Arena *arena, OS_SystemPath path) os_string_list_from_argcv(Arena *arena, int argc, char **argv)
{ {
String8List strs = {0}; String8List result = {0};
os_string_list_from_system_path(arena, path, &strs); for(int i = 0; i < argc; i += 1)
String8 result = str8_list_first(&strs); {
return result; String8 str = str8_cstring(argv[i]);
} str8_list_push(arena, &result, str);
}
//////////////////////////////// return result;
//~ rjf: Command Line Argc/Argv Helper (Helper, Implemented Once) }
internal String8List ////////////////////////////////
os_string_list_from_argcv(Arena *arena, int argc, char **argv) //~ rjf: Filesystem Helpers (Helpers, Implemented Once)
{
String8List result = {0}; internal String8
for(int i = 0; i < argc; i += 1) os_data_from_file_path(Arena *arena, String8 path)
{ {
String8 str = str8_cstring(argv[i]); OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead, path);
str8_list_push(arena, &result, str); FileProperties props = os_properties_from_file(file);
} String8 data = os_string_from_file_range(arena, file, r1u64(0, props.size));
return result; os_file_close(file);
} return data;
}
////////////////////////////////
//~ rjf: Process Helpers (Helper, Implemented Once) internal B32
os_write_data_to_file_path(String8 path, String8 data)
internal void {
os_relaunch_self(void){ B32 good = 0;
Temp scratch = scratch_begin(0, 0); OS_Handle file = os_file_open(OS_AccessFlag_Write, path);
OS_LaunchOptions opts = {0}; if(!os_handle_match(file, os_handle_zero()))
opts.cmd_line = os_get_command_line_arguments(); {
opts.path = os_string_from_system_path(scratch.arena, OS_SystemPath_Initial); good = 1;
os_launch_process(&opts, 0); os_file_write(file, r1u64(0, data.size), data.str);
scratch_end(scratch); os_file_close(file);
} }
return good;
//////////////////////////////// }
//~ rjf: Filesystem Helpers (Helpers, Implemented Once)
internal B32
internal String8 os_write_data_list_to_file_path(String8 path, String8List list)
os_data_from_file_path(Arena *arena, String8 path) {
{ B32 good = 0;
OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_Shared, path); OS_Handle file = os_file_open(OS_AccessFlag_Write, path);
FileProperties props = os_properties_from_file(file); if(!os_handle_match(file, os_handle_zero()))
String8 data = os_string_from_file_range(arena, file, r1u64(0, props.size)); {
os_file_close(file); good = 1;
return data; U64 off = 0;
} for(String8Node *n = list.first; n != 0; n = n->next)
{
internal B32 os_file_write(file, r1u64(off, off+n->string.size), n->string.str);
os_write_data_to_file_path(String8 path, String8 data) off += n->string.size;
{ }
B32 good = 0; os_file_close(file);
OS_Handle file = os_file_open(OS_AccessFlag_Write, path); }
if(!os_handle_match(file, os_handle_zero())) return good;
{ }
good = 1;
os_file_write(file, r1u64(0, data.size), data.str); internal B32
os_file_close(file); os_append_data_to_file_path(String8 path, String8 data)
} {
return good; B32 good = 0;
} if(data.size != 0)
{
internal B32 OS_Handle file = os_file_open(OS_AccessFlag_Write|OS_AccessFlag_Append, path);
os_write_data_list_to_file_path(String8 path, String8List list) if(!os_handle_match(file, os_handle_zero()))
{ {
B32 good = 0; good = 1;
OS_Handle file = os_file_open(OS_AccessFlag_Write, path); U64 pos = os_properties_from_file(file).size;
if(!os_handle_match(file, os_handle_zero())) os_file_write(file, r1u64(pos, pos+data.size), data.str);
{ os_file_close(file);
good = 1; }
U64 off = 0; }
for(String8Node *n = list.first; n != 0; n = n->next) return good;
{ }
os_file_write(file, r1u64(off, off+n->string.size), n->string.str);
off += n->string.size; internal OS_FileID
} os_id_from_file_path(String8 path)
os_file_close(file); {
} OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead, path);
return good; OS_FileID id = os_id_from_file(file);
} os_file_close(file);
return id;
internal FileProperties }
os_properties_from_file_path(String8 path)
{ internal S64
OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_Shared, path); os_file_id_compare(OS_FileID a, OS_FileID b)
FileProperties props = os_properties_from_file(file); {
os_file_close(file); S64 cmp = MemoryCompare((void*)&a.v[0], (void*)&b.v[0], sizeof(a.v));
return props; return cmp;
} }
internal OS_FileID internal String8
os_id_from_file_path(String8 path) os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range)
{ {
OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_Shared, path); U64 pre_pos = arena_pos(arena);
OS_FileID id = os_id_from_file(file); String8 result;
os_file_close(file); result.size = dim_1u64(range);
return id; result.str = push_array_no_zero(arena, U8, result.size);
} U64 actual_read_size = os_file_read(file, range, result.str);
if(actual_read_size < result.size)
internal S64 {
os_file_id_compare(OS_FileID a, OS_FileID b) arena_pop_to(arena, pre_pos + actual_read_size);
{ result.size = actual_read_size;
S64 cmp = MemoryCompare((void*)&a.v[0], (void*)&b.v[0], sizeof(a.v)); }
return cmp; return result;
} }
internal String8 ////////////////////////////////
os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range) //~ rjf: GUID Helpers (Helpers, Implemented Once)
{
U64 pre_pos = arena_pos(arena); internal String8
String8 result; os_string_from_guid(Arena *arena, OS_Guid guid)
result.size = dim_1u64(range); {
result.str = push_array_no_zero(arena, U8, result.size); String8 result = push_str8f(arena, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
U64 actual_read_size = os_file_read(file, range, result.str); guid.data1,
if(actual_read_size < result.size) guid.data2,
{ guid.data3,
arena_pop_to(arena, pre_pos + actual_read_size); guid.data4[0],
result.size = actual_read_size; guid.data4[1],
} guid.data4[2],
return result; guid.data4[3],
} guid.data4[4],
guid.data4[5],
//////////////////////////////// guid.data4[6],
//~ rjf: Synchronization Primitive Helpers (Helpers, Implemented Once) guid.data4[7]);
return result;
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
os_string_from_guid(Arena *arena, OS_Guid guid)
{
String8 result = push_str8f(arena, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
guid.data1,
guid.data2,
guid.data3,
guid.data4[0],
guid.data4[1],
guid.data4[2],
guid.data4[3],
guid.data4[4],
guid.data4[5],
guid.data4[6],
guid.data4[7]);
return result;
}
+336 -365
View File
@@ -1,365 +1,336 @@
// 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 OS_CORE_H #ifndef OS_CORE_H
#define OS_CORE_H #define OS_CORE_H
//////////////////////////////// ////////////////////////////////
//~ rjf: Access Flags //~ rjf: System Info
typedef U32 OS_AccessFlags; typedef struct OS_SystemInfo OS_SystemInfo;
enum struct OS_SystemInfo
{ {
OS_AccessFlag_Read = (1<<0), U32 logical_processor_count;
OS_AccessFlag_Write = (1<<1), U64 page_size;
OS_AccessFlag_Execute = (1<<2), U64 large_page_size;
OS_AccessFlag_Shared = (1<<3), U64 allocation_granularity;
}; String8 machine_name;
};
////////////////////////////////
//~ allen: Files ////////////////////////////////
//~ rjf: Process Info
typedef U32 OS_FileIterFlags;
enum typedef struct OS_ProcessInfo OS_ProcessInfo;
{ struct OS_ProcessInfo
OS_FileIterFlag_SkipFolders = (1 << 0), {
OS_FileIterFlag_SkipFiles = (1 << 1), U32 pid;
OS_FileIterFlag_SkipHiddenFiles = (1 << 2), String8 binary_path;
OS_FileIterFlag_Done = (1 << 31), String8 initial_path;
}; String8 user_program_data_path;
String8List module_load_paths;
typedef struct OS_FileIter OS_FileIter; String8List environment;
struct OS_FileIter };
{
OS_FileIterFlags flags; ////////////////////////////////
U8 memory[600]; //~ rjf: Access Flags
};
typedef U32 OS_AccessFlags;
typedef struct OS_FileInfo OS_FileInfo; enum
struct OS_FileInfo {
{ OS_AccessFlag_Read = (1<<0),
String8 name; OS_AccessFlag_Write = (1<<1),
FileProperties props; OS_AccessFlag_Execute = (1<<2),
}; OS_AccessFlag_Append = (1<<3),
OS_AccessFlag_ShareRead = (1<<4),
// nick: on-disk file identifier OS_AccessFlag_ShareWrite = (1<<5),
typedef struct OS_FileID OS_FileID; };
struct OS_FileID
{ ////////////////////////////////
U64 v[3]; //~ rjf: Files
};
typedef U32 OS_FileIterFlags;
//////////////////////////////// enum
//~ rjf: System Paths {
OS_FileIterFlag_SkipFolders = (1 << 0),
typedef enum OS_SystemPath OS_FileIterFlag_SkipFiles = (1 << 1),
{ OS_FileIterFlag_SkipHiddenFiles = (1 << 2),
OS_SystemPath_Binary, OS_FileIterFlag_Done = (1 << 31),
OS_SystemPath_Initial, };
OS_SystemPath_Current,
OS_SystemPath_UserProgramData, typedef struct OS_FileIter OS_FileIter;
OS_SystemPath_ModuleLoad, struct OS_FileIter
} {
OS_SystemPath; OS_FileIterFlags flags;
U8 memory[800];
typedef enum OS_PathFromUserKind };
{
OS_PathFromUserKind_Save, typedef struct OS_FileInfo OS_FileInfo;
OS_PathFromUserKind_Load, struct OS_FileInfo
} {
OS_PathFromUserKind; String8 name;
FileProperties props;
typedef struct OS_PathFromUser OS_PathFromUser; };
struct OS_PathFromUser
{ // nick: on-disk file identifier
OS_PathFromUserKind kind; typedef struct OS_FileID OS_FileID;
String8 path; struct OS_FileID
U64 filter_count; {
String8 *filter_extensions; U64 v[3];
String8 *filter_names; };
};
////////////////////////////////
//////////////////////////////// //~ rjf: Process Launch Parameters
//~ allen: Launch Input
typedef struct OS_ProcessLaunchParams OS_ProcessLaunchParams;
typedef struct OS_LaunchOptions OS_LaunchOptions; struct OS_ProcessLaunchParams
struct OS_LaunchOptions {
{ String8List cmd_line;
String8List cmd_line; String8 path;
String8 path; String8List env;
String8List env; B32 inherit_env;
B32 inherit_env; B32 consoleless;
B32 consoleless; };
};
////////////////////////////////
//////////////////////////////// //~ rjf: Handle Type
//~ rjf: Handle Type
typedef struct OS_Handle OS_Handle;
typedef struct OS_Handle OS_Handle; struct OS_Handle
struct OS_Handle {
{ U64 u64[1];
U64 u64[1]; };
};
typedef struct OS_HandleNode OS_HandleNode;
typedef struct OS_HandleNode OS_HandleNode; struct OS_HandleNode
struct OS_HandleNode {
{ OS_HandleNode *next;
OS_HandleNode *next; OS_Handle v;
OS_Handle v; };
};
typedef struct OS_HandleList OS_HandleList;
typedef struct OS_HandleList OS_HandleList; struct OS_HandleList
struct OS_HandleList {
{ OS_HandleNode *first;
OS_HandleNode *first; OS_HandleNode *last;
OS_HandleNode *last; U64 count;
U64 count; };
};
typedef struct OS_HandleArray OS_HandleArray;
typedef struct OS_HandleArray OS_HandleArray; struct OS_HandleArray
struct OS_HandleArray {
{ OS_Handle *v;
OS_Handle *v; U64 count;
U64 count; };
};
////////////////////////////////
//////////////////////////////// //~ rjf: Globally Unique IDs
// Time
typedef struct OS_Guid OS_Guid;
#define OS_UNIX_TIME_MAX max_U32 struct OS_Guid
typedef U32 OS_UnixTime; {
U32 data1;
//////////////////////////////// U16 data2;
// Global Unique ID U16 data3;
U8 data4[8];
typedef struct OS_Guid };
{ StaticAssert(sizeof(OS_Guid) == 16, os_guid_check);
U32 data1;
U16 data2; ////////////////////////////////
U16 data3; //~ rjf: Thread Types
U8 data4[8];
} OS_Guid; typedef void OS_ThreadFunctionType(void *ptr);
StaticAssert(sizeof(OS_Guid) == 16, os_guid_check);
////////////////////////////////
//////////////////////////////// //~ rjf: Handle Type Functions (Helpers, Implemented Once)
//~ rjf: Thread Types
internal OS_Handle os_handle_zero(void);
typedef void OS_ThreadFunctionType(void *ptr); 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 OS_HandleArray os_handle_array_from_list(Arena *arena, OS_HandleList *list);
//~ rjf: Handle Type Functions (Helpers, Implemented Once)
////////////////////////////////
internal OS_Handle os_handle_zero(void); //~ rjf: Command Line Argc/Argv Helper (Helper, Implemented Once)
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 String8List os_string_list_from_argcv(Arena *arena, int argc, char **argv);
internal OS_HandleArray os_handle_array_from_list(Arena *arena, OS_HandleList *list);
////////////////////////////////
//////////////////////////////// //~ rjf: Filesystem Helpers (Helpers, Implemented Once)
//~ rjf: System Path Helper (Helper, Implemented Once)
internal String8 os_data_from_file_path(Arena *arena, String8 path);
internal String8 os_string_from_system_path(Arena *arena, OS_SystemPath path); 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_append_data_to_file_path(String8 path, String8 data);
//~ rjf: Command Line Argc/Argv Helper (Helper, Implemented Once) internal OS_FileID os_id_from_file_path(String8 path);
internal S64 os_file_id_compare(OS_FileID a, OS_FileID b);
internal String8List os_string_list_from_argcv(Arena *arena, int argc, char **argv); internal String8 os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range);
//////////////////////////////// ////////////////////////////////
//~ rjf: Process Helpers (Helper, Implemented Once) //~ rjf: GUID Helpers (Helpers, Implemented Once)
internal void os_relaunch_self(void); internal String8 os_string_from_guid(Arena *arena, OS_Guid guid);
//////////////////////////////// ////////////////////////////////
//~ rjf: Filesystem Helpers (Helpers, Implemented Once) //~ rjf: @os_hooks System/Process Info (Implemented Per-OS)
internal String8 os_data_from_file_path(Arena *arena, String8 path); internal OS_SystemInfo *os_get_system_info(void);
internal B32 os_write_data_to_file_path(String8 path, String8 data); internal OS_ProcessInfo *os_get_process_info(void);
internal B32 os_write_data_list_to_file_path(String8 path, String8List list); internal String8 os_get_current_path(Arena *arena);
internal FileProperties os_properties_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); //~ rjf: @os_hooks Memory Allocation (Implemented Per-OS)
internal String8 os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range);
//- rjf: basic
//////////////////////////////// internal void *os_reserve(U64 size);
//~ rjf: Synchronization Primitive Helpers (Helpers, Implemented Once) internal B32 os_commit(void *ptr, U64 size);
internal void os_decommit(void *ptr, U64 size);
internal void os_mutex_take(OS_Handle mutex); internal void os_release(void *ptr, U64 size);
internal void os_mutex_drop(OS_Handle mutex);
internal void os_rw_mutex_take_r(OS_Handle rw_mutex); //- rjf: large pages
internal void os_rw_mutex_drop_r(OS_Handle rw_mutex); internal void *os_reserve_large(U64 size);
internal void os_rw_mutex_take_w(OS_Handle rw_mutex); internal B32 os_commit_large(void *ptr, U64 size);
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); //~ rjf: @os_hooks Thread Info (Implemented Per-OS)
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 U32 os_tid(void);
internal void os_condition_variable_signal(OS_Handle cv); internal void os_set_thread_name(String8 string);
internal void os_condition_variable_broadcast(OS_Handle cv);
////////////////////////////////
#define OS_MutexScope(mutex) DeferLoop(os_mutex_take(mutex), os_mutex_drop(mutex)) //~ rjf: @os_hooks Aborting (Implemented Per-OS)
#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)) internal void os_abort(S32 exit_code);
//////////////////////////////// ////////////////////////////////
//~ rjf: @os_hooks Main Initialization API (Implemented Per-OS) //~ rjf: @os_hooks File System (Implemented Per-OS)
internal void os_init(int argc, char **argv); //- rjf: files
internal OS_Handle os_file_open(OS_AccessFlags flags, String8 path);
//////////////////////////////// internal void os_file_close(OS_Handle file);
//~ rjf: @os_hooks Memory Allocation (Implemented Per-OS) internal U64 os_file_read(OS_Handle file, Rng1U64 rng, void *out_data);
internal U64 os_file_write(OS_Handle file, Rng1U64 rng, void *data);
internal void* os_reserve(U64 size); internal B32 os_file_set_times(OS_Handle file, DateTime time);
internal B32 os_commit(void *ptr, U64 size); internal FileProperties os_properties_from_file(OS_Handle file);
internal void* os_reserve_large(U64 size); internal OS_FileID os_id_from_file(OS_Handle file);
internal B32 os_commit_large(void *ptr, U64 size); internal B32 os_delete_file_at_path(String8 path);
internal void os_decommit(void *ptr, U64 size); internal B32 os_copy_file_path(String8 dst, String8 src);
internal void os_release(void *ptr, U64 size); internal String8 os_full_path_from_path(Arena *arena, String8 path);
internal B32 os_file_path_exists(String8 path);
internal B32 os_set_large_pages(B32 flag); internal FileProperties os_properties_from_file_path(String8 path);
internal B32 os_large_pages_enabled(void);
internal U64 os_large_page_size(void); //- rjf: file maps
internal OS_Handle os_file_map_open(OS_AccessFlags flags, OS_Handle file);
internal void* os_alloc_ring_buffer(U64 size, U64 *actual_size_out); internal void os_file_map_close(OS_Handle map);
internal void os_free_ring_buffer(void *ring_buffer, U64 actual_size); 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, Rng1U64 range);
////////////////////////////////
//~ rjf: @os_hooks System Info (Implemented Per-OS) //- rjf: directory iteration
internal OS_FileIter *os_file_iter_begin(Arena *arena, String8 path, OS_FileIterFlags flags);
internal String8 os_machine_name(void); internal B32 os_file_iter_next(Arena *arena, OS_FileIter *iter, OS_FileInfo *info_out);
internal U64 os_page_size(void); internal void os_file_iter_end(OS_FileIter *iter);
internal U64 os_allocation_granularity(void);
internal U64 os_logical_core_count(void); //- rjf: directory creation
internal B32 os_make_directory(String8 path);
////////////////////////////////
//~ rjf: @os_hooks Process Info (Implemented Per-OS) ////////////////////////////////
//~ rjf: @os_hooks Shared Memory (Implemented Per-OS)
internal String8List os_get_command_line_arguments(void);
internal S32 os_get_pid(void); internal OS_Handle os_shared_memory_alloc(U64 size, String8 name);
internal S32 os_get_tid(void); internal OS_Handle os_shared_memory_open(String8 name);
internal String8List os_get_environment(void); internal void os_shared_memory_close(OS_Handle handle);
internal U64 os_string_list_from_system_path(Arena *arena, OS_SystemPath path, String8List *out); internal void * os_shared_memory_view_open(OS_Handle handle, Rng1U64 range);
internal void os_shared_memory_view_close(OS_Handle handle, void *ptr, Rng1U64 range);
////////////////////////////////
//~ rjf: @os_hooks Process Control (Implemented Per-OS) ////////////////////////////////
//~ rjf: @os_hooks Time (Implemented Per-OS)
internal void os_exit_process(S32 exit_code);
internal U64 os_now_microseconds(void);
//////////////////////////////// internal U32 os_now_unix(void);
//~ rjf: @os_hooks File System (Implemented Per-OS) internal DateTime os_now_universal_time(void);
internal DateTime os_universal_time_from_local(DateTime *local_time);
//- rjf: files internal DateTime os_local_time_from_universal(DateTime *universal_time);
internal OS_Handle os_file_open(OS_AccessFlags flags, String8 path); internal void os_sleep_milliseconds(U32 msec);
internal void os_file_close(OS_Handle file);
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); //~ rjf: @os_hooks Child Processes (Implemented Per-OS)
internal B32 os_file_set_times(OS_Handle file, DateTime time);
internal FileProperties os_properties_from_file(OS_Handle file); internal OS_Handle os_process_launch(OS_ProcessLaunchParams *params);
internal OS_FileID os_id_from_file(OS_Handle file); internal B32 os_process_join(OS_Handle handle, U64 endt_us);
internal B32 os_delete_file_at_path(String8 path); internal void os_process_detach(OS_Handle handle);
internal B32 os_copy_file_path(String8 dst, String8 src);
internal String8 os_full_path_from_path(Arena *arena, String8 path); ////////////////////////////////
internal B32 os_file_path_exists(String8 path); //~ rjf: @os_hooks Threads (Implemented Per-OS)
//- rjf: file maps internal OS_Handle os_thread_launch(OS_ThreadFunctionType *func, void *ptr, void *params);
internal OS_Handle os_file_map_open(OS_AccessFlags flags, OS_Handle file); internal B32 os_thread_join(OS_Handle handle, U64 endt_us);
internal void os_file_map_close(OS_Handle map); internal void os_thread_detach(OS_Handle handle);
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); ////////////////////////////////
//~ rjf: @os_hooks Synchronization Primitives (Implemented Per-OS)
//- rjf: directory iteration
internal OS_FileIter *os_file_iter_begin(Arena *arena, String8 path, OS_FileIterFlags flags); //- rjf: recursive mutexes
internal B32 os_file_iter_next(Arena *arena, OS_FileIter *iter, OS_FileInfo *info_out); internal OS_Handle os_mutex_alloc(void);
internal void os_file_iter_end(OS_FileIter *iter); internal void os_mutex_release(OS_Handle mutex);
internal void os_mutex_take(OS_Handle mutex);
//- rjf: directory creation internal void os_mutex_drop(OS_Handle mutex);
internal B32 os_make_directory(String8 path);
//- rjf: reader/writer mutexes
//////////////////////////////// internal OS_Handle os_rw_mutex_alloc(void);
//~ rjf: @os_hooks Shared Memory (Implemented Per-OS) internal void os_rw_mutex_release(OS_Handle rw_mutex);
internal void os_rw_mutex_take_r(OS_Handle mutex);
internal OS_Handle os_shared_memory_alloc(U64 size, String8 name); internal void os_rw_mutex_drop_r(OS_Handle mutex);
internal OS_Handle os_shared_memory_open(String8 name); internal void os_rw_mutex_take_w(OS_Handle mutex);
internal void os_shared_memory_close(OS_Handle handle); internal void os_rw_mutex_drop_w(OS_Handle mutex);
internal void * os_shared_memory_view_open(OS_Handle handle, Rng1U64 range);
internal void os_shared_memory_view_close(OS_Handle handle, void *ptr); //- rjf: condition variables
internal OS_Handle os_condition_variable_alloc(void);
//////////////////////////////// internal void os_condition_variable_release(OS_Handle cv);
//~ rjf: @os_hooks Time (Implemented Per-OS) // 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 OS_UnixTime os_now_unix(void); internal B32 os_condition_variable_wait_rw_r(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us);
internal DateTime os_now_universal_time(void); internal B32 os_condition_variable_wait_rw_w(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us);
internal DateTime os_universal_time_from_local_time(DateTime *local_time); internal void os_condition_variable_signal(OS_Handle cv);
internal DateTime os_local_time_from_universal_time(DateTime *universal_time); internal void os_condition_variable_broadcast(OS_Handle cv);
internal U64 os_now_microseconds(void);
internal void os_sleep_milliseconds(U32 msec); //- rjf: cross-process semaphores
internal OS_Handle os_semaphore_alloc(U32 initial_count, U32 max_count, String8 name);
//////////////////////////////// internal void os_semaphore_release(OS_Handle semaphore);
//~ rjf: @os_hooks Child Processes (Implemented Per-OS) internal OS_Handle os_semaphore_open(String8 name);
internal void os_semaphore_close(OS_Handle semaphore);
internal B32 os_launch_process(OS_LaunchOptions *options, OS_Handle *handle_out); internal B32 os_semaphore_take(OS_Handle semaphore, U64 endt_us);
internal B32 os_process_wait(OS_Handle handle, U64 endt_us); internal void os_semaphore_drop(OS_Handle semaphore);
internal void os_process_release_handle(OS_Handle handle);
//- rjf: scope macros
//////////////////////////////// #define OS_MutexScope(mutex) DeferLoop(os_mutex_take(mutex), os_mutex_drop(mutex))
//~ rjf: @os_hooks Threads (Implemented Per-OS) #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))
internal OS_Handle os_launch_thread(OS_ThreadFunctionType *func, void *ptr, void *params); #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)))
internal void os_release_thread_handle(OS_Handle thread);
////////////////////////////////
//////////////////////////////// //~ rjf: @os_hooks Dynamically-Loaded Libraries (Implemented Per-OS)
//~ rjf: @os_hooks Synchronization Primitives (Implemented Per-OS)
internal OS_Handle os_library_open(String8 path);
// NOTE(allen): Mutexes are recursive - support counted acquire/release nesting internal void os_library_close(OS_Handle lib);
// on a single thread internal VoidProc *os_library_load_proc(OS_Handle lib, String8 name);
//- rjf: recursive mutexes ////////////////////////////////
internal OS_Handle os_mutex_alloc(void); //~ rjf: @os_hooks Safe Calls (Implemented Per-OS)
internal void os_mutex_release(OS_Handle mutex);
internal void os_mutex_take_(OS_Handle mutex); internal void os_safe_call(OS_ThreadFunctionType *func, OS_ThreadFunctionType *fail_handler, void *ptr);
internal void os_mutex_drop_(OS_Handle mutex);
////////////////////////////////
//- rjf: reader/writer mutexes //~ rjf: @os_hooks GUIDs (Implemented Per-OS)
internal OS_Handle os_rw_mutex_alloc(void);
internal void os_rw_mutex_release(OS_Handle rw_mutex); internal OS_Guid os_make_guid(void);
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_take_w_(OS_Handle mutex); //~ rjf: @os_hooks Entry Points (Implemented Per-OS)
internal void os_rw_mutex_drop_w_(OS_Handle mutex);
// NOTE(rjf): The implementation of `os_core` will define low-level entry
//- rjf: condition variables // points if BUILD_ENTRY_DEFINING_UNIT is defined to 1. These will call
internal OS_Handle os_condition_variable_alloc(void); // into the standard codebase program entry points, named "entry_point".
internal void os_condition_variable_release(OS_Handle cv);
// returns false on timeout, true on signal, (max_wait_ms = max_U64) -> no timeout #if BUILD_ENTRY_DEFINING_UNIT
internal B32 os_condition_variable_wait_(OS_Handle cv, OS_Handle mutex, U64 endt_us); internal void entry_point(CmdLine *cmdline);
internal B32 os_condition_variable_wait_rw_r_(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us); #endif
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); #endif // OS_CORE_H
internal void os_condition_variable_broadcast_(OS_Handle cv);
//- rjf: cross-process semaphores
internal OS_Handle os_semaphore_alloc(U32 initial_count, U32 max_count, String8 name);
internal void os_semaphore_release(OS_Handle semaphore);
internal OS_Handle os_semaphore_open(String8 name);
internal void os_semaphore_close(OS_Handle semaphore);
internal B32 os_semaphore_take(OS_Handle semaphore, U64 endt_us);
internal void os_semaphore_drop(OS_Handle semaphore);
////////////////////////////////
//~ rjf: @os_hooks Dynamically-Loaded Libraries (Implemented Per-OS)
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);
////////////////////////////////
//~ rjf: @os_hooks Safe Calls (Implemented Per-OS)
internal void os_safe_call(OS_ThreadFunctionType *func, OS_ThreadFunctionType *fail_handler, void *ptr);
////////////////////////////////
//~ rjf: @os_hooks GUIDs (Implemented Per-OS)
internal OS_Guid os_make_guid(void);
internal String8 os_string_from_guid(Arena *arena, OS_Guid guid);
#endif // OS_CORE_H
File diff suppressed because it is too large Load Diff
@@ -1,91 +1,122 @@
// 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>
#include <processthreadsapi.h>
#if OS_FEATURE_GRAPHICAL #pragma comment(lib, "user32")
#include <shellscalingapi.h> #pragma comment(lib, "winmm")
#endif #pragma comment(lib, "shell32")
#pragma comment(lib, "advapi32")
#if OS_FEATURE_SOCKET #pragma comment(lib, "rpcrt4")
#include <WS2tcpip.h> #pragma comment(lib, "shlwapi")
#include <Mswsock.h> #pragma comment(lib, "comctl32")
#endif #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
#include <processthreadsapi.h> ////////////////////////////////
//~ rjf: File Iterator Types
////////////////////////////////
//~ NOTE(allen): File Iterator typedef struct OS_W32_FileIter OS_W32_FileIter;
struct OS_W32_FileIter
typedef struct W32_FileIter W32_FileIter; {
struct W32_FileIter HANDLE handle;
{ WIN32_FIND_DATAW find_data;
HANDLE handle; B32 is_volume_iter;
WIN32_FIND_DATAW find_data; 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, {
W32_EntityKind_Thread, OS_W32_EntityKind_Null,
W32_EntityKind_Mutex, OS_W32_EntityKind_Thread,
W32_EntityKind_RWMutex, OS_W32_EntityKind_Mutex,
W32_EntityKind_ConditionVariable, OS_W32_EntityKind_RWMutex,
} OS_W32_EntityKind_ConditionVariable,
W32_EntityKind; }
OS_W32_EntityKind;
typedef struct W32_Entity W32_Entity;
struct W32_Entity typedef struct OS_W32_Entity OS_W32_Entity;
{ struct OS_W32_Entity
W32_Entity *next; {
W32_EntityKind kind; OS_W32_Entity *next;
volatile U32 reference_mask; OS_W32_EntityKind kind;
union{ union
struct{ {
OS_ThreadFunctionType *func; struct
void *ptr; {
HANDLE handle; OS_ThreadFunctionType *func;
DWORD tid; void *ptr;
} thread; HANDLE handle;
CRITICAL_SECTION mutex; DWORD tid;
SRWLOCK rw_mutex; } thread;
CONDITION_VARIABLE cv; CRITICAL_SECTION mutex;
}; SRWLOCK rw_mutex;
}; CONDITION_VARIABLE cv;
};
//////////////////////////////// };
//~ rjf: Helpers
////////////////////////////////
//- rjf: files //~ rjf: State
internal FilePropertyFlags w32_file_property_flags_from_dwFileAttributes(DWORD dwFileAttributes);
internal void w32_file_properties_from_attributes(FileProperties *properties, WIN32_FILE_ATTRIBUTE_DATA *attributes); typedef struct OS_W32_State OS_W32_State;
struct OS_W32_State
//- rjf: time {
internal void w32_date_time_from_system_time(DateTime *out, SYSTEMTIME *in); Arena *arena;
internal void w32_system_time_from_date_time(SYSTEMTIME *out, DateTime *in);
internal void w32_dense_time_from_file_time(DenseTime *out, FILETIME *in); // rjf: info
internal U32 w32_sleep_ms_from_endt_us(U64 endt_us); OS_SystemInfo system_info;
OS_ProcessInfo process_info;
//- rjf: entities U64 microsecond_resolution;
internal W32_Entity* w32_alloc_entity(W32_EntityKind kind);
internal void w32_free_entity(W32_Entity *entity); // rjf: entity storage
CRITICAL_SECTION entity_mutex;
//- rjf: threads Arena *entity_arena;
internal DWORD w32_thread_base(void *ptr); OS_W32_Entity *entity_free;
};
#endif //WIN32_H
////////////////////////////////
//~ rjf: Globals
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
+12 -29
View File
@@ -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
#if OS_WINDOWS
#include "core/metagen_os_core.c" # include "metagen/metagen_os/core/win32/metagen_os_core_win32.c"
#elif OS_LINUX
#if OS_FEATURE_SOCKET # include "metagen/metagen_os/core/linux/metagen_os_core_linux.c"
#include "socket/metagen_os_socket.c" #else
#endif # error OS core layer not implemented for this operating system.
#endif
#if OS_FEATURE_GRAPHICAL
#include "gfx/metagen_os_gfx.c"
#endif
#if OS_WINDOWS
# include "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
# include "core/linux/metagen_os_core_linux.c"
#else
# error no OS layer setup
#endif
+6 -20
View File
@@ -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