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