More cleanup

This commit is contained in:
doylet 2026-03-08 12:18:23 +11:00
parent 0f9af50a6d
commit dbbaa5fbf7
12 changed files with 432 additions and 415 deletions

View File

@ -1473,7 +1473,7 @@ DN_API bool DN_ErrSinkEndLogError_(DN_ErrSink *err, DN_CallSite call_site, DN_St
// NOTE: Log the error // NOTE: Log the error
DN_Str8 log = DN_Str8BuilderBuild(&builder, err->arena); DN_Str8 log = DN_Str8BuilderBuild(&builder, err->arena);
DN_LogEmitFromType(DN_LogMakeU32LogTypeParam(DN_LogType_Error), call_site, "%.*s", DN_Str8PrintFmt(log)); DN_LogPrint(DN_LogMakeU32LogTypeParam(DN_LogType_Error), call_site, "%.*s", DN_Str8PrintFmt(log));
if (node->mode == DN_ErrSinkMode_DebugBreakOnErrorLog) if (node->mode == DN_ErrSinkMode_DebugBreakOnErrorLog)
DN_DebugBreak; DN_DebugBreak;
@ -1552,6 +1552,7 @@ DN_API void DN_TCInit(DN_TCCore *tc, DN_U64 thread_id, DN_Arena *main_arena, DN_
tc->temp_a_arena = temp_a_arena; tc->temp_a_arena = temp_a_arena;
tc->temp_b_arena = temp_b_arena; tc->temp_b_arena = temp_b_arena;
tc->err_sink.arena = err_sink_arena; tc->err_sink.arena = err_sink_arena;
tc->lane.count = 1;
} }
DN_API void DN_TCInitFromMemFuncs(DN_TCCore *tc, DN_U64 thread_id, DN_TCInitArgs *args, DN_ArenaMemFuncs mem_funcs) DN_API void DN_TCInitFromMemFuncs(DN_TCCore *tc, DN_U64 thread_id, DN_TCInitArgs *args, DN_ArenaMemFuncs mem_funcs)
@ -1671,6 +1672,21 @@ DN_API DN_ErrSink *DN_TCErrSink()
return result; return result;
} }
DN_API DN_TCLane *DN_TCLaneGet()
{
DN_TCCore *tc = DN_TCGet();
DN_TCLane *result = &tc->lane;
return result;
}
DN_API DN_TCLane DN_TCLaneEquip(DN_TCLane lane)
{
DN_TCLane *curr = DN_TCLaneGet();
DN_TCLane result = *curr;
*curr = lane;
return result;
}
DN_API void *DN_PoolCopy(DN_Pool *pool, void const *data, DN_U64 size, uint8_t align) DN_API void *DN_PoolCopy(DN_Pool *pool, void const *data, DN_U64 size, uint8_t align)
{ {
if (!pool || !data || size == 0) if (!pool || !data || size == 0)
@ -4063,8 +4079,6 @@ DN_API DN_U32 DN_MurmurHash3HashU32FromBytesX64(void const *bytes, int len, DN_U
return result; return result;
} }
static DN_LogEmitFromTypeFVFunc *g_dn_base_log_emit_from_type_fv_func_;
static void *g_dn_base_log_emit_from_type_fv_user_context_;
DN_API DN_Str8 DN_LogColourEscapeCodeStr8FromRGB(DN_LogColourType colour, DN_U8 r, DN_U8 g, DN_U8 b) DN_API DN_Str8 DN_LogColourEscapeCodeStr8FromRGB(DN_LogColourType colour, DN_U8 r, DN_U8 g, DN_U8 b)
{ {
DN_THREAD_LOCAL char buffer[32]; DN_THREAD_LOCAL char buffer[32];
@ -4161,20 +4175,19 @@ DN_API DN_LogPrefixSize DN_LogMakePrefix(DN_LogStyle style, DN_LogTypeParam type
return result; return result;
} }
DN_API void DN_LogSetEmitFromTypeFVFunc(DN_LogEmitFromTypeFVFunc *print_func, void *user_data) DN_API void DN_LogSetPrintFunc(DN_LogPrintFunc *print_func, void *user_data)
{ {
g_dn_base_log_emit_from_type_fv_func_ = print_func; g_dn_->print_func = print_func;
g_dn_base_log_emit_from_type_fv_user_context_ = user_data; g_dn_->print_func_context = user_data;
} }
DN_API void DN_LogEmitFromType(DN_LogTypeParam type, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...) DN_API void DN_LogPrint(DN_LogTypeParam type, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...)
{ {
DN_LogEmitFromTypeFVFunc *func = g_dn_base_log_emit_from_type_fv_func_; DN_LogPrintFunc *func = g_dn_->print_func;
void *user_context = g_dn_base_log_emit_from_type_fv_user_context_;
if (func) { if (func) {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
func(type, user_context, call_site, fmt, args); func(type, g_dn_->print_func_context, call_site, fmt, args);
va_end(args); va_end(args);
} }
} }

View File

@ -1041,6 +1041,14 @@ struct DN_ErrSink
DN_USize stack_size; DN_USize stack_size;
}; };
struct DN_TCLane
{
DN_USize index;
DN_USize count;
DN_U64 barrier_handle;
void* shared_mem;
};
struct DN_TCScratch struct DN_TCScratch
{ {
DN_Arena* arena; DN_Arena* arena;
@ -1072,6 +1080,7 @@ struct DN_TCCore // (T)hread (C)ontext sitting in thread-local storage
DN_Str8x64 name; DN_Str8x64 name;
DN_U64 thread_id; DN_U64 thread_id;
DN_CallSite call_site; DN_CallSite call_site;
DN_TCLane lane;
DN_Arena main_arena_; DN_Arena main_arena_;
DN_Arena temp_a_arena_; DN_Arena temp_a_arena_;
@ -1174,7 +1183,7 @@ struct DN_StackTraceWalkResultIterator
DN_U16 index; DN_U16 index;
}; };
typedef void DN_LogEmitFromTypeFVFunc(DN_LogTypeParam type, void *user_data, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args); typedef void DN_LogPrintFunc(DN_LogTypeParam type, void *user_data, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args);
#if !defined(DN_STB_SPRINTF_HEADER_ONLY) #if !defined(DN_STB_SPRINTF_HEADER_ONLY)
#define STB_SPRINTF_IMPLEMENTATION #define STB_SPRINTF_IMPLEMENTATION
@ -1189,8 +1198,6 @@ DN_GCC_WARNING_DISABLE(-Wunused-function)
DN_GCC_WARNING_POP DN_GCC_WARNING_POP
DN_MSVC_WARNING_POP DN_MSVC_WARNING_POP
DN_API void DN_BeginFrame ();
#define DN_SPrintF(...) STB_SPRINTF_DECORATE(sprintf)(__VA_ARGS__) #define DN_SPrintF(...) STB_SPRINTF_DECORATE(sprintf)(__VA_ARGS__)
#define DN_SNPrintF(...) STB_SPRINTF_DECORATE(snprintf)(__VA_ARGS__) #define DN_SNPrintF(...) STB_SPRINTF_DECORATE(snprintf)(__VA_ARGS__)
#define DN_VSPrintF(...) STB_SPRINTF_DECORATE(vsprintf)(__VA_ARGS__) #define DN_VSPrintF(...) STB_SPRINTF_DECORATE(vsprintf)(__VA_ARGS__)
@ -1367,6 +1374,7 @@ DN_API DN_Arena* DN_TCFrameArena
DN_API DN_ErrSink* DN_TCErrSink (); DN_API DN_ErrSink* DN_TCErrSink ();
#define DN_TCErrSinkBegin(mode) DN_ErrSinkBegin(DN_TCErrSink(), mode) #define DN_TCErrSinkBegin(mode) DN_ErrSinkBegin(DN_TCErrSink(), mode)
#define DN_TCErrSinkBeginDefault() DN_ErrSinkBeginDefault(DN_TCErrSink()) #define DN_TCErrSinkBeginDefault() DN_ErrSinkBeginDefault(DN_TCErrSink())
DN_API DN_TCLane DN_TCLaneEquip (DN_TCLane lane);
DN_API bool DN_CharIsAlphabet (char ch); DN_API bool DN_CharIsAlphabet (char ch);
DN_API bool DN_CharIsDigit (char ch); DN_API bool DN_CharIsDigit (char ch);
@ -1602,13 +1610,13 @@ DN_API DN_U32 DN_MurmurHash3HashU32FromBytesX64
DN_API DN_Str8 DN_LogColourEscapeCodeStr8FromRGB (DN_LogColourType colour, DN_U8 r, DN_U8 g, DN_U8 b); DN_API DN_Str8 DN_LogColourEscapeCodeStr8FromRGB (DN_LogColourType colour, DN_U8 r, DN_U8 g, DN_U8 b);
DN_API DN_Str8 DN_LogColourEscapeCodeStr8FromU32 (DN_LogColourType colour, DN_U32 value); DN_API DN_Str8 DN_LogColourEscapeCodeStr8FromU32 (DN_LogColourType colour, DN_U32 value);
DN_API DN_LogPrefixSize DN_LogMakePrefix (DN_LogStyle style, DN_LogTypeParam type, DN_CallSite call_site, DN_LogDate date, char *dest, DN_USize dest_size); DN_API DN_LogPrefixSize DN_LogMakePrefix (DN_LogStyle style, DN_LogTypeParam type, DN_CallSite call_site, DN_LogDate date, char *dest, DN_USize dest_size);
DN_API void DN_LogSetEmitFromTypeFVFunc (DN_LogEmitFromTypeFVFunc *print_func, void *user_data); DN_API void DN_LogSetPrintFunc (DN_LogPrintFunc *print_func, void *user_data);
DN_API void DN_LogEmitFromType (DN_LogTypeParam type, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...); DN_API void DN_LogPrint (DN_LogTypeParam type, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...);
DN_API DN_LogTypeParam DN_LogMakeU32LogTypeParam (DN_LogType type); DN_API DN_LogTypeParam DN_LogMakeU32LogTypeParam (DN_LogType type);
#define DN_LogDebugF(fmt, ...) DN_LogEmitFromType(DN_LogMakeU32LogTypeParam(DN_LogType_Debug), DN_CALL_SITE, fmt, ##__VA_ARGS__) #define DN_LogDebugF(fmt, ...) DN_LogPrint(DN_LogMakeU32LogTypeParam(DN_LogType_Debug), DN_CALL_SITE, fmt, ##__VA_ARGS__)
#define DN_LogInfoF(fmt, ...) DN_LogEmitFromType(DN_LogMakeU32LogTypeParam(DN_LogType_Info), DN_CALL_SITE, fmt, ##__VA_ARGS__) #define DN_LogInfoF(fmt, ...) DN_LogPrint(DN_LogMakeU32LogTypeParam(DN_LogType_Info), DN_CALL_SITE, fmt, ##__VA_ARGS__)
#define DN_LogWarningF(fmt, ...) DN_LogEmitFromType(DN_LogMakeU32LogTypeParam(DN_LogType_Warning), DN_CALL_SITE, fmt, ##__VA_ARGS__) #define DN_LogWarningF(fmt, ...) DN_LogPrint(DN_LogMakeU32LogTypeParam(DN_LogType_Warning), DN_CALL_SITE, fmt, ##__VA_ARGS__)
#define DN_LogErrorF(fmt, ...) DN_LogEmitFromType(DN_LogMakeU32LogTypeParam(DN_LogType_Error), DN_CALL_SITE, fmt, ##__VA_ARGS__) #define DN_LogErrorF(fmt, ...) DN_LogPrint(DN_LogMakeU32LogTypeParam(DN_LogType_Error), DN_CALL_SITE, fmt, ##__VA_ARGS__)
// NOTE: OS primitives that the OS layer can provide for the base layer but is optional. // NOTE: OS primitives that the OS layer can provide for the base layer but is optional.
#if defined(DN_FREESTANDING) #if defined(DN_FREESTANDING)

View File

@ -64,7 +64,7 @@ DN_API void DN_ASYNC_Deinit(DN_ASYNCCore *async)
DN_AtomicSetValue32(&async->join_threads, true); DN_AtomicSetValue32(&async->join_threads, true);
DN_OS_SemaphoreIncrement(&async->worker_sem, async->thread_count); DN_OS_SemaphoreIncrement(&async->worker_sem, async->thread_count);
for (DN_ForItSize(it, DN_OSThread, async->threads, async->thread_count)) for (DN_ForItSize(it, DN_OSThread, async->threads, async->thread_count))
DN_OS_ThreadDeinit(it.data); DN_OS_ThreadJoin(it.data);
} }
static bool DN_ASYNC_QueueTask_(DN_ASYNCCore *async, DN_ASYNCTask const *task, DN_U64 wait_time_ms) { static bool DN_ASYNC_QueueTask_(DN_ASYNCCore *async, DN_ASYNCTask const *task, DN_U64 wait_time_ms) {

View File

@ -413,7 +413,7 @@ void DN_NET_CurlDeinit(DN_NETCore *net)
DN_NETCurlCore *curl = DN_Cast(DN_NETCurlCore *) net->context; DN_NETCurlCore *curl = DN_Cast(DN_NETCurlCore *) net->context;
curl->kill_thread = true; curl->kill_thread = true;
curl_multi_wakeup(curl->thread_curlm); curl_multi_wakeup(curl->thread_curlm);
DN_OS_ThreadDeinit(&curl->thread); DN_OS_ThreadJoin(&curl->thread);
} }
static DN_NETRequestHandle DN_NET_CurlDoRequest_(DN_NETCore *net, DN_Str8 url, DN_Str8 method, DN_NETDoHTTPArgs const *args, DN_NETRequestType type) static DN_NETRequestHandle DN_NET_CurlDoRequest_(DN_NETCore *net, DN_Str8 url, DN_Str8 method, DN_NETDoHTTPArgs const *args, DN_NETRequestType type)

View File

@ -1,9 +1,9 @@
#define DN_OS_CPP #define DN_OS_CPP
#if defined(_CLANGD) #if defined(_CLANGD)
#include "../Base/dn_base.h" #define DN_H_WITH_OS 1
#include "../dn_os.h" #define DN_H_WITH_CORE 1
#include "../dn_os_w32.h" #include "../dn.h"
#endif #endif
#if defined(DN_PLATFORM_POSIX) #if defined(DN_PLATFORM_POSIX)
@ -30,6 +30,7 @@ DN_API DN_ArenaMemFuncs DN_ArenaMemFuncsGet(DN_ArenaMemFuncType type)
}; };
case DN_ArenaMemFuncType_VMem: { case DN_ArenaMemFuncType_VMem: {
DN_Assert(g_dn_->init_flags & DN_InitFlags_OS);
result.type = DN_ArenaMemFuncType_VMem; result.type = DN_ArenaMemFuncType_VMem;
result.vmem_page_size = g_dn_->os.page_size; result.vmem_page_size = g_dn_->os.page_size;
result.vmem_reserve = DN_OS_MemReserve; result.vmem_reserve = DN_OS_MemReserve;
@ -42,12 +43,13 @@ DN_API DN_ArenaMemFuncs DN_ArenaMemFuncsGet(DN_ArenaMemFuncType type)
DN_API DN_ArenaMemFuncs DN_ArenaMemFuncsGetDefaults() DN_API DN_ArenaMemFuncs DN_ArenaMemFuncsGetDefaults()
{ {
DN_ArenaMemFuncs result = {}; DN_ArenaMemFuncType type = DN_ArenaMemFuncType_Basic;
#if defined(DN_PLATFORM_EMSCRIPTEN) if (g_dn_->os_init) {
result = DN_ArenaMemFuncsGet(DN_ArenaMemFuncType_Basic); #if !defined(DN_PLATFORM_EMSCRIPTEN)
#else type = DN_ArenaMemFuncType_VMem;
result = DN_ArenaMemFuncsGet(DN_ArenaMemFuncType_VMem);
#endif #endif
}
DN_ArenaMemFuncs result = DN_ArenaMemFuncsGet(type);
return result; return result;
} }
@ -133,24 +135,24 @@ DN_API DN_Str8 DN_Str8BuilderBuildFromHeap(DN_Str8Builder const *builder)
return result; return result;
} }
static void DN_OS_LOGEmitFromTypeTypeFV_(DN_LogTypeParam type, void *user_data, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args) DN_API void DN_OS_LogPrint(DN_LogTypeParam type, void *user_data, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args)
{ {
DN_Assert(user_data); DN_Assert(user_data);
DN_OSCore *core = DN_Cast(DN_OSCore *)user_data; DN_OSCore *os = DN_Cast(DN_OSCore *)user_data;
// NOTE: Open log file for appending if requested // NOTE: Open log file for appending if requested
DN_TicketMutex_Begin(&core->log_file_mutex); DN_TicketMutex_Begin(&os->log_file_mutex);
if (core->log_to_file && !core->log_file.handle && !core->log_file.error) { if (os->log_to_file && !os->log_file.handle && !os->log_file.error) {
DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0); DN_TCScratch scratch = DN_TCScratchBegin(nullptr, 0);
DN_Str8 exe_dir = DN_OS_EXEDir(scratch.arena); DN_Str8 exe_dir = DN_OS_EXEDir(scratch.arena);
DN_Str8 log_path = DN_OS_PathF(scratch.arena, "%.*s/dn.log", DN_Str8PrintFmt(exe_dir)); DN_Str8 log_path = DN_OS_PathF(scratch.arena, "%.*s/dn.log", DN_Str8PrintFmt(exe_dir));
core->log_file = DN_OS_FileOpen(log_path, DN_OSFileOpen_CreateAlways, DN_OSFileAccess_AppendOnly, nullptr); os->log_file = DN_OS_FileOpen(log_path, DN_OSFileOpen_CreateAlways, DN_OSFileAccess_AppendOnly, nullptr);
DN_TCScratchEnd(&scratch); DN_TCScratchEnd(&scratch);
} }
DN_TicketMutex_End(&core->log_file_mutex); DN_TicketMutex_End(&os->log_file_mutex);
DN_LogStyle style = {}; DN_LogStyle style = {};
if (!core->log_no_colour) { if (!os->log_no_colour) {
style.colour = true; style.colour = true;
style.bold = DN_LogBold_Yes; style.bold = DN_LogBold_Yes;
if (type.is_u32_enum) { if (type.is_u32_enum) {
@ -191,14 +193,14 @@ static void DN_OS_LOGEmitFromTypeTypeFV_(DN_LogTypeParam type, void *user_data,
va_list args_copy; va_list args_copy;
va_copy(args_copy, args); va_copy(args_copy, args);
DN_TicketMutex_Begin(&core->log_file_mutex); DN_TicketMutex_Begin(&os->log_file_mutex);
{ {
DN_OS_FileWrite(&core->log_file, DN_Str8FromPtr(prefix_buffer, prefix_size.size), nullptr); DN_OS_FileWrite(&os->log_file, DN_Str8FromPtr(prefix_buffer, prefix_size.size), nullptr);
DN_OS_FileWriteF(&core->log_file, nullptr, "%*s ", DN_Cast(int)prefix_size.padding, ""); DN_OS_FileWriteF(&os->log_file, nullptr, "%*s ", DN_Cast(int)prefix_size.padding, "");
DN_OS_FileWriteFV(&core->log_file, nullptr, fmt, args_copy); DN_OS_FileWriteFV(&os->log_file, nullptr, fmt, args_copy);
DN_OS_FileWrite(&core->log_file, DN_Str8Lit("\n"), nullptr); DN_OS_FileWrite(&os->log_file, DN_Str8Lit("\n"), nullptr);
} }
DN_TicketMutex_End(&core->log_file_mutex); DN_TicketMutex_End(&os->log_file_mutex);
va_end(args_copy); va_end(args_copy);
DN_OSPrintDest dest = (type.is_u32_enum && type.u32 == DN_LogType_Error) ? DN_OSPrintDest_Err : DN_OSPrintDest_Out; DN_OSPrintDest dest = (type.is_u32_enum && type.u32 == DN_LogType_Error) ? DN_OSPrintDest_Err : DN_OSPrintDest_Out;
@ -207,76 +209,9 @@ static void DN_OS_LOGEmitFromTypeTypeFV_(DN_LogTypeParam type, void *user_data,
DN_OS_PrintLnFV(dest, fmt, args); DN_OS_PrintLnFV(dest, fmt, args);
} }
DN_API void DN_OS_EmitLogsWithOSPrintFunctions(DN_OSCore *os) DN_API void DN_OS_SetLogPrintFuncToOS()
{ {
DN_Assert(os); DN_LogSetPrintFunc(DN_OS_LogPrint, &g_dn_->os);
DN_LogSetEmitFromTypeFVFunc(DN_OS_LOGEmitFromTypeTypeFV_, os);
}
DN_API void DN_OS_DumpThreadContextArenaStat(DN_Str8 file_path)
{
#if defined(DN_DEBUG_THREAD_CONTEXT)
// NOTE: Open a file to write the arena stats to
FILE *file = nullptr;
fopen_s(&file, file_path.data, "a+b");
if (file) {
DN_LogErrorF("Failed to dump thread context arenas [file=%.*s]", DN_Str8PrintFmt(file_path));
return;
}
// NOTE: Copy the stats from library book-keeping
// NOTE: Extremely short critical section, copy the stats then do our
// work on it.
DN_ArenaStat stats[DN_ArrayCountU(g_dn_core->thread_context_arena_stats)];
int stats_size = 0;
DN_TicketMutex_Begin(&g_dn_core->thread_context_mutex);
stats_size = g_dn_core->thread_context_arena_stats_count;
DN_Memcpy(stats, g_dn_core->thread_context_arena_stats, sizeof(stats[0]) * stats_size);
DN_TicketMutex_End(&g_dn_core->thread_context_mutex);
// NOTE: Print the cumulative stat
DN_DateHMSTimeStr now = DN_Date_HMSLocalTimeStrNow();
fprintf(file,
"Time=%.*s %.*s | Thread Context Arenas | Count=%d\n",
now.date_size,
now.date,
now.hms_size,
now.hms,
g_dn_core->thread_context_arena_stats_count);
// NOTE: Write the cumulative thread arena data
{
DN_ArenaStat stat = {};
for (DN_USize index = 0; index < stats_size; index++) {
DN_ArenaStat const *current = stats + index;
stat.capacity += current->capacity;
stat.used += current->used;
stat.wasted += current->wasted;
stat.blocks += current->blocks;
stat.capacity_hwm = DN_Max(stat.capacity_hwm, current->capacity_hwm);
stat.used_hwm = DN_Max(stat.used_hwm, current->used_hwm);
stat.wasted_hwm = DN_Max(stat.wasted_hwm, current->wasted_hwm);
stat.blocks_hwm = DN_Max(stat.blocks_hwm, current->blocks_hwm);
}
DN_ArenaStatStr stats_string = DN_ArenaStatStr(&stat);
fprintf(file, " [ALL] CURR %.*s\n", stats_string.size, stats_string.data);
}
// NOTE: Print individual thread arena data
for (DN_USize index = 0; index < stats_size; index++) {
DN_ArenaStat const *current = stats + index;
DN_ArenaStatStr current_string = DN_ArenaStatStr(current);
fprintf(file, " [%03d] CURR %.*s\n", DN_Cast(int) index, current_string.size, current_string.data);
}
fclose(file);
DN_LogInfoF("Dumped thread context arenas [file=%.*s]", DN_Str8PrintFmt(file_path));
#else
(void)file_path;
#endif // #if defined(DN_DEBUG_THREAD_CONTEXT)
} }
// NOTE: Date // NOTE: Date
@ -759,14 +694,21 @@ static void DN_OS_ThreadExecute_(void *user_context)
DN_ArenaMemFuncs mem_funcs = DN_ArenaMemFuncsGetDefaults(); DN_ArenaMemFuncs mem_funcs = DN_ArenaMemFuncsGetDefaults();
DN_TCInitFromMemFuncs(&thread->context, thread->thread_id, /*args=*/nullptr, mem_funcs); DN_TCInitFromMemFuncs(&thread->context, thread->thread_id, /*args=*/nullptr, mem_funcs);
DN_TCEquip(&thread->context); DN_TCEquip(&thread->context);
if (thread->is_lane_set)
DN_TCLaneEquip(thread->lane);
DN_OS_SemaphoreWait(&thread->init_semaphore, DN_OS_SEMAPHORE_INFINITE_TIMEOUT); DN_OS_SemaphoreWait(&thread->init_semaphore, DN_OS_SEMAPHORE_INFINITE_TIMEOUT);
thread->func(thread); thread->func(thread);
} }
DN_API void DN_OS_ThreadSetName(DN_Str8 name) DN_API void DN_OS_ThreadSetNameFmt(char const *fmt, ...)
{ {
DN_TCCore *tls = DN_TCGet(); DN_TCCore *tls = DN_TCGet();
tls->name = DN_Str8x64FromFmt("%.*s", DN_Str8PrintFmt(name)); va_list args;
va_start(args, fmt);
tls->name = DN_Str8x64FromFmtV(fmt, args);
va_end(args);
DN_Str8 name = DN_Str8FromPtr(tls->name.data, tls->name.size);
#if defined(DN_PLATFORM_WIN32) #if defined(DN_PLATFORM_WIN32)
DN_OS_W32ThreadSetName(name); DN_OS_W32ThreadSetName(name);
#else #else

View File

@ -203,6 +203,8 @@ struct DN_OSThread
{ {
DN_Str8x64 name; DN_Str8x64 name;
DN_TCCore context; DN_TCCore context;
DN_TCLane lane;
bool is_lane_set;
void *handle; void *handle;
DN_U64 thread_id; DN_U64 thread_id;
void *user_context; void *user_context;
@ -251,8 +253,6 @@ struct DN_OSCore
DN_CPUReport cpu_report; DN_CPUReport cpu_report;
// NOTE: Logging // NOTE: Logging
DN_LogEmitFromTypeFVFunc * log_callback; // Set this pointer to override the logging routine
void * log_user_data; // User pointer passed into 'log_callback'
bool log_to_file; // Output logs to file as well as standard out bool log_to_file; // Output logs to file as well as standard out
DN_OSFile log_file; // TODO(dn): Hmmm, how should we do this... ? DN_OSFile log_file; // TODO(dn): Hmmm, how should we do this... ?
DN_TicketMutex log_file_mutex; // Is locked when instantiating the log_file for the first time DN_TicketMutex log_file_mutex; // Is locked when instantiating the log_file for the first time
@ -293,7 +293,8 @@ DN_API DN_Str8 DN_Str8FromHeapF (D
DN_API DN_Str8 DN_Str8FromHeap (DN_USize size, DN_ZMem z_mem); DN_API DN_Str8 DN_Str8FromHeap (DN_USize size, DN_ZMem z_mem);
DN_API DN_Str8 DN_Str8BuilderBuildFromHeap (DN_Str8Builder const *builder); DN_API DN_Str8 DN_Str8BuilderBuildFromHeap (DN_Str8Builder const *builder);
DN_API void DN_OS_EmitLogsWithOSPrintFunctions (DN_OSCore *os); DN_API void DN_OS_LogPrint (DN_LogTypeParam type, void *user_data, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args);
DN_API void DN_OS_SetLogPrintFuncToOS ();
DN_API void DN_OS_DumpThreadContextArenaStat (DN_Str8 file_path); DN_API void DN_OS_DumpThreadContextArenaStat (DN_Str8 file_path);
DN_API void * DN_OS_MemReserve (DN_USize size, DN_MemCommit commit, DN_MemPage page_flags); DN_API void * DN_OS_MemReserve (DN_USize size, DN_MemCommit commit, DN_MemPage page_flags);
@ -410,10 +411,10 @@ DN_API bool DN_OS_ConditionVariableWaitUntil (D
DN_API void DN_OS_ConditionVariableSignal (DN_OSConditionVariable *cv); DN_API void DN_OS_ConditionVariableSignal (DN_OSConditionVariable *cv);
DN_API void DN_OS_ConditionVariableBroadcast (DN_OSConditionVariable *cv); DN_API void DN_OS_ConditionVariableBroadcast (DN_OSConditionVariable *cv);
DN_API bool DN_OS_ThreadInit (DN_OSThread *thread, DN_OSThreadFunc *func, void *user_context); DN_API bool DN_OS_ThreadInit (DN_OSThread *thread, DN_OSThreadFunc *func, DN_TCLane *lane, void *user_context);
DN_API void DN_OS_ThreadDeinit (DN_OSThread *thread); DN_API bool DN_OS_ThreadJoin (DN_OSThread *thread);
DN_API DN_U32 DN_OS_ThreadID (); DN_API DN_U32 DN_OS_ThreadID ();
DN_API void DN_OS_ThreadSetName (DN_Str8 name); DN_API void DN_OS_ThreadSetNameFmt (char const *fmt, ...);
DN_API void DN_OS_HttpRequestAsync (DN_OSHttpResponse *response, DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers); DN_API void DN_OS_HttpRequestAsync (DN_OSHttpResponse *response, DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers);
DN_API void DN_OS_HttpRequestWait (DN_OSHttpResponse *response); DN_API void DN_OS_HttpRequestWait (DN_OSHttpResponse *response);

View File

@ -1289,7 +1289,7 @@ static void *DN_OS_ThreadFunc_(void *user_context)
return nullptr; return nullptr;
} }
DN_API bool DN_OS_ThreadInit(DN_OSThread *thread, DN_OSThreadFunc *func, void *user_context) DN_API bool DN_OS_ThreadInit(DN_OSThread *thread, DN_OSThreadFunc *func, DN_TCLane *lane, void *user_context)
{ {
bool result = false; bool result = false;
if (!thread) if (!thread)
@ -1298,6 +1298,7 @@ DN_API bool DN_OS_ThreadInit(DN_OSThread *thread, DN_OSThreadFunc *func, void *u
thread->func = func; thread->func = func;
thread->user_context = user_context; thread->user_context = user_context;
thread->init_semaphore = DN_OS_SemaphoreInit(0 /*initial_count*/); thread->init_semaphore = DN_OS_SemaphoreInit(0 /*initial_count*/);
thread->lane = lane;
// TODO(doyle): Check if semaphore is valid // TODO(doyle): Check if semaphore is valid
// NOTE: pthread_t is essentially the thread ID. In Windows, the handle and // NOTE: pthread_t is essentially the thread ID. In Windows, the handle and
@ -1331,18 +1332,19 @@ DN_API bool DN_OS_ThreadInit(DN_OSThread *thread, DN_OSThreadFunc *func, void *u
return result; return result;
} }
DN_API void DN_OS_ThreadDeinit(DN_OSThread *thread) DN_API bool DN_OS_ThreadJoin(DN_OSThread *thread)
{ {
if (!thread || !thread->handle) bool result = false;
return; if (thread && thread->handle) {
pthread_t thread_id = {}; pthread_t thread_id = {};
DN_Memcpy(&thread_id, &thread->thread_id, sizeof(thread_id)); DN_Memcpy(&thread_id, &thread->thread_id, sizeof(thread_id));
void *return_val = nullptr; void *return_val = nullptr;
pthread_join(thread_id, &return_val); result = pthread_join(thread_id, &return_val) == 0;
thread->handle = {}; thread->handle = {};
thread->thread_id = {}; thread->thread_id = {};
}
return result;
} }
DN_API DN_U32 DN_OS_ThreadID() DN_API DN_U32 DN_OS_ThreadID()

View File

@ -2,6 +2,7 @@
#if defined(_CLANGD) #if defined(_CLANGD)
#define DN_H_WITH_CORE 1 #define DN_H_WITH_CORE 1
#define DN_H_WITH_OS 1
#include "../dn.h" #include "../dn.h"
#include "dn_os_w32.h" #include "dn_os_w32.h"
#endif #endif
@ -1235,14 +1236,14 @@ DN_API void DN_OS_ConditionVariableBroadcast(DN_OSConditionVariable *cv)
} }
} }
// NOTE: DN_OSThread /////////////////////////////////////////////////////////////////////////////// // NOTE: DN_OSThread
static DWORD __stdcall DN_OS_ThreadFunc_(void *user_context) static DWORD __stdcall DN_OS_ThreadFunc_(void *user_context)
{ {
DN_OS_ThreadExecute_(user_context); DN_OS_ThreadExecute_(user_context);
return 0; return 0;
} }
DN_API bool DN_OS_ThreadInit(DN_OSThread *thread, DN_OSThreadFunc *func, void *user_context) DN_API bool DN_OS_ThreadInit(DN_OSThread *thread, DN_OSThreadFunc *func, DN_TCLane *lane, void *user_context)
{ {
bool result = false; bool result = false;
if (!thread) if (!thread)
@ -1251,6 +1252,10 @@ DN_API bool DN_OS_ThreadInit(DN_OSThread *thread, DN_OSThreadFunc *func, void *u
thread->func = func; thread->func = func;
thread->user_context = user_context; thread->user_context = user_context;
thread->init_semaphore = DN_OS_SemaphoreInit(0 /*initial_count*/); thread->init_semaphore = DN_OS_SemaphoreInit(0 /*initial_count*/);
if (lane) {
thread->is_lane_set = true;
thread->lane = *lane;
}
// TODO(doyle): Check if semaphore is valid // TODO(doyle): Check if semaphore is valid
DWORD thread_id = 0; DWORD thread_id = 0;
@ -1277,16 +1282,18 @@ DN_API bool DN_OS_ThreadInit(DN_OSThread *thread, DN_OSThreadFunc *func, void *u
return result; return result;
} }
DN_API void DN_OS_ThreadDeinit(DN_OSThread *thread) DN_API bool DN_OS_ThreadJoin(DN_OSThread *thread)
{ {
if (!thread || !thread->handle) bool result = false;
return; if (thread && thread->handle) {
DWORD wait_result = WaitForSingleObject(thread->handle, INFINITE);
WaitForSingleObject(thread->handle, INFINITE); result = wait_result == WAIT_OBJECT_0;
CloseHandle(thread->handle); CloseHandle(thread->handle);
thread->handle = INVALID_HANDLE_VALUE; thread->handle = INVALID_HANDLE_VALUE;
thread->thread_id = {}; thread->thread_id = {};
DN_TCDeinit(&thread->context); DN_TCDeinit(&thread->context);
}
return result;
} }
DN_API DN_U32 DN_OS_ThreadID() DN_API DN_U32 DN_OS_ThreadID()

View File

@ -1,3 +1,8 @@
#if (_CLANGD)
#define DN_H_WITH_OS 1
#include "dn.h"
#endif
#include "Base/dn_base.cpp" #include "Base/dn_base.cpp"
#include "Base/dn_base_containers.cpp" #include "Base/dn_base_containers.cpp"
#include "Base/dn_base_leak.cpp" #include "Base/dn_base_leak.cpp"
@ -13,9 +18,210 @@
#endif #endif
#endif #endif
#if DN_H_WITH_CORE DN_Core *g_dn_;
#include "dn_core.cpp"
#endif DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags, DN_InitArgs *args)
{
g_dn_ = dn;
dn->init_flags = flags;
if (DN_BitIsSet(flags, DN_InitFlags_OS)) {
#if DN_H_WITH_OS
DN_OSCore *os = &dn->os;
dn->os_init = true;
DN_OS_SetLogPrintFuncToOS(os);
// NOTE: Query OS information
{
#if defined(DN_PLATFORM_WIN32)
SYSTEM_INFO system_info = {};
GetSystemInfo(&system_info);
os->logical_processor_count = system_info.dwNumberOfProcessors;
os->page_size = system_info.dwPageSize;
os->alloc_granularity = system_info.dwAllocationGranularity;
#else
#if defined(DN_PLATFORM_EMSCRIPTEN)
os->logical_processor_count = 1;
#else
os->logical_processor_count = get_nprocs();
#endif
os->page_size = getpagesize();
os->alloc_granularity = os->page_size;
#endif
}
{
#if defined(DN_PLATFORM_EMSCRIPTEN)
os->arena = DN_ArenaFromHeap(DN_Megabytes(1), DN_ArenaFlags_NoAllocTrack);
#else
os->arena = DN_ArenaFromVMem(DN_Megabytes(1), DN_Kilobytes(4), DN_ArenaFlags_NoAllocTrack);
#endif
#if defined(DN_PLATFORM_WIN32)
os->platform_context = DN_ArenaNew(&os->arena, DN_OSW32Core, DN_ZMem_Yes);
#elif defined(DN_PLATFORM_POSIX) || defined(DN_PLATFORM_EMSCRIPTEN)
os->platform_context = DN_ArenaNew(&os->arena, DN_OSPOSIXCore, DN_ZMem_Yes);
#endif
#if defined(DN_PLATFORM_WIN32)
DN_OSW32Core *w32 = DN_Cast(DN_OSW32Core *) os->platform_context;
InitializeCriticalSection(&w32->sync_primitive_free_list_mutex);
QueryPerformanceFrequency(&w32->qpc_frequency);
HMODULE module = LoadLibraryA("kernel32.dll");
if (module) {
w32->set_thread_description = DN_Cast(DN_OSW32SetThreadDescriptionFunc *) GetProcAddress(module, "SetThreadDescription");
FreeLibrary(module);
}
// NOTE: win32 bcrypt
wchar_t const BCRYPT_ALGORITHM[] = L"RNG";
long /*NTSTATUS*/ init_status = BCryptOpenAlgorithmProvider(&w32->bcrypt_rng_handle, BCRYPT_ALGORITHM, nullptr /*implementation*/, 0 /*flags*/);
if (w32->bcrypt_rng_handle && init_status == 0)
w32->bcrypt_init_success = true;
else
DN_LogErrorF("Failed to initialise Windows secure random number generator, error: %d", init_status);
#else
DN_OS_PosixInit(DN_Cast(DN_OSPosixCore *)os->platform_context);
#endif
}
os->cpu_report = DN_CPUGetReport();
#define DN_CPU_FEAT_XENTRY(label) g_dn_cpu_feature_decl[DN_CPUFeature_##label] = {DN_CPUFeature_##label, DN_Str8Lit(#label)};
DN_CPU_FEAT_XMACRO
#undef DN_CPU_FEAT_XENTRY
DN_Assert(g_dn_);
#endif
}
if (DN_BitIsSet(flags, DN_InitFlags_LeakTracker)) {
DN_Assert(dn->os_init);
#if DN_H_WITH_OS
// NOTE: Setup the allocation table with allocation tracking turned off on
// the arena we're using to initialise the table.
dn->leak.alloc_table_arena = DN_ArenaFromVMem(DN_Megabytes(1), DN_Kilobytes(512), DN_ArenaFlags_NoAllocTrack | DN_ArenaFlags_AllocCanLeak);
dn->leak.alloc_table = DN_DSMapInit<DN_LeakAlloc>(&dn->leak.alloc_table_arena, 4096, DN_DSMapFlags_Nil);
#endif
}
if (DN_BitIsSet(flags, DN_InitFlags_ThreadContext)) {
DN_Assert(dn->os_init);
#if DN_H_WITH_OS
DN_TCInitArgs *tc_init_args = args ? &args->thread_context_init_args : nullptr;
DN_TCInitFromMemFuncs(&dn->main_tc, DN_OS_ThreadID(), tc_init_args, DN_ArenaMemFuncsGetDefaults());
DN_TCEquip(&dn->main_tc);
#endif
}
// NOTE: Print out init features
char buf[4096];
DN_USize buf_size = 0;
if (DN_BitIsSet(flags, DN_InitFlags_LogLibFeatures)) {
DN_FmtAppendTruncate(buf, &buf_size, sizeof(buf), DN_Str8Lit("..."), "DN initialised:\n");
#if DN_H_WITH_OS
DN_F32 page_size_kib = dn->os.page_size / 1024.0f;
DN_F32 alloc_granularity_kib = dn->os.alloc_granularity / 1024.0f;
DN_FmtAppendTruncate(buf,
&buf_size,
sizeof(buf),
DN_Str8Lit("..."),
" OS Page/Granularity/Cores: %.0fKiB/%.0fKiB/%u\n",
page_size_kib,
alloc_granularity_kib,
dn->os.logical_processor_count);
#endif
DN_FmtAppendTruncate(buf, &buf_size, sizeof(buf), DN_Str8Lit("..."), " Thread Context: ");
if (DN_BitIsSet(flags, DN_InitFlags_ThreadContext)) {
DN_Arena *arena = dn->main_tc.main_arena;
DN_Str8 mem_funcs = DN_Str8Lit("");
switch (arena->mem_funcs.type) {
case DN_ArenaMemFuncType_Nil: break;
case DN_ArenaMemFuncType_Basic: mem_funcs = DN_Str8Lit("Basic"); break;
case DN_ArenaMemFuncType_VMem: mem_funcs = DN_Str8Lit("VMem"); break;
}
DN_Str8x32 main_commit = DN_ByteCountStr8x32(dn->main_tc.main_arena->curr->commit);
DN_Str8x32 main_reserve = DN_ByteCountStr8x32(dn->main_tc.main_arena->curr->reserve);
DN_Str8x32 temp_commit = DN_ByteCountStr8x32(dn->main_tc.temp_a_arena->curr->commit);
DN_Str8x32 temp_reserve = DN_ByteCountStr8x32(dn->main_tc.temp_a_arena->curr->reserve);
DN_Str8x32 err_commit = DN_ByteCountStr8x32(dn->main_tc.err_sink.arena->curr->commit);
DN_Str8x32 err_reserve = DN_ByteCountStr8x32(dn->main_tc.err_sink.arena->curr->reserve);
DN_FmtAppendTruncate(buf,
&buf_size,
sizeof(buf),
DN_Str8Lit("..."),
"M %.*s/%.*s S(x2) %.*s/%.*s E %.*s/%.*s (%.*s)\n",
DN_Str8PrintFmt(main_commit),
DN_Str8PrintFmt(main_reserve),
DN_Str8PrintFmt(temp_commit),
DN_Str8PrintFmt(temp_reserve),
DN_Str8PrintFmt(err_commit),
DN_Str8PrintFmt(err_reserve),
DN_Str8PrintFmt(mem_funcs));
} else {
DN_FmtAppendTruncate(buf, &buf_size, sizeof(buf), DN_Str8Lit("..."), "N/A\n");
}
#if DN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
if (DN_ASAN_POISON) {
DN_FmtAppendTruncate(buf, &buf_size, sizeof(buf), DN_Str8Lit("..."), " ASAN manual poisoning%s\n", DN_ASAN_VET_POISON ? " (+vet sanity checks)" : "");
DN_FmtAppendTruncate(buf, &buf_size, sizeof(buf), DN_Str8Lit("..."), " ASAN poison guard size: %u\n", DN_ASAN_POISON_GUARD_SIZE);
}
#endif
#if defined(DN_LEAK_TRACKING)
DN_FmtAppendTruncate(buf, &buf_size, sizeof(buf), DN_Str8Lit("..."), " Allocation leak tracing\n");
#endif
#if defined(DN_PLATFORM_EMSCRIPTEN) || defined(DN_PLATFORM_POSIX)
DN_OSPosixCore *posix = DN_Cast(DN_OSPosixCore *)g_dn_->os.platform_context;
DN_FmtAppendTruncate(buf, &buf_size, sizeof(buf), DN_Str8Lit("..."), " Clock GetTime: %S\n", posix->clock_monotonic_raw ? DN_Str8Lit("CLOCK_MONOTONIC_RAW") : DN_Str8Lit("CLOCK_MONOTONIC"));
#endif
// TODO(doyle): Add stacktrace feature log
}
if (DN_BitIsSet(flags, DN_InitFlags_LogCPUFeatures)) {
DN_Assert(dn->os_init);
#if DN_H_WITH_OS
DN_CPUReport const *report = &dn->os.cpu_report;
DN_Str8 brand = DN_Str8TrimWhitespaceAround(DN_Str8FromPtr(report->brand, sizeof(report->brand) - 1));
DN_FmtAppendTruncate(buf, &buf_size, sizeof(buf), DN_Str8Lit("..."), " CPU '%.*s' from '%s' detected:\n", DN_Str8PrintFmt(brand), report->vendor);
DN_USize longest_feature_name = 0;
for (DN_ForIndexU(feature_index, DN_CPUFeature_Count)) {
DN_CPUFeatureDecl feature_decl = g_dn_cpu_feature_decl[feature_index];
longest_feature_name = DN_Max(longest_feature_name, feature_decl.label.size);
}
for (DN_ForIndexU(feature_index, DN_CPUFeature_Count)) {
DN_CPUFeatureDecl feature_decl = g_dn_cpu_feature_decl[feature_index];
bool has_feature = DN_CPUHasFeature(report, feature_decl.value);
DN_FmtAppendTruncate(buf,
&buf_size,
sizeof(buf),
DN_Str8Lit("..."),
" %.*s:%*s%s\n",
DN_Str8PrintFmt(feature_decl.label),
DN_Cast(int)(longest_feature_name - feature_decl.label.size),
"",
has_feature ? "available" : "not available");
}
#endif
}
if (buf_size)
DN_LogDebugF("%.*s", DN_Cast(int)buf_size, buf);
}
DN_API void DN_BeginFrame()
{
#if DN_H_WITH_OS
DN_AtomicSetValue64(&g_dn_->os.mem_allocs_frame, 0);
#endif
}
#if DN_H_WITH_MATH #if DN_H_WITH_MATH
#include "Extra/dn_math.cpp" #include "Extra/dn_math.cpp"

View File

@ -1,10 +1,16 @@
#if !defined(DN_H) #if !defined(DN_H)
#define DN_H #define DN_H
// NOTE: DN configuration // NOTE: DN
// Enabling DN modules // Getting Started
// By including this mega header 'dn.h' you must define the following symbols to 0 or 1 in order // Include this mega header `dn.h` and define the following symbols to `1` to conditionally
// to include the module's implementation into the library as follows // enable the interfaces for those features. Additionally in the same or different translation
// unit, include `dn.cpp` with the same symbols defined to enable the implementation of these
// features.
//
// See the configuration section for more information on other symbols that can be defined.
//
// The following is a single translation unit example:
/* /*
#define DN_H_WITH_OS 1 #define DN_H_WITH_OS 1
#define DN_H_WITH_CORE 1 #define DN_H_WITH_CORE 1
@ -18,10 +24,22 @@
#define DN_CPP_WITH_DEMO 1 #define DN_CPP_WITH_DEMO 1
#include "dn.cpp" #include "dn.cpp"
*/ */
// Then initialise the library at runtime by calling DN_Init(...). The library is laid out as:
//
// - The base layer (dn_base.h) which provides primitives that do not require a host operating
// system (e.g. freestanding) such as string manipulation, compiler intrinsics and containers.
// This layer is unconditionallly always available by compiling with this library.
//
// - The OS layer (dn_os.h) which provides primitives that use the OS such as file IO, threading
// synchronisation, memory allocation. This layer is OPTIONAL.
//
// - Extra layer provides helper utilities that are opt-in. These layers are OPTIONAL.
//
// Configuration
// Platform Target // Platform Target
// Define one of the following directives to configure this library to compile for that platform. // Define one of the following directives to configure this library to compile for that
// By default, the library will auto-detect the current host platform and select that as the // platform. By default, the library will auto-detect the current host platform and select that
// target platform. // as the target platform.
// //
// DN_PLATFORM_EMSCRIPTEN // DN_PLATFORM_EMSCRIPTEN
// DN_PLATFORM_POSIX // DN_PLATFORM_POSIX
@ -40,16 +58,17 @@
// //
// DN_STATIC_API // DN_STATIC_API
// //
// To replace all the prefixed with 'static' ensuring that the functions in the library do not // To replace all the functions prefixed with DN_API to be prefixed with 'static' ensuring that
// export an entry into the linking table and thereby optimise compilation times as the linker // the functions in the library do not export an entry into the linking table.
// will not try to resolve symbols from other translation units from the the unit including the // translation units.
// DN library.
// //
// Using the in-built replacement header for <Windows.h> (requires dn_os_inc.h) // Disabling the in-built <Windows.h> (if #define DN_H_WITH_OS 1)
// If you are building DN for the Windows platform, <Windows.h> is a large legacy header that // If you are building DN for the Windows platform, <Windows.h> is a large legacy header that
// applications have to link to use Windows syscalls. By default DN library uses a replacement // applications have to include to use Windows APIs. By default this library uses a replacement
// header for all the Windows functions that it uses in the OS layer removing the need to include // header for all the Windows functions that it uses in the OS layer removing the need to
// <Windows.h> to improve compilation times. This can be disabled by defining: // include <Windows.h> to improve compilation times. This mini header will conflict with
// <Windows.h> if it needs to be included in your project. The mini header can be disabled by
// defining:
// //
// DN_NO_WINDOWS_H_REPLACEMENT_HEADER // DN_NO_WINDOWS_H_REPLACEMENT_HEADER
// //
@ -83,9 +102,43 @@
#include "OS/dn_os.h" #include "OS/dn_os.h"
#endif #endif
#if DN_H_WITH_CORE struct DN_InitArgs
#include "dn_core.h" {
#endif DN_TCInitArgs thread_context_init_args;
};
typedef DN_USize DN_InitFlags;
enum DN_InitFlags_
{
DN_InitFlags_Nil = 0,
DN_InitFlags_OS = (1 << 0),
DN_InitFlags_LeakTracker = (1 << 1) | DN_InitFlags_OS,
DN_InitFlags_LogLibFeatures = (1 << 2),
DN_InitFlags_LogCPUFeatures = (1 << 3) | DN_InitFlags_OS,
DN_InitFlags_ThreadContext = (1 << 4) | DN_InitFlags_OS,
DN_InitFlags_LogAllFeatures = DN_InitFlags_LogLibFeatures | DN_InitFlags_LogCPUFeatures,
};
struct DN_Core
{
DN_InitFlags init_flags;
DN_TCCore main_tc;
DN_USize mem_allocs_frame;
DN_LeakTracker leak;
DN_LogPrintFunc* print_func;
void* print_func_context;
bool os_init;
#if defined(DN_OS_H)
DN_OSCore os;
#endif
};
extern DN_Core *g_dn_;
DN_API void DN_Init (DN_Core *dn, DN_InitFlags flags, DN_InitArgs *args);
DN_API void DN_BeginFrame();
#if DN_H_WITH_MATH #if DN_H_WITH_MATH
#include "Extra/dn_math.h" #include "Extra/dn_math.h"

View File

@ -1,171 +0,0 @@
#define DN_INC_CPP
#if defined(_CLANGD)
#include "../Base/dn_base.h"
#include "../OS/dn_os.h"
#endif
DN_Core *g_dn_;
static void DN_InitOS_(DN_OSCore *os)
{
#if defined(DN_OS_H) && defined(DN_OS_CPP)
// NOTE: OS
{
#if defined(DN_PLATFORM_WIN32)
SYSTEM_INFO system_info = {};
GetSystemInfo(&system_info);
os->logical_processor_count = system_info.dwNumberOfProcessors;
os->page_size = system_info.dwPageSize;
os->alloc_granularity = system_info.dwAllocationGranularity;
#else
#if defined(DN_PLATFORM_EMSCRIPTEN)
os->logical_processor_count = 1;
#else
os->logical_processor_count = get_nprocs();
#endif
os->page_size = getpagesize();
os->alloc_granularity = os->page_size;
#endif
}
// NOTE: Setup logging
DN_OS_EmitLogsWithOSPrintFunctions(os);
{
#if defined(DN_PLATFORM_EMSCRIPTEN)
os->arena = DN_ArenaFromHeap(DN_Megabytes(1), DN_ArenaFlags_NoAllocTrack);
#else
os->arena = DN_ArenaFromVMem(DN_Megabytes(1), DN_Kilobytes(4), DN_ArenaFlags_NoAllocTrack);
#endif
#if defined(DN_PLATFORM_WIN32)
os->platform_context = DN_ArenaNew(&os->arena, DN_OSW32Core, DN_ZMem_Yes);
#elif defined(DN_PLATFORM_POSIX) || defined(DN_PLATFORM_EMSCRIPTEN)
os->platform_context = DN_ArenaNew(&os->arena, DN_OSPOSIXCore, DN_ZMem_Yes);
#endif
#if defined(DN_PLATFORM_WIN32)
DN_OSW32Core *w32 = DN_Cast(DN_OSW32Core *) os->platform_context;
InitializeCriticalSection(&w32->sync_primitive_free_list_mutex);
QueryPerformanceFrequency(&w32->qpc_frequency);
HMODULE module = LoadLibraryA("kernel32.dll");
if (module) {
w32->set_thread_description = DN_Cast(DN_OSW32SetThreadDescriptionFunc *) GetProcAddress(module, "SetThreadDescription");
FreeLibrary(module);
}
// NOTE: win32 bcrypt
wchar_t const BCRYPT_ALGORITHM[] = L"RNG";
long /*NTSTATUS*/ init_status = BCryptOpenAlgorithmProvider(&w32->bcrypt_rng_handle, BCRYPT_ALGORITHM, nullptr /*implementation*/, 0 /*flags*/);
if (w32->bcrypt_rng_handle && init_status == 0)
w32->bcrypt_init_success = true;
else
DN_LogErrorF("Failed to initialise Windows secure random number generator, error: %d", init_status);
#else
DN_OS_PosixInit(DN_Cast(DN_OSPosixCore *)os->platform_context);
#endif
}
os->cpu_report = DN_CPUGetReport();
#define DN_CPU_FEAT_XENTRY(label) g_dn_cpu_feature_decl[DN_CPUFeature_##label] = {DN_CPUFeature_##label, DN_Str8Lit(#label)};
DN_CPU_FEAT_XMACRO
#undef DN_CPU_FEAT_XENTRY
DN_Assert(g_dn_);
#endif // defined(DN_OS_H) && defined(DN_OS_CPP)
}
DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags)
{
g_dn_ = dn;
dn->init_flags = flags;
if (flags & DN_InitFlags_OS) {
#if defined(DN_OS_H) && defined(DN_OS_CPP)
DN_InitOS_(&dn->os);
if (flags & DN_InitFlags_OSLeakTracker) {
// NOTE: Setup the allocation table with allocation tracking turned off on
// the arena we're using to initialise the table.
dn->leak.alloc_table_arena = DN_ArenaFromVMem(DN_Megabytes(1), DN_Kilobytes(512), DN_ArenaFlags_NoAllocTrack | DN_ArenaFlags_AllocCanLeak);
dn->leak.alloc_table = DN_DSMapInit<DN_LeakAlloc>(&dn->leak.alloc_table_arena, 4096, DN_DSMapFlags_Nil);
}
#endif
}
// NOTE: Print out init features
char buf[4096];
DN_USize buf_size = 0;
if (flags & DN_InitFlags_LogLibFeatures) {
DN_FmtAppendTruncate(buf, &buf_size, sizeof(buf), DN_Str8Lit("..."), "DN initialised:\n");
#if defined(DN_OS_CPP)
DN_F32 page_size_kib = dn->os.page_size / 1024.0f;
DN_F32 alloc_granularity_kib = dn->os.alloc_granularity / 1024.0f;
DN_FmtAppendTruncate(buf,
&buf_size,
sizeof(buf),
DN_Str8Lit("..."),
" OS Page Size/Alloc Granularity: %.1f/%.1fKiB\n"
" Logical Processor Count: %u\n",
page_size_kib,
alloc_granularity_kib,
dn->os.logical_processor_count);
#endif
#if DN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
if (DN_ASAN_POISON) {
DN_FmtAppendTruncate(buf, &buf_size, sizeof(buf), DN_Str8Lit("..."), " ASAN manual poisoning%s\n", DN_ASAN_VET_POISON ? " (+vet sanity checks)" : "");
DN_FmtAppendTruncate(buf, &buf_size, sizeof(buf), DN_Str8Lit("..."), " ASAN poison guard size: %u\n", DN_ASAN_POISON_GUARD_SIZE);
}
#endif
#if defined(DN_LEAK_TRACKING)
DN_FmtAppendTruncate(buf, &buf_size, sizeof(buf), DN_Str8Lit("..."), " Allocation leak tracing\n");
#endif
#if defined(DN_PLATFORM_EMSCRIPTEN) || defined(DN_PLATFORM_POSIX)
DN_OSPosixCore *posix = DN_Cast(DN_OSPosixCore *)g_dn_->os.platform_context;
DN_FmtAppendTruncate(buf, &buf_size, sizeof(buf), DN_Str8Lit("..."), " Clock GetTime: %S\n", posix->clock_monotonic_raw ? DN_Str8Lit("CLOCK_MONOTONIC_RAW") : DN_Str8Lit("CLOCK_MONOTONIC"));
#endif
// TODO(doyle): Add stacktrace feature log
}
if (flags & DN_InitFlags_LogCPUFeatures) {
DN_CPUReport const *report = &dn->os.cpu_report;
DN_Str8 brand = DN_Str8TrimWhitespaceAround(DN_Str8FromPtr(report->brand, sizeof(report->brand) - 1));
DN_MSVC_WARNING_PUSH
DN_MSVC_WARNING_DISABLE(6284) // Object passed as _Param_(3) when a string is required in call to 'DN_Str8BuilderAppendF' Actual type: 'struct DN_Str8'.
DN_FmtAppendTruncate(buf, &buf_size, sizeof(buf), DN_Str8Lit("..."), " CPU '%S' from '%s' detected:\n", brand, report->vendor);
DN_MSVC_WARNING_POP
DN_USize longest_feature_name = 0;
for (DN_ForIndexU(feature_index, DN_CPUFeature_Count)) {
DN_CPUFeatureDecl feature_decl = g_dn_cpu_feature_decl[feature_index];
longest_feature_name = DN_Max(longest_feature_name, feature_decl.label.size);
}
for (DN_ForIndexU(feature_index, DN_CPUFeature_Count)) {
DN_CPUFeatureDecl feature_decl = g_dn_cpu_feature_decl[feature_index];
bool has_feature = DN_CPUHasFeature(report, feature_decl.value);
DN_FmtAppendTruncate(buf,
&buf_size,
sizeof(buf),
DN_Str8Lit("..."),
" %.*s:%*s%s\n",
DN_Str8PrintFmt(feature_decl.label),
DN_Cast(int)(longest_feature_name - feature_decl.label.size),
"",
has_feature ? "available" : "not available");
}
}
if (buf_size)
DN_LogDebugF("%.*s", DN_Cast(int)buf_size, buf);
}
DN_API void DN_BeginFrame()
{
DN_AtomicSetValue64(&g_dn_->os.mem_allocs_frame, 0);
}

View File

@ -1,44 +0,0 @@
#if !defined(DN_INC_H)
#define DN_INC_H
#if defined(_CLANGD)
#define DN_H_WITH_OS 1
#include "dn.h"
#endif
struct DN_InitArgs
{
DN_U64 os_tls_reserve;
DN_U64 os_tls_commit;
DN_U64 os_tls_err_sink_reserve;
DN_U64 os_tls_err_sink_commit;
};
typedef DN_USize DN_InitFlags;
enum DN_InitFlags_
{
DN_InitFlags_Nil = 0,
DN_InitFlags_OS = 1 << 0,
DN_InitFlags_OSLeakTracker = 1 << 1,
DN_InitFlags_LogLibFeatures = 1 << 2,
DN_InitFlags_LogCPUFeatures = 1 << 3,
DN_InitFlags_LogAllFeatures = DN_InitFlags_LogLibFeatures | DN_InitFlags_LogCPUFeatures,
};
struct DN_Core
{
DN_InitFlags init_flags;
DN_USize mem_allocs_frame;
DN_LeakTracker leak;
#if defined(DN_OS_H)
DN_OSCore os;
#endif
};
extern DN_Core *g_dn_;
DN_API void DN_Init(DN_Core *dn, DN_InitFlags flags, DN_InitArgs *args);
DN_API void DN_ThreadContextInit();
DN_API void DN_BeginFrame();
#endif // !defined(DN_INC_H)