More cleanup
This commit is contained in:
parent
0f9af50a6d
commit
dbbaa5fbf7
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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)
|
||||||
@ -20,7 +20,7 @@ static void *DN_ArenaBasicAllocFromOSHeap(DN_USize size)
|
|||||||
DN_API DN_ArenaMemFuncs DN_ArenaMemFuncsGet(DN_ArenaMemFuncType type)
|
DN_API DN_ArenaMemFuncs DN_ArenaMemFuncsGet(DN_ArenaMemFuncType type)
|
||||||
{
|
{
|
||||||
DN_ArenaMemFuncs result = {};
|
DN_ArenaMemFuncs result = {};
|
||||||
result.type = type;
|
result.type = type;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case DN_ArenaMemFuncType_Nil: break;
|
case DN_ArenaMemFuncType_Nil: break;
|
||||||
case DN_ArenaMemFuncType_Basic: {
|
case DN_ArenaMemFuncType_Basic: {
|
||||||
@ -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
|
||||||
|
|||||||
@ -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;
|
||||||
@ -248,32 +250,30 @@ struct DN_OSHttpResponse
|
|||||||
|
|
||||||
struct DN_OSCore
|
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
|
bool log_to_file; // Output logs to file as well as standard out
|
||||||
void * log_user_data; // User pointer passed into 'log_callback'
|
DN_OSFile log_file; // TODO(dn): Hmmm, how should we do this... ?
|
||||||
bool log_to_file; // Output logs to file as well as standard out
|
DN_TicketMutex log_file_mutex; // Is locked when instantiating the log_file for the first time
|
||||||
DN_OSFile log_file; // TODO(dn): Hmmm, how should we do this... ?
|
bool log_no_colour; // Disable colours in the logging output
|
||||||
DN_TicketMutex log_file_mutex; // Is locked when instantiating the log_file for the first time
|
|
||||||
bool log_no_colour; // Disable colours in the logging output
|
|
||||||
|
|
||||||
// NOTE: OS
|
// NOTE: OS
|
||||||
DN_U32 logical_processor_count;
|
DN_U32 logical_processor_count;
|
||||||
DN_U32 page_size;
|
DN_U32 page_size;
|
||||||
DN_U32 alloc_granularity;
|
DN_U32 alloc_granularity;
|
||||||
|
|
||||||
// NOTE: Memory
|
// NOTE: Memory
|
||||||
// Total OS mem allocs in lifetime of program (e.g. malloc, VirtualAlloc, HeapAlloc ...). This
|
// Total OS mem allocs in lifetime of program (e.g. malloc, VirtualAlloc, HeapAlloc ...). This
|
||||||
// only includes allocations routed through the library such as the growing nature of arenas or
|
// only includes allocations routed through the library such as the growing nature of arenas or
|
||||||
// using the memory allocation routines in the library like DN_OS_MemCommit and so forth.
|
// using the memory allocation routines in the library like DN_OS_MemCommit and so forth.
|
||||||
DN_U64 vmem_allocs_total;
|
DN_U64 vmem_allocs_total;
|
||||||
DN_U64 vmem_allocs_frame; // Total OS virtual memory allocs since the last 'DN_Core_FrameBegin' was invoked
|
DN_U64 vmem_allocs_frame; // Total OS virtual memory allocs since the last 'DN_Core_FrameBegin' was invoked
|
||||||
DN_U64 mem_allocs_total;
|
DN_U64 mem_allocs_total;
|
||||||
DN_U64 mem_allocs_frame; // Total OS heap allocs since the last 'DN_Core_FrameBegin' was invoked
|
DN_U64 mem_allocs_frame; // Total OS heap allocs since the last 'DN_Core_FrameBegin' was invoked
|
||||||
|
|
||||||
DN_Arena arena;
|
DN_Arena arena;
|
||||||
void *platform_context;
|
void *platform_context;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DN_OSDiskSpace
|
struct DN_OSDiskSpace
|
||||||
@ -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);
|
||||||
|
|||||||
@ -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 = {};
|
||||||
|
DN_Memcpy(&thread_id, &thread->thread_id, sizeof(thread_id));
|
||||||
|
|
||||||
pthread_t thread_id = {};
|
void *return_val = nullptr;
|
||||||
DN_Memcpy(&thread_id, &thread->thread_id, sizeof(thread_id));
|
result = pthread_join(thread_id, &return_val) == 0;
|
||||||
|
thread->handle = {};
|
||||||
void *return_val = nullptr;
|
thread->thread_id = {};
|
||||||
pthread_join(thread_id, &return_val);
|
}
|
||||||
thread->handle = {};
|
return result;
|
||||||
thread->thread_id = {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_U32 DN_OS_ThreadID()
|
DN_API DN_U32 DN_OS_ThreadID()
|
||||||
|
|||||||
@ -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()
|
||||||
|
|||||||
212
Source/dn.cpp
212
Source/dn.cpp
@ -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"
|
||||||
|
|||||||
133
Source/dn.h
133
Source/dn.h
@ -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,52 +24,65 @@
|
|||||||
#define DN_CPP_WITH_DEMO 1
|
#define DN_CPP_WITH_DEMO 1
|
||||||
#include "dn.cpp"
|
#include "dn.cpp"
|
||||||
*/
|
*/
|
||||||
// Platform Target
|
// Then initialise the library at runtime by calling DN_Init(...). The library is laid out as:
|
||||||
// Define one of the following directives to configure this library to compile for that platform.
|
|
||||||
// By default, the library will auto-detect the current host platform and select that as the
|
|
||||||
// target platform.
|
|
||||||
//
|
//
|
||||||
// DN_PLATFORM_EMSCRIPTEN
|
// - The base layer (dn_base.h) which provides primitives that do not require a host operating
|
||||||
// DN_PLATFORM_POSIX
|
// system (e.g. freestanding) such as string manipulation, compiler intrinsics and containers.
|
||||||
// DN_PLATFORM_WIN32
|
// This layer is unconditionallly always available by compiling with this library.
|
||||||
//
|
//
|
||||||
// For example
|
// - 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.
|
||||||
//
|
//
|
||||||
// #define DN_PLATFORM_WIN32
|
// - Extra layer provides helper utilities that are opt-in. These layers are OPTIONAL.
|
||||||
//
|
//
|
||||||
// Will ensure that <Windows.h> is included and the OS layer is implemented using Win32
|
// Configuration
|
||||||
// primitives.
|
// Platform Target
|
||||||
|
// Define one of the following directives to configure this library to compile for that
|
||||||
|
// platform. By default, the library will auto-detect the current host platform and select that
|
||||||
|
// as the target platform.
|
||||||
//
|
//
|
||||||
// Static functions
|
// DN_PLATFORM_EMSCRIPTEN
|
||||||
// All public functions in the DN library are prefixed with the macro '#define DN_API'. By
|
// DN_PLATFORM_POSIX
|
||||||
// default 'DN_API' is not defined to anything. Define
|
// DN_PLATFORM_WIN32
|
||||||
//
|
//
|
||||||
// DN_STATIC_API
|
// For example
|
||||||
//
|
//
|
||||||
// To replace all the prefixed with 'static' ensuring that the functions in the library do not
|
// #define DN_PLATFORM_WIN32
|
||||||
// export an entry into the linking table and thereby optimise compilation times as the linker
|
|
||||||
// will not try to resolve symbols from other translation units from the the unit including the
|
|
||||||
// DN library.
|
|
||||||
//
|
//
|
||||||
// Using the in-built replacement header for <Windows.h> (requires dn_os_inc.h)
|
// Will ensure that <Windows.h> is included and the OS layer is implemented using Win32
|
||||||
// If you are building DN for the Windows platform, <Windows.h> is a large legacy header that
|
// primitives.
|
||||||
// applications have to link to use Windows syscalls. By default DN library uses a replacement
|
|
||||||
// header for all the Windows functions that it uses in the OS layer removing the need to include
|
|
||||||
// <Windows.h> to improve compilation times. This can be disabled by defining:
|
|
||||||
//
|
//
|
||||||
// DN_NO_WINDOWS_H_REPLACEMENT_HEADER
|
// Static functions
|
||||||
|
// All public functions in the DN library are prefixed with the macro '#define DN_API'. By
|
||||||
|
// default 'DN_API' is not defined to anything. Define
|
||||||
//
|
//
|
||||||
// To instead use <Windows.h>. DN automatically detects if <Windows.h> is included in an earlier
|
// DN_STATIC_API
|
||||||
// translation unit and will automatically disable the in-built replacement header in which case
|
|
||||||
// this does not need to be defined.
|
|
||||||
//
|
//
|
||||||
// Freestanding
|
// To replace all the functions prefixed with DN_API to be prefixed with 'static' ensuring that
|
||||||
// The base layer can be used without an OS implementation by defining DN_FREESTANDING like:
|
// the functions in the library do not export an entry into the linking table.
|
||||||
|
// translation units.
|
||||||
//
|
//
|
||||||
// #define DN_FREESTANDING
|
// 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
|
||||||
|
// 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 <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:
|
||||||
//
|
//
|
||||||
// This means functionality that relies on the OS like printing, memory allocation, stack traces
|
// DN_NO_WINDOWS_H_REPLACEMENT_HEADER
|
||||||
// and so forth are disabled.
|
//
|
||||||
|
// To instead use <Windows.h>. DN automatically detects if <Windows.h> is included in an earlier
|
||||||
|
// translation unit and will automatically disable the in-built replacement header in which case
|
||||||
|
// this does not need to be defined.
|
||||||
|
//
|
||||||
|
// Freestanding
|
||||||
|
// The base layer can be used without an OS implementation by defining DN_FREESTANDING like:
|
||||||
|
//
|
||||||
|
// #define DN_FREESTANDING
|
||||||
|
//
|
||||||
|
// This means functionality that relies on the OS like printing, memory allocation, stack traces
|
||||||
|
// and so forth are disabled.
|
||||||
|
|
||||||
#include "Base/dn_base.h"
|
#include "Base/dn_base.h"
|
||||||
#include "Base/dn_base_assert.h"
|
#include "Base/dn_base_assert.h"
|
||||||
@ -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"
|
||||||
|
|||||||
@ -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);
|
|
||||||
}
|
|
||||||
@ -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)
|
|
||||||
Loading…
x
Reference in New Issue
Block a user