Clean up some of the base layer and port Seasight changes over

This commit is contained in:
2025-07-25 22:34:07 +10:00
parent 172362cdb8
commit 31efa0cdcb
25 changed files with 954 additions and 1068 deletions
+67 -38
View File
@@ -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;