Clean up some of the base layer and port Seasight changes over
This commit is contained in:
parent
172362cdb8
commit
31efa0cdcb
@ -1,26 +1,55 @@
|
||||
// Generated by the DN single header generator 2025-07-24 22:18:42
|
||||
// Generated by the DN single header generator 2025-07-25 22:33:12
|
||||
|
||||
#define DN_BASE_INC_CPP
|
||||
|
||||
// DN: Single header generator inlined this file => #include "Base/dn_base.cpp"
|
||||
#define DN_BASE_CPP
|
||||
|
||||
// DN: Single header generator commented out this header => #include "../dn_clangd.h"
|
||||
|
||||
// NOTE: [$INTR] Intrinsics ////////////////////////////////////////////////////////////////////////
|
||||
DN_CPUFeatureDecl g_dn_cpu_feature_decl[DN_CPUFeature_Count];
|
||||
// DN: Single header generator commented out this header => #include "../dn_base_inc.h"
|
||||
|
||||
#if !defined(DN_PLATFORM_ARM64) && !defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
#define DN_SUPPORTS_CPU_ID
|
||||
#endif
|
||||
|
||||
#if defined(DN_SUPPORTS_CPU_ID)
|
||||
#if defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG)
|
||||
#include <cpuid.h>
|
||||
#endif
|
||||
#endif // defined(DN_SUPPORTS_CPU_ID)
|
||||
#if defined(DN_SUPPORTS_CPU_ID) && (defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG))
|
||||
#include <cpuid.h>
|
||||
#endif
|
||||
|
||||
DN_API DN_CPUIDResult DN_CPU_ID(DN_CPUIDArgs args)
|
||||
static DN_CPUFeatureDecl g_dn_cpu_feature_decl[DN_CPUFeature_Count];
|
||||
|
||||
DN_API DN_U64 DN_AtomicSetValue64(DN_U64 volatile *target, DN_U64 value)
|
||||
{
|
||||
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
|
||||
__int64 result;
|
||||
do {
|
||||
result = *target;
|
||||
} while (DN_AtomicCompareExchange64(target, value, result) != result);
|
||||
return DN_CAST(DN_U64) result;
|
||||
#elif defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG)
|
||||
DN_U64 result = __sync_lock_test_and_set(target, value);
|
||||
return result;
|
||||
#else
|
||||
#error Unsupported compiler
|
||||
#endif
|
||||
}
|
||||
|
||||
DN_API DN_U32 DN_AtomicSetValue32(DN_U32 volatile *target, DN_U32 value)
|
||||
{
|
||||
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
|
||||
long result;
|
||||
do {
|
||||
result = *target;
|
||||
} while (DN_AtomicCompareExchange32(target, value, result) != result);
|
||||
return result;
|
||||
#elif defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG)
|
||||
long result = __sync_lock_test_and_set(target, value);
|
||||
return result;
|
||||
#else
|
||||
#error Unsupported compiler
|
||||
#endif
|
||||
}
|
||||
|
||||
DN_API DN_CPUIDResult DN_CPUID(DN_CPUIDArgs args)
|
||||
{
|
||||
DN_CPUIDResult result = {};
|
||||
#if defined(DN_SUPPORTS_CPU_ID)
|
||||
@ -29,7 +58,7 @@ DN_API DN_CPUIDResult DN_CPU_ID(DN_CPUIDArgs args)
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_USize DN_CPU_HasFeatureArray(DN_CPUReport const *report, DN_CPUFeatureQuery *features, DN_USize features_size)
|
||||
DN_API DN_USize DN_CPUHasFeatureArray(DN_CPUReport const *report, DN_CPUFeatureQuery *features, DN_USize features_size)
|
||||
{
|
||||
DN_USize result = 0;
|
||||
DN_USize const BITS = sizeof(report->features[0]) * 8;
|
||||
@ -45,23 +74,23 @@ DN_API DN_USize DN_CPU_HasFeatureArray(DN_CPUReport const *report, DN_CPUFeature
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_CPU_HasFeature(DN_CPUReport const *report, DN_CPUFeature feature)
|
||||
DN_API bool DN_CPUHasFeature(DN_CPUReport const *report, DN_CPUFeature feature)
|
||||
{
|
||||
DN_CPUFeatureQuery query = {};
|
||||
query.feature = feature;
|
||||
bool result = DN_CPU_HasFeatureArray(report, &query, 1) == 1;
|
||||
bool result = DN_CPUHasFeatureArray(report, &query, 1) == 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_CPU_HasAllFeatures(DN_CPUReport const *report, DN_CPUFeature const *features, DN_USize features_size)
|
||||
DN_API bool DN_CPUHasAllFeatures(DN_CPUReport const *report, DN_CPUFeature const *features, DN_USize features_size)
|
||||
{
|
||||
bool result = true;
|
||||
for (DN_USize index = 0; result && index < features_size; index++)
|
||||
result &= DN_CPU_HasFeature(report, features[index]);
|
||||
result &= DN_CPUHasFeature(report, features[index]);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API void DN_CPU_SetFeature(DN_CPUReport *report, DN_CPUFeature feature)
|
||||
DN_API void DN_CPUSetFeature(DN_CPUReport *report, DN_CPUFeature feature)
|
||||
{
|
||||
DN_Assert(feature < DN_CPUFeature_Count);
|
||||
DN_USize const BITS = sizeof(report->features[0]) * 8;
|
||||
@ -70,7 +99,7 @@ DN_API void DN_CPU_SetFeature(DN_CPUReport *report, DN_CPUFeature feature)
|
||||
report->features[chunk_index] |= (1ULL << chunk_bit);
|
||||
}
|
||||
|
||||
DN_API DN_CPUReport DN_CPU_Report()
|
||||
DN_API DN_CPUReport DN_CPUGetReport()
|
||||
{
|
||||
DN_CPUReport result = {};
|
||||
#if defined(DN_SUPPORTS_CPU_ID)
|
||||
@ -85,12 +114,12 @@ DN_API DN_CPUReport DN_CPU_Report()
|
||||
|
||||
// NOTE: Query standard function (e.g. eax = 0x0) for function count + cpu vendor
|
||||
args = {};
|
||||
fn_0000_[0] = DN_CPU_ID(args);
|
||||
fn_0000_[0] = DN_CPUID(args);
|
||||
|
||||
// NOTE: Query extended function (e.g. eax = 0x8000'0000) for function count + cpu vendor
|
||||
args = {};
|
||||
args.eax = DN_CAST(int) EXTENDED_FUNC_BASE_EAX;
|
||||
fn_8000_[0] = DN_CPU_ID(args);
|
||||
fn_8000_[0] = DN_CPUID(args);
|
||||
}
|
||||
|
||||
// NOTE: Extract function count ////////////////////////////////////////////////////////////////
|
||||
@ -109,13 +138,13 @@ DN_API DN_CPUReport DN_CPU_Report()
|
||||
for (int eax = 1; eax <= STANDARD_FUNC_MAX_EAX; eax++) {
|
||||
DN_CPUIDArgs args = {};
|
||||
args.eax = eax;
|
||||
fn_0000_[eax] = DN_CPU_ID(args);
|
||||
fn_0000_[eax] = DN_CPUID(args);
|
||||
}
|
||||
|
||||
for (int eax = EXTENDED_FUNC_BASE_EAX + 1, index = 1; eax <= EXTENDED_FUNC_MAX_EAX; eax++, index++) {
|
||||
DN_CPUIDArgs args = {};
|
||||
args.eax = eax;
|
||||
fn_8000_[index] = DN_CPU_ID(args);
|
||||
fn_8000_[index] = DN_CPUID(args);
|
||||
}
|
||||
}
|
||||
|
||||
@ -212,7 +241,7 @@ DN_API DN_CPUReport DN_CPU_Report()
|
||||
}
|
||||
|
||||
if (available)
|
||||
DN_CPU_SetFeature(&result, DN_CAST(DN_CPUFeature) ext_index);
|
||||
DN_CPUSetFeature(&result, DN_CAST(DN_CPUFeature) ext_index);
|
||||
}
|
||||
#endif // DN_SUPPORTS_CPU_ID
|
||||
return result;
|
||||
@ -221,18 +250,18 @@ DN_API DN_CPUReport DN_CPU_Report()
|
||||
// NOTE: DN_TicketMutex ////////////////////////////////////////////////////////////////////////////
|
||||
DN_API void DN_TicketMutex_Begin(DN_TicketMutex *mutex)
|
||||
{
|
||||
unsigned int ticket = DN_Atomic_AddU32(&mutex->ticket, 1);
|
||||
unsigned int ticket = DN_AtomicAddU32(&mutex->ticket, 1);
|
||||
DN_TicketMutex_BeginTicket(mutex, ticket);
|
||||
}
|
||||
|
||||
DN_API void DN_TicketMutex_End(DN_TicketMutex *mutex)
|
||||
{
|
||||
DN_Atomic_AddU32(&mutex->serving, 1);
|
||||
DN_AtomicAddU32(&mutex->serving, 1);
|
||||
}
|
||||
|
||||
DN_API DN_UInt DN_TicketMutex_MakeTicket(DN_TicketMutex *mutex)
|
||||
{
|
||||
DN_UInt result = DN_Atomic_AddU32(&mutex->ticket, 1);
|
||||
DN_UInt result = DN_AtomicAddU32(&mutex->ticket, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -262,60 +291,60 @@ DN_API bool DN_TicketMutex_CanLock(DN_TicketMutex const *mutex, DN_UInt ticket)
|
||||
#endif
|
||||
|
||||
// NOTE: DN_Bit ////////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API void DN_Bit_UnsetInplace(DN_USize *flags, DN_USize bitfield)
|
||||
DN_API void DN_BitUnsetInplace(DN_USize *flags, DN_USize bitfield)
|
||||
{
|
||||
*flags = (*flags & ~bitfield);
|
||||
}
|
||||
|
||||
DN_API void DN_Bit_SetInplace(DN_USize *flags, DN_USize bitfield)
|
||||
DN_API void DN_BitSetInplace(DN_USize *flags, DN_USize bitfield)
|
||||
{
|
||||
*flags = (*flags | bitfield);
|
||||
}
|
||||
|
||||
DN_API bool DN_Bit_IsSet(DN_USize bits, DN_USize bits_to_set)
|
||||
DN_API bool DN_BitIsSet(DN_USize bits, DN_USize bits_to_set)
|
||||
{
|
||||
auto result = DN_CAST(bool)((bits & bits_to_set) == bits_to_set);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_Bit_IsNotSet(DN_USize bits, DN_USize bits_to_check)
|
||||
DN_API bool DN_BitIsNotSet(DN_USize bits, DN_USize bits_to_check)
|
||||
{
|
||||
auto result = !DN_Bit_IsSet(bits, bits_to_check);
|
||||
auto result = !DN_BitIsSet(bits, bits_to_check);
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: DN_Safe ///////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_I64 DN_Safe_AddI64(int64_t a, int64_t b)
|
||||
DN_API DN_I64 DN_SafeAddI64(int64_t a, int64_t b)
|
||||
{
|
||||
DN_I64 result = DN_CheckF(a <= INT64_MAX - b, "a=%zd, b=%zd", a, b) ? (a + b) : INT64_MAX;
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_I64 DN_Safe_MulI64(int64_t a, int64_t b)
|
||||
DN_API DN_I64 DN_SafeMulI64(int64_t a, int64_t b)
|
||||
{
|
||||
DN_I64 result = DN_CheckF(a <= INT64_MAX / b, "a=%zd, b=%zd", a, b) ? (a * b) : INT64_MAX;
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_U64 DN_Safe_AddU64(DN_U64 a, DN_U64 b)
|
||||
DN_API DN_U64 DN_SafeAddU64(DN_U64 a, DN_U64 b)
|
||||
{
|
||||
DN_U64 result = DN_CheckF(a <= UINT64_MAX - b, "a=%zu, b=%zu", a, b) ? (a + b) : UINT64_MAX;
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_U64 DN_Safe_SubU64(DN_U64 a, DN_U64 b)
|
||||
DN_API DN_U64 DN_SafeSubU64(DN_U64 a, DN_U64 b)
|
||||
{
|
||||
DN_U64 result = DN_CheckF(a >= b, "a=%zu, b=%zu", a, b) ? (a - b) : 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_U64 DN_Safe_MulU64(DN_U64 a, DN_U64 b)
|
||||
DN_API DN_U64 DN_SafeMulU64(DN_U64 a, DN_U64 b)
|
||||
{
|
||||
DN_U64 result = DN_CheckF(a <= UINT64_MAX / b, "a=%zu, b=%zu", a, b) ? (a * b) : UINT64_MAX;
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_U32 DN_Safe_SubU32(DN_U32 a, DN_U32 b)
|
||||
DN_API DN_U32 DN_SafeSubU32(DN_U32 a, DN_U32 b)
|
||||
{
|
||||
DN_U32 result = DN_CheckF(a >= b, "a=%u, b=%u", a, b) ? (a - b) : 0;
|
||||
return result;
|
||||
@ -704,7 +733,7 @@ static_assert(DN_IsPowerOfTwoAligned(DN_ASAN_POISON_GUARD_SIZE, DN_ASAN_POISON_A
|
||||
"ASAN poison guard size must be a power-of-two and aligned to ASAN's alignment"
|
||||
"requirement (8 bytes)");
|
||||
|
||||
DN_API void DN_ASAN_PoisonMemoryRegion(void const volatile *ptr, DN_USize size)
|
||||
DN_API void DN_ASanPoisonMemoryRegion(void const volatile *ptr, DN_USize size)
|
||||
{
|
||||
if (!ptr || !size)
|
||||
return;
|
||||
@ -724,7 +753,7 @@ DN_API void DN_ASAN_PoisonMemoryRegion(void const volatile *ptr, DN_USize size)
|
||||
#endif
|
||||
}
|
||||
|
||||
DN_API void DN_ASAN_UnpoisonMemoryRegion(void const volatile *ptr, DN_USize size)
|
||||
DN_API void DN_ASanUnpoisonMemoryRegion(void const volatile *ptr, DN_USize size)
|
||||
{
|
||||
if (!ptr || !size)
|
||||
return;
|
||||
@ -2627,7 +2656,7 @@ static DN_ArenaBlock *DN_Arena_BlockInitFromMemFuncs_(DN_U64 reserve, DN_U64 com
|
||||
}
|
||||
|
||||
if (track_alloc && result)
|
||||
DN_Debug_TrackAlloc(result, result->reserve, alloc_can_leak);
|
||||
DN_DBGTrackAlloc(result, result->reserve, alloc_can_leak);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -2638,7 +2667,7 @@ static DN_ArenaBlock *DN_Arena_BlockInitFlagsFromMemFuncs_(DN_U64 reserve, DN_U6
|
||||
bool alloc_can_leak = flags & DN_ArenaFlags_AllocCanLeak;
|
||||
DN_ArenaBlock *result = DN_Arena_BlockInitFromMemFuncs_(reserve, commit, track_alloc, alloc_can_leak, mem_funcs);
|
||||
if (result && ((flags & DN_ArenaFlags_NoPoison) == 0))
|
||||
DN_ASAN_PoisonMemoryRegion(DN_CAST(char *) result + DN_ARENA_HEADER_SIZE, result->commit - DN_ARENA_HEADER_SIZE);
|
||||
DN_ASanPoisonMemoryRegion(DN_CAST(char *) result + DN_ARENA_HEADER_SIZE, result->commit - DN_ARENA_HEADER_SIZE);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -2670,7 +2699,7 @@ DN_API DN_Arena DN_Arena_InitFromBuffer(void *buffer, DN_USize size, DN_ArenaFla
|
||||
block->reserve = size;
|
||||
block->used = DN_ARENA_HEADER_SIZE;
|
||||
if (block && ((flags & DN_ArenaFlags_NoPoison) == 0))
|
||||
DN_ASAN_PoisonMemoryRegion(DN_CAST(char *) block + DN_ARENA_HEADER_SIZE, block->commit - DN_ARENA_HEADER_SIZE);
|
||||
DN_ASanPoisonMemoryRegion(DN_CAST(char *) block + DN_ARENA_HEADER_SIZE, block->commit - DN_ARENA_HEADER_SIZE);
|
||||
|
||||
DN_Arena result = {};
|
||||
result.flags = flags | DN_ArenaFlags_NoGrow | DN_ArenaFlags_NoAllocTrack | DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_UserBuffer;
|
||||
@ -2693,9 +2722,9 @@ DN_API DN_Arena DN_Arena_InitFromMemFuncs(DN_U64 reserve, DN_U64 commit, DN_Aren
|
||||
static void DN_Arena_BlockDeinit_(DN_Arena const *arena, DN_ArenaBlock *block)
|
||||
{
|
||||
DN_USize release_size = block->reserve;
|
||||
if (DN_Bit_IsNotSet(arena->flags, DN_ArenaFlags_NoAllocTrack))
|
||||
DN_Debug_TrackDealloc(block);
|
||||
DN_ASAN_UnpoisonMemoryRegion(block, block->commit);
|
||||
if (DN_BitIsNotSet(arena->flags, DN_ArenaFlags_NoAllocTrack))
|
||||
DN_DBGTrackDealloc(block);
|
||||
DN_ASanUnpoisonMemoryRegion(block, block->commit);
|
||||
if (arena->flags & DN_ArenaFlags_MemFuncs) {
|
||||
if (arena->mem_funcs.type == DN_ArenaMemFuncType_Basic)
|
||||
arena->mem_funcs.basic_dealloc(block);
|
||||
@ -2737,7 +2766,7 @@ DN_API bool DN_Arena_CommitTo(DN_Arena *arena, DN_U64 pos)
|
||||
|
||||
bool poison = DN_ASAN_POISON && ((arena->flags & DN_ArenaFlags_NoPoison) == 0);
|
||||
if (poison)
|
||||
DN_ASAN_PoisonMemoryRegion(commit_ptr, commit_size);
|
||||
DN_ASanPoisonMemoryRegion(commit_ptr, commit_size);
|
||||
|
||||
curr->commit = end_commit;
|
||||
return true;
|
||||
@ -2811,7 +2840,7 @@ DN_API void *DN_Arena_Alloc(DN_Arena *arena, DN_U64 size, uint8_t align, DN_Zero
|
||||
if (!arena->mem_funcs.vmem_commit(commit_ptr, commit_size, DN_MemPage_ReadWrite))
|
||||
return nullptr;
|
||||
if (poison)
|
||||
DN_ASAN_PoisonMemoryRegion(commit_ptr, commit_size);
|
||||
DN_ASanPoisonMemoryRegion(commit_ptr, commit_size);
|
||||
curr->commit = end_commit;
|
||||
arena->stats.info.commit += commit_size;
|
||||
arena->stats.hwm.commit = DN_Max(arena->stats.hwm.commit, arena->stats.info.commit);
|
||||
@ -2821,7 +2850,7 @@ DN_API void *DN_Arena_Alloc(DN_Arena *arena, DN_U64 size, uint8_t align, DN_Zero
|
||||
curr->used += alloc_size;
|
||||
arena->stats.info.used += alloc_size;
|
||||
arena->stats.hwm.used = DN_Max(arena->stats.hwm.used, arena->stats.info.used);
|
||||
DN_ASAN_UnpoisonMemoryRegion(result, size);
|
||||
DN_ASanUnpoisonMemoryRegion(result, size);
|
||||
|
||||
if (zero_mem == DN_ZeroMem_Yes) {
|
||||
DN_USize reused_bytes = DN_Min(prev_arena_commit - offset_pos, size);
|
||||
@ -2877,7 +2906,7 @@ DN_API void DN_Arena_PopTo(DN_Arena *arena, DN_U64 init_used)
|
||||
curr->used = used - curr->reserve_sum;
|
||||
char *poison_ptr = (char *)curr + DN_AlignUpPowerOfTwo(curr->used, DN_ASAN_POISON_ALIGNMENT);
|
||||
DN_USize poison_size = ((char *)curr + curr->commit) - poison_ptr;
|
||||
DN_ASAN_PoisonMemoryRegion(poison_ptr, poison_size);
|
||||
DN_ASanPoisonMemoryRegion(poison_ptr, poison_size);
|
||||
arena->stats.info.used += curr->used;
|
||||
}
|
||||
|
||||
@ -3676,9 +3705,9 @@ DN_API DN_Str8ToU64Result DN_Str8_ToU64(DN_Str8 string, char separator)
|
||||
if (!DN_Char_IsDigit(ch))
|
||||
return result;
|
||||
|
||||
result.value = DN_Safe_MulU64(result.value, 10);
|
||||
result.value = DN_SafeMulU64(result.value, 10);
|
||||
uint64_t digit = ch - '0';
|
||||
result.value = DN_Safe_AddU64(result.value, digit);
|
||||
result.value = DN_SafeAddU64(result.value, digit);
|
||||
}
|
||||
|
||||
result.success = true;
|
||||
@ -3721,9 +3750,9 @@ DN_API DN_Str8ToI64Result DN_Str8_ToI64(DN_Str8 string, char separator)
|
||||
if (!DN_Char_IsDigit(ch))
|
||||
return result;
|
||||
|
||||
result.value = DN_Safe_MulU64(result.value, 10);
|
||||
result.value = DN_SafeMulU64(result.value, 10);
|
||||
uint64_t digit = ch - '0';
|
||||
result.value = DN_Safe_AddU64(result.value, digit);
|
||||
result.value = DN_SafeAddU64(result.value, digit);
|
||||
}
|
||||
|
||||
if (negative)
|
||||
@ -4325,7 +4354,7 @@ DN_API int DN_UTF16_EncodeCodepoint(uint16_t utf16[2], uint32_t codepoint)
|
||||
// DN: Single header generator inlined this file => #include "Base/dn_base_log.cpp"
|
||||
#define DN_BASE_LOG_CPP
|
||||
|
||||
// DN: Single header generator commented out this header => #include "../dn_clangd.h"
|
||||
// DN: Single header generator commented out this header => #include "../dn_base_inc.h"
|
||||
|
||||
static DN_LOGEmitFromTypeFVFunc *g_dn_base_log_emit_from_type_fv_func_;
|
||||
static void *g_dn_base_log_emit_from_type_fv_user_context_;
|
||||
@ -5012,7 +5041,7 @@ DN_API void DN_OS_Init(DN_OSCore *os, DN_OSInitArgs *args)
|
||||
|
||||
DN_OS_TLSInit(&os->tls, tls_init_args);
|
||||
DN_OS_TLSSetCurrentThreadTLS(&os->tls);
|
||||
os->cpu_report = DN_CPU_Report();
|
||||
os->cpu_report = DN_CPUGetReport();
|
||||
|
||||
#define DN_CPU_FEAT_XENTRY(label) g_dn_cpu_feature_decl[DN_CPUFeature_##label] = {DN_CPUFeature_##label, DN_STR8(#label)};
|
||||
DN_CPU_FEAT_XMACRO
|
||||
@ -5230,13 +5259,13 @@ DN_API uint64_t DN_OS_EstimateTSCPerSecond(uint64_t duration_ms_to_gauge_tsc_fre
|
||||
{
|
||||
uint64_t os_frequency = DN_OS_PerfCounterFrequency();
|
||||
uint64_t os_target_elapsed = duration_ms_to_gauge_tsc_frequency * os_frequency / 1000ULL;
|
||||
uint64_t tsc_begin = DN_CPU_TSC();
|
||||
uint64_t tsc_begin = DN_CPUGetTSC();
|
||||
uint64_t result = 0;
|
||||
if (tsc_begin) {
|
||||
uint64_t os_elapsed = 0;
|
||||
for (uint64_t os_begin = DN_OS_PerfCounterNow(); os_elapsed < os_target_elapsed;)
|
||||
os_elapsed = DN_OS_PerfCounterNow() - os_begin;
|
||||
uint64_t tsc_end = DN_CPU_TSC();
|
||||
uint64_t tsc_end = DN_CPUGetTSC();
|
||||
uint64_t tsc_elapsed = tsc_end - tsc_begin;
|
||||
result = tsc_elapsed / os_elapsed * os_frequency;
|
||||
}
|
||||
@ -7909,8 +7938,8 @@ DN_API void *DN_OS_MemReserve(DN_USize size, DN_MemCommit commit, DN_U32 page_fl
|
||||
void *result = VirtualAlloc(nullptr, size, flags, os_page_flags);
|
||||
if (flags & MEM_COMMIT) {
|
||||
DN_Assert(g_dn_os_core_);
|
||||
DN_Atomic_AddU64(&g_dn_os_core_->vmem_allocs_total, 1);
|
||||
DN_Atomic_AddU64(&g_dn_os_core_->vmem_allocs_frame, 1);
|
||||
DN_AtomicAddU64(&g_dn_os_core_->vmem_allocs_total, 1);
|
||||
DN_AtomicAddU64(&g_dn_os_core_->vmem_allocs_frame, 1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -7923,8 +7952,8 @@ DN_API bool DN_OS_MemCommit(void *ptr, DN_USize size, DN_U32 page_flags)
|
||||
unsigned long os_page_flags = DN_OS_MemConvertPageToOSFlags_(page_flags);
|
||||
result = VirtualAlloc(ptr, size, MEM_COMMIT, os_page_flags) != nullptr;
|
||||
DN_Assert(g_dn_os_core_);
|
||||
DN_Atomic_AddU64(&g_dn_os_core_->vmem_allocs_total, 1);
|
||||
DN_Atomic_AddU64(&g_dn_os_core_->vmem_allocs_frame, 1);
|
||||
DN_AtomicAddU64(&g_dn_os_core_->vmem_allocs_total, 1);
|
||||
DN_AtomicAddU64(&g_dn_os_core_->vmem_allocs_frame, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -7971,8 +8000,8 @@ DN_API void *DN_OS_MemAlloc(DN_USize size, DN_ZeroMem zero_mem)
|
||||
DN_Assert(size <= DN_CAST(DWORD)(-1));
|
||||
void *result = HeapAlloc(GetProcessHeap(), flags, DN_CAST(DWORD) size);
|
||||
DN_Assert(g_dn_os_core_);
|
||||
DN_Atomic_AddU64(&g_dn_os_core_->mem_allocs_total, 1);
|
||||
DN_Atomic_AddU64(&g_dn_os_core_->mem_allocs_frame, 1);
|
||||
DN_AtomicAddU64(&g_dn_os_core_->mem_allocs_total, 1);
|
||||
DN_AtomicAddU64(&g_dn_os_core_->mem_allocs_frame, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -8746,7 +8775,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line, DN_OSExe
|
||||
}
|
||||
};
|
||||
|
||||
if (DN_Bit_IsSet(args->flags, DN_OSExecFlags_SaveStdout)) {
|
||||
if (DN_BitIsSet(args->flags, DN_OSExecFlags_SaveStdout)) {
|
||||
if (!CreatePipe(&stdout_read, &stdout_write, &save_std_security_attribs, /*nSize*/ 0)) {
|
||||
DN_W32Error win_error = DN_W32_LastError(tmem.arena);
|
||||
result.os_error_code = win_error.code;
|
||||
@ -8783,8 +8812,8 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line, DN_OSExe
|
||||
}
|
||||
};
|
||||
|
||||
if (DN_Bit_IsSet(args->flags, DN_OSExecFlags_SaveStderr)) {
|
||||
if (DN_Bit_IsSet(args->flags, DN_OSExecFlags_MergeStderrToStdout)) {
|
||||
if (DN_BitIsSet(args->flags, DN_OSExecFlags_SaveStderr)) {
|
||||
if (DN_BitIsSet(args->flags, DN_OSExecFlags_MergeStderrToStdout)) {
|
||||
stderr_read = stdout_read;
|
||||
stderr_write = stdout_write;
|
||||
} else {
|
||||
@ -8848,7 +8877,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line, DN_OSExe
|
||||
result.process = proc_info.hProcess;
|
||||
result.stdout_read = stdout_read;
|
||||
result.stdout_write = stdout_write;
|
||||
if (DN_Bit_IsSet(args->flags, DN_OSExecFlags_SaveStderr) && DN_Bit_IsNotSet(args->flags, DN_OSExecFlags_MergeStderrToStdout)) {
|
||||
if (DN_BitIsSet(args->flags, DN_OSExecFlags_SaveStderr) && DN_BitIsNotSet(args->flags, DN_OSExecFlags_MergeStderrToStdout)) {
|
||||
result.stderr_read = stderr_read;
|
||||
result.stderr_write = stderr_write;
|
||||
}
|
||||
@ -9246,7 +9275,7 @@ void DN_OS_HttpRequestWin32Callback(HINTERNET session, DWORD *dwContext, DWORD d
|
||||
|
||||
if (read_complete || dwInternetStatus == WINHTTP_CALLBACK_STATUS_REQUEST_ERROR || error.code) {
|
||||
DN_OS_SemaphoreIncrement(&response->on_complete_semaphore, 1);
|
||||
DN_Atomic_AddU32(&response->done, 1);
|
||||
DN_AtomicAddU32(&response->done, 1);
|
||||
}
|
||||
|
||||
if (error.code) {
|
||||
@ -9285,7 +9314,7 @@ DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response,
|
||||
// NOTE: 'Wait' handles failures gracefully, skipping the wait and
|
||||
// cleans up the request
|
||||
DN_OS_HttpRequestWait(response);
|
||||
DN_Atomic_AddU32(&response->done, 1);
|
||||
DN_AtomicAddU32(&response->done, 1);
|
||||
}
|
||||
};
|
||||
|
||||
@ -9777,7 +9806,7 @@ DN_API void DN_Core_Init(DN_Core *core, DN_CoreOnInit on_init)
|
||||
|
||||
for (DN_ForIndexU(feature_index, DN_CPUFeature_Count)) {
|
||||
DN_CPUFeatureDecl feature_decl = g_dn_cpu_feature_decl[feature_index];
|
||||
bool has_feature = DN_CPU_HasFeature(report, feature_decl.value);
|
||||
bool has_feature = DN_CPUHasFeature(report, feature_decl.value);
|
||||
DN_Str8Builder_AppendF(&builder,
|
||||
" %.*s:%*s%s\n",
|
||||
DN_STR_FMT(feature_decl.label),
|
||||
@ -9794,7 +9823,7 @@ DN_API void DN_Core_Init(DN_Core *core, DN_CoreOnInit on_init)
|
||||
|
||||
DN_API void DN_Core_BeginFrame()
|
||||
{
|
||||
DN_Atomic_SetValue64(&g_dn_os_core_->mem_allocs_frame, 0);
|
||||
DN_AtomicSetValue64(&g_dn_os_core_->mem_allocs_frame, 0);
|
||||
}
|
||||
|
||||
#if !defined(DN_NO_PROFILER)
|
||||
@ -9807,6 +9836,9 @@ DN_API void DN_Core_SetProfiler(DN_Profiler *profiler)
|
||||
// DN: Single header generator inlined this file => #include "Core/dn_core_debug.cpp"
|
||||
#define DN_CORE_DEBUG_CPP
|
||||
|
||||
// DN: Single header generator commented out this header => #include "../dn_base_inc.h"
|
||||
// DN: Single header generator commented out this header => #include "../dn_os_inc.h"
|
||||
|
||||
DN_API DN_StackTraceWalkResult DN_StackTrace_Walk(DN_Arena *arena, uint16_t limit)
|
||||
{
|
||||
DN_StackTraceWalkResult result = {};
|
||||
@ -10016,7 +10048,7 @@ DN_API void DN_StackTrace_ReloadSymbols()
|
||||
|
||||
// NOTE: DN_Debug //////////////////////////////////////////////////////////////////////////////////
|
||||
#if defined(DN_LEAK_TRACKING)
|
||||
DN_API void DN_Debug_TrackAlloc(void *ptr, DN_USize size, bool leak_permitted)
|
||||
DN_API void DN_DBGTrackAlloc(void *ptr, DN_USize size, bool leak_permitted)
|
||||
{
|
||||
if (!ptr)
|
||||
return;
|
||||
@ -10043,7 +10075,7 @@ DN_API void DN_Debug_TrackAlloc(void *ptr, DN_USize size, bool leak_permitted)
|
||||
"This pointer is already in the leak tracker, however it has not been freed yet. This "
|
||||
"same pointer is being ask to be tracked twice in the allocation table, e.g. one if its "
|
||||
"previous free calls has not being marked freed with an equivalent call to "
|
||||
"DN_Debug_TrackDealloc()\n"
|
||||
"DN_DBGTrackDealloc()\n"
|
||||
"\n"
|
||||
"The pointer (0x%p) originally allocated %.*s at:\n"
|
||||
"\n"
|
||||
@ -10075,7 +10107,7 @@ DN_API void DN_Debug_TrackAlloc(void *ptr, DN_USize size, bool leak_permitted)
|
||||
g_dn_core->alloc_table_bytes_allocated_for_stack_traces += alloc->stack_trace.size;
|
||||
}
|
||||
|
||||
DN_API void DN_Debug_TrackDealloc(void *ptr)
|
||||
DN_API void DN_DBGTrackDealloc(void *ptr)
|
||||
{
|
||||
if (!ptr)
|
||||
return;
|
||||
@ -10124,7 +10156,7 @@ DN_API void DN_Debug_TrackDealloc(void *ptr)
|
||||
g_dn_core->alloc_table_bytes_allocated_for_stack_traces += alloc->freed_stack_trace.size;
|
||||
}
|
||||
|
||||
DN_API void DN_Debug_DumpLeaks()
|
||||
DN_API void DN_DBGDumpLeaks()
|
||||
{
|
||||
uint64_t leak_count = 0;
|
||||
uint64_t leaked_bytes = 0;
|
||||
@ -10190,7 +10222,7 @@ DN_API DN_ProfilerZone DN_Profiler_BeginZoneAtIndex(DN_Str8 name, uint16_t ancho
|
||||
#endif
|
||||
anchor->name = name;
|
||||
DN_ProfilerZone result = {};
|
||||
result.begin_tsc = DN_CPU_TSC();
|
||||
result.begin_tsc = DN_CPUGetTSC();
|
||||
result.anchor_index = anchor_index;
|
||||
result.parent_zone = g_dn_core->profiler->parent_zone;
|
||||
result.elapsed_tsc_at_zone_start = anchor->tsc_inclusive;
|
||||
@ -10200,7 +10232,7 @@ DN_API DN_ProfilerZone DN_Profiler_BeginZoneAtIndex(DN_Str8 name, uint16_t ancho
|
||||
|
||||
DN_API void DN_Profiler_EndZone(DN_ProfilerZone zone)
|
||||
{
|
||||
uint64_t elapsed_tsc = DN_CPU_TSC() - zone.begin_tsc;
|
||||
uint64_t elapsed_tsc = DN_CPUGetTSC() - zone.begin_tsc;
|
||||
DN_ProfilerAnchor *anchor_buffer = DN_Profiler_WriteBuffer();
|
||||
DN_ProfilerAnchor *anchor = anchor_buffer + zone.anchor_index;
|
||||
|
||||
@ -10290,15 +10322,15 @@ void DN_Docs_Demo()
|
||||
DN_Core_Init(&core, DN_CoreOnInit_Nil);
|
||||
#endif
|
||||
|
||||
// NOTE: DN_Atomic_SetValue64 /////////////////////////////////////////////////////////////////
|
||||
// NOTE: DN_Atomic_SetValue32 /////////////////////////////////////////////////////////////////
|
||||
// NOTE: DN_AtomicSetValue64 /////////////////////////////////////////////////////////////////
|
||||
// NOTE: DN_AtomicSetValue32 /////////////////////////////////////////////////////////////////
|
||||
// Atomically set the value into the target using an atomic compare and swap
|
||||
// idiom. The return value of the function is the value that was last stored
|
||||
// in the target.
|
||||
{
|
||||
uint64_t target = 8;
|
||||
uint64_t value_to_set = 0xCAFE;
|
||||
if (DN_Atomic_SetValue64(&target, value_to_set) == 8) {
|
||||
if (DN_AtomicSetValue64(&target, value_to_set) == 8) {
|
||||
// Atomic swap was successful, e.g. the last value that this thread
|
||||
// observed was '8' which is the value we initialised with e.g. no
|
||||
// other thread has modified the value.
|
||||
@ -13135,9 +13167,9 @@ static DN_I32 DN_ASYNC_ThreadEntryPoint_(DN_OSThread *thread)
|
||||
args.input = task.work.input;
|
||||
args.thread = thread;
|
||||
|
||||
DN_Atomic_AddU32(&async->busy_threads, 1);
|
||||
DN_AtomicAddU32(&async->busy_threads, 1);
|
||||
task.work.func(args);
|
||||
DN_Atomic_SubU32(&async->busy_threads, 1);
|
||||
DN_AtomicSubU32(&async->busy_threads, 1);
|
||||
|
||||
if (task.completion_sem.handle != 0)
|
||||
DN_OS_SemaphoreIncrement(&task.completion_sem, 1);
|
||||
@ -13167,7 +13199,7 @@ DN_API void DN_ASYNC_Init(DN_ASYNCCore *async, char *base, DN_USize base_size, D
|
||||
DN_API void DN_ASYNC_Deinit(DN_ASYNCCore *async)
|
||||
{
|
||||
DN_Assert(async);
|
||||
DN_Atomic_SetValue32(&async->join_threads, true);
|
||||
DN_AtomicSetValue32(&async->join_threads, true);
|
||||
DN_OS_SemaphoreIncrement(&async->worker_sem, async->thread_count);
|
||||
for (DN_ForItSize(it, DN_OSThread, async->threads, async->thread_count))
|
||||
DN_OS_ThreadDeinit(it.data);
|
||||
@ -14302,9 +14334,9 @@ DN_API int32_t DN_OS_JobQueueSPMCThread(DN_OSThread *thread)
|
||||
queue->read_index += 1;
|
||||
DN_OS_MutexUnlock(&queue->mutex);
|
||||
|
||||
job.elapsed_tsc -= DN_CPU_TSC();
|
||||
job.elapsed_tsc -= DN_CPUGetTSC();
|
||||
job.func(thread, job.user_context);
|
||||
job.elapsed_tsc += DN_CPU_TSC();
|
||||
job.elapsed_tsc += DN_CPUGetTSC();
|
||||
|
||||
if (job.add_to_completion_queue) {
|
||||
DN_OS_SemaphoreWait(&queue->complete_queue_write_semaphore, DN_OS_SEMAPHORE_INFINITE_TIMEOUT);
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Generated by the DN single header generator 2025-07-24 22:18:42
|
||||
// Generated by the DN single header generator 2025-07-25 22:33:12
|
||||
|
||||
#if !defined(DN_BASE_INC_H)
|
||||
#define DN_BASE_INC_H
|
||||
@ -45,6 +45,14 @@
|
||||
// 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.
|
||||
|
||||
// DN: Single header generator inlined this file => #include "Base/dn_base_compiler.h"
|
||||
#if !defined(DN_BASE_COMPILER_H)
|
||||
@ -211,6 +219,8 @@
|
||||
#if !defined(DN_BASE_H)
|
||||
#define DN_BASE_H
|
||||
|
||||
// DN: Single header generator commented out this header => #include "../dn_base_inc.h"
|
||||
|
||||
// NOTE: Macros ////////////////////////////////////////////////////////////////////////////////////
|
||||
#define DN_Stringify(x) #x
|
||||
#define DN_TokenCombine2(x, y) x ## y
|
||||
@ -359,7 +369,7 @@ struct DN_DeferHelper
|
||||
};
|
||||
|
||||
#define DN_UniqueName(prefix) DN_TokenCombine(prefix, __LINE__)
|
||||
#define DN_DEFER const auto DN_UniqueName(defer_lambda_) = DN_DeferHelper() + [&]()
|
||||
#define DN_DEFER const auto DN_UniqueName(defer_lambda_) = DN_DeferHelper() + [&]()
|
||||
#endif // defined(__cplusplus)
|
||||
|
||||
#define DN_DeferLoop(begin, end) \
|
||||
@ -443,30 +453,25 @@ struct DN_CallSite
|
||||
DN_Str8 function;
|
||||
DN_U32 line;
|
||||
};
|
||||
|
||||
#define DN_CALL_SITE \
|
||||
DN_CallSite \
|
||||
{ \
|
||||
DN_STR8(__FILE__), DN_STR8(__func__), __LINE__ \
|
||||
}
|
||||
#define DN_CALL_SITE DN_CallSite { DN_STR8(__FILE__), DN_STR8(__func__), __LINE__ }
|
||||
|
||||
// NOTE: Intrinsics ////////////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: DN_Atomic_Add/Exchange return the previous value store in the target
|
||||
// NOTE: DN_AtomicAdd/Exchange return the previous value store in the target
|
||||
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
|
||||
#include <intrin.h>
|
||||
#define DN_Atomic_CompareExchange64(dest, desired_val, prev_val) _InterlockedCompareExchange64((__int64 volatile *)dest, desired_val, prev_val)
|
||||
#define DN_Atomic_CompareExchange32(dest, desired_val, prev_val) _InterlockedCompareExchange((long volatile *)dest, desired_val, prev_val)
|
||||
#define DN_AtomicCompareExchange64(dest, desired_val, prev_val) _InterlockedCompareExchange64((__int64 volatile *)dest, desired_val, prev_val)
|
||||
#define DN_AtomicCompareExchange32(dest, desired_val, prev_val) _InterlockedCompareExchange((long volatile *)dest, desired_val, prev_val)
|
||||
|
||||
#define DN_Atomic_LoadU64(target) *(target)
|
||||
#define DN_Atomic_LoadU32(target) *(target)
|
||||
#define DN_Atomic_AddU32(target, value) _InterlockedExchangeAdd((long volatile *)target, value)
|
||||
#define DN_Atomic_AddU64(target, value) _InterlockedExchangeAdd64((__int64 volatile *)target, value)
|
||||
#define DN_Atomic_SubU32(target, value) DN_Atomic_AddU32(DN_CAST(long volatile *) target, (long)-value)
|
||||
#define DN_Atomic_SubU64(target, value) DN_Atomic_AddU64(target, (DN_U64) - value)
|
||||
#define DN_AtomicLoadU64(target) *(target)
|
||||
#define DN_AtomicLoadU32(target) *(target)
|
||||
#define DN_AtomicAddU32(target, value) _InterlockedExchangeAdd((long volatile *)target, value)
|
||||
#define DN_AtomicAddU64(target, value) _InterlockedExchangeAdd64((__int64 volatile *)target, value)
|
||||
#define DN_AtomicSubU32(target, value) DN_AtomicAddU32(DN_CAST(long volatile *) target, (long)-value)
|
||||
#define DN_AtomicSubU64(target, value) DN_AtomicAddU64(target, (DN_U64) - value)
|
||||
|
||||
#define DN_CountLeadingZerosU64(value) __lzcnt64(value)
|
||||
#define DN_CountLeadingZerosU32(value) __lzcnt(value)
|
||||
#define DN_CPU_TSC() __rdtsc()
|
||||
#define DN_CPUGetTSC() __rdtsc()
|
||||
#define DN_CompilerReadBarrierAndCPUReadFence _ReadBarrier(); _mm_lfence()
|
||||
#define DN_CompilerWriteBarrierAndCPUWriteFence _WriteBarrier(); _mm_sfence()
|
||||
#elif defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG)
|
||||
@ -480,20 +485,20 @@ struct DN_CallSite
|
||||
#include <x86intrin.h>
|
||||
#endif
|
||||
|
||||
#define DN_Atomic_LoadU64(target) __atomic_load_n(x, __ATOMIC_SEQ_CST)
|
||||
#define DN_Atomic_LoadU32(target) __atomic_load_n(x, __ATOMIC_SEQ_CST)
|
||||
#define DN_Atomic_AddU32(target, value) __atomic_fetch_add(target, value, __ATOMIC_ACQ_REL)
|
||||
#define DN_Atomic_AddU64(target, value) __atomic_fetch_add(target, value, __ATOMIC_ACQ_REL)
|
||||
#define DN_Atomic_SubU32(target, value) __atomic_fetch_sub(target, value, __ATOMIC_ACQ_REL)
|
||||
#define DN_Atomic_SubU64(target, value) __atomic_fetch_sub(target, value, __ATOMIC_ACQ_REL)
|
||||
#define DN_AtomicLoadU64(target) __atomic_load_n(x, __ATOMIC_SEQ_CST)
|
||||
#define DN_AtomicLoadU32(target) __atomic_load_n(x, __ATOMIC_SEQ_CST)
|
||||
#define DN_AtomicAddU32(target, value) __atomic_fetch_add(target, value, __ATOMIC_ACQ_REL)
|
||||
#define DN_AtomicAddU64(target, value) __atomic_fetch_add(target, value, __ATOMIC_ACQ_REL)
|
||||
#define DN_AtomicSubU32(target, value) __atomic_fetch_sub(target, value, __ATOMIC_ACQ_REL)
|
||||
#define DN_AtomicSubU64(target, value) __atomic_fetch_sub(target, value, __ATOMIC_ACQ_REL)
|
||||
|
||||
#define DN_CountLeadingZerosU64(value) __builtin_clzll(value)
|
||||
#define DN_CountLeadingZerosU32(value) __builtin_clzl(value)
|
||||
|
||||
#if defined(DN_COMPILER_GCC)
|
||||
#define DN_CPU_TSC() __rdtsc()
|
||||
#define DN_CPUTSC() __rdtsc()
|
||||
#else
|
||||
#define DN_CPU_TSC() __builtin_readcyclecounter()
|
||||
#define DN_CPUTSC() __builtin_readcyclecounter()
|
||||
#endif
|
||||
|
||||
#if defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
@ -513,7 +518,6 @@ struct DN_CallSite
|
||||
#define DN_CountLeadingZerosUSize(value) DN_CountLeadingZerosU32(value)
|
||||
#endif
|
||||
|
||||
#if !defined(DN_PLATFORM_ARM64)
|
||||
struct DN_CPURegisters
|
||||
{
|
||||
int eax;
|
||||
@ -528,67 +532,63 @@ union DN_CPUIDResult
|
||||
int values[4];
|
||||
};
|
||||
|
||||
struct DN_CPUIDArgs
|
||||
{
|
||||
int eax;
|
||||
int ecx;
|
||||
};
|
||||
struct DN_CPUIDArgs { int eax; int ecx; };
|
||||
|
||||
#define DN_CPU_FEAT_XMACRO \
|
||||
DN_CPU_FEAT_XENTRY(3DNow) \
|
||||
DN_CPU_FEAT_XENTRY(3DNowExt) \
|
||||
DN_CPU_FEAT_XENTRY(ABM) \
|
||||
DN_CPU_FEAT_XENTRY(AES) \
|
||||
DN_CPU_FEAT_XENTRY(AVX) \
|
||||
DN_CPU_FEAT_XENTRY(AVX2) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512F) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512DQ) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512IFMA) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512PF) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512ER) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512CD) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512BW) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512VL) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512VBMI) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512VBMI2) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512VNNI) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512BITALG) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512VPOPCNTDQ) \
|
||||
DN_CPU_FEAT_XENTRY(AVX5124VNNIW) \
|
||||
DN_CPU_FEAT_XENTRY(AVX5124FMAPS) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512VP2INTERSECT) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512FP16) \
|
||||
DN_CPU_FEAT_XENTRY(CLZERO) \
|
||||
DN_CPU_FEAT_XENTRY(CMPXCHG8B) \
|
||||
DN_CPU_FEAT_XENTRY(CMPXCHG16B) \
|
||||
DN_CPU_FEAT_XENTRY(F16C) \
|
||||
DN_CPU_FEAT_XENTRY(FMA) \
|
||||
DN_CPU_FEAT_XENTRY(FMA4) \
|
||||
DN_CPU_FEAT_XENTRY(FP128) \
|
||||
DN_CPU_FEAT_XENTRY(FP256) \
|
||||
DN_CPU_FEAT_XENTRY(FPU) \
|
||||
DN_CPU_FEAT_XENTRY(MMX) \
|
||||
DN_CPU_FEAT_XENTRY(MONITOR) \
|
||||
DN_CPU_FEAT_XENTRY(MOVBE) \
|
||||
DN_CPU_FEAT_XENTRY(MOVU) \
|
||||
DN_CPU_FEAT_XENTRY(MmxExt) \
|
||||
DN_CPU_FEAT_XENTRY(PCLMULQDQ) \
|
||||
DN_CPU_FEAT_XENTRY(POPCNT) \
|
||||
DN_CPU_FEAT_XENTRY(RDRAND) \
|
||||
DN_CPU_FEAT_XENTRY(RDSEED) \
|
||||
DN_CPU_FEAT_XENTRY(RDTSCP) \
|
||||
DN_CPU_FEAT_XENTRY(SHA) \
|
||||
DN_CPU_FEAT_XENTRY(SSE) \
|
||||
DN_CPU_FEAT_XENTRY(SSE2) \
|
||||
DN_CPU_FEAT_XENTRY(SSE3) \
|
||||
DN_CPU_FEAT_XENTRY(SSE41) \
|
||||
DN_CPU_FEAT_XENTRY(SSE42) \
|
||||
DN_CPU_FEAT_XENTRY(SSE4A) \
|
||||
DN_CPU_FEAT_XENTRY(SSSE3) \
|
||||
DN_CPU_FEAT_XENTRY(TSC) \
|
||||
DN_CPU_FEAT_XENTRY(TscInvariant) \
|
||||
DN_CPU_FEAT_XENTRY(VAES) \
|
||||
DN_CPU_FEAT_XENTRY(VPCMULQDQ)
|
||||
#define DN_CPU_FEAT_XMACRO \
|
||||
DN_CPU_FEAT_XENTRY(3DNow) \
|
||||
DN_CPU_FEAT_XENTRY(3DNowExt) \
|
||||
DN_CPU_FEAT_XENTRY(ABM) \
|
||||
DN_CPU_FEAT_XENTRY(AES) \
|
||||
DN_CPU_FEAT_XENTRY(AVX) \
|
||||
DN_CPU_FEAT_XENTRY(AVX2) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512F) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512DQ) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512IFMA) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512PF) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512ER) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512CD) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512BW) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512VL) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512VBMI) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512VBMI2) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512VNNI) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512BITALG) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512VPOPCNTDQ) \
|
||||
DN_CPU_FEAT_XENTRY(AVX5124VNNIW) \
|
||||
DN_CPU_FEAT_XENTRY(AVX5124FMAPS) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512VP2INTERSECT) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512FP16) \
|
||||
DN_CPU_FEAT_XENTRY(CLZERO) \
|
||||
DN_CPU_FEAT_XENTRY(CMPXCHG8B) \
|
||||
DN_CPU_FEAT_XENTRY(CMPXCHG16B) \
|
||||
DN_CPU_FEAT_XENTRY(F16C) \
|
||||
DN_CPU_FEAT_XENTRY(FMA) \
|
||||
DN_CPU_FEAT_XENTRY(FMA4) \
|
||||
DN_CPU_FEAT_XENTRY(FP128) \
|
||||
DN_CPU_FEAT_XENTRY(FP256) \
|
||||
DN_CPU_FEAT_XENTRY(FPU) \
|
||||
DN_CPU_FEAT_XENTRY(MMX) \
|
||||
DN_CPU_FEAT_XENTRY(MONITOR) \
|
||||
DN_CPU_FEAT_XENTRY(MOVBE) \
|
||||
DN_CPU_FEAT_XENTRY(MOVU) \
|
||||
DN_CPU_FEAT_XENTRY(MmxExt) \
|
||||
DN_CPU_FEAT_XENTRY(PCLMULQDQ) \
|
||||
DN_CPU_FEAT_XENTRY(POPCNT) \
|
||||
DN_CPU_FEAT_XENTRY(RDRAND) \
|
||||
DN_CPU_FEAT_XENTRY(RDSEED) \
|
||||
DN_CPU_FEAT_XENTRY(RDTSCP) \
|
||||
DN_CPU_FEAT_XENTRY(SHA) \
|
||||
DN_CPU_FEAT_XENTRY(SSE) \
|
||||
DN_CPU_FEAT_XENTRY(SSE2) \
|
||||
DN_CPU_FEAT_XENTRY(SSE3) \
|
||||
DN_CPU_FEAT_XENTRY(SSE41) \
|
||||
DN_CPU_FEAT_XENTRY(SSE42) \
|
||||
DN_CPU_FEAT_XENTRY(SSE4A) \
|
||||
DN_CPU_FEAT_XENTRY(SSSE3) \
|
||||
DN_CPU_FEAT_XENTRY(TSC) \
|
||||
DN_CPU_FEAT_XENTRY(TscInvariant) \
|
||||
DN_CPU_FEAT_XENTRY(VAES) \
|
||||
DN_CPU_FEAT_XENTRY(VPCMULQDQ)
|
||||
|
||||
enum DN_CPUFeature
|
||||
{
|
||||
@ -617,225 +617,104 @@ struct DN_CPUReport
|
||||
DN_U64 features[(DN_CPUFeature_Count / (sizeof(DN_U64) * 8)) + 1];
|
||||
};
|
||||
|
||||
extern DN_CPUFeatureDecl g_dn_cpu_feature_decl[DN_CPUFeature_Count];
|
||||
#endif // DN_PLATFORM_ARM64
|
||||
|
||||
// NOTE: DN_TicketMutex ////////////////////////////////////////////////////////////////////////////
|
||||
struct DN_TicketMutex
|
||||
{
|
||||
unsigned int volatile ticket; // The next ticket to give out to the thread taking the mutex
|
||||
unsigned int volatile serving; // The ticket ID to block the mutex on until it is returned
|
||||
};
|
||||
|
||||
// NOTE: Intrinsics ////////////////////////////////////////////////////////////////////////////////
|
||||
DN_FORCE_INLINE DN_U64 DN_Atomic_SetValue64 (DN_U64 volatile *target, DN_U64 value);
|
||||
DN_FORCE_INLINE DN_U32 DN_Atomic_SetValue32 (DN_U32 volatile *target, DN_U32 value);
|
||||
DN_API DN_U64 DN_AtomicSetValue64 (DN_U64 volatile *target, DN_U64 value);
|
||||
DN_API DN_U32 DN_AtomicSetValue32 (DN_U32 volatile *target, DN_U32 value);
|
||||
|
||||
#if !defined (DN_PLATFORM_ARM64)
|
||||
DN_API DN_CPUIDResult DN_CPU_ID (DN_CPUIDArgs args);
|
||||
DN_API DN_USize DN_CPU_HasFeatureArray (DN_CPUReport const *report, DN_CPUFeatureQuery *features, DN_USize features_size);
|
||||
DN_API bool DN_CPU_HasFeature (DN_CPUReport const *report, DN_CPUFeature feature);
|
||||
DN_API bool DN_CPU_HasAllFeatures (DN_CPUReport const *report, DN_CPUFeature const *features, DN_USize features_size);
|
||||
template <DN_USize N>
|
||||
bool DN_CPU_HasAllFeaturesCArray(DN_CPUReport const *report, DN_CPUFeature const (&features)[N]);
|
||||
DN_API void DN_CPU_SetFeature (DN_CPUReport *report, DN_CPUFeature feature);
|
||||
DN_API DN_CPUReport DN_CPU_Report ();
|
||||
#endif
|
||||
DN_API DN_CPUIDResult DN_CPUID (DN_CPUIDArgs args);
|
||||
DN_API DN_USize DN_CPUHasFeatureArray (DN_CPUReport const *report, DN_CPUFeatureQuery *features, DN_USize features_size);
|
||||
DN_API bool DN_CPUHasFeature (DN_CPUReport const *report, DN_CPUFeature feature);
|
||||
DN_API bool DN_CPUHasAllFeatures (DN_CPUReport const *report, DN_CPUFeature const *features, DN_USize features_size);
|
||||
DN_API void DN_CPUSetFeature (DN_CPUReport *report, DN_CPUFeature feature);
|
||||
DN_API DN_CPUReport DN_CPUGetReport ();
|
||||
|
||||
// NOTE: DN_TicketMutex ////////////////////////////////////////////////////////////////////////////
|
||||
DN_API void DN_TicketMutex_Begin (DN_TicketMutex *mutex);
|
||||
DN_API void DN_TicketMutex_End (DN_TicketMutex *mutex);
|
||||
DN_API DN_UInt DN_TicketMutex_MakeTicket (DN_TicketMutex *mutex);
|
||||
DN_API void DN_TicketMutex_BeginTicket(DN_TicketMutex const *mutex, DN_UInt ticket);
|
||||
DN_API bool DN_TicketMutex_CanLock (DN_TicketMutex const *mutex, DN_UInt ticket);
|
||||
DN_API void DN_TicketMutex_Begin (DN_TicketMutex *mutex);
|
||||
DN_API void DN_TicketMutex_End (DN_TicketMutex *mutex);
|
||||
DN_API DN_UInt DN_TicketMutex_MakeTicket (DN_TicketMutex *mutex);
|
||||
DN_API void DN_TicketMutex_BeginTicket (DN_TicketMutex const *mutex, DN_UInt ticket);
|
||||
DN_API bool DN_TicketMutex_CanLock (DN_TicketMutex const *mutex, DN_UInt ticket);
|
||||
|
||||
// NOTE: DN_DLList /////////////////////////////////////////////////////////////////////////////////
|
||||
#define DN_DLList_Init(list) \
|
||||
(list)->next = (list)->prev = (list)
|
||||
DN_API void DN_BitUnsetInplace (DN_USize *flags, DN_USize bitfield);
|
||||
DN_API void DN_BitSetInplace (DN_USize *flags, DN_USize bitfield);
|
||||
DN_API bool DN_BitIsSet (DN_USize bits, DN_USize bits_to_set);
|
||||
DN_API bool DN_BitIsNotSet (DN_USize bits, DN_USize bits_to_check);
|
||||
#define DN_BitClearNextLSB(value) (value) & ((value) - 1)
|
||||
|
||||
#define DN_DLList_IsSentinel(list, item) ((list) == (item))
|
||||
DN_API DN_I64 DN_SafeAddI64 (DN_I64 a, DN_I64 b);
|
||||
DN_API DN_I64 DN_SafeMulI64 (DN_I64 a, DN_I64 b);
|
||||
|
||||
#define DN_DLList_InitArena(list, T, arena) \
|
||||
do { \
|
||||
(list) = DN_Arena_New(arena, T, DN_ZeroMem_Yes); \
|
||||
DN_DLList_Init(list); \
|
||||
} while (0)
|
||||
DN_API DN_U64 DN_SafeAddU64 (DN_U64 a, DN_U64 b);
|
||||
DN_API DN_U64 DN_SafeMulU64 (DN_U64 a, DN_U64 b);
|
||||
|
||||
#define DN_DLList_InitPool(list, T, pool) \
|
||||
do { \
|
||||
(list) = DN_Pool_New(pool, T); \
|
||||
DN_DLList_Init(list); \
|
||||
} while (0)
|
||||
DN_API DN_U64 DN_SafeSubU64 (DN_U64 a, DN_U64 b);
|
||||
DN_API DN_U32 DN_SafeSubU32 (DN_U32 a, DN_U32 b);
|
||||
|
||||
#define DN_DLList_Detach(item) \
|
||||
do { \
|
||||
if (item) { \
|
||||
(item)->prev->next = (item)->next; \
|
||||
(item)->next->prev = (item)->prev; \
|
||||
(item)->next = nullptr; \
|
||||
(item)->prev = nullptr; \
|
||||
} \
|
||||
} while (0)
|
||||
DN_API int DN_SaturateCastUSizeToInt (DN_USize val);
|
||||
DN_API DN_I8 DN_SaturateCastUSizeToI8 (DN_USize val);
|
||||
DN_API DN_I16 DN_SaturateCastUSizeToI16 (DN_USize val);
|
||||
DN_API DN_I32 DN_SaturateCastUSizeToI32 (DN_USize val);
|
||||
DN_API DN_I64 DN_SaturateCastUSizeToI64 (DN_USize val);
|
||||
|
||||
#define DN_DLList_Dequeue(list, dest_ptr) \
|
||||
if (DN_DLList_HasItems(list)) { \
|
||||
dest_ptr = (list)->next; \
|
||||
DN_DLList_Detach(dest_ptr); \
|
||||
}
|
||||
DN_API int DN_SaturateCastU64ToInt (DN_U64 val);
|
||||
DN_API DN_I8 DN_SaturateCastU8ToI8 (DN_U64 val);
|
||||
DN_API DN_I16 DN_SaturateCastU16ToI16 (DN_U64 val);
|
||||
DN_API DN_I32 DN_SaturateCastU32ToI32 (DN_U64 val);
|
||||
DN_API DN_I64 DN_SaturateCastU64ToI64 (DN_U64 val);
|
||||
DN_API DN_UInt DN_SaturateCastU64ToUInt (DN_U64 val);
|
||||
DN_API DN_U8 DN_SaturateCastU64ToU8 (DN_U64 val);
|
||||
DN_API DN_U16 DN_SaturateCastU64ToU16 (DN_U64 val);
|
||||
DN_API DN_U32 DN_SaturateCastU64ToU32 (DN_U64 val);
|
||||
|
||||
#define DN_DLList_Append(list, item) \
|
||||
do { \
|
||||
if (item) { \
|
||||
if ((item)->next) \
|
||||
DN_DLList_Detach(item); \
|
||||
(item)->next = (list)->next; \
|
||||
(item)->prev = (list); \
|
||||
(item)->next->prev = (item); \
|
||||
(item)->prev->next = (item); \
|
||||
} \
|
||||
} while (0)
|
||||
DN_API DN_U8 DN_SaturateCastUSizeToU8 (DN_USize val);
|
||||
DN_API DN_U16 DN_SaturateCastUSizeToU16 (DN_USize val);
|
||||
DN_API DN_U32 DN_SaturateCastUSizeToU32 (DN_USize val);
|
||||
DN_API DN_U64 DN_SaturateCastUSizeToU64 (DN_USize val);
|
||||
|
||||
#define DN_DLList_Prepend(list, item) \
|
||||
do { \
|
||||
if (item) { \
|
||||
if ((item)->next) \
|
||||
DN_DLList_Detach(item); \
|
||||
(item)->next = (list); \
|
||||
(item)->prev = (list)->prev; \
|
||||
(item)->next->prev = (item); \
|
||||
(item)->prev->next = (item); \
|
||||
} \
|
||||
} while (0)
|
||||
DN_API int DN_SaturateCastISizeToInt (DN_ISize val);
|
||||
DN_API DN_I8 DN_SaturateCastISizeToI8 (DN_ISize val);
|
||||
DN_API DN_I16 DN_SaturateCastISizeToI16 (DN_ISize val);
|
||||
DN_API DN_I32 DN_SaturateCastISizeToI32 (DN_ISize val);
|
||||
DN_API DN_I64 DN_SaturateCastISizeToI64 (DN_ISize val);
|
||||
|
||||
#define DN_DLList_IsEmpty(list) \
|
||||
(!(list) || ((list) == (list)->next))
|
||||
DN_API DN_UInt DN_SaturateCastISizeToUInt (DN_ISize val);
|
||||
DN_API DN_U8 DN_SaturateCastISizeToU8 (DN_ISize val);
|
||||
DN_API DN_U16 DN_SaturateCastISizeToU16 (DN_ISize val);
|
||||
DN_API DN_U32 DN_SaturateCastISizeToU32 (DN_ISize val);
|
||||
DN_API DN_U64 DN_SaturateCastISizeToU64 (DN_ISize val);
|
||||
|
||||
#define DN_DLList_IsInit(list) \
|
||||
((list)->next && (list)->prev)
|
||||
DN_API DN_ISize DN_SaturateCastI64ToISize (DN_I64 val);
|
||||
DN_API DN_I8 DN_SaturateCastI64ToI8 (DN_I64 val);
|
||||
DN_API DN_I16 DN_SaturateCastI64ToI16 (DN_I64 val);
|
||||
DN_API DN_I32 DN_SaturateCastI64ToI32 (DN_I64 val);
|
||||
|
||||
#define DN_DLList_HasItems(list) \
|
||||
((list) && ((list) != (list)->next))
|
||||
DN_API DN_UInt DN_SaturateCastI64ToUInt (DN_I64 val);
|
||||
DN_API DN_ISize DN_SaturateCastI64ToUSize (DN_I64 val);
|
||||
DN_API DN_U8 DN_SaturateCastI64ToU8 (DN_I64 val);
|
||||
DN_API DN_U16 DN_SaturateCastI64ToU16 (DN_I64 val);
|
||||
DN_API DN_U32 DN_SaturateCastI64ToU32 (DN_I64 val);
|
||||
DN_API DN_U64 DN_SaturateCastI64ToU64 (DN_I64 val);
|
||||
|
||||
#define DN_DLList_ForEach(it, list) \
|
||||
auto *it = (list)->next; (it) != (list); (it) = (it)->next
|
||||
DN_API DN_I8 DN_SaturateCastIntToI8 (int val);
|
||||
DN_API DN_I16 DN_SaturateCastIntToI16 (int val);
|
||||
DN_API DN_U8 DN_SaturateCastIntToU8 (int val);
|
||||
DN_API DN_U16 DN_SaturateCastIntToU16 (int val);
|
||||
DN_API DN_U32 DN_SaturateCastIntToU32 (int val);
|
||||
DN_API DN_U64 DN_SaturateCastIntToU64 (int val);
|
||||
|
||||
// NOTE: Intrinsics ////////////////////////////////////////////////////////////////////////////////
|
||||
DN_FORCE_INLINE DN_U64 DN_Atomic_SetValue64(DN_U64 volatile *target, DN_U64 value)
|
||||
{
|
||||
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
|
||||
__int64 result;
|
||||
do {
|
||||
result = *target;
|
||||
} while (DN_Atomic_CompareExchange64(target, value, result) != result);
|
||||
return DN_CAST(DN_U64) result;
|
||||
#elif defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG)
|
||||
DN_U64 result = __sync_lock_test_and_set(target, value);
|
||||
return result;
|
||||
#else
|
||||
#error Unsupported compiler
|
||||
#endif
|
||||
}
|
||||
|
||||
DN_FORCE_INLINE DN_U32 DN_Atomic_SetValue32(DN_U32 volatile *target, DN_U32 value)
|
||||
{
|
||||
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
|
||||
long result;
|
||||
do {
|
||||
result = *target;
|
||||
} while (DN_Atomic_CompareExchange32(target, value, result) != result);
|
||||
return result;
|
||||
#elif defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG)
|
||||
long result = __sync_lock_test_and_set(target, value);
|
||||
return result;
|
||||
#else
|
||||
#error Unsupported compiler
|
||||
#endif
|
||||
}
|
||||
|
||||
template <DN_USize N>
|
||||
bool DN_CPU_HasAllFeaturesCArray(DN_CPUReport const *report, DN_CPUFeature const (&features)[N])
|
||||
{
|
||||
bool result = DN_CPU_HasAllFeatures(report, features, N);
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: DN_Bit ////////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API void DN_Bit_UnsetInplace (DN_USize *flags, DN_USize bitfield);
|
||||
DN_API void DN_Bit_SetInplace (DN_USize *flags, DN_USize bitfield);
|
||||
DN_API bool DN_Bit_IsSet (DN_USize bits, DN_USize bits_to_set);
|
||||
DN_API bool DN_Bit_IsNotSet (DN_USize bits, DN_USize bits_to_check);
|
||||
#define DN_Bit_ClearNextLSB(value) (value) & ((value) - 1)
|
||||
|
||||
// NOTE: DN_Safe ///////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_I64 DN_Safe_AddI64 (DN_I64 a, DN_I64 b);
|
||||
DN_API DN_I64 DN_Safe_MulI64 (DN_I64 a, DN_I64 b);
|
||||
|
||||
DN_API DN_U64 DN_Safe_AddU64 (DN_U64 a, DN_U64 b);
|
||||
DN_API DN_U64 DN_Safe_MulU64 (DN_U64 a, DN_U64 b);
|
||||
|
||||
DN_API DN_U64 DN_Safe_SubU64 (DN_U64 a, DN_U64 b);
|
||||
DN_API DN_U32 DN_Safe_SubU32 (DN_U32 a, DN_U32 b);
|
||||
|
||||
DN_API int DN_SaturateCastUSizeToInt (DN_USize val);
|
||||
DN_API DN_I8 DN_SaturateCastUSizeToI8 (DN_USize val);
|
||||
DN_API DN_I16 DN_SaturateCastUSizeToI16 (DN_USize val);
|
||||
DN_API DN_I32 DN_SaturateCastUSizeToI32 (DN_USize val);
|
||||
DN_API DN_I64 DN_SaturateCastUSizeToI64 (DN_USize val);
|
||||
|
||||
DN_API int DN_SaturateCastU64ToInt (DN_U64 val);
|
||||
DN_API DN_I8 DN_SaturateCastU8ToI8 (DN_U64 val);
|
||||
DN_API DN_I16 DN_SaturateCastU16ToI16 (DN_U64 val);
|
||||
DN_API DN_I32 DN_SaturateCastU32ToI32 (DN_U64 val);
|
||||
DN_API DN_I64 DN_SaturateCastU64ToI64 (DN_U64 val);
|
||||
DN_API DN_UInt DN_SaturateCastU64ToUInt (DN_U64 val);
|
||||
DN_API DN_U8 DN_SaturateCastU64ToU8 (DN_U64 val);
|
||||
DN_API DN_U16 DN_SaturateCastU64ToU16 (DN_U64 val);
|
||||
DN_API DN_U32 DN_SaturateCastU64ToU32 (DN_U64 val);
|
||||
|
||||
DN_API DN_U8 DN_SaturateCastUSizeToU8 (DN_USize val);
|
||||
DN_API DN_U16 DN_SaturateCastUSizeToU16 (DN_USize val);
|
||||
DN_API DN_U32 DN_SaturateCastUSizeToU32 (DN_USize val);
|
||||
DN_API DN_U64 DN_SaturateCastUSizeToU64 (DN_USize val);
|
||||
|
||||
DN_API int DN_SaturateCastISizeToInt (DN_ISize val);
|
||||
DN_API DN_I8 DN_SaturateCastISizeToI8 (DN_ISize val);
|
||||
DN_API DN_I16 DN_SaturateCastISizeToI16 (DN_ISize val);
|
||||
DN_API DN_I32 DN_SaturateCastISizeToI32 (DN_ISize val);
|
||||
DN_API DN_I64 DN_SaturateCastISizeToI64 (DN_ISize val);
|
||||
|
||||
DN_API DN_UInt DN_SaturateCastISizeToUInt (DN_ISize val);
|
||||
DN_API DN_U8 DN_SaturateCastISizeToU8 (DN_ISize val);
|
||||
DN_API DN_U16 DN_SaturateCastISizeToU16 (DN_ISize val);
|
||||
DN_API DN_U32 DN_SaturateCastISizeToU32 (DN_ISize val);
|
||||
DN_API DN_U64 DN_SaturateCastISizeToU64 (DN_ISize val);
|
||||
|
||||
DN_API DN_ISize DN_SaturateCastI64ToISize (DN_I64 val);
|
||||
DN_API DN_I8 DN_SaturateCastI64ToI8 (DN_I64 val);
|
||||
DN_API DN_I16 DN_SaturateCastI64ToI16 (DN_I64 val);
|
||||
DN_API DN_I32 DN_SaturateCastI64ToI32 (DN_I64 val);
|
||||
|
||||
DN_API DN_UInt DN_SaturateCastI64ToUInt (DN_I64 val);
|
||||
DN_API DN_ISize DN_SaturateCastI64ToUSize (DN_I64 val);
|
||||
DN_API DN_U8 DN_SaturateCastI64ToU8 (DN_I64 val);
|
||||
DN_API DN_U16 DN_SaturateCastI64ToU16 (DN_I64 val);
|
||||
DN_API DN_U32 DN_SaturateCastI64ToU32 (DN_I64 val);
|
||||
DN_API DN_U64 DN_SaturateCastI64ToU64 (DN_I64 val);
|
||||
|
||||
DN_API DN_I8 DN_SaturateCastIntToI8 (int val);
|
||||
DN_API DN_I16 DN_SaturateCastIntToI16 (int val);
|
||||
DN_API DN_U8 DN_SaturateCastIntToU8 (int val);
|
||||
DN_API DN_U16 DN_SaturateCastIntToU16 (int val);
|
||||
DN_API DN_U32 DN_SaturateCastIntToU32 (int val);
|
||||
DN_API DN_U64 DN_SaturateCastIntToU64 (int val);
|
||||
|
||||
// NOTE: DN_Asan ///////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API void DN_ASAN_PoisonMemoryRegion (void const volatile *ptr, DN_USize size);
|
||||
DN_API void DN_ASAN_UnpoisonMemoryRegion (void const volatile *ptr, DN_USize size);
|
||||
DN_API void DN_ASanPoisonMemoryRegion (void const volatile *ptr, DN_USize size);
|
||||
DN_API void DN_ASanUnpoisonMemoryRegion(void const volatile *ptr, DN_USize size);
|
||||
#endif // !defined(DN_BASE_H)
|
||||
// DN: Single header generator inlined this file => #include "Base/dn_base_os.h"
|
||||
#if !defined(DN_BASE_OS_H)
|
||||
#define DN_BASE_OS_H
|
||||
|
||||
// DN: Single header generator commented out this header => #include "../dn_base_inc.h"
|
||||
|
||||
// NOTE: OS primitives that the OS layer can provide for the base layer but is optional.
|
||||
|
||||
struct DN_StackTraceFrame
|
||||
@ -865,7 +744,19 @@ struct DN_StackTraceWalkResultIterator
|
||||
DN_U16 index;
|
||||
};
|
||||
|
||||
DN_API DN_Str8 DN_StackTrace_WalkStr8FromHeap (DN_U16 limit, DN_U16 skip);
|
||||
|
||||
#if defined(DN_FREESTANDING)
|
||||
#define DN_StackTrace_WalkStr8FromHeap(...) DN_STR8("N/A")
|
||||
#define DN_StackTrace_Walk(...)
|
||||
#define DN_StackTrace_WalkResultIterate(...)
|
||||
#define DN_StackTrace_WalkResultToStr8(...) DN_STR8("N/A")
|
||||
#define DN_StackTrace_WalkStr8(...) DN_STR8("N/A")
|
||||
#define DN_StackTrace_WalkStr8FromHeap(...) DN_STR8("N/A")
|
||||
#define DN_StackTrace_GetFrames(...)
|
||||
#define DN_StackTrace_RawFrameToFrame(...)
|
||||
#define DN_StackTrace_Print(...)
|
||||
#define DN_StackTrace_ReloadSymbols(...)
|
||||
#else
|
||||
DN_API DN_StackTraceWalkResult DN_StackTrace_Walk (struct DN_Arena *arena, DN_U16 limit);
|
||||
DN_API bool DN_StackTrace_WalkResultIterate(DN_StackTraceWalkResultIterator *it, DN_StackTraceWalkResult const *walk);
|
||||
DN_API DN_Str8 DN_StackTrace_WalkResultToStr8 (struct DN_Arena *arena, DN_StackTraceWalkResult const *walk, DN_U16 skip);
|
||||
@ -875,64 +766,40 @@ DN_API DN_Slice<DN_StackTraceFrame> DN_StackTrace_GetFrames (struct DN_Ar
|
||||
DN_API DN_StackTraceFrame DN_StackTrace_RawFrameToFrame (struct DN_Arena *arena, DN_StackTraceRawFrame raw_frame);
|
||||
DN_API void DN_StackTrace_Print (DN_U16 limit);
|
||||
DN_API void DN_StackTrace_ReloadSymbols ();
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif // !defined(DN_BASE_OS_H)
|
||||
// DN: Single header generator inlined this file => #include "Base/dn_base_assert.h"
|
||||
#if !defined(DN_BASE_ASSERT_H)
|
||||
#define DN_BASE_ASSERT_H
|
||||
|
||||
#define DN_HardAssertF(expr, fmt, ...) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
DN_Str8 stack_trace_ = DN_StackTrace_WalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \
|
||||
DN_LOG_ErrorF("Hard assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \
|
||||
DN_STR_FMT(stack_trace_), \
|
||||
##__VA_ARGS__); \
|
||||
DN_DebugBreak; \
|
||||
} \
|
||||
} while (0)
|
||||
#define DN_HardAssert(expr) DN_HardAssertF(expr, "")
|
||||
|
||||
#if defined(DN_FREESTANDING)
|
||||
#define DN_HardAssertF(expr, fmt, ...) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
DN_DebugBreak; \
|
||||
(*(int *)0) = 0; \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define DN_HardAssertF(expr, fmt, ...) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
DN_Str8 stack_trace_ = DN_StackTrace_WalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \
|
||||
DN_LOG_ErrorF("Hard assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \
|
||||
DN_STR_FMT(stack_trace_), \
|
||||
##__VA_ARGS__); \
|
||||
DN_DebugBreak; \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#if defined(DN_NO_ASSERT)
|
||||
#define DN_Assert(...)
|
||||
#define DN_AssertOnce(...)
|
||||
#define DN_AssertF(...)
|
||||
#define DN_AssertFOnce(...)
|
||||
#else
|
||||
#if defined(DN_FREESTANDING)
|
||||
#define DN_AssertF(expr, fmt, ...) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
DN_DebugBreak; \
|
||||
(*(int *)0) = 0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
#define DN_AssertF(expr, fmt, ...) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
DN_Str8 stack_trace_ = DN_StackTrace_WalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \
|
||||
DN_LOG_ErrorF("Assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \
|
||||
DN_STR_FMT(stack_trace_), \
|
||||
##__VA_ARGS__); \
|
||||
DN_DebugBreak; \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
#define DN_AssertF(expr, fmt, ...) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
DN_Str8 stack_trace_ = DN_StackTrace_WalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \
|
||||
DN_LOG_ErrorF("Assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \
|
||||
DN_STR_FMT(stack_trace_), \
|
||||
##__VA_ARGS__); \
|
||||
DN_DebugBreak; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DN_AssertFOnce(expr, fmt, ...) \
|
||||
do { \
|
||||
@ -954,19 +821,13 @@ DN_API void DN_StackTrace_ReloadSymbols ();
|
||||
#define DN_InvalidCodePathF(fmt, ...) DN_HardAssertF(0, fmt, ##__VA_ARGS__)
|
||||
#define DN_InvalidCodePath DN_InvalidCodePathF("Invalid code path triggered")
|
||||
|
||||
// NOTE: Check macro ///////////////////////////////////////////////////////////////////////////////
|
||||
#define DN_Check(expr) DN_CheckF(expr, "")
|
||||
|
||||
#if defined(DN_FREESTANDING)
|
||||
#define DN_CheckF(expr, fmt, ...) (expr)
|
||||
#if defined(DN_NO_CHECK_BREAK)
|
||||
#define DN_CheckF(expr, fmt, ...) \
|
||||
((expr) ? true : (DN_LOG_WarningF(fmt, ##__VA_ARGS__), false))
|
||||
#else
|
||||
#if defined(DN_NO_CHECK_BREAK)
|
||||
#define DN_CheckF(expr, fmt, ...) \
|
||||
((expr) ? true : (DN_LOG_WarningF(fmt, ##__VA_ARGS__), false))
|
||||
#else
|
||||
#define DN_CheckF(expr, fmt, ...) \
|
||||
((expr) ? true : (DN_LOG_ErrorF(fmt, ##__VA_ARGS__), DN_StackTrace_Print(128 /*limit*/), DN_DebugBreak, false))
|
||||
#endif
|
||||
#define DN_CheckF(expr, fmt, ...) \
|
||||
((expr) ? true : (DN_LOG_ErrorF(fmt, ##__VA_ARGS__), DN_StackTrace_Print(128 /*limit*/), DN_DebugBreak, false))
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -974,7 +835,7 @@ DN_API void DN_StackTrace_ReloadSymbols ();
|
||||
#if !defined(DN_BASE_MEM_H)
|
||||
#define DN_BASE_MEM_H
|
||||
|
||||
// DN: Single header generator commented out this header => #include "../dn_clangd.h"
|
||||
// DN: Single header generator commented out this header => #include "../dn_base_inc.h"
|
||||
|
||||
enum DN_MemCommit
|
||||
{
|
||||
@ -1119,32 +980,6 @@ struct DN_ArenaTempMemScope
|
||||
|
||||
DN_USize const DN_ARENA_HEADER_SIZE = DN_AlignUpPowerOfTwo(sizeof(DN_Arena), 64);
|
||||
|
||||
// NOTE: DN_Arena //////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_Arena DN_Arena_InitFromBuffer (void *buffer, DN_USize size, DN_ArenaFlags flags);
|
||||
DN_API DN_Arena DN_Arena_InitFromMemFuncs (DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags, DN_ArenaMemFuncs mem_funcs);
|
||||
DN_API void DN_Arena_Deinit (DN_Arena *arena);
|
||||
DN_API bool DN_Arena_Commit (DN_Arena *arena, DN_U64 size);
|
||||
DN_API bool DN_Arena_CommitTo (DN_Arena *arena, DN_U64 pos);
|
||||
DN_API bool DN_Arena_Grow (DN_Arena *arena, DN_U64 reserve, DN_U64 commit);
|
||||
DN_API void * DN_Arena_Alloc (DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZeroMem zero_mem);
|
||||
DN_API void * DN_Arena_AllocContiguous (DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZeroMem zero_mem);
|
||||
DN_API void * DN_Arena_Copy (DN_Arena *arena, void const *data, DN_U64 size, uint8_t align);
|
||||
DN_API void DN_Arena_PopTo (DN_Arena *arena, DN_U64 init_used);
|
||||
DN_API void DN_Arena_Pop (DN_Arena *arena, DN_U64 amount);
|
||||
DN_API DN_U64 DN_Arena_Pos (DN_Arena const *arena);
|
||||
DN_API void DN_Arena_Clear (DN_Arena *arena);
|
||||
DN_API bool DN_Arena_OwnsPtr (DN_Arena const *arena, void *ptr);
|
||||
DN_API DN_ArenaStats DN_Arena_SumStatsArray (DN_ArenaStats const *array, DN_USize size);
|
||||
DN_API DN_ArenaStats DN_Arena_SumStats (DN_ArenaStats lhs, DN_ArenaStats rhs);
|
||||
DN_API DN_ArenaStats DN_Arena_SumArenaArrayToStats (DN_Arena const *array, DN_USize size);
|
||||
DN_API DN_ArenaTempMem DN_Arena_TempMemBegin (DN_Arena *arena);
|
||||
DN_API void DN_Arena_TempMemEnd (DN_ArenaTempMem mem);
|
||||
#define DN_Arena_New_Frame(T, zero_mem) (T *)DN_Arena_Alloc(DN_OS_TLSGet()->frame_arena, sizeof(T), alignof(T), zero_mem)
|
||||
#define DN_Arena_New(arena, T, zero_mem) (T *)DN_Arena_Alloc(arena, sizeof(T), alignof(T), zero_mem)
|
||||
#define DN_Arena_NewArray(arena, T, count, zero_mem) (T *)DN_Arena_Alloc(arena, sizeof(T) * (count), alignof(T), zero_mem)
|
||||
#define DN_Arena_NewCopy(arena, T, src) (T *)DN_Arena_Copy (arena, (src), sizeof(T), alignof(T))
|
||||
#define DN_Arena_NewArrayCopy(arena, T, src, count) (T *)DN_Arena_Copy (arena, (src), sizeof(T) * (count), alignof(T))
|
||||
|
||||
#if !defined(DN_POOL_DEFAULT_ALIGN)
|
||||
#define DN_POOL_DEFAULT_ALIGN 16
|
||||
#endif
|
||||
@ -1198,36 +1033,51 @@ struct DN_Pool
|
||||
DN_U8 align;
|
||||
};
|
||||
|
||||
// NOTE: DN_Pool ///////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_Pool DN_Pool_Init (DN_Arena *arena, DN_U8 align);
|
||||
DN_API bool DN_Pool_IsValid (DN_Pool const *pool);
|
||||
DN_API void * DN_Pool_Alloc (DN_Pool *pool, DN_USize size);
|
||||
DN_API DN_Str8 DN_Pool_AllocStr8FV (DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API DN_Str8 DN_Pool_AllocStr8F (DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API DN_Str8 DN_Pool_AllocStr8Copy (DN_Pool *pool, DN_Str8 string);
|
||||
DN_API void DN_Pool_Dealloc (DN_Pool *pool, void *ptr);
|
||||
DN_API void * DN_Pool_Copy (DN_Pool *pool, void const *data, DN_U64 size, uint8_t align);
|
||||
DN_API DN_Arena DN_Arena_InitFromBuffer (void *buffer, DN_USize size, DN_ArenaFlags flags);
|
||||
DN_API DN_Arena DN_Arena_InitFromMemFuncs (DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags, DN_ArenaMemFuncs mem_funcs);
|
||||
DN_API void DN_Arena_Deinit (DN_Arena *arena);
|
||||
DN_API bool DN_Arena_Commit (DN_Arena *arena, DN_U64 size);
|
||||
DN_API bool DN_Arena_CommitTo (DN_Arena *arena, DN_U64 pos);
|
||||
DN_API bool DN_Arena_Grow (DN_Arena *arena, DN_U64 reserve, DN_U64 commit);
|
||||
DN_API void * DN_Arena_Alloc (DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZeroMem zero_mem);
|
||||
DN_API void * DN_Arena_AllocContiguous (DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZeroMem zero_mem);
|
||||
DN_API void * DN_Arena_Copy (DN_Arena *arena, void const *data, DN_U64 size, uint8_t align);
|
||||
DN_API void DN_Arena_PopTo (DN_Arena *arena, DN_U64 init_used);
|
||||
DN_API void DN_Arena_Pop (DN_Arena *arena, DN_U64 amount);
|
||||
DN_API DN_U64 DN_Arena_Pos (DN_Arena const *arena);
|
||||
DN_API void DN_Arena_Clear (DN_Arena *arena);
|
||||
DN_API bool DN_Arena_OwnsPtr (DN_Arena const *arena, void *ptr);
|
||||
DN_API DN_ArenaStats DN_Arena_SumStatsArray (DN_ArenaStats const *array, DN_USize size);
|
||||
DN_API DN_ArenaStats DN_Arena_SumStats (DN_ArenaStats lhs, DN_ArenaStats rhs);
|
||||
DN_API DN_ArenaStats DN_Arena_SumArenaArrayToStats (DN_Arena const *array, DN_USize size);
|
||||
DN_API DN_ArenaTempMem DN_Arena_TempMemBegin (DN_Arena *arena);
|
||||
DN_API void DN_Arena_TempMemEnd (DN_ArenaTempMem mem);
|
||||
#define DN_Arena_New_Frame(T, zero_mem) (T *)DN_Arena_Alloc(DN_OS_TLSGet()->frame_arena, sizeof(T), alignof(T), zero_mem)
|
||||
#define DN_Arena_New(arena, T, zero_mem) (T *)DN_Arena_Alloc(arena, sizeof(T), alignof(T), zero_mem)
|
||||
#define DN_Arena_NewArray(arena, T, count, zero_mem) (T *)DN_Arena_Alloc(arena, sizeof(T) * (count), alignof(T), zero_mem)
|
||||
#define DN_Arena_NewCopy(arena, T, src) (T *)DN_Arena_Copy (arena, (src), sizeof(T), alignof(T))
|
||||
#define DN_Arena_NewArrayCopy(arena, T, src, count) (T *)DN_Arena_Copy (arena, (src), sizeof(T) * (count), alignof(T))
|
||||
|
||||
#define DN_Pool_New(pool, T) (T *)DN_Pool_Alloc(pool, sizeof(T))
|
||||
#define DN_Pool_NewArray(pool, T, count) (T *)DN_Pool_Alloc(pool, count * sizeof(T))
|
||||
#define DN_Pool_NewCopy(arena, T, src) (T *)DN_Pool_Copy (arena, (src), sizeof(T), alignof(T))
|
||||
#define DN_Pool_NewArrayCopy(arena, T, src, count) (T *)DN_Pool_Copy (arena, (src), sizeof(T) * (count), alignof(T))
|
||||
DN_API DN_Pool DN_Pool_Init (DN_Arena *arena, DN_U8 align);
|
||||
DN_API bool DN_Pool_IsValid (DN_Pool const *pool);
|
||||
DN_API void * DN_Pool_Alloc (DN_Pool *pool, DN_USize size);
|
||||
DN_API DN_Str8 DN_Pool_AllocStr8FV (DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API DN_Str8 DN_Pool_AllocStr8F (DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API DN_Str8 DN_Pool_AllocStr8Copy (DN_Pool *pool, DN_Str8 string);
|
||||
DN_API void DN_Pool_Dealloc (DN_Pool *pool, void *ptr);
|
||||
DN_API void * DN_Pool_Copy (DN_Pool *pool, void const *data, DN_U64 size, uint8_t align);
|
||||
|
||||
// NOTE: DN_Debug //////////////////////////////////////////////////////////////////////////////////
|
||||
#if defined(DN_LEAK_TRACKING) && !defined(DN_FREESTANDING)
|
||||
DN_API void DN_Debug_TrackAlloc (void *ptr, DN_USize size, bool alloc_can_leak);
|
||||
DN_API void DN_Debug_TrackDealloc(void *ptr);
|
||||
DN_API void DN_Debug_DumpLeaks ();
|
||||
#else
|
||||
#define DN_Debug_TrackAlloc(ptr, size, alloc_can_leak) do { (void)ptr; (void)size; (void)alloc_can_leak; } while (0)
|
||||
#define DN_Debug_TrackDealloc(ptr) do { (void)ptr; } while (0)
|
||||
#define DN_Debug_DumpLeaks() do { } while (0)
|
||||
#endif
|
||||
#define DN_Pool_New(pool, T) (T *)DN_Pool_Alloc(pool, sizeof(T))
|
||||
#define DN_Pool_NewArray(pool, T, count) (T *)DN_Pool_Alloc(pool, count * sizeof(T))
|
||||
#define DN_Pool_NewCopy(arena, T, src) (T *)DN_Pool_Copy (arena, (src), sizeof(T), alignof(T))
|
||||
#define DN_Pool_NewArrayCopy(arena, T, src, count) (T *)DN_Pool_Copy (arena, (src), sizeof(T) * (count), alignof(T))
|
||||
#endif // !defined(DN_BASE_MEM_H)
|
||||
// DN: Single header generator inlined this file => #include "Base/dn_base_log.h"
|
||||
#if !defined(DN_BASE_LOG_H)
|
||||
#define DN_BASE_LOG_H
|
||||
|
||||
// DN: Single header generator commented out this header => #include "../dn_base_inc.h"
|
||||
|
||||
enum DN_LOGType
|
||||
{
|
||||
DN_LOGType_Debug,
|
||||
@ -1294,8 +1144,6 @@ DN_API DN_LOGTypeParam DN_LOG_MakeU32LogTypeParam (DN_LOGType type);
|
||||
#define DN_LOG_InfoF(fmt, ...) DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Info), DN_CALL_SITE, fmt, ##__VA_ARGS__)
|
||||
#define DN_LOG_WarningF(fmt, ...) DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Warning), DN_CALL_SITE, fmt, ##__VA_ARGS__)
|
||||
#define DN_LOG_ErrorF(fmt, ...) DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Error), DN_CALL_SITE, fmt, ##__VA_ARGS__)
|
||||
|
||||
|
||||
#endif // !defined(DN_BASE_LOG_H)
|
||||
// DN: Single header generator inlined this file => #include "Base/dn_base_string.h"
|
||||
#if !defined(DN_BASE_STRING_H)
|
||||
@ -3245,24 +3093,6 @@ DN_MSVC_WARNING_POP
|
||||
#define DN_VSPrintF(...) STB_SPRINTF_DECORATE(vsprintf)(__VA_ARGS__)
|
||||
#define DN_VSNPrintF(...) STB_SPRINTF_DECORATE(vsnprintf)(__VA_ARGS__)
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// $$$$$$\ $$$$$$$$\ $$$$$$$\ $$$$$$\ $$\ $$\ $$$$$$\
|
||||
// $$ __$$\\__$$ __|$$ __$$\ \_$$ _|$$$\ $$ |$$ __$$\
|
||||
// $$ / \__| $$ | $$ | $$ | $$ | $$$$\ $$ |$$ / \__|
|
||||
// \$$$$$$\ $$ | $$$$$$$ | $$ | $$ $$\$$ |$$ |$$$$\
|
||||
// \____$$\ $$ | $$ __$$< $$ | $$ \$$$$ |$$ |\_$$ |
|
||||
// $$\ $$ | $$ | $$ | $$ | $$ | $$ |\$$$ |$$ | $$ |
|
||||
// \$$$$$$ | $$ | $$ | $$ |$$$$$$\ $$ | \$$ |\$$$$$$ |
|
||||
// \______/ \__| \__| \__|\______|\__| \__| \______/
|
||||
//
|
||||
// dn_base_string.h
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
// NOTE: DN_Str8 //////////////////////////////////////////////////////////////////////////////////
|
||||
struct DN_Str8Link
|
||||
{
|
||||
DN_Str8 string; // The string
|
||||
@ -3332,7 +3162,6 @@ struct DN_Str8DotTruncateResult
|
||||
DN_Str8 str8;
|
||||
};
|
||||
|
||||
// NOTE: DN_FStr8 //////////////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DN_NO_FSTR8)
|
||||
template <DN_USize N>
|
||||
struct DN_FStr8
|
||||
@ -3956,6 +3785,76 @@ template <typename T> struct DN_List
|
||||
// MyLinkItem *first_item = DN_ISLList_Detach(&my_link, MyLinkItem);
|
||||
// ```
|
||||
|
||||
#define DN_DLList_Init(list) \
|
||||
(list)->next = (list)->prev = (list)
|
||||
|
||||
#define DN_DLList_IsSentinel(list, item) ((list) == (item))
|
||||
|
||||
#define DN_DLList_InitArena(list, T, arena) \
|
||||
do { \
|
||||
(list) = DN_Arena_New(arena, T, DN_ZeroMem_Yes); \
|
||||
DN_DLList_Init(list); \
|
||||
} while (0)
|
||||
|
||||
#define DN_DLList_InitPool(list, T, pool) \
|
||||
do { \
|
||||
(list) = DN_Pool_New(pool, T); \
|
||||
DN_DLList_Init(list); \
|
||||
} while (0)
|
||||
|
||||
#define DN_DLList_Detach(item) \
|
||||
do { \
|
||||
if (item) { \
|
||||
(item)->prev->next = (item)->next; \
|
||||
(item)->next->prev = (item)->prev; \
|
||||
(item)->next = nullptr; \
|
||||
(item)->prev = nullptr; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DN_DLList_Dequeue(list, dest_ptr) \
|
||||
if (DN_DLList_HasItems(list)) { \
|
||||
dest_ptr = (list)->next; \
|
||||
DN_DLList_Detach(dest_ptr); \
|
||||
}
|
||||
|
||||
#define DN_DLList_Append(list, item) \
|
||||
do { \
|
||||
if (item) { \
|
||||
if ((item)->next) \
|
||||
DN_DLList_Detach(item); \
|
||||
(item)->next = (list)->next; \
|
||||
(item)->prev = (list); \
|
||||
(item)->next->prev = (item); \
|
||||
(item)->prev->next = (item); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DN_DLList_Prepend(list, item) \
|
||||
do { \
|
||||
if (item) { \
|
||||
if ((item)->next) \
|
||||
DN_DLList_Detach(item); \
|
||||
(item)->next = (list); \
|
||||
(item)->prev = (list)->prev; \
|
||||
(item)->next->prev = (item); \
|
||||
(item)->prev->next = (item); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DN_DLList_IsEmpty(list) \
|
||||
(!(list) || ((list) == (list)->next))
|
||||
|
||||
#define DN_DLList_IsInit(list) \
|
||||
((list)->next && (list)->prev)
|
||||
|
||||
#define DN_DLList_HasItems(list) \
|
||||
((list) && ((list) != (list)->next))
|
||||
|
||||
#define DN_DLList_ForEach(it, list) \
|
||||
auto *it = (list)->next; (it) != (list); (it) = (it)->next
|
||||
|
||||
|
||||
#define DN_ISLList_Detach(list) (decltype(list)) DN_CSLList_Detach((void **)&(list), (void **)&(list)->next)
|
||||
|
||||
#define DN_LArray_ResizeFromPool(c_array, size, max, pool, new_max) DN_CArray2_ResizeFromPool((void **)&(c_array), size, max, sizeof((c_array)[0]), pool, new_max)
|
||||
@ -4216,13 +4115,13 @@ DN_API DN_Str8 DN_CVT_BytesToHex (DN_Arena
|
||||
#define DN_CVT_BytesToHexFromTLS(...) DN_CVT_BytesToHex(DN_OS_TLSTopArena(), __VA_ARGS__)
|
||||
#define DN_CVT_BytesToHexFromFrame(...) DN_CVT_BytesToHex(DN_OS_TLSFrameArena(), __VA_ARGS__)
|
||||
|
||||
DN_API DN_USize DN_CVT_HexToBytesPtrUnchecked (DN_Str8 hex, void *dest, DN_USize dest_size);
|
||||
DN_API DN_USize DN_CVT_HexToBytesPtr (DN_Str8 hex, void *dest, DN_USize dest_size);
|
||||
DN_API DN_Str8 DN_CVT_HexToBytesUnchecked (DN_Arena *arena, DN_Str8 hex);
|
||||
#define DN_CVT_HexToBytesUncheckedFromTLS(...) DN_CVT_HexToBytesUnchecked(DN_OS_TLSTopArena(), __VA_ARGS__)
|
||||
DN_API DN_Str8 DN_CVT_HexToBytes (DN_Arena *arena, DN_Str8 hex);
|
||||
#define DN_CVT_HexToBytesFromFrame(...) DN_CVT_HexToBytes(DN_OS_TLSFrameArena(), __VA_ARGS__)
|
||||
#define DN_CVT_HexToBytesFromTLS(...) DN_CVT_HexToBytes(DN_OS_TLSTopArena(), __VA_ARGS__)
|
||||
DN_API DN_USize DN_CVT_HexToBytesPtrUnchecked (DN_Str8 hex, void *dest, DN_USize dest_size);
|
||||
DN_API DN_USize DN_CVT_HexToBytesPtr (DN_Str8 hex, void *dest, DN_USize dest_size);
|
||||
DN_API DN_Str8 DN_CVT_HexToBytesUnchecked (DN_Arena *arena, DN_Str8 hex);
|
||||
#define DN_CVT_HexToBytesUncheckedFromTLS(...) DN_CVT_HexToBytesUnchecked(DN_OS_TLSTopArena(), __VA_ARGS__)
|
||||
DN_API DN_Str8 DN_CVT_HexToBytes (DN_Arena *arena, DN_Str8 hex);
|
||||
#define DN_CVT_HexToBytesFromFrame(...) DN_CVT_HexToBytes(DN_OS_TLSFrameArena(), __VA_ARGS__)
|
||||
#define DN_CVT_HexToBytesFromTLS(...) DN_CVT_HexToBytes(DN_OS_TLSTopArena(), __VA_ARGS__)
|
||||
#endif // defined(DN_BASE_CONVERT_H)
|
||||
|
||||
#endif // !defined(DN_BASE_INC_H)
|
||||
@ -6503,7 +6402,7 @@ DN_API DN_Str8Builder DN_Str8Builder_CopyFromFrame (DN_Str8Bu
|
||||
DN_API DN_Str8Builder DN_Str8Builder_CopyFromTLS (DN_Str8Builder const *builder) { return DN_Str8Builder_Copy(DN_OS_TLSTopArena(), builder); }
|
||||
|
||||
DN_API DN_Str8 DN_Str8Builder_BuildFromFrame (DN_Str8Builder const *builder) { return DN_Str8Builder_Build(builder, DN_OS_TLSGet()->frame_arena); }
|
||||
DN_API DN_Slice<DN_Str8> DN_Str8Builder_BuildFromOSHeap (DN_Str8Builder const *builder, DN_Arena *arena);
|
||||
DN_API DN_Str8 DN_Str8Builder_BuildFromOSHeap (DN_Str8Builder const *builder, DN_Arena *arena);
|
||||
DN_API DN_Str8 DN_Str8Builder_BuildFromTLS (DN_Str8Builder const *builder) { return DN_Str8Builder_Build(builder, DN_OS_TLSTopArena()); }
|
||||
|
||||
DN_API DN_Str8 DN_Str8Builder_BuildDelimitedFromFrame(DN_Str8Builder const *builder, DN_Str8 delimiter) { return DN_Str8Builder_BuildDelimited(builder, delimiter, DN_OS_TLSGet()->frame_arena); }
|
||||
@ -6522,6 +6421,8 @@ DN_API DN_Slice<DN_Str8> DN_Str8Builder_BuildSliceFromTLS (DN_Str8Bu
|
||||
#if !defined(DN_CORE_DEBUG_H)
|
||||
#define DN_CORE_DEBUG_H
|
||||
|
||||
// DN: Single header generator commented out this header => #include "../dn_base_inc.h"
|
||||
|
||||
// NOTE: DN_StackTrace /////////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: DN_Debug //////////////////////////////////////////////////////////////////////////////////
|
||||
enum DN_DebugAllocFlag
|
||||
@ -6614,8 +6515,18 @@ DN_API void DN_Profiler_EndZone (DN_ProfilerZ
|
||||
DN_API DN_ProfilerAnchor * DN_Profiler_AnchorBuffer (DN_ProfilerAnchorBuffer buffer);
|
||||
DN_API void DN_Profiler_SwapAnchorBuffer ();
|
||||
DN_API void DN_Profiler_Dump (DN_U64 tsc_per_second);
|
||||
|
||||
#endif // !defined(DN_NO_PROFILER)
|
||||
|
||||
|
||||
#if defined(DN_LEAK_TRACKING)
|
||||
DN_API void DN_DBGTrackAlloc (void *ptr, DN_USize size, bool alloc_can_leak);
|
||||
DN_API void DN_DBGTrackDealloc (void *ptr);
|
||||
DN_API void DN_DBGDumpLeaks ();
|
||||
#else
|
||||
#define DN_DBGTrackAlloc(ptr, size, alloc_can_leak) do { (void)ptr; (void)size; (void)alloc_can_leak; } while (0)
|
||||
#define DN_DBGTrackDealloc(ptr) do { (void)ptr; } while (0)
|
||||
#define DN_DBGDumpLeaks() do { } while (0)
|
||||
#endif
|
||||
#endif // DN_CORE_DEBUG_H
|
||||
// DN: Single header generator inlined this file => #include "Core/dn_core.h"
|
||||
#if !defined(DN_CORE_H)
|
||||
|
@ -1,21 +1,50 @@
|
||||
#define DN_BASE_CPP
|
||||
|
||||
#include "../dn_clangd.h"
|
||||
|
||||
// NOTE: [$INTR] Intrinsics ////////////////////////////////////////////////////////////////////////
|
||||
DN_CPUFeatureDecl g_dn_cpu_feature_decl[DN_CPUFeature_Count];
|
||||
#include "../dn_base_inc.h"
|
||||
|
||||
#if !defined(DN_PLATFORM_ARM64) && !defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
#define DN_SUPPORTS_CPU_ID
|
||||
#endif
|
||||
|
||||
#if defined(DN_SUPPORTS_CPU_ID)
|
||||
#if defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG)
|
||||
#include <cpuid.h>
|
||||
#endif
|
||||
#endif // defined(DN_SUPPORTS_CPU_ID)
|
||||
#if defined(DN_SUPPORTS_CPU_ID) && (defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG))
|
||||
#include <cpuid.h>
|
||||
#endif
|
||||
|
||||
DN_API DN_CPUIDResult DN_CPU_ID(DN_CPUIDArgs args)
|
||||
static DN_CPUFeatureDecl g_dn_cpu_feature_decl[DN_CPUFeature_Count];
|
||||
|
||||
DN_API DN_U64 DN_AtomicSetValue64(DN_U64 volatile *target, DN_U64 value)
|
||||
{
|
||||
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
|
||||
__int64 result;
|
||||
do {
|
||||
result = *target;
|
||||
} while (DN_AtomicCompareExchange64(target, value, result) != result);
|
||||
return DN_CAST(DN_U64) result;
|
||||
#elif defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG)
|
||||
DN_U64 result = __sync_lock_test_and_set(target, value);
|
||||
return result;
|
||||
#else
|
||||
#error Unsupported compiler
|
||||
#endif
|
||||
}
|
||||
|
||||
DN_API DN_U32 DN_AtomicSetValue32(DN_U32 volatile *target, DN_U32 value)
|
||||
{
|
||||
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
|
||||
long result;
|
||||
do {
|
||||
result = *target;
|
||||
} while (DN_AtomicCompareExchange32(target, value, result) != result);
|
||||
return result;
|
||||
#elif defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG)
|
||||
long result = __sync_lock_test_and_set(target, value);
|
||||
return result;
|
||||
#else
|
||||
#error Unsupported compiler
|
||||
#endif
|
||||
}
|
||||
|
||||
DN_API DN_CPUIDResult DN_CPUID(DN_CPUIDArgs args)
|
||||
{
|
||||
DN_CPUIDResult result = {};
|
||||
#if defined(DN_SUPPORTS_CPU_ID)
|
||||
@ -24,7 +53,7 @@ DN_API DN_CPUIDResult DN_CPU_ID(DN_CPUIDArgs args)
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_USize DN_CPU_HasFeatureArray(DN_CPUReport const *report, DN_CPUFeatureQuery *features, DN_USize features_size)
|
||||
DN_API DN_USize DN_CPUHasFeatureArray(DN_CPUReport const *report, DN_CPUFeatureQuery *features, DN_USize features_size)
|
||||
{
|
||||
DN_USize result = 0;
|
||||
DN_USize const BITS = sizeof(report->features[0]) * 8;
|
||||
@ -40,23 +69,23 @@ DN_API DN_USize DN_CPU_HasFeatureArray(DN_CPUReport const *report, DN_CPUFeature
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_CPU_HasFeature(DN_CPUReport const *report, DN_CPUFeature feature)
|
||||
DN_API bool DN_CPUHasFeature(DN_CPUReport const *report, DN_CPUFeature feature)
|
||||
{
|
||||
DN_CPUFeatureQuery query = {};
|
||||
query.feature = feature;
|
||||
bool result = DN_CPU_HasFeatureArray(report, &query, 1) == 1;
|
||||
bool result = DN_CPUHasFeatureArray(report, &query, 1) == 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_CPU_HasAllFeatures(DN_CPUReport const *report, DN_CPUFeature const *features, DN_USize features_size)
|
||||
DN_API bool DN_CPUHasAllFeatures(DN_CPUReport const *report, DN_CPUFeature const *features, DN_USize features_size)
|
||||
{
|
||||
bool result = true;
|
||||
for (DN_USize index = 0; result && index < features_size; index++)
|
||||
result &= DN_CPU_HasFeature(report, features[index]);
|
||||
result &= DN_CPUHasFeature(report, features[index]);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API void DN_CPU_SetFeature(DN_CPUReport *report, DN_CPUFeature feature)
|
||||
DN_API void DN_CPUSetFeature(DN_CPUReport *report, DN_CPUFeature feature)
|
||||
{
|
||||
DN_Assert(feature < DN_CPUFeature_Count);
|
||||
DN_USize const BITS = sizeof(report->features[0]) * 8;
|
||||
@ -65,7 +94,7 @@ DN_API void DN_CPU_SetFeature(DN_CPUReport *report, DN_CPUFeature feature)
|
||||
report->features[chunk_index] |= (1ULL << chunk_bit);
|
||||
}
|
||||
|
||||
DN_API DN_CPUReport DN_CPU_Report()
|
||||
DN_API DN_CPUReport DN_CPUGetReport()
|
||||
{
|
||||
DN_CPUReport result = {};
|
||||
#if defined(DN_SUPPORTS_CPU_ID)
|
||||
@ -80,12 +109,12 @@ DN_API DN_CPUReport DN_CPU_Report()
|
||||
|
||||
// NOTE: Query standard function (e.g. eax = 0x0) for function count + cpu vendor
|
||||
args = {};
|
||||
fn_0000_[0] = DN_CPU_ID(args);
|
||||
fn_0000_[0] = DN_CPUID(args);
|
||||
|
||||
// NOTE: Query extended function (e.g. eax = 0x8000'0000) for function count + cpu vendor
|
||||
args = {};
|
||||
args.eax = DN_CAST(int) EXTENDED_FUNC_BASE_EAX;
|
||||
fn_8000_[0] = DN_CPU_ID(args);
|
||||
fn_8000_[0] = DN_CPUID(args);
|
||||
}
|
||||
|
||||
// NOTE: Extract function count ////////////////////////////////////////////////////////////////
|
||||
@ -104,13 +133,13 @@ DN_API DN_CPUReport DN_CPU_Report()
|
||||
for (int eax = 1; eax <= STANDARD_FUNC_MAX_EAX; eax++) {
|
||||
DN_CPUIDArgs args = {};
|
||||
args.eax = eax;
|
||||
fn_0000_[eax] = DN_CPU_ID(args);
|
||||
fn_0000_[eax] = DN_CPUID(args);
|
||||
}
|
||||
|
||||
for (int eax = EXTENDED_FUNC_BASE_EAX + 1, index = 1; eax <= EXTENDED_FUNC_MAX_EAX; eax++, index++) {
|
||||
DN_CPUIDArgs args = {};
|
||||
args.eax = eax;
|
||||
fn_8000_[index] = DN_CPU_ID(args);
|
||||
fn_8000_[index] = DN_CPUID(args);
|
||||
}
|
||||
}
|
||||
|
||||
@ -207,7 +236,7 @@ DN_API DN_CPUReport DN_CPU_Report()
|
||||
}
|
||||
|
||||
if (available)
|
||||
DN_CPU_SetFeature(&result, DN_CAST(DN_CPUFeature) ext_index);
|
||||
DN_CPUSetFeature(&result, DN_CAST(DN_CPUFeature) ext_index);
|
||||
}
|
||||
#endif // DN_SUPPORTS_CPU_ID
|
||||
return result;
|
||||
@ -216,18 +245,18 @@ DN_API DN_CPUReport DN_CPU_Report()
|
||||
// NOTE: DN_TicketMutex ////////////////////////////////////////////////////////////////////////////
|
||||
DN_API void DN_TicketMutex_Begin(DN_TicketMutex *mutex)
|
||||
{
|
||||
unsigned int ticket = DN_Atomic_AddU32(&mutex->ticket, 1);
|
||||
unsigned int ticket = DN_AtomicAddU32(&mutex->ticket, 1);
|
||||
DN_TicketMutex_BeginTicket(mutex, ticket);
|
||||
}
|
||||
|
||||
DN_API void DN_TicketMutex_End(DN_TicketMutex *mutex)
|
||||
{
|
||||
DN_Atomic_AddU32(&mutex->serving, 1);
|
||||
DN_AtomicAddU32(&mutex->serving, 1);
|
||||
}
|
||||
|
||||
DN_API DN_UInt DN_TicketMutex_MakeTicket(DN_TicketMutex *mutex)
|
||||
{
|
||||
DN_UInt result = DN_Atomic_AddU32(&mutex->ticket, 1);
|
||||
DN_UInt result = DN_AtomicAddU32(&mutex->ticket, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -257,60 +286,60 @@ DN_API bool DN_TicketMutex_CanLock(DN_TicketMutex const *mutex, DN_UInt ticket)
|
||||
#endif
|
||||
|
||||
// NOTE: DN_Bit ////////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API void DN_Bit_UnsetInplace(DN_USize *flags, DN_USize bitfield)
|
||||
DN_API void DN_BitUnsetInplace(DN_USize *flags, DN_USize bitfield)
|
||||
{
|
||||
*flags = (*flags & ~bitfield);
|
||||
}
|
||||
|
||||
DN_API void DN_Bit_SetInplace(DN_USize *flags, DN_USize bitfield)
|
||||
DN_API void DN_BitSetInplace(DN_USize *flags, DN_USize bitfield)
|
||||
{
|
||||
*flags = (*flags | bitfield);
|
||||
}
|
||||
|
||||
DN_API bool DN_Bit_IsSet(DN_USize bits, DN_USize bits_to_set)
|
||||
DN_API bool DN_BitIsSet(DN_USize bits, DN_USize bits_to_set)
|
||||
{
|
||||
auto result = DN_CAST(bool)((bits & bits_to_set) == bits_to_set);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_Bit_IsNotSet(DN_USize bits, DN_USize bits_to_check)
|
||||
DN_API bool DN_BitIsNotSet(DN_USize bits, DN_USize bits_to_check)
|
||||
{
|
||||
auto result = !DN_Bit_IsSet(bits, bits_to_check);
|
||||
auto result = !DN_BitIsSet(bits, bits_to_check);
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: DN_Safe ///////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_I64 DN_Safe_AddI64(int64_t a, int64_t b)
|
||||
DN_API DN_I64 DN_SafeAddI64(int64_t a, int64_t b)
|
||||
{
|
||||
DN_I64 result = DN_CheckF(a <= INT64_MAX - b, "a=%zd, b=%zd", a, b) ? (a + b) : INT64_MAX;
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_I64 DN_Safe_MulI64(int64_t a, int64_t b)
|
||||
DN_API DN_I64 DN_SafeMulI64(int64_t a, int64_t b)
|
||||
{
|
||||
DN_I64 result = DN_CheckF(a <= INT64_MAX / b, "a=%zd, b=%zd", a, b) ? (a * b) : INT64_MAX;
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_U64 DN_Safe_AddU64(DN_U64 a, DN_U64 b)
|
||||
DN_API DN_U64 DN_SafeAddU64(DN_U64 a, DN_U64 b)
|
||||
{
|
||||
DN_U64 result = DN_CheckF(a <= UINT64_MAX - b, "a=%zu, b=%zu", a, b) ? (a + b) : UINT64_MAX;
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_U64 DN_Safe_SubU64(DN_U64 a, DN_U64 b)
|
||||
DN_API DN_U64 DN_SafeSubU64(DN_U64 a, DN_U64 b)
|
||||
{
|
||||
DN_U64 result = DN_CheckF(a >= b, "a=%zu, b=%zu", a, b) ? (a - b) : 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_U64 DN_Safe_MulU64(DN_U64 a, DN_U64 b)
|
||||
DN_API DN_U64 DN_SafeMulU64(DN_U64 a, DN_U64 b)
|
||||
{
|
||||
DN_U64 result = DN_CheckF(a <= UINT64_MAX / b, "a=%zu, b=%zu", a, b) ? (a * b) : UINT64_MAX;
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_U32 DN_Safe_SubU32(DN_U32 a, DN_U32 b)
|
||||
DN_API DN_U32 DN_SafeSubU32(DN_U32 a, DN_U32 b)
|
||||
{
|
||||
DN_U32 result = DN_CheckF(a >= b, "a=%u, b=%u", a, b) ? (a - b) : 0;
|
||||
return result;
|
||||
@ -699,7 +728,7 @@ static_assert(DN_IsPowerOfTwoAligned(DN_ASAN_POISON_GUARD_SIZE, DN_ASAN_POISON_A
|
||||
"ASAN poison guard size must be a power-of-two and aligned to ASAN's alignment"
|
||||
"requirement (8 bytes)");
|
||||
|
||||
DN_API void DN_ASAN_PoisonMemoryRegion(void const volatile *ptr, DN_USize size)
|
||||
DN_API void DN_ASanPoisonMemoryRegion(void const volatile *ptr, DN_USize size)
|
||||
{
|
||||
if (!ptr || !size)
|
||||
return;
|
||||
@ -719,7 +748,7 @@ DN_API void DN_ASAN_PoisonMemoryRegion(void const volatile *ptr, DN_USize size)
|
||||
#endif
|
||||
}
|
||||
|
||||
DN_API void DN_ASAN_UnpoisonMemoryRegion(void const volatile *ptr, DN_USize size)
|
||||
DN_API void DN_ASanUnpoisonMemoryRegion(void const volatile *ptr, DN_USize size)
|
||||
{
|
||||
if (!ptr || !size)
|
||||
return;
|
||||
|
@ -1,6 +1,8 @@
|
||||
#if !defined(DN_BASE_H)
|
||||
#define DN_BASE_H
|
||||
|
||||
#include "../dn_base_inc.h"
|
||||
|
||||
// NOTE: Macros ////////////////////////////////////////////////////////////////////////////////////
|
||||
#define DN_Stringify(x) #x
|
||||
#define DN_TokenCombine2(x, y) x ## y
|
||||
@ -149,7 +151,7 @@ struct DN_DeferHelper
|
||||
};
|
||||
|
||||
#define DN_UniqueName(prefix) DN_TokenCombine(prefix, __LINE__)
|
||||
#define DN_DEFER const auto DN_UniqueName(defer_lambda_) = DN_DeferHelper() + [&]()
|
||||
#define DN_DEFER const auto DN_UniqueName(defer_lambda_) = DN_DeferHelper() + [&]()
|
||||
#endif // defined(__cplusplus)
|
||||
|
||||
#define DN_DeferLoop(begin, end) \
|
||||
@ -233,30 +235,25 @@ struct DN_CallSite
|
||||
DN_Str8 function;
|
||||
DN_U32 line;
|
||||
};
|
||||
|
||||
#define DN_CALL_SITE \
|
||||
DN_CallSite \
|
||||
{ \
|
||||
DN_STR8(__FILE__), DN_STR8(__func__), __LINE__ \
|
||||
}
|
||||
#define DN_CALL_SITE DN_CallSite { DN_STR8(__FILE__), DN_STR8(__func__), __LINE__ }
|
||||
|
||||
// NOTE: Intrinsics ////////////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: DN_Atomic_Add/Exchange return the previous value store in the target
|
||||
// NOTE: DN_AtomicAdd/Exchange return the previous value store in the target
|
||||
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
|
||||
#include <intrin.h>
|
||||
#define DN_Atomic_CompareExchange64(dest, desired_val, prev_val) _InterlockedCompareExchange64((__int64 volatile *)dest, desired_val, prev_val)
|
||||
#define DN_Atomic_CompareExchange32(dest, desired_val, prev_val) _InterlockedCompareExchange((long volatile *)dest, desired_val, prev_val)
|
||||
#define DN_AtomicCompareExchange64(dest, desired_val, prev_val) _InterlockedCompareExchange64((__int64 volatile *)dest, desired_val, prev_val)
|
||||
#define DN_AtomicCompareExchange32(dest, desired_val, prev_val) _InterlockedCompareExchange((long volatile *)dest, desired_val, prev_val)
|
||||
|
||||
#define DN_Atomic_LoadU64(target) *(target)
|
||||
#define DN_Atomic_LoadU32(target) *(target)
|
||||
#define DN_Atomic_AddU32(target, value) _InterlockedExchangeAdd((long volatile *)target, value)
|
||||
#define DN_Atomic_AddU64(target, value) _InterlockedExchangeAdd64((__int64 volatile *)target, value)
|
||||
#define DN_Atomic_SubU32(target, value) DN_Atomic_AddU32(DN_CAST(long volatile *) target, (long)-value)
|
||||
#define DN_Atomic_SubU64(target, value) DN_Atomic_AddU64(target, (DN_U64) - value)
|
||||
#define DN_AtomicLoadU64(target) *(target)
|
||||
#define DN_AtomicLoadU32(target) *(target)
|
||||
#define DN_AtomicAddU32(target, value) _InterlockedExchangeAdd((long volatile *)target, value)
|
||||
#define DN_AtomicAddU64(target, value) _InterlockedExchangeAdd64((__int64 volatile *)target, value)
|
||||
#define DN_AtomicSubU32(target, value) DN_AtomicAddU32(DN_CAST(long volatile *) target, (long)-value)
|
||||
#define DN_AtomicSubU64(target, value) DN_AtomicAddU64(target, (DN_U64) - value)
|
||||
|
||||
#define DN_CountLeadingZerosU64(value) __lzcnt64(value)
|
||||
#define DN_CountLeadingZerosU32(value) __lzcnt(value)
|
||||
#define DN_CPU_TSC() __rdtsc()
|
||||
#define DN_CPUGetTSC() __rdtsc()
|
||||
#define DN_CompilerReadBarrierAndCPUReadFence _ReadBarrier(); _mm_lfence()
|
||||
#define DN_CompilerWriteBarrierAndCPUWriteFence _WriteBarrier(); _mm_sfence()
|
||||
#elif defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG)
|
||||
@ -270,20 +267,20 @@ struct DN_CallSite
|
||||
#include <x86intrin.h>
|
||||
#endif
|
||||
|
||||
#define DN_Atomic_LoadU64(target) __atomic_load_n(x, __ATOMIC_SEQ_CST)
|
||||
#define DN_Atomic_LoadU32(target) __atomic_load_n(x, __ATOMIC_SEQ_CST)
|
||||
#define DN_Atomic_AddU32(target, value) __atomic_fetch_add(target, value, __ATOMIC_ACQ_REL)
|
||||
#define DN_Atomic_AddU64(target, value) __atomic_fetch_add(target, value, __ATOMIC_ACQ_REL)
|
||||
#define DN_Atomic_SubU32(target, value) __atomic_fetch_sub(target, value, __ATOMIC_ACQ_REL)
|
||||
#define DN_Atomic_SubU64(target, value) __atomic_fetch_sub(target, value, __ATOMIC_ACQ_REL)
|
||||
#define DN_AtomicLoadU64(target) __atomic_load_n(x, __ATOMIC_SEQ_CST)
|
||||
#define DN_AtomicLoadU32(target) __atomic_load_n(x, __ATOMIC_SEQ_CST)
|
||||
#define DN_AtomicAddU32(target, value) __atomic_fetch_add(target, value, __ATOMIC_ACQ_REL)
|
||||
#define DN_AtomicAddU64(target, value) __atomic_fetch_add(target, value, __ATOMIC_ACQ_REL)
|
||||
#define DN_AtomicSubU32(target, value) __atomic_fetch_sub(target, value, __ATOMIC_ACQ_REL)
|
||||
#define DN_AtomicSubU64(target, value) __atomic_fetch_sub(target, value, __ATOMIC_ACQ_REL)
|
||||
|
||||
#define DN_CountLeadingZerosU64(value) __builtin_clzll(value)
|
||||
#define DN_CountLeadingZerosU32(value) __builtin_clzl(value)
|
||||
|
||||
#if defined(DN_COMPILER_GCC)
|
||||
#define DN_CPU_TSC() __rdtsc()
|
||||
#define DN_CPUTSC() __rdtsc()
|
||||
#else
|
||||
#define DN_CPU_TSC() __builtin_readcyclecounter()
|
||||
#define DN_CPUTSC() __builtin_readcyclecounter()
|
||||
#endif
|
||||
|
||||
#if defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
@ -303,7 +300,6 @@ struct DN_CallSite
|
||||
#define DN_CountLeadingZerosUSize(value) DN_CountLeadingZerosU32(value)
|
||||
#endif
|
||||
|
||||
#if !defined(DN_PLATFORM_ARM64)
|
||||
struct DN_CPURegisters
|
||||
{
|
||||
int eax;
|
||||
@ -318,67 +314,63 @@ union DN_CPUIDResult
|
||||
int values[4];
|
||||
};
|
||||
|
||||
struct DN_CPUIDArgs
|
||||
{
|
||||
int eax;
|
||||
int ecx;
|
||||
};
|
||||
struct DN_CPUIDArgs { int eax; int ecx; };
|
||||
|
||||
#define DN_CPU_FEAT_XMACRO \
|
||||
DN_CPU_FEAT_XENTRY(3DNow) \
|
||||
DN_CPU_FEAT_XENTRY(3DNowExt) \
|
||||
DN_CPU_FEAT_XENTRY(ABM) \
|
||||
DN_CPU_FEAT_XENTRY(AES) \
|
||||
DN_CPU_FEAT_XENTRY(AVX) \
|
||||
DN_CPU_FEAT_XENTRY(AVX2) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512F) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512DQ) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512IFMA) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512PF) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512ER) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512CD) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512BW) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512VL) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512VBMI) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512VBMI2) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512VNNI) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512BITALG) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512VPOPCNTDQ) \
|
||||
DN_CPU_FEAT_XENTRY(AVX5124VNNIW) \
|
||||
DN_CPU_FEAT_XENTRY(AVX5124FMAPS) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512VP2INTERSECT) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512FP16) \
|
||||
DN_CPU_FEAT_XENTRY(CLZERO) \
|
||||
DN_CPU_FEAT_XENTRY(CMPXCHG8B) \
|
||||
DN_CPU_FEAT_XENTRY(CMPXCHG16B) \
|
||||
DN_CPU_FEAT_XENTRY(F16C) \
|
||||
DN_CPU_FEAT_XENTRY(FMA) \
|
||||
DN_CPU_FEAT_XENTRY(FMA4) \
|
||||
DN_CPU_FEAT_XENTRY(FP128) \
|
||||
DN_CPU_FEAT_XENTRY(FP256) \
|
||||
DN_CPU_FEAT_XENTRY(FPU) \
|
||||
DN_CPU_FEAT_XENTRY(MMX) \
|
||||
DN_CPU_FEAT_XENTRY(MONITOR) \
|
||||
DN_CPU_FEAT_XENTRY(MOVBE) \
|
||||
DN_CPU_FEAT_XENTRY(MOVU) \
|
||||
DN_CPU_FEAT_XENTRY(MmxExt) \
|
||||
DN_CPU_FEAT_XENTRY(PCLMULQDQ) \
|
||||
DN_CPU_FEAT_XENTRY(POPCNT) \
|
||||
DN_CPU_FEAT_XENTRY(RDRAND) \
|
||||
DN_CPU_FEAT_XENTRY(RDSEED) \
|
||||
DN_CPU_FEAT_XENTRY(RDTSCP) \
|
||||
DN_CPU_FEAT_XENTRY(SHA) \
|
||||
DN_CPU_FEAT_XENTRY(SSE) \
|
||||
DN_CPU_FEAT_XENTRY(SSE2) \
|
||||
DN_CPU_FEAT_XENTRY(SSE3) \
|
||||
DN_CPU_FEAT_XENTRY(SSE41) \
|
||||
DN_CPU_FEAT_XENTRY(SSE42) \
|
||||
DN_CPU_FEAT_XENTRY(SSE4A) \
|
||||
DN_CPU_FEAT_XENTRY(SSSE3) \
|
||||
DN_CPU_FEAT_XENTRY(TSC) \
|
||||
DN_CPU_FEAT_XENTRY(TscInvariant) \
|
||||
DN_CPU_FEAT_XENTRY(VAES) \
|
||||
DN_CPU_FEAT_XENTRY(VPCMULQDQ)
|
||||
#define DN_CPU_FEAT_XMACRO \
|
||||
DN_CPU_FEAT_XENTRY(3DNow) \
|
||||
DN_CPU_FEAT_XENTRY(3DNowExt) \
|
||||
DN_CPU_FEAT_XENTRY(ABM) \
|
||||
DN_CPU_FEAT_XENTRY(AES) \
|
||||
DN_CPU_FEAT_XENTRY(AVX) \
|
||||
DN_CPU_FEAT_XENTRY(AVX2) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512F) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512DQ) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512IFMA) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512PF) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512ER) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512CD) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512BW) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512VL) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512VBMI) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512VBMI2) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512VNNI) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512BITALG) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512VPOPCNTDQ) \
|
||||
DN_CPU_FEAT_XENTRY(AVX5124VNNIW) \
|
||||
DN_CPU_FEAT_XENTRY(AVX5124FMAPS) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512VP2INTERSECT) \
|
||||
DN_CPU_FEAT_XENTRY(AVX512FP16) \
|
||||
DN_CPU_FEAT_XENTRY(CLZERO) \
|
||||
DN_CPU_FEAT_XENTRY(CMPXCHG8B) \
|
||||
DN_CPU_FEAT_XENTRY(CMPXCHG16B) \
|
||||
DN_CPU_FEAT_XENTRY(F16C) \
|
||||
DN_CPU_FEAT_XENTRY(FMA) \
|
||||
DN_CPU_FEAT_XENTRY(FMA4) \
|
||||
DN_CPU_FEAT_XENTRY(FP128) \
|
||||
DN_CPU_FEAT_XENTRY(FP256) \
|
||||
DN_CPU_FEAT_XENTRY(FPU) \
|
||||
DN_CPU_FEAT_XENTRY(MMX) \
|
||||
DN_CPU_FEAT_XENTRY(MONITOR) \
|
||||
DN_CPU_FEAT_XENTRY(MOVBE) \
|
||||
DN_CPU_FEAT_XENTRY(MOVU) \
|
||||
DN_CPU_FEAT_XENTRY(MmxExt) \
|
||||
DN_CPU_FEAT_XENTRY(PCLMULQDQ) \
|
||||
DN_CPU_FEAT_XENTRY(POPCNT) \
|
||||
DN_CPU_FEAT_XENTRY(RDRAND) \
|
||||
DN_CPU_FEAT_XENTRY(RDSEED) \
|
||||
DN_CPU_FEAT_XENTRY(RDTSCP) \
|
||||
DN_CPU_FEAT_XENTRY(SHA) \
|
||||
DN_CPU_FEAT_XENTRY(SSE) \
|
||||
DN_CPU_FEAT_XENTRY(SSE2) \
|
||||
DN_CPU_FEAT_XENTRY(SSE3) \
|
||||
DN_CPU_FEAT_XENTRY(SSE41) \
|
||||
DN_CPU_FEAT_XENTRY(SSE42) \
|
||||
DN_CPU_FEAT_XENTRY(SSE4A) \
|
||||
DN_CPU_FEAT_XENTRY(SSSE3) \
|
||||
DN_CPU_FEAT_XENTRY(TSC) \
|
||||
DN_CPU_FEAT_XENTRY(TscInvariant) \
|
||||
DN_CPU_FEAT_XENTRY(VAES) \
|
||||
DN_CPU_FEAT_XENTRY(VPCMULQDQ)
|
||||
|
||||
enum DN_CPUFeature
|
||||
{
|
||||
@ -407,218 +399,95 @@ struct DN_CPUReport
|
||||
DN_U64 features[(DN_CPUFeature_Count / (sizeof(DN_U64) * 8)) + 1];
|
||||
};
|
||||
|
||||
extern DN_CPUFeatureDecl g_dn_cpu_feature_decl[DN_CPUFeature_Count];
|
||||
#endif // DN_PLATFORM_ARM64
|
||||
|
||||
// NOTE: DN_TicketMutex ////////////////////////////////////////////////////////////////////////////
|
||||
struct DN_TicketMutex
|
||||
{
|
||||
unsigned int volatile ticket; // The next ticket to give out to the thread taking the mutex
|
||||
unsigned int volatile serving; // The ticket ID to block the mutex on until it is returned
|
||||
};
|
||||
|
||||
// NOTE: Intrinsics ////////////////////////////////////////////////////////////////////////////////
|
||||
DN_FORCE_INLINE DN_U64 DN_Atomic_SetValue64 (DN_U64 volatile *target, DN_U64 value);
|
||||
DN_FORCE_INLINE DN_U32 DN_Atomic_SetValue32 (DN_U32 volatile *target, DN_U32 value);
|
||||
DN_API DN_U64 DN_AtomicSetValue64 (DN_U64 volatile *target, DN_U64 value);
|
||||
DN_API DN_U32 DN_AtomicSetValue32 (DN_U32 volatile *target, DN_U32 value);
|
||||
|
||||
#if !defined (DN_PLATFORM_ARM64)
|
||||
DN_API DN_CPUIDResult DN_CPU_ID (DN_CPUIDArgs args);
|
||||
DN_API DN_USize DN_CPU_HasFeatureArray (DN_CPUReport const *report, DN_CPUFeatureQuery *features, DN_USize features_size);
|
||||
DN_API bool DN_CPU_HasFeature (DN_CPUReport const *report, DN_CPUFeature feature);
|
||||
DN_API bool DN_CPU_HasAllFeatures (DN_CPUReport const *report, DN_CPUFeature const *features, DN_USize features_size);
|
||||
template <DN_USize N>
|
||||
bool DN_CPU_HasAllFeaturesCArray(DN_CPUReport const *report, DN_CPUFeature const (&features)[N]);
|
||||
DN_API void DN_CPU_SetFeature (DN_CPUReport *report, DN_CPUFeature feature);
|
||||
DN_API DN_CPUReport DN_CPU_Report ();
|
||||
#endif
|
||||
DN_API DN_CPUIDResult DN_CPUID (DN_CPUIDArgs args);
|
||||
DN_API DN_USize DN_CPUHasFeatureArray (DN_CPUReport const *report, DN_CPUFeatureQuery *features, DN_USize features_size);
|
||||
DN_API bool DN_CPUHasFeature (DN_CPUReport const *report, DN_CPUFeature feature);
|
||||
DN_API bool DN_CPUHasAllFeatures (DN_CPUReport const *report, DN_CPUFeature const *features, DN_USize features_size);
|
||||
DN_API void DN_CPUSetFeature (DN_CPUReport *report, DN_CPUFeature feature);
|
||||
DN_API DN_CPUReport DN_CPUGetReport ();
|
||||
|
||||
// NOTE: DN_TicketMutex ////////////////////////////////////////////////////////////////////////////
|
||||
DN_API void DN_TicketMutex_Begin (DN_TicketMutex *mutex);
|
||||
DN_API void DN_TicketMutex_End (DN_TicketMutex *mutex);
|
||||
DN_API DN_UInt DN_TicketMutex_MakeTicket (DN_TicketMutex *mutex);
|
||||
DN_API void DN_TicketMutex_BeginTicket(DN_TicketMutex const *mutex, DN_UInt ticket);
|
||||
DN_API bool DN_TicketMutex_CanLock (DN_TicketMutex const *mutex, DN_UInt ticket);
|
||||
DN_API void DN_TicketMutex_Begin (DN_TicketMutex *mutex);
|
||||
DN_API void DN_TicketMutex_End (DN_TicketMutex *mutex);
|
||||
DN_API DN_UInt DN_TicketMutex_MakeTicket (DN_TicketMutex *mutex);
|
||||
DN_API void DN_TicketMutex_BeginTicket (DN_TicketMutex const *mutex, DN_UInt ticket);
|
||||
DN_API bool DN_TicketMutex_CanLock (DN_TicketMutex const *mutex, DN_UInt ticket);
|
||||
|
||||
// NOTE: DN_DLList /////////////////////////////////////////////////////////////////////////////////
|
||||
#define DN_DLList_Init(list) \
|
||||
(list)->next = (list)->prev = (list)
|
||||
DN_API void DN_BitUnsetInplace (DN_USize *flags, DN_USize bitfield);
|
||||
DN_API void DN_BitSetInplace (DN_USize *flags, DN_USize bitfield);
|
||||
DN_API bool DN_BitIsSet (DN_USize bits, DN_USize bits_to_set);
|
||||
DN_API bool DN_BitIsNotSet (DN_USize bits, DN_USize bits_to_check);
|
||||
#define DN_BitClearNextLSB(value) (value) & ((value) - 1)
|
||||
|
||||
#define DN_DLList_IsSentinel(list, item) ((list) == (item))
|
||||
DN_API DN_I64 DN_SafeAddI64 (DN_I64 a, DN_I64 b);
|
||||
DN_API DN_I64 DN_SafeMulI64 (DN_I64 a, DN_I64 b);
|
||||
|
||||
#define DN_DLList_InitArena(list, T, arena) \
|
||||
do { \
|
||||
(list) = DN_Arena_New(arena, T, DN_ZeroMem_Yes); \
|
||||
DN_DLList_Init(list); \
|
||||
} while (0)
|
||||
DN_API DN_U64 DN_SafeAddU64 (DN_U64 a, DN_U64 b);
|
||||
DN_API DN_U64 DN_SafeMulU64 (DN_U64 a, DN_U64 b);
|
||||
|
||||
#define DN_DLList_InitPool(list, T, pool) \
|
||||
do { \
|
||||
(list) = DN_Pool_New(pool, T); \
|
||||
DN_DLList_Init(list); \
|
||||
} while (0)
|
||||
DN_API DN_U64 DN_SafeSubU64 (DN_U64 a, DN_U64 b);
|
||||
DN_API DN_U32 DN_SafeSubU32 (DN_U32 a, DN_U32 b);
|
||||
|
||||
#define DN_DLList_Detach(item) \
|
||||
do { \
|
||||
if (item) { \
|
||||
(item)->prev->next = (item)->next; \
|
||||
(item)->next->prev = (item)->prev; \
|
||||
(item)->next = nullptr; \
|
||||
(item)->prev = nullptr; \
|
||||
} \
|
||||
} while (0)
|
||||
DN_API int DN_SaturateCastUSizeToInt (DN_USize val);
|
||||
DN_API DN_I8 DN_SaturateCastUSizeToI8 (DN_USize val);
|
||||
DN_API DN_I16 DN_SaturateCastUSizeToI16 (DN_USize val);
|
||||
DN_API DN_I32 DN_SaturateCastUSizeToI32 (DN_USize val);
|
||||
DN_API DN_I64 DN_SaturateCastUSizeToI64 (DN_USize val);
|
||||
|
||||
#define DN_DLList_Dequeue(list, dest_ptr) \
|
||||
if (DN_DLList_HasItems(list)) { \
|
||||
dest_ptr = (list)->next; \
|
||||
DN_DLList_Detach(dest_ptr); \
|
||||
}
|
||||
DN_API int DN_SaturateCastU64ToInt (DN_U64 val);
|
||||
DN_API DN_I8 DN_SaturateCastU8ToI8 (DN_U64 val);
|
||||
DN_API DN_I16 DN_SaturateCastU16ToI16 (DN_U64 val);
|
||||
DN_API DN_I32 DN_SaturateCastU32ToI32 (DN_U64 val);
|
||||
DN_API DN_I64 DN_SaturateCastU64ToI64 (DN_U64 val);
|
||||
DN_API DN_UInt DN_SaturateCastU64ToUInt (DN_U64 val);
|
||||
DN_API DN_U8 DN_SaturateCastU64ToU8 (DN_U64 val);
|
||||
DN_API DN_U16 DN_SaturateCastU64ToU16 (DN_U64 val);
|
||||
DN_API DN_U32 DN_SaturateCastU64ToU32 (DN_U64 val);
|
||||
|
||||
#define DN_DLList_Append(list, item) \
|
||||
do { \
|
||||
if (item) { \
|
||||
if ((item)->next) \
|
||||
DN_DLList_Detach(item); \
|
||||
(item)->next = (list)->next; \
|
||||
(item)->prev = (list); \
|
||||
(item)->next->prev = (item); \
|
||||
(item)->prev->next = (item); \
|
||||
} \
|
||||
} while (0)
|
||||
DN_API DN_U8 DN_SaturateCastUSizeToU8 (DN_USize val);
|
||||
DN_API DN_U16 DN_SaturateCastUSizeToU16 (DN_USize val);
|
||||
DN_API DN_U32 DN_SaturateCastUSizeToU32 (DN_USize val);
|
||||
DN_API DN_U64 DN_SaturateCastUSizeToU64 (DN_USize val);
|
||||
|
||||
#define DN_DLList_Prepend(list, item) \
|
||||
do { \
|
||||
if (item) { \
|
||||
if ((item)->next) \
|
||||
DN_DLList_Detach(item); \
|
||||
(item)->next = (list); \
|
||||
(item)->prev = (list)->prev; \
|
||||
(item)->next->prev = (item); \
|
||||
(item)->prev->next = (item); \
|
||||
} \
|
||||
} while (0)
|
||||
DN_API int DN_SaturateCastISizeToInt (DN_ISize val);
|
||||
DN_API DN_I8 DN_SaturateCastISizeToI8 (DN_ISize val);
|
||||
DN_API DN_I16 DN_SaturateCastISizeToI16 (DN_ISize val);
|
||||
DN_API DN_I32 DN_SaturateCastISizeToI32 (DN_ISize val);
|
||||
DN_API DN_I64 DN_SaturateCastISizeToI64 (DN_ISize val);
|
||||
|
||||
#define DN_DLList_IsEmpty(list) \
|
||||
(!(list) || ((list) == (list)->next))
|
||||
DN_API DN_UInt DN_SaturateCastISizeToUInt (DN_ISize val);
|
||||
DN_API DN_U8 DN_SaturateCastISizeToU8 (DN_ISize val);
|
||||
DN_API DN_U16 DN_SaturateCastISizeToU16 (DN_ISize val);
|
||||
DN_API DN_U32 DN_SaturateCastISizeToU32 (DN_ISize val);
|
||||
DN_API DN_U64 DN_SaturateCastISizeToU64 (DN_ISize val);
|
||||
|
||||
#define DN_DLList_IsInit(list) \
|
||||
((list)->next && (list)->prev)
|
||||
DN_API DN_ISize DN_SaturateCastI64ToISize (DN_I64 val);
|
||||
DN_API DN_I8 DN_SaturateCastI64ToI8 (DN_I64 val);
|
||||
DN_API DN_I16 DN_SaturateCastI64ToI16 (DN_I64 val);
|
||||
DN_API DN_I32 DN_SaturateCastI64ToI32 (DN_I64 val);
|
||||
|
||||
#define DN_DLList_HasItems(list) \
|
||||
((list) && ((list) != (list)->next))
|
||||
DN_API DN_UInt DN_SaturateCastI64ToUInt (DN_I64 val);
|
||||
DN_API DN_ISize DN_SaturateCastI64ToUSize (DN_I64 val);
|
||||
DN_API DN_U8 DN_SaturateCastI64ToU8 (DN_I64 val);
|
||||
DN_API DN_U16 DN_SaturateCastI64ToU16 (DN_I64 val);
|
||||
DN_API DN_U32 DN_SaturateCastI64ToU32 (DN_I64 val);
|
||||
DN_API DN_U64 DN_SaturateCastI64ToU64 (DN_I64 val);
|
||||
|
||||
#define DN_DLList_ForEach(it, list) \
|
||||
auto *it = (list)->next; (it) != (list); (it) = (it)->next
|
||||
DN_API DN_I8 DN_SaturateCastIntToI8 (int val);
|
||||
DN_API DN_I16 DN_SaturateCastIntToI16 (int val);
|
||||
DN_API DN_U8 DN_SaturateCastIntToU8 (int val);
|
||||
DN_API DN_U16 DN_SaturateCastIntToU16 (int val);
|
||||
DN_API DN_U32 DN_SaturateCastIntToU32 (int val);
|
||||
DN_API DN_U64 DN_SaturateCastIntToU64 (int val);
|
||||
|
||||
// NOTE: Intrinsics ////////////////////////////////////////////////////////////////////////////////
|
||||
DN_FORCE_INLINE DN_U64 DN_Atomic_SetValue64(DN_U64 volatile *target, DN_U64 value)
|
||||
{
|
||||
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
|
||||
__int64 result;
|
||||
do {
|
||||
result = *target;
|
||||
} while (DN_Atomic_CompareExchange64(target, value, result) != result);
|
||||
return DN_CAST(DN_U64) result;
|
||||
#elif defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG)
|
||||
DN_U64 result = __sync_lock_test_and_set(target, value);
|
||||
return result;
|
||||
#else
|
||||
#error Unsupported compiler
|
||||
#endif
|
||||
}
|
||||
|
||||
DN_FORCE_INLINE DN_U32 DN_Atomic_SetValue32(DN_U32 volatile *target, DN_U32 value)
|
||||
{
|
||||
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
|
||||
long result;
|
||||
do {
|
||||
result = *target;
|
||||
} while (DN_Atomic_CompareExchange32(target, value, result) != result);
|
||||
return result;
|
||||
#elif defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG)
|
||||
long result = __sync_lock_test_and_set(target, value);
|
||||
return result;
|
||||
#else
|
||||
#error Unsupported compiler
|
||||
#endif
|
||||
}
|
||||
|
||||
template <DN_USize N>
|
||||
bool DN_CPU_HasAllFeaturesCArray(DN_CPUReport const *report, DN_CPUFeature const (&features)[N])
|
||||
{
|
||||
bool result = DN_CPU_HasAllFeatures(report, features, N);
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: DN_Bit ////////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API void DN_Bit_UnsetInplace (DN_USize *flags, DN_USize bitfield);
|
||||
DN_API void DN_Bit_SetInplace (DN_USize *flags, DN_USize bitfield);
|
||||
DN_API bool DN_Bit_IsSet (DN_USize bits, DN_USize bits_to_set);
|
||||
DN_API bool DN_Bit_IsNotSet (DN_USize bits, DN_USize bits_to_check);
|
||||
#define DN_Bit_ClearNextLSB(value) (value) & ((value) - 1)
|
||||
|
||||
// NOTE: DN_Safe ///////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_I64 DN_Safe_AddI64 (DN_I64 a, DN_I64 b);
|
||||
DN_API DN_I64 DN_Safe_MulI64 (DN_I64 a, DN_I64 b);
|
||||
|
||||
DN_API DN_U64 DN_Safe_AddU64 (DN_U64 a, DN_U64 b);
|
||||
DN_API DN_U64 DN_Safe_MulU64 (DN_U64 a, DN_U64 b);
|
||||
|
||||
DN_API DN_U64 DN_Safe_SubU64 (DN_U64 a, DN_U64 b);
|
||||
DN_API DN_U32 DN_Safe_SubU32 (DN_U32 a, DN_U32 b);
|
||||
|
||||
DN_API int DN_SaturateCastUSizeToInt (DN_USize val);
|
||||
DN_API DN_I8 DN_SaturateCastUSizeToI8 (DN_USize val);
|
||||
DN_API DN_I16 DN_SaturateCastUSizeToI16 (DN_USize val);
|
||||
DN_API DN_I32 DN_SaturateCastUSizeToI32 (DN_USize val);
|
||||
DN_API DN_I64 DN_SaturateCastUSizeToI64 (DN_USize val);
|
||||
|
||||
DN_API int DN_SaturateCastU64ToInt (DN_U64 val);
|
||||
DN_API DN_I8 DN_SaturateCastU8ToI8 (DN_U64 val);
|
||||
DN_API DN_I16 DN_SaturateCastU16ToI16 (DN_U64 val);
|
||||
DN_API DN_I32 DN_SaturateCastU32ToI32 (DN_U64 val);
|
||||
DN_API DN_I64 DN_SaturateCastU64ToI64 (DN_U64 val);
|
||||
DN_API DN_UInt DN_SaturateCastU64ToUInt (DN_U64 val);
|
||||
DN_API DN_U8 DN_SaturateCastU64ToU8 (DN_U64 val);
|
||||
DN_API DN_U16 DN_SaturateCastU64ToU16 (DN_U64 val);
|
||||
DN_API DN_U32 DN_SaturateCastU64ToU32 (DN_U64 val);
|
||||
|
||||
DN_API DN_U8 DN_SaturateCastUSizeToU8 (DN_USize val);
|
||||
DN_API DN_U16 DN_SaturateCastUSizeToU16 (DN_USize val);
|
||||
DN_API DN_U32 DN_SaturateCastUSizeToU32 (DN_USize val);
|
||||
DN_API DN_U64 DN_SaturateCastUSizeToU64 (DN_USize val);
|
||||
|
||||
DN_API int DN_SaturateCastISizeToInt (DN_ISize val);
|
||||
DN_API DN_I8 DN_SaturateCastISizeToI8 (DN_ISize val);
|
||||
DN_API DN_I16 DN_SaturateCastISizeToI16 (DN_ISize val);
|
||||
DN_API DN_I32 DN_SaturateCastISizeToI32 (DN_ISize val);
|
||||
DN_API DN_I64 DN_SaturateCastISizeToI64 (DN_ISize val);
|
||||
|
||||
DN_API DN_UInt DN_SaturateCastISizeToUInt (DN_ISize val);
|
||||
DN_API DN_U8 DN_SaturateCastISizeToU8 (DN_ISize val);
|
||||
DN_API DN_U16 DN_SaturateCastISizeToU16 (DN_ISize val);
|
||||
DN_API DN_U32 DN_SaturateCastISizeToU32 (DN_ISize val);
|
||||
DN_API DN_U64 DN_SaturateCastISizeToU64 (DN_ISize val);
|
||||
|
||||
DN_API DN_ISize DN_SaturateCastI64ToISize (DN_I64 val);
|
||||
DN_API DN_I8 DN_SaturateCastI64ToI8 (DN_I64 val);
|
||||
DN_API DN_I16 DN_SaturateCastI64ToI16 (DN_I64 val);
|
||||
DN_API DN_I32 DN_SaturateCastI64ToI32 (DN_I64 val);
|
||||
|
||||
DN_API DN_UInt DN_SaturateCastI64ToUInt (DN_I64 val);
|
||||
DN_API DN_ISize DN_SaturateCastI64ToUSize (DN_I64 val);
|
||||
DN_API DN_U8 DN_SaturateCastI64ToU8 (DN_I64 val);
|
||||
DN_API DN_U16 DN_SaturateCastI64ToU16 (DN_I64 val);
|
||||
DN_API DN_U32 DN_SaturateCastI64ToU32 (DN_I64 val);
|
||||
DN_API DN_U64 DN_SaturateCastI64ToU64 (DN_I64 val);
|
||||
|
||||
DN_API DN_I8 DN_SaturateCastIntToI8 (int val);
|
||||
DN_API DN_I16 DN_SaturateCastIntToI16 (int val);
|
||||
DN_API DN_U8 DN_SaturateCastIntToU8 (int val);
|
||||
DN_API DN_U16 DN_SaturateCastIntToU16 (int val);
|
||||
DN_API DN_U32 DN_SaturateCastIntToU32 (int val);
|
||||
DN_API DN_U64 DN_SaturateCastIntToU64 (int val);
|
||||
|
||||
// NOTE: DN_Asan ///////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API void DN_ASAN_PoisonMemoryRegion (void const volatile *ptr, DN_USize size);
|
||||
DN_API void DN_ASAN_UnpoisonMemoryRegion (void const volatile *ptr, DN_USize size);
|
||||
DN_API void DN_ASanPoisonMemoryRegion (void const volatile *ptr, DN_USize size);
|
||||
DN_API void DN_ASanUnpoisonMemoryRegion(void const volatile *ptr, DN_USize size);
|
||||
#endif // !defined(DN_BASE_H)
|
||||
|
@ -1,56 +1,34 @@
|
||||
#if !defined(DN_BASE_ASSERT_H)
|
||||
#define DN_BASE_ASSERT_H
|
||||
|
||||
#define DN_HardAssertF(expr, fmt, ...) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
DN_Str8 stack_trace_ = DN_StackTrace_WalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \
|
||||
DN_LOG_ErrorF("Hard assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \
|
||||
DN_STR_FMT(stack_trace_), \
|
||||
##__VA_ARGS__); \
|
||||
DN_DebugBreak; \
|
||||
} \
|
||||
} while (0)
|
||||
#define DN_HardAssert(expr) DN_HardAssertF(expr, "")
|
||||
|
||||
#if defined(DN_FREESTANDING)
|
||||
#define DN_HardAssertF(expr, fmt, ...) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
DN_DebugBreak; \
|
||||
(*(int *)0) = 0; \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define DN_HardAssertF(expr, fmt, ...) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
DN_Str8 stack_trace_ = DN_StackTrace_WalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \
|
||||
DN_LOG_ErrorF("Hard assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \
|
||||
DN_STR_FMT(stack_trace_), \
|
||||
##__VA_ARGS__); \
|
||||
DN_DebugBreak; \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#if defined(DN_NO_ASSERT)
|
||||
#define DN_Assert(...)
|
||||
#define DN_AssertOnce(...)
|
||||
#define DN_AssertF(...)
|
||||
#define DN_AssertFOnce(...)
|
||||
#else
|
||||
#if defined(DN_FREESTANDING)
|
||||
#define DN_AssertF(expr, fmt, ...) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
DN_DebugBreak; \
|
||||
(*(int *)0) = 0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
#define DN_AssertF(expr, fmt, ...) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
DN_Str8 stack_trace_ = DN_StackTrace_WalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \
|
||||
DN_LOG_ErrorF("Assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \
|
||||
DN_STR_FMT(stack_trace_), \
|
||||
##__VA_ARGS__); \
|
||||
DN_DebugBreak; \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
#define DN_AssertF(expr, fmt, ...) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
DN_Str8 stack_trace_ = DN_StackTrace_WalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \
|
||||
DN_LOG_ErrorF("Assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \
|
||||
DN_STR_FMT(stack_trace_), \
|
||||
##__VA_ARGS__); \
|
||||
DN_DebugBreak; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DN_AssertFOnce(expr, fmt, ...) \
|
||||
do { \
|
||||
@ -72,19 +50,13 @@
|
||||
#define DN_InvalidCodePathF(fmt, ...) DN_HardAssertF(0, fmt, ##__VA_ARGS__)
|
||||
#define DN_InvalidCodePath DN_InvalidCodePathF("Invalid code path triggered")
|
||||
|
||||
// NOTE: Check macro ///////////////////////////////////////////////////////////////////////////////
|
||||
#define DN_Check(expr) DN_CheckF(expr, "")
|
||||
|
||||
#if defined(DN_FREESTANDING)
|
||||
#define DN_CheckF(expr, fmt, ...) (expr)
|
||||
#if defined(DN_NO_CHECK_BREAK)
|
||||
#define DN_CheckF(expr, fmt, ...) \
|
||||
((expr) ? true : (DN_LOG_WarningF(fmt, ##__VA_ARGS__), false))
|
||||
#else
|
||||
#if defined(DN_NO_CHECK_BREAK)
|
||||
#define DN_CheckF(expr, fmt, ...) \
|
||||
((expr) ? true : (DN_LOG_WarningF(fmt, ##__VA_ARGS__), false))
|
||||
#else
|
||||
#define DN_CheckF(expr, fmt, ...) \
|
||||
((expr) ? true : (DN_LOG_ErrorF(fmt, ##__VA_ARGS__), DN_StackTrace_Print(128 /*limit*/), DN_DebugBreak, false))
|
||||
#endif
|
||||
#define DN_CheckF(expr, fmt, ...) \
|
||||
((expr) ? true : (DN_LOG_ErrorF(fmt, ##__VA_ARGS__), DN_StackTrace_Print(128 /*limit*/), DN_DebugBreak, false))
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -203,6 +203,76 @@ template <typename T> struct DN_List
|
||||
// MyLinkItem *first_item = DN_ISLList_Detach(&my_link, MyLinkItem);
|
||||
// ```
|
||||
|
||||
#define DN_DLList_Init(list) \
|
||||
(list)->next = (list)->prev = (list)
|
||||
|
||||
#define DN_DLList_IsSentinel(list, item) ((list) == (item))
|
||||
|
||||
#define DN_DLList_InitArena(list, T, arena) \
|
||||
do { \
|
||||
(list) = DN_Arena_New(arena, T, DN_ZeroMem_Yes); \
|
||||
DN_DLList_Init(list); \
|
||||
} while (0)
|
||||
|
||||
#define DN_DLList_InitPool(list, T, pool) \
|
||||
do { \
|
||||
(list) = DN_Pool_New(pool, T); \
|
||||
DN_DLList_Init(list); \
|
||||
} while (0)
|
||||
|
||||
#define DN_DLList_Detach(item) \
|
||||
do { \
|
||||
if (item) { \
|
||||
(item)->prev->next = (item)->next; \
|
||||
(item)->next->prev = (item)->prev; \
|
||||
(item)->next = nullptr; \
|
||||
(item)->prev = nullptr; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DN_DLList_Dequeue(list, dest_ptr) \
|
||||
if (DN_DLList_HasItems(list)) { \
|
||||
dest_ptr = (list)->next; \
|
||||
DN_DLList_Detach(dest_ptr); \
|
||||
}
|
||||
|
||||
#define DN_DLList_Append(list, item) \
|
||||
do { \
|
||||
if (item) { \
|
||||
if ((item)->next) \
|
||||
DN_DLList_Detach(item); \
|
||||
(item)->next = (list)->next; \
|
||||
(item)->prev = (list); \
|
||||
(item)->next->prev = (item); \
|
||||
(item)->prev->next = (item); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DN_DLList_Prepend(list, item) \
|
||||
do { \
|
||||
if (item) { \
|
||||
if ((item)->next) \
|
||||
DN_DLList_Detach(item); \
|
||||
(item)->next = (list); \
|
||||
(item)->prev = (list)->prev; \
|
||||
(item)->next->prev = (item); \
|
||||
(item)->prev->next = (item); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DN_DLList_IsEmpty(list) \
|
||||
(!(list) || ((list) == (list)->next))
|
||||
|
||||
#define DN_DLList_IsInit(list) \
|
||||
((list)->next && (list)->prev)
|
||||
|
||||
#define DN_DLList_HasItems(list) \
|
||||
((list) && ((list) != (list)->next))
|
||||
|
||||
#define DN_DLList_ForEach(it, list) \
|
||||
auto *it = (list)->next; (it) != (list); (it) = (it)->next
|
||||
|
||||
|
||||
#define DN_ISLList_Detach(list) (decltype(list)) DN_CSLList_Detach((void **)&(list), (void **)&(list)->next)
|
||||
|
||||
#define DN_LArray_ResizeFromPool(c_array, size, max, pool, new_max) DN_CArray2_ResizeFromPool((void **)&(c_array), size, max, sizeof((c_array)[0]), pool, new_max)
|
||||
|
@ -78,11 +78,11 @@ DN_API DN_Str8 DN_CVT_BytesToHex (DN_Arena
|
||||
#define DN_CVT_BytesToHexFromTLS(...) DN_CVT_BytesToHex(DN_OS_TLSTopArena(), __VA_ARGS__)
|
||||
#define DN_CVT_BytesToHexFromFrame(...) DN_CVT_BytesToHex(DN_OS_TLSFrameArena(), __VA_ARGS__)
|
||||
|
||||
DN_API DN_USize DN_CVT_HexToBytesPtrUnchecked (DN_Str8 hex, void *dest, DN_USize dest_size);
|
||||
DN_API DN_USize DN_CVT_HexToBytesPtr (DN_Str8 hex, void *dest, DN_USize dest_size);
|
||||
DN_API DN_Str8 DN_CVT_HexToBytesUnchecked (DN_Arena *arena, DN_Str8 hex);
|
||||
#define DN_CVT_HexToBytesUncheckedFromTLS(...) DN_CVT_HexToBytesUnchecked(DN_OS_TLSTopArena(), __VA_ARGS__)
|
||||
DN_API DN_Str8 DN_CVT_HexToBytes (DN_Arena *arena, DN_Str8 hex);
|
||||
#define DN_CVT_HexToBytesFromFrame(...) DN_CVT_HexToBytes(DN_OS_TLSFrameArena(), __VA_ARGS__)
|
||||
#define DN_CVT_HexToBytesFromTLS(...) DN_CVT_HexToBytes(DN_OS_TLSTopArena(), __VA_ARGS__)
|
||||
DN_API DN_USize DN_CVT_HexToBytesPtrUnchecked (DN_Str8 hex, void *dest, DN_USize dest_size);
|
||||
DN_API DN_USize DN_CVT_HexToBytesPtr (DN_Str8 hex, void *dest, DN_USize dest_size);
|
||||
DN_API DN_Str8 DN_CVT_HexToBytesUnchecked (DN_Arena *arena, DN_Str8 hex);
|
||||
#define DN_CVT_HexToBytesUncheckedFromTLS(...) DN_CVT_HexToBytesUnchecked(DN_OS_TLSTopArena(), __VA_ARGS__)
|
||||
DN_API DN_Str8 DN_CVT_HexToBytes (DN_Arena *arena, DN_Str8 hex);
|
||||
#define DN_CVT_HexToBytesFromFrame(...) DN_CVT_HexToBytes(DN_OS_TLSFrameArena(), __VA_ARGS__)
|
||||
#define DN_CVT_HexToBytesFromTLS(...) DN_CVT_HexToBytes(DN_OS_TLSTopArena(), __VA_ARGS__)
|
||||
#endif // defined(DN_BASE_CONVERT_H)
|
||||
|
@ -1,6 +1,6 @@
|
||||
#define DN_BASE_LOG_CPP
|
||||
|
||||
#include "../dn_clangd.h"
|
||||
#include "../dn_base_inc.h"
|
||||
|
||||
static DN_LOGEmitFromTypeFVFunc *g_dn_base_log_emit_from_type_fv_func_;
|
||||
static void *g_dn_base_log_emit_from_type_fv_user_context_;
|
||||
|
@ -1,6 +1,8 @@
|
||||
#if !defined(DN_BASE_LOG_H)
|
||||
#define DN_BASE_LOG_H
|
||||
|
||||
#include "../dn_base_inc.h"
|
||||
|
||||
enum DN_LOGType
|
||||
{
|
||||
DN_LOGType_Debug,
|
||||
@ -67,6 +69,4 @@ DN_API DN_LOGTypeParam DN_LOG_MakeU32LogTypeParam (DN_LOGType type);
|
||||
#define DN_LOG_InfoF(fmt, ...) DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Info), DN_CALL_SITE, fmt, ##__VA_ARGS__)
|
||||
#define DN_LOG_WarningF(fmt, ...) DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Warning), DN_CALL_SITE, fmt, ##__VA_ARGS__)
|
||||
#define DN_LOG_ErrorF(fmt, ...) DN_LOG_EmitFromType(DN_LOG_MakeU32LogTypeParam(DN_LOGType_Error), DN_CALL_SITE, fmt, ##__VA_ARGS__)
|
||||
|
||||
|
||||
#endif // !defined(DN_BASE_LOG_H)
|
||||
|
@ -46,7 +46,7 @@ static DN_ArenaBlock *DN_Arena_BlockInitFromMemFuncs_(DN_U64 reserve, DN_U64 com
|
||||
}
|
||||
|
||||
if (track_alloc && result)
|
||||
DN_Debug_TrackAlloc(result, result->reserve, alloc_can_leak);
|
||||
DN_DBGTrackAlloc(result, result->reserve, alloc_can_leak);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -57,7 +57,7 @@ static DN_ArenaBlock *DN_Arena_BlockInitFlagsFromMemFuncs_(DN_U64 reserve, DN_U6
|
||||
bool alloc_can_leak = flags & DN_ArenaFlags_AllocCanLeak;
|
||||
DN_ArenaBlock *result = DN_Arena_BlockInitFromMemFuncs_(reserve, commit, track_alloc, alloc_can_leak, mem_funcs);
|
||||
if (result && ((flags & DN_ArenaFlags_NoPoison) == 0))
|
||||
DN_ASAN_PoisonMemoryRegion(DN_CAST(char *) result + DN_ARENA_HEADER_SIZE, result->commit - DN_ARENA_HEADER_SIZE);
|
||||
DN_ASanPoisonMemoryRegion(DN_CAST(char *) result + DN_ARENA_HEADER_SIZE, result->commit - DN_ARENA_HEADER_SIZE);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -89,7 +89,7 @@ DN_API DN_Arena DN_Arena_InitFromBuffer(void *buffer, DN_USize size, DN_ArenaFla
|
||||
block->reserve = size;
|
||||
block->used = DN_ARENA_HEADER_SIZE;
|
||||
if (block && ((flags & DN_ArenaFlags_NoPoison) == 0))
|
||||
DN_ASAN_PoisonMemoryRegion(DN_CAST(char *) block + DN_ARENA_HEADER_SIZE, block->commit - DN_ARENA_HEADER_SIZE);
|
||||
DN_ASanPoisonMemoryRegion(DN_CAST(char *) block + DN_ARENA_HEADER_SIZE, block->commit - DN_ARENA_HEADER_SIZE);
|
||||
|
||||
DN_Arena result = {};
|
||||
result.flags = flags | DN_ArenaFlags_NoGrow | DN_ArenaFlags_NoAllocTrack | DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_UserBuffer;
|
||||
@ -112,9 +112,9 @@ DN_API DN_Arena DN_Arena_InitFromMemFuncs(DN_U64 reserve, DN_U64 commit, DN_Aren
|
||||
static void DN_Arena_BlockDeinit_(DN_Arena const *arena, DN_ArenaBlock *block)
|
||||
{
|
||||
DN_USize release_size = block->reserve;
|
||||
if (DN_Bit_IsNotSet(arena->flags, DN_ArenaFlags_NoAllocTrack))
|
||||
DN_Debug_TrackDealloc(block);
|
||||
DN_ASAN_UnpoisonMemoryRegion(block, block->commit);
|
||||
if (DN_BitIsNotSet(arena->flags, DN_ArenaFlags_NoAllocTrack))
|
||||
DN_DBGTrackDealloc(block);
|
||||
DN_ASanUnpoisonMemoryRegion(block, block->commit);
|
||||
if (arena->flags & DN_ArenaFlags_MemFuncs) {
|
||||
if (arena->mem_funcs.type == DN_ArenaMemFuncType_Basic)
|
||||
arena->mem_funcs.basic_dealloc(block);
|
||||
@ -156,7 +156,7 @@ DN_API bool DN_Arena_CommitTo(DN_Arena *arena, DN_U64 pos)
|
||||
|
||||
bool poison = DN_ASAN_POISON && ((arena->flags & DN_ArenaFlags_NoPoison) == 0);
|
||||
if (poison)
|
||||
DN_ASAN_PoisonMemoryRegion(commit_ptr, commit_size);
|
||||
DN_ASanPoisonMemoryRegion(commit_ptr, commit_size);
|
||||
|
||||
curr->commit = end_commit;
|
||||
return true;
|
||||
@ -230,7 +230,7 @@ DN_API void *DN_Arena_Alloc(DN_Arena *arena, DN_U64 size, uint8_t align, DN_Zero
|
||||
if (!arena->mem_funcs.vmem_commit(commit_ptr, commit_size, DN_MemPage_ReadWrite))
|
||||
return nullptr;
|
||||
if (poison)
|
||||
DN_ASAN_PoisonMemoryRegion(commit_ptr, commit_size);
|
||||
DN_ASanPoisonMemoryRegion(commit_ptr, commit_size);
|
||||
curr->commit = end_commit;
|
||||
arena->stats.info.commit += commit_size;
|
||||
arena->stats.hwm.commit = DN_Max(arena->stats.hwm.commit, arena->stats.info.commit);
|
||||
@ -240,7 +240,7 @@ DN_API void *DN_Arena_Alloc(DN_Arena *arena, DN_U64 size, uint8_t align, DN_Zero
|
||||
curr->used += alloc_size;
|
||||
arena->stats.info.used += alloc_size;
|
||||
arena->stats.hwm.used = DN_Max(arena->stats.hwm.used, arena->stats.info.used);
|
||||
DN_ASAN_UnpoisonMemoryRegion(result, size);
|
||||
DN_ASanUnpoisonMemoryRegion(result, size);
|
||||
|
||||
if (zero_mem == DN_ZeroMem_Yes) {
|
||||
DN_USize reused_bytes = DN_Min(prev_arena_commit - offset_pos, size);
|
||||
@ -296,7 +296,7 @@ DN_API void DN_Arena_PopTo(DN_Arena *arena, DN_U64 init_used)
|
||||
curr->used = used - curr->reserve_sum;
|
||||
char *poison_ptr = (char *)curr + DN_AlignUpPowerOfTwo(curr->used, DN_ASAN_POISON_ALIGNMENT);
|
||||
DN_USize poison_size = ((char *)curr + curr->commit) - poison_ptr;
|
||||
DN_ASAN_PoisonMemoryRegion(poison_ptr, poison_size);
|
||||
DN_ASanPoisonMemoryRegion(poison_ptr, poison_size);
|
||||
arena->stats.info.used += curr->used;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#if !defined(DN_BASE_MEM_H)
|
||||
#define DN_BASE_MEM_H
|
||||
|
||||
#include "../dn_clangd.h"
|
||||
#include "../dn_base_inc.h"
|
||||
|
||||
enum DN_MemCommit
|
||||
{
|
||||
@ -146,32 +146,6 @@ struct DN_ArenaTempMemScope
|
||||
|
||||
DN_USize const DN_ARENA_HEADER_SIZE = DN_AlignUpPowerOfTwo(sizeof(DN_Arena), 64);
|
||||
|
||||
// NOTE: DN_Arena //////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_Arena DN_Arena_InitFromBuffer (void *buffer, DN_USize size, DN_ArenaFlags flags);
|
||||
DN_API DN_Arena DN_Arena_InitFromMemFuncs (DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags, DN_ArenaMemFuncs mem_funcs);
|
||||
DN_API void DN_Arena_Deinit (DN_Arena *arena);
|
||||
DN_API bool DN_Arena_Commit (DN_Arena *arena, DN_U64 size);
|
||||
DN_API bool DN_Arena_CommitTo (DN_Arena *arena, DN_U64 pos);
|
||||
DN_API bool DN_Arena_Grow (DN_Arena *arena, DN_U64 reserve, DN_U64 commit);
|
||||
DN_API void * DN_Arena_Alloc (DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZeroMem zero_mem);
|
||||
DN_API void * DN_Arena_AllocContiguous (DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZeroMem zero_mem);
|
||||
DN_API void * DN_Arena_Copy (DN_Arena *arena, void const *data, DN_U64 size, uint8_t align);
|
||||
DN_API void DN_Arena_PopTo (DN_Arena *arena, DN_U64 init_used);
|
||||
DN_API void DN_Arena_Pop (DN_Arena *arena, DN_U64 amount);
|
||||
DN_API DN_U64 DN_Arena_Pos (DN_Arena const *arena);
|
||||
DN_API void DN_Arena_Clear (DN_Arena *arena);
|
||||
DN_API bool DN_Arena_OwnsPtr (DN_Arena const *arena, void *ptr);
|
||||
DN_API DN_ArenaStats DN_Arena_SumStatsArray (DN_ArenaStats const *array, DN_USize size);
|
||||
DN_API DN_ArenaStats DN_Arena_SumStats (DN_ArenaStats lhs, DN_ArenaStats rhs);
|
||||
DN_API DN_ArenaStats DN_Arena_SumArenaArrayToStats (DN_Arena const *array, DN_USize size);
|
||||
DN_API DN_ArenaTempMem DN_Arena_TempMemBegin (DN_Arena *arena);
|
||||
DN_API void DN_Arena_TempMemEnd (DN_ArenaTempMem mem);
|
||||
#define DN_Arena_New_Frame(T, zero_mem) (T *)DN_Arena_Alloc(DN_OS_TLSGet()->frame_arena, sizeof(T), alignof(T), zero_mem)
|
||||
#define DN_Arena_New(arena, T, zero_mem) (T *)DN_Arena_Alloc(arena, sizeof(T), alignof(T), zero_mem)
|
||||
#define DN_Arena_NewArray(arena, T, count, zero_mem) (T *)DN_Arena_Alloc(arena, sizeof(T) * (count), alignof(T), zero_mem)
|
||||
#define DN_Arena_NewCopy(arena, T, src) (T *)DN_Arena_Copy (arena, (src), sizeof(T), alignof(T))
|
||||
#define DN_Arena_NewArrayCopy(arena, T, src, count) (T *)DN_Arena_Copy (arena, (src), sizeof(T) * (count), alignof(T))
|
||||
|
||||
#if !defined(DN_POOL_DEFAULT_ALIGN)
|
||||
#define DN_POOL_DEFAULT_ALIGN 16
|
||||
#endif
|
||||
@ -225,29 +199,42 @@ struct DN_Pool
|
||||
DN_U8 align;
|
||||
};
|
||||
|
||||
// NOTE: DN_Pool ///////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_Pool DN_Pool_Init (DN_Arena *arena, DN_U8 align);
|
||||
DN_API bool DN_Pool_IsValid (DN_Pool const *pool);
|
||||
DN_API void * DN_Pool_Alloc (DN_Pool *pool, DN_USize size);
|
||||
DN_API DN_Str8 DN_Pool_AllocStr8FV (DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API DN_Str8 DN_Pool_AllocStr8F (DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API DN_Str8 DN_Pool_AllocStr8Copy (DN_Pool *pool, DN_Str8 string);
|
||||
DN_API void DN_Pool_Dealloc (DN_Pool *pool, void *ptr);
|
||||
DN_API void * DN_Pool_Copy (DN_Pool *pool, void const *data, DN_U64 size, uint8_t align);
|
||||
DN_API DN_Arena DN_Arena_InitFromBuffer (void *buffer, DN_USize size, DN_ArenaFlags flags);
|
||||
DN_API DN_Arena DN_Arena_InitFromMemFuncs (DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags, DN_ArenaMemFuncs mem_funcs);
|
||||
DN_API void DN_Arena_Deinit (DN_Arena *arena);
|
||||
DN_API bool DN_Arena_Commit (DN_Arena *arena, DN_U64 size);
|
||||
DN_API bool DN_Arena_CommitTo (DN_Arena *arena, DN_U64 pos);
|
||||
DN_API bool DN_Arena_Grow (DN_Arena *arena, DN_U64 reserve, DN_U64 commit);
|
||||
DN_API void * DN_Arena_Alloc (DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZeroMem zero_mem);
|
||||
DN_API void * DN_Arena_AllocContiguous (DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZeroMem zero_mem);
|
||||
DN_API void * DN_Arena_Copy (DN_Arena *arena, void const *data, DN_U64 size, uint8_t align);
|
||||
DN_API void DN_Arena_PopTo (DN_Arena *arena, DN_U64 init_used);
|
||||
DN_API void DN_Arena_Pop (DN_Arena *arena, DN_U64 amount);
|
||||
DN_API DN_U64 DN_Arena_Pos (DN_Arena const *arena);
|
||||
DN_API void DN_Arena_Clear (DN_Arena *arena);
|
||||
DN_API bool DN_Arena_OwnsPtr (DN_Arena const *arena, void *ptr);
|
||||
DN_API DN_ArenaStats DN_Arena_SumStatsArray (DN_ArenaStats const *array, DN_USize size);
|
||||
DN_API DN_ArenaStats DN_Arena_SumStats (DN_ArenaStats lhs, DN_ArenaStats rhs);
|
||||
DN_API DN_ArenaStats DN_Arena_SumArenaArrayToStats (DN_Arena const *array, DN_USize size);
|
||||
DN_API DN_ArenaTempMem DN_Arena_TempMemBegin (DN_Arena *arena);
|
||||
DN_API void DN_Arena_TempMemEnd (DN_ArenaTempMem mem);
|
||||
#define DN_Arena_New_Frame(T, zero_mem) (T *)DN_Arena_Alloc(DN_OS_TLSGet()->frame_arena, sizeof(T), alignof(T), zero_mem)
|
||||
#define DN_Arena_New(arena, T, zero_mem) (T *)DN_Arena_Alloc(arena, sizeof(T), alignof(T), zero_mem)
|
||||
#define DN_Arena_NewArray(arena, T, count, zero_mem) (T *)DN_Arena_Alloc(arena, sizeof(T) * (count), alignof(T), zero_mem)
|
||||
#define DN_Arena_NewCopy(arena, T, src) (T *)DN_Arena_Copy (arena, (src), sizeof(T), alignof(T))
|
||||
#define DN_Arena_NewArrayCopy(arena, T, src, count) (T *)DN_Arena_Copy (arena, (src), sizeof(T) * (count), alignof(T))
|
||||
|
||||
#define DN_Pool_New(pool, T) (T *)DN_Pool_Alloc(pool, sizeof(T))
|
||||
#define DN_Pool_NewArray(pool, T, count) (T *)DN_Pool_Alloc(pool, count * sizeof(T))
|
||||
#define DN_Pool_NewCopy(arena, T, src) (T *)DN_Pool_Copy (arena, (src), sizeof(T), alignof(T))
|
||||
#define DN_Pool_NewArrayCopy(arena, T, src, count) (T *)DN_Pool_Copy (arena, (src), sizeof(T) * (count), alignof(T))
|
||||
DN_API DN_Pool DN_Pool_Init (DN_Arena *arena, DN_U8 align);
|
||||
DN_API bool DN_Pool_IsValid (DN_Pool const *pool);
|
||||
DN_API void * DN_Pool_Alloc (DN_Pool *pool, DN_USize size);
|
||||
DN_API DN_Str8 DN_Pool_AllocStr8FV (DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||
DN_API DN_Str8 DN_Pool_AllocStr8F (DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, ...);
|
||||
DN_API DN_Str8 DN_Pool_AllocStr8Copy (DN_Pool *pool, DN_Str8 string);
|
||||
DN_API void DN_Pool_Dealloc (DN_Pool *pool, void *ptr);
|
||||
DN_API void * DN_Pool_Copy (DN_Pool *pool, void const *data, DN_U64 size, uint8_t align);
|
||||
|
||||
// NOTE: DN_Debug //////////////////////////////////////////////////////////////////////////////////
|
||||
#if defined(DN_LEAK_TRACKING) && !defined(DN_FREESTANDING)
|
||||
DN_API void DN_Debug_TrackAlloc (void *ptr, DN_USize size, bool alloc_can_leak);
|
||||
DN_API void DN_Debug_TrackDealloc(void *ptr);
|
||||
DN_API void DN_Debug_DumpLeaks ();
|
||||
#else
|
||||
#define DN_Debug_TrackAlloc(ptr, size, alloc_can_leak) do { (void)ptr; (void)size; (void)alloc_can_leak; } while (0)
|
||||
#define DN_Debug_TrackDealloc(ptr) do { (void)ptr; } while (0)
|
||||
#define DN_Debug_DumpLeaks() do { } while (0)
|
||||
#endif
|
||||
#define DN_Pool_New(pool, T) (T *)DN_Pool_Alloc(pool, sizeof(T))
|
||||
#define DN_Pool_NewArray(pool, T, count) (T *)DN_Pool_Alloc(pool, count * sizeof(T))
|
||||
#define DN_Pool_NewCopy(arena, T, src) (T *)DN_Pool_Copy (arena, (src), sizeof(T), alignof(T))
|
||||
#define DN_Pool_NewArrayCopy(arena, T, src, count) (T *)DN_Pool_Copy (arena, (src), sizeof(T) * (count), alignof(T))
|
||||
#endif // !defined(DN_BASE_MEM_H)
|
||||
|
@ -1,6 +1,8 @@
|
||||
#if !defined(DN_BASE_OS_H)
|
||||
#define DN_BASE_OS_H
|
||||
|
||||
#include "../dn_base_inc.h"
|
||||
|
||||
// NOTE: OS primitives that the OS layer can provide for the base layer but is optional.
|
||||
|
||||
struct DN_StackTraceFrame
|
||||
@ -30,7 +32,19 @@ struct DN_StackTraceWalkResultIterator
|
||||
DN_U16 index;
|
||||
};
|
||||
|
||||
DN_API DN_Str8 DN_StackTrace_WalkStr8FromHeap (DN_U16 limit, DN_U16 skip);
|
||||
|
||||
#if defined(DN_FREESTANDING)
|
||||
#define DN_StackTrace_WalkStr8FromHeap(...) DN_STR8("N/A")
|
||||
#define DN_StackTrace_Walk(...)
|
||||
#define DN_StackTrace_WalkResultIterate(...)
|
||||
#define DN_StackTrace_WalkResultToStr8(...) DN_STR8("N/A")
|
||||
#define DN_StackTrace_WalkStr8(...) DN_STR8("N/A")
|
||||
#define DN_StackTrace_WalkStr8FromHeap(...) DN_STR8("N/A")
|
||||
#define DN_StackTrace_GetFrames(...)
|
||||
#define DN_StackTrace_RawFrameToFrame(...)
|
||||
#define DN_StackTrace_Print(...)
|
||||
#define DN_StackTrace_ReloadSymbols(...)
|
||||
#else
|
||||
DN_API DN_StackTraceWalkResult DN_StackTrace_Walk (struct DN_Arena *arena, DN_U16 limit);
|
||||
DN_API bool DN_StackTrace_WalkResultIterate(DN_StackTraceWalkResultIterator *it, DN_StackTraceWalkResult const *walk);
|
||||
DN_API DN_Str8 DN_StackTrace_WalkResultToStr8 (struct DN_Arena *arena, DN_StackTraceWalkResult const *walk, DN_U16 skip);
|
||||
@ -40,7 +54,5 @@ DN_API DN_Slice<DN_StackTraceFrame> DN_StackTrace_GetFrames (struct DN_Ar
|
||||
DN_API DN_StackTraceFrame DN_StackTrace_RawFrameToFrame (struct DN_Arena *arena, DN_StackTraceRawFrame raw_frame);
|
||||
DN_API void DN_StackTrace_Print (DN_U16 limit);
|
||||
DN_API void DN_StackTrace_ReloadSymbols ();
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif // !defined(DN_BASE_OS_H)
|
||||
|
@ -542,9 +542,9 @@ DN_API DN_Str8ToU64Result DN_Str8_ToU64(DN_Str8 string, char separator)
|
||||
if (!DN_Char_IsDigit(ch))
|
||||
return result;
|
||||
|
||||
result.value = DN_Safe_MulU64(result.value, 10);
|
||||
result.value = DN_SafeMulU64(result.value, 10);
|
||||
uint64_t digit = ch - '0';
|
||||
result.value = DN_Safe_AddU64(result.value, digit);
|
||||
result.value = DN_SafeAddU64(result.value, digit);
|
||||
}
|
||||
|
||||
result.success = true;
|
||||
@ -587,9 +587,9 @@ DN_API DN_Str8ToI64Result DN_Str8_ToI64(DN_Str8 string, char separator)
|
||||
if (!DN_Char_IsDigit(ch))
|
||||
return result;
|
||||
|
||||
result.value = DN_Safe_MulU64(result.value, 10);
|
||||
result.value = DN_SafeMulU64(result.value, 10);
|
||||
uint64_t digit = ch - '0';
|
||||
result.value = DN_Safe_AddU64(result.value, digit);
|
||||
result.value = DN_SafeAddU64(result.value, digit);
|
||||
}
|
||||
|
||||
if (negative)
|
||||
|
@ -18,24 +18,6 @@ DN_MSVC_WARNING_POP
|
||||
#define DN_VSPrintF(...) STB_SPRINTF_DECORATE(vsprintf)(__VA_ARGS__)
|
||||
#define DN_VSNPrintF(...) STB_SPRINTF_DECORATE(vsnprintf)(__VA_ARGS__)
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// $$$$$$\ $$$$$$$$\ $$$$$$$\ $$$$$$\ $$\ $$\ $$$$$$\
|
||||
// $$ __$$\\__$$ __|$$ __$$\ \_$$ _|$$$\ $$ |$$ __$$\
|
||||
// $$ / \__| $$ | $$ | $$ | $$ | $$$$\ $$ |$$ / \__|
|
||||
// \$$$$$$\ $$ | $$$$$$$ | $$ | $$ $$\$$ |$$ |$$$$\
|
||||
// \____$$\ $$ | $$ __$$< $$ | $$ \$$$$ |$$ |\_$$ |
|
||||
// $$\ $$ | $$ | $$ | $$ | $$ | $$ |\$$$ |$$ | $$ |
|
||||
// \$$$$$$ | $$ | $$ | $$ |$$$$$$\ $$ | \$$ |\$$$$$$ |
|
||||
// \______/ \__| \__| \__|\______|\__| \__| \______/
|
||||
//
|
||||
// dn_base_string.h
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
// NOTE: DN_Str8 //////////////////////////////////////////////////////////////////////////////////
|
||||
struct DN_Str8Link
|
||||
{
|
||||
DN_Str8 string; // The string
|
||||
@ -105,7 +87,6 @@ struct DN_Str8DotTruncateResult
|
||||
DN_Str8 str8;
|
||||
};
|
||||
|
||||
// NOTE: DN_FStr8 //////////////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DN_NO_FSTR8)
|
||||
template <DN_USize N>
|
||||
struct DN_FStr8
|
||||
|
@ -71,7 +71,7 @@ DN_API void DN_Core_Init(DN_Core *core, DN_CoreOnInit on_init)
|
||||
|
||||
for (DN_ForIndexU(feature_index, DN_CPUFeature_Count)) {
|
||||
DN_CPUFeatureDecl feature_decl = g_dn_cpu_feature_decl[feature_index];
|
||||
bool has_feature = DN_CPU_HasFeature(report, feature_decl.value);
|
||||
bool has_feature = DN_CPUHasFeature(report, feature_decl.value);
|
||||
DN_Str8Builder_AppendF(&builder,
|
||||
" %.*s:%*s%s\n",
|
||||
DN_STR_FMT(feature_decl.label),
|
||||
@ -88,7 +88,7 @@ DN_API void DN_Core_Init(DN_Core *core, DN_CoreOnInit on_init)
|
||||
|
||||
DN_API void DN_Core_BeginFrame()
|
||||
{
|
||||
DN_Atomic_SetValue64(&g_dn_os_core_->mem_allocs_frame, 0);
|
||||
DN_AtomicSetValue64(&g_dn_os_core_->mem_allocs_frame, 0);
|
||||
}
|
||||
|
||||
#if !defined(DN_NO_PROFILER)
|
||||
|
@ -1,5 +1,8 @@
|
||||
#define DN_CORE_DEBUG_CPP
|
||||
|
||||
#include "../dn_base_inc.h"
|
||||
#include "../dn_os_inc.h"
|
||||
|
||||
DN_API DN_StackTraceWalkResult DN_StackTrace_Walk(DN_Arena *arena, uint16_t limit)
|
||||
{
|
||||
DN_StackTraceWalkResult result = {};
|
||||
@ -209,7 +212,7 @@ DN_API void DN_StackTrace_ReloadSymbols()
|
||||
|
||||
// NOTE: DN_Debug //////////////////////////////////////////////////////////////////////////////////
|
||||
#if defined(DN_LEAK_TRACKING)
|
||||
DN_API void DN_Debug_TrackAlloc(void *ptr, DN_USize size, bool leak_permitted)
|
||||
DN_API void DN_DBGTrackAlloc(void *ptr, DN_USize size, bool leak_permitted)
|
||||
{
|
||||
if (!ptr)
|
||||
return;
|
||||
@ -236,7 +239,7 @@ DN_API void DN_Debug_TrackAlloc(void *ptr, DN_USize size, bool leak_permitted)
|
||||
"This pointer is already in the leak tracker, however it has not been freed yet. This "
|
||||
"same pointer is being ask to be tracked twice in the allocation table, e.g. one if its "
|
||||
"previous free calls has not being marked freed with an equivalent call to "
|
||||
"DN_Debug_TrackDealloc()\n"
|
||||
"DN_DBGTrackDealloc()\n"
|
||||
"\n"
|
||||
"The pointer (0x%p) originally allocated %.*s at:\n"
|
||||
"\n"
|
||||
@ -268,7 +271,7 @@ DN_API void DN_Debug_TrackAlloc(void *ptr, DN_USize size, bool leak_permitted)
|
||||
g_dn_core->alloc_table_bytes_allocated_for_stack_traces += alloc->stack_trace.size;
|
||||
}
|
||||
|
||||
DN_API void DN_Debug_TrackDealloc(void *ptr)
|
||||
DN_API void DN_DBGTrackDealloc(void *ptr)
|
||||
{
|
||||
if (!ptr)
|
||||
return;
|
||||
@ -317,7 +320,7 @@ DN_API void DN_Debug_TrackDealloc(void *ptr)
|
||||
g_dn_core->alloc_table_bytes_allocated_for_stack_traces += alloc->freed_stack_trace.size;
|
||||
}
|
||||
|
||||
DN_API void DN_Debug_DumpLeaks()
|
||||
DN_API void DN_DBGDumpLeaks()
|
||||
{
|
||||
uint64_t leak_count = 0;
|
||||
uint64_t leaked_bytes = 0;
|
||||
@ -383,7 +386,7 @@ DN_API DN_ProfilerZone DN_Profiler_BeginZoneAtIndex(DN_Str8 name, uint16_t ancho
|
||||
#endif
|
||||
anchor->name = name;
|
||||
DN_ProfilerZone result = {};
|
||||
result.begin_tsc = DN_CPU_TSC();
|
||||
result.begin_tsc = DN_CPUGetTSC();
|
||||
result.anchor_index = anchor_index;
|
||||
result.parent_zone = g_dn_core->profiler->parent_zone;
|
||||
result.elapsed_tsc_at_zone_start = anchor->tsc_inclusive;
|
||||
@ -393,7 +396,7 @@ DN_API DN_ProfilerZone DN_Profiler_BeginZoneAtIndex(DN_Str8 name, uint16_t ancho
|
||||
|
||||
DN_API void DN_Profiler_EndZone(DN_ProfilerZone zone)
|
||||
{
|
||||
uint64_t elapsed_tsc = DN_CPU_TSC() - zone.begin_tsc;
|
||||
uint64_t elapsed_tsc = DN_CPUGetTSC() - zone.begin_tsc;
|
||||
DN_ProfilerAnchor *anchor_buffer = DN_Profiler_WriteBuffer();
|
||||
DN_ProfilerAnchor *anchor = anchor_buffer + zone.anchor_index;
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
#if !defined(DN_CORE_DEBUG_H)
|
||||
#define DN_CORE_DEBUG_H
|
||||
|
||||
#include "../dn_base_inc.h"
|
||||
|
||||
// NOTE: DN_StackTrace /////////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: DN_Debug //////////////////////////////////////////////////////////////////////////////////
|
||||
enum DN_DebugAllocFlag
|
||||
@ -93,6 +95,16 @@ DN_API void DN_Profiler_EndZone (DN_ProfilerZ
|
||||
DN_API DN_ProfilerAnchor * DN_Profiler_AnchorBuffer (DN_ProfilerAnchorBuffer buffer);
|
||||
DN_API void DN_Profiler_SwapAnchorBuffer ();
|
||||
DN_API void DN_Profiler_Dump (DN_U64 tsc_per_second);
|
||||
|
||||
#endif // !defined(DN_NO_PROFILER)
|
||||
|
||||
|
||||
#if defined(DN_LEAK_TRACKING)
|
||||
DN_API void DN_DBGTrackAlloc (void *ptr, DN_USize size, bool alloc_can_leak);
|
||||
DN_API void DN_DBGTrackDealloc (void *ptr);
|
||||
DN_API void DN_DBGDumpLeaks ();
|
||||
#else
|
||||
#define DN_DBGTrackAlloc(ptr, size, alloc_can_leak) do { (void)ptr; (void)size; (void)alloc_can_leak; } while (0)
|
||||
#define DN_DBGTrackDealloc(ptr) do { (void)ptr; } while (0)
|
||||
#define DN_DBGDumpLeaks() do { } while (0)
|
||||
#endif
|
||||
#endif // DN_CORE_DEBUG_H
|
||||
|
@ -39,15 +39,15 @@ void DN_Docs_Demo()
|
||||
DN_Core_Init(&core, DN_CoreOnInit_Nil);
|
||||
#endif
|
||||
|
||||
// NOTE: DN_Atomic_SetValue64 /////////////////////////////////////////////////////////////////
|
||||
// NOTE: DN_Atomic_SetValue32 /////////////////////////////////////////////////////////////////
|
||||
// NOTE: DN_AtomicSetValue64 /////////////////////////////////////////////////////////////////
|
||||
// NOTE: DN_AtomicSetValue32 /////////////////////////////////////////////////////////////////
|
||||
// Atomically set the value into the target using an atomic compare and swap
|
||||
// idiom. The return value of the function is the value that was last stored
|
||||
// in the target.
|
||||
{
|
||||
uint64_t target = 8;
|
||||
uint64_t value_to_set = 0xCAFE;
|
||||
if (DN_Atomic_SetValue64(&target, value_to_set) == 8) {
|
||||
if (DN_AtomicSetValue64(&target, value_to_set) == 8) {
|
||||
// Atomic swap was successful, e.g. the last value that this thread
|
||||
// observed was '8' which is the value we initialised with e.g. no
|
||||
// other thread has modified the value.
|
||||
|
@ -27,9 +27,9 @@ static DN_I32 DN_ASYNC_ThreadEntryPoint_(DN_OSThread *thread)
|
||||
args.input = task.work.input;
|
||||
args.thread = thread;
|
||||
|
||||
DN_Atomic_AddU32(&async->busy_threads, 1);
|
||||
DN_AtomicAddU32(&async->busy_threads, 1);
|
||||
task.work.func(args);
|
||||
DN_Atomic_SubU32(&async->busy_threads, 1);
|
||||
DN_AtomicSubU32(&async->busy_threads, 1);
|
||||
|
||||
if (task.completion_sem.handle != 0)
|
||||
DN_OS_SemaphoreIncrement(&task.completion_sem, 1);
|
||||
@ -59,7 +59,7 @@ DN_API void DN_ASYNC_Init(DN_ASYNCCore *async, char *base, DN_USize base_size, D
|
||||
DN_API void DN_ASYNC_Deinit(DN_ASYNCCore *async)
|
||||
{
|
||||
DN_Assert(async);
|
||||
DN_Atomic_SetValue32(&async->join_threads, true);
|
||||
DN_AtomicSetValue32(&async->join_threads, true);
|
||||
DN_OS_SemaphoreIncrement(&async->worker_sem, async->thread_count);
|
||||
for (DN_ForItSize(it, DN_OSThread, async->threads, async->thread_count))
|
||||
DN_OS_ThreadDeinit(it.data);
|
||||
|
@ -314,9 +314,9 @@ DN_API int32_t DN_OS_JobQueueSPMCThread(DN_OSThread *thread)
|
||||
queue->read_index += 1;
|
||||
DN_OS_MutexUnlock(&queue->mutex);
|
||||
|
||||
job.elapsed_tsc -= DN_CPU_TSC();
|
||||
job.elapsed_tsc -= DN_CPUGetTSC();
|
||||
job.func(thread, job.user_context);
|
||||
job.elapsed_tsc += DN_CPU_TSC();
|
||||
job.elapsed_tsc += DN_CPUGetTSC();
|
||||
|
||||
if (job.add_to_completion_queue) {
|
||||
DN_OS_SemaphoreWait(&queue->complete_queue_write_semaphore, DN_OS_SEMAPHORE_INFINITE_TIMEOUT);
|
||||
|
@ -244,63 +244,63 @@ static DN_UTCore DN_Tests_Base()
|
||||
DN_UT_LogF(&result, "DN_Base\n");
|
||||
{
|
||||
for (DN_UT_Test(&result, "Query CPUID")) {
|
||||
DN_CPUReport cpu_report = DN_CPU_Report();
|
||||
DN_CPUReport cpu_report = DN_CPUGetReport();
|
||||
|
||||
// NOTE: Sanity check our report against MSDN's example ////////////////////////////////////////
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_3DNow) == ref_cpu_report._3DNOW());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_3DNowExt) == ref_cpu_report._3DNOWEXT());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_ABM) == ref_cpu_report.ABM());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_AES) == ref_cpu_report.AES());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_AVX) == ref_cpu_report.AVX());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_AVX2) == ref_cpu_report.AVX2());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_AVX512CD) == ref_cpu_report.AVX512CD());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_AVX512ER) == ref_cpu_report.AVX512ER());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_AVX512F) == ref_cpu_report.AVX512F());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_AVX512PF) == ref_cpu_report.AVX512PF());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_CMPXCHG16B) == ref_cpu_report.CMPXCHG16B());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_F16C) == ref_cpu_report.F16C());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_FMA) == ref_cpu_report.FMA());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_MMX) == ref_cpu_report.MMX());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_MmxExt) == ref_cpu_report.MMXEXT());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_MONITOR) == ref_cpu_report.MONITOR());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_MOVBE) == ref_cpu_report.MOVBE());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_PCLMULQDQ) == ref_cpu_report.PCLMULQDQ());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_POPCNT) == ref_cpu_report.POPCNT());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_RDRAND) == ref_cpu_report.RDRAND());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_RDSEED) == ref_cpu_report.RDSEED());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_RDTSCP) == ref_cpu_report.RDTSCP());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_SHA) == ref_cpu_report.SHA());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_SSE) == ref_cpu_report.SSE());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_SSE2) == ref_cpu_report.SSE2());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_SSE3) == ref_cpu_report.SSE3());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_SSE41) == ref_cpu_report.SSE41());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_SSE42) == ref_cpu_report.SSE42());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_SSE4A) == ref_cpu_report.SSE4a());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_SSSE3) == ref_cpu_report.SSSE3());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_3DNow) == ref_cpu_report._3DNOW());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_3DNowExt) == ref_cpu_report._3DNOWEXT());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_ABM) == ref_cpu_report.ABM());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_AES) == ref_cpu_report.AES());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_AVX) == ref_cpu_report.AVX());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_AVX2) == ref_cpu_report.AVX2());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_AVX512CD) == ref_cpu_report.AVX512CD());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_AVX512ER) == ref_cpu_report.AVX512ER());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_AVX512F) == ref_cpu_report.AVX512F());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_AVX512PF) == ref_cpu_report.AVX512PF());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_CMPXCHG16B) == ref_cpu_report.CMPXCHG16B());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_F16C) == ref_cpu_report.F16C());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_FMA) == ref_cpu_report.FMA());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_MMX) == ref_cpu_report.MMX());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_MmxExt) == ref_cpu_report.MMXEXT());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_MONITOR) == ref_cpu_report.MONITOR());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_MOVBE) == ref_cpu_report.MOVBE());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_PCLMULQDQ) == ref_cpu_report.PCLMULQDQ());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_POPCNT) == ref_cpu_report.POPCNT());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_RDRAND) == ref_cpu_report.RDRAND());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_RDSEED) == ref_cpu_report.RDSEED());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_RDTSCP) == ref_cpu_report.RDTSCP());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_SHA) == ref_cpu_report.SHA());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_SSE) == ref_cpu_report.SSE());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_SSE2) == ref_cpu_report.SSE2());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_SSE3) == ref_cpu_report.SSE3());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_SSE41) == ref_cpu_report.SSE41());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_SSE42) == ref_cpu_report.SSE42());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_SSE4A) == ref_cpu_report.SSE4a());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_SSSE3) == ref_cpu_report.SSSE3());
|
||||
|
||||
// NOTE: Feature flags we haven't bothered detecting yet but are in MSDN's example /////////////
|
||||
#if 0
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_ADX) == DN_RefImplCPUReport::ADX());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_BMI1) == DN_RefImplCPUReport::BMI1());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_BMI2) == DN_RefImplCPUReport::BMI2());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_CLFSH) == DN_RefImplCPUReport::CLFSH());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_CX8) == DN_RefImplCPUReport::CX8());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_ERMS) == DN_RefImplCPUReport::ERMS());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_FSGSBASE) == DN_RefImplCPUReport::FSGSBASE());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_FXSR) == DN_RefImplCPUReport::FXSR());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_HLE) == DN_RefImplCPUReport::HLE());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_INVPCID) == DN_RefImplCPUReport::INVPCID());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_LAHF) == DN_RefImplCPUReport::LAHF());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_LZCNT) == DN_RefImplCPUReport::LZCNT());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_MSR) == DN_RefImplCPUReport::MSR());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_OSXSAVE) == DN_RefImplCPUReport::OSXSAVE());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_PREFETCHWT1) == DN_RefImplCPUReport::PREFETCHWT1());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_RTM) == DN_RefImplCPUReport::RTM());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_SEP) == DN_RefImplCPUReport::SEP());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_SYSCALL) == DN_RefImplCPUReport::SYSCALL());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_TBM) == DN_RefImplCPUReport::TBM());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_XOP) == DN_RefImplCPUReport::XOP());
|
||||
DN_UT_Assert(&result, DN_CPU_HasFeature(&cpu_report, DN_CPUFeature_XSAVE) == DN_RefImplCPUReport::XSAVE());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_ADX) == DN_RefImplCPUReport::ADX());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_BMI1) == DN_RefImplCPUReport::BMI1());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_BMI2) == DN_RefImplCPUReport::BMI2());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_CLFSH) == DN_RefImplCPUReport::CLFSH());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_CX8) == DN_RefImplCPUReport::CX8());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_ERMS) == DN_RefImplCPUReport::ERMS());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_FSGSBASE) == DN_RefImplCPUReport::FSGSBASE());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_FXSR) == DN_RefImplCPUReport::FXSR());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_HLE) == DN_RefImplCPUReport::HLE());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_INVPCID) == DN_RefImplCPUReport::INVPCID());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_LAHF) == DN_RefImplCPUReport::LAHF());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_LZCNT) == DN_RefImplCPUReport::LZCNT());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_MSR) == DN_RefImplCPUReport::MSR());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_OSXSAVE) == DN_RefImplCPUReport::OSXSAVE());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_PREFETCHWT1) == DN_RefImplCPUReport::PREFETCHWT1());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_RTM) == DN_RefImplCPUReport::RTM());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_SEP) == DN_RefImplCPUReport::SEP());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_SYSCALL) == DN_RefImplCPUReport::SYSCALL());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_TBM) == DN_RefImplCPUReport::TBM());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_XOP) == DN_RefImplCPUReport::XOP());
|
||||
DN_UT_Assert(&result, DN_CPUHasFeature(&cpu_report, DN_CPUFeature_XSAVE) == DN_RefImplCPUReport::XSAVE());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -1371,46 +1371,46 @@ static DN_UTCore DN_Tests_Intrinsics()
|
||||
|
||||
DN_UT_LogF(&result, "DN_Atomic\n");
|
||||
{
|
||||
for (DN_UT_Test(&result, "DN_Atomic_AddU32")) {
|
||||
for (DN_UT_Test(&result, "DN_AtomicAddU32")) {
|
||||
uint32_t val = 0;
|
||||
DN_Atomic_AddU32(&val, 1);
|
||||
DN_AtomicAddU32(&val, 1);
|
||||
DN_UT_AssertF(&result, val == 1, "val: %u", val);
|
||||
}
|
||||
|
||||
for (DN_UT_Test(&result, "DN_Atomic_AddU64")) {
|
||||
for (DN_UT_Test(&result, "DN_AtomicAddU64")) {
|
||||
uint64_t val = 0;
|
||||
DN_Atomic_AddU64(&val, 1);
|
||||
DN_AtomicAddU64(&val, 1);
|
||||
DN_UT_AssertF(&result, val == 1, "val: %" PRIu64, val);
|
||||
}
|
||||
|
||||
for (DN_UT_Test(&result, "DN_Atomic_SubU32")) {
|
||||
for (DN_UT_Test(&result, "DN_AtomicSubU32")) {
|
||||
uint32_t val = 1;
|
||||
DN_Atomic_SubU32(&val, 1);
|
||||
DN_AtomicSubU32(&val, 1);
|
||||
DN_UT_AssertF(&result, val == 0, "val: %u", val);
|
||||
}
|
||||
|
||||
for (DN_UT_Test(&result, "DN_Atomic_SubU64")) {
|
||||
for (DN_UT_Test(&result, "DN_AtomicSubU64")) {
|
||||
uint64_t val = 1;
|
||||
DN_Atomic_SubU64(&val, 1);
|
||||
DN_AtomicSubU64(&val, 1);
|
||||
DN_UT_AssertF(&result, val == 0, "val: %" PRIu64, val);
|
||||
}
|
||||
|
||||
for (DN_UT_Test(&result, "DN_Atomic_SetValue32")) {
|
||||
for (DN_UT_Test(&result, "DN_AtomicSetValue32")) {
|
||||
DN_U32 a = 0;
|
||||
DN_U32 b = 111;
|
||||
DN_Atomic_SetValue32(&a, b);
|
||||
DN_AtomicSetValue32(&a, b);
|
||||
DN_UT_AssertF(&result, a == b, "a: %ld, b: %ld", a, b);
|
||||
}
|
||||
|
||||
for (DN_UT_Test(&result, "DN_Atomic_SetValue64")) {
|
||||
for (DN_UT_Test(&result, "DN_AtomicSetValue64")) {
|
||||
int64_t a = 0;
|
||||
int64_t b = 111;
|
||||
DN_Atomic_SetValue64(DN_CAST(uint64_t *) & a, b);
|
||||
DN_AtomicSetValue64(DN_CAST(uint64_t *) & a, b);
|
||||
DN_UT_AssertF(&result, a == b, "a: %" PRId64 ", b: %" PRId64, a, b);
|
||||
}
|
||||
|
||||
DN_UT_BeginF(&result, "DN_CPU_TSC");
|
||||
DN_CPU_TSC();
|
||||
DN_UT_BeginF(&result, "DN_CPUGetTSC");
|
||||
DN_CPUGetTSC();
|
||||
DN_UT_End(&result);
|
||||
|
||||
DN_UT_BeginF(&result, "DN_CompilerReadBarrierAndCPUReadFence");
|
||||
|
@ -158,7 +158,7 @@ DN_API void DN_OS_Init(DN_OSCore *os, DN_OSInitArgs *args)
|
||||
|
||||
DN_OS_TLSInit(&os->tls, tls_init_args);
|
||||
DN_OS_TLSSetCurrentThreadTLS(&os->tls);
|
||||
os->cpu_report = DN_CPU_Report();
|
||||
os->cpu_report = DN_CPUGetReport();
|
||||
|
||||
#define DN_CPU_FEAT_XENTRY(label) g_dn_cpu_feature_decl[DN_CPUFeature_##label] = {DN_CPUFeature_##label, DN_STR8(#label)};
|
||||
DN_CPU_FEAT_XMACRO
|
||||
@ -376,13 +376,13 @@ DN_API uint64_t DN_OS_EstimateTSCPerSecond(uint64_t duration_ms_to_gauge_tsc_fre
|
||||
{
|
||||
uint64_t os_frequency = DN_OS_PerfCounterFrequency();
|
||||
uint64_t os_target_elapsed = duration_ms_to_gauge_tsc_frequency * os_frequency / 1000ULL;
|
||||
uint64_t tsc_begin = DN_CPU_TSC();
|
||||
uint64_t tsc_begin = DN_CPUGetTSC();
|
||||
uint64_t result = 0;
|
||||
if (tsc_begin) {
|
||||
uint64_t os_elapsed = 0;
|
||||
for (uint64_t os_begin = DN_OS_PerfCounterNow(); os_elapsed < os_target_elapsed;)
|
||||
os_elapsed = DN_OS_PerfCounterNow() - os_begin;
|
||||
uint64_t tsc_end = DN_CPU_TSC();
|
||||
uint64_t tsc_end = DN_CPUGetTSC();
|
||||
uint64_t tsc_elapsed = tsc_end - tsc_begin;
|
||||
result = tsc_elapsed / os_elapsed * os_frequency;
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ DN_API DN_Str8Builder DN_Str8Builder_CopyFromFrame (DN_Str8Bu
|
||||
DN_API DN_Str8Builder DN_Str8Builder_CopyFromTLS (DN_Str8Builder const *builder) { return DN_Str8Builder_Copy(DN_OS_TLSTopArena(), builder); }
|
||||
|
||||
DN_API DN_Str8 DN_Str8Builder_BuildFromFrame (DN_Str8Builder const *builder) { return DN_Str8Builder_Build(builder, DN_OS_TLSGet()->frame_arena); }
|
||||
DN_API DN_Slice<DN_Str8> DN_Str8Builder_BuildFromOSHeap (DN_Str8Builder const *builder, DN_Arena *arena);
|
||||
DN_API DN_Str8 DN_Str8Builder_BuildFromOSHeap (DN_Str8Builder const *builder, DN_Arena *arena);
|
||||
DN_API DN_Str8 DN_Str8Builder_BuildFromTLS (DN_Str8Builder const *builder) { return DN_Str8Builder_Build(builder, DN_OS_TLSTopArena()); }
|
||||
|
||||
DN_API DN_Str8 DN_Str8Builder_BuildDelimitedFromFrame(DN_Str8Builder const *builder, DN_Str8 delimiter) { return DN_Str8Builder_BuildDelimited(builder, delimiter, DN_OS_TLSGet()->frame_arena); }
|
||||
|
@ -52,8 +52,8 @@ DN_API void *DN_OS_MemReserve(DN_USize size, DN_MemCommit commit, DN_U32 page_fl
|
||||
void *result = VirtualAlloc(nullptr, size, flags, os_page_flags);
|
||||
if (flags & MEM_COMMIT) {
|
||||
DN_Assert(g_dn_os_core_);
|
||||
DN_Atomic_AddU64(&g_dn_os_core_->vmem_allocs_total, 1);
|
||||
DN_Atomic_AddU64(&g_dn_os_core_->vmem_allocs_frame, 1);
|
||||
DN_AtomicAddU64(&g_dn_os_core_->vmem_allocs_total, 1);
|
||||
DN_AtomicAddU64(&g_dn_os_core_->vmem_allocs_frame, 1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -66,8 +66,8 @@ DN_API bool DN_OS_MemCommit(void *ptr, DN_USize size, DN_U32 page_flags)
|
||||
unsigned long os_page_flags = DN_OS_MemConvertPageToOSFlags_(page_flags);
|
||||
result = VirtualAlloc(ptr, size, MEM_COMMIT, os_page_flags) != nullptr;
|
||||
DN_Assert(g_dn_os_core_);
|
||||
DN_Atomic_AddU64(&g_dn_os_core_->vmem_allocs_total, 1);
|
||||
DN_Atomic_AddU64(&g_dn_os_core_->vmem_allocs_frame, 1);
|
||||
DN_AtomicAddU64(&g_dn_os_core_->vmem_allocs_total, 1);
|
||||
DN_AtomicAddU64(&g_dn_os_core_->vmem_allocs_frame, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -114,8 +114,8 @@ DN_API void *DN_OS_MemAlloc(DN_USize size, DN_ZeroMem zero_mem)
|
||||
DN_Assert(size <= DN_CAST(DWORD)(-1));
|
||||
void *result = HeapAlloc(GetProcessHeap(), flags, DN_CAST(DWORD) size);
|
||||
DN_Assert(g_dn_os_core_);
|
||||
DN_Atomic_AddU64(&g_dn_os_core_->mem_allocs_total, 1);
|
||||
DN_Atomic_AddU64(&g_dn_os_core_->mem_allocs_frame, 1);
|
||||
DN_AtomicAddU64(&g_dn_os_core_->mem_allocs_total, 1);
|
||||
DN_AtomicAddU64(&g_dn_os_core_->mem_allocs_frame, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -889,7 +889,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line, DN_OSExe
|
||||
}
|
||||
};
|
||||
|
||||
if (DN_Bit_IsSet(args->flags, DN_OSExecFlags_SaveStdout)) {
|
||||
if (DN_BitIsSet(args->flags, DN_OSExecFlags_SaveStdout)) {
|
||||
if (!CreatePipe(&stdout_read, &stdout_write, &save_std_security_attribs, /*nSize*/ 0)) {
|
||||
DN_W32Error win_error = DN_W32_LastError(tmem.arena);
|
||||
result.os_error_code = win_error.code;
|
||||
@ -926,8 +926,8 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line, DN_OSExe
|
||||
}
|
||||
};
|
||||
|
||||
if (DN_Bit_IsSet(args->flags, DN_OSExecFlags_SaveStderr)) {
|
||||
if (DN_Bit_IsSet(args->flags, DN_OSExecFlags_MergeStderrToStdout)) {
|
||||
if (DN_BitIsSet(args->flags, DN_OSExecFlags_SaveStderr)) {
|
||||
if (DN_BitIsSet(args->flags, DN_OSExecFlags_MergeStderrToStdout)) {
|
||||
stderr_read = stdout_read;
|
||||
stderr_write = stdout_write;
|
||||
} else {
|
||||
@ -991,7 +991,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line, DN_OSExe
|
||||
result.process = proc_info.hProcess;
|
||||
result.stdout_read = stdout_read;
|
||||
result.stdout_write = stdout_write;
|
||||
if (DN_Bit_IsSet(args->flags, DN_OSExecFlags_SaveStderr) && DN_Bit_IsNotSet(args->flags, DN_OSExecFlags_MergeStderrToStdout)) {
|
||||
if (DN_BitIsSet(args->flags, DN_OSExecFlags_SaveStderr) && DN_BitIsNotSet(args->flags, DN_OSExecFlags_MergeStderrToStdout)) {
|
||||
result.stderr_read = stderr_read;
|
||||
result.stderr_write = stderr_write;
|
||||
}
|
||||
@ -1389,7 +1389,7 @@ void DN_OS_HttpRequestWin32Callback(HINTERNET session, DWORD *dwContext, DWORD d
|
||||
|
||||
if (read_complete || dwInternetStatus == WINHTTP_CALLBACK_STATUS_REQUEST_ERROR || error.code) {
|
||||
DN_OS_SemaphoreIncrement(&response->on_complete_semaphore, 1);
|
||||
DN_Atomic_AddU32(&response->done, 1);
|
||||
DN_AtomicAddU32(&response->done, 1);
|
||||
}
|
||||
|
||||
if (error.code) {
|
||||
@ -1428,7 +1428,7 @@ DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response,
|
||||
// NOTE: 'Wait' handles failures gracefully, skipping the wait and
|
||||
// cleans up the request
|
||||
DN_OS_HttpRequestWait(response);
|
||||
DN_Atomic_AddU32(&response->done, 1);
|
||||
DN_AtomicAddU32(&response->done, 1);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -43,6 +43,14 @@
|
||||
// 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_compiler.h"
|
||||
#include "Base/dn_base.h"
|
||||
|
Loading…
x
Reference in New Issue
Block a user