Get latest changes from LPP bot
This commit is contained in:
+35
-19
@@ -1,5 +1,10 @@
|
||||
#define DN_OS_CPP
|
||||
|
||||
#if defined(DN_PLATFORM_POSIX)
|
||||
#include <sys/sysinfo.h> // get_nprocs
|
||||
#include <unistd.h> // getpagesize
|
||||
#endif
|
||||
|
||||
static DN_OSCore *g_dn_os_core_;
|
||||
|
||||
static void DN_OS_LOGEmitFromTypeTypeFV_(DN_LOGTypeParam type, void *user_data, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args)
|
||||
@@ -86,34 +91,46 @@ DN_API void DN_OS_Init(DN_OSCore *os, DN_OSInitArgs *args)
|
||||
#if defined(DN_PLATFORM_WIN32)
|
||||
SYSTEM_INFO system_info = {};
|
||||
GetSystemInfo(&system_info);
|
||||
os->page_size = system_info.dwPageSize;
|
||||
os->alloc_granularity = system_info.dwAllocationGranularity;
|
||||
QueryPerformanceFrequency(&os->win32_qpc_frequency);
|
||||
|
||||
HMODULE module = LoadLibraryA("kernel32.dll");
|
||||
os->win32_set_thread_description = DN_CAST(DN_WinSetThreadDescriptionFunc *) GetProcAddress(module, "SetThreadDescription");
|
||||
FreeLibrary(module);
|
||||
os->logical_processor_count = system_info.dwNumberOfProcessors;
|
||||
os->page_size = system_info.dwPageSize;
|
||||
os->alloc_granularity = system_info.dwAllocationGranularity;
|
||||
#else
|
||||
// TODO(doyle): Get the proper page size from the OS.
|
||||
os->page_size = DN_Kilobytes(4);
|
||||
os->alloc_granularity = DN_Kilobytes(64);
|
||||
os->logical_processor_count = get_nprocs();
|
||||
os->page_size = getpagesize();
|
||||
os->alloc_granularity = os->page_size;
|
||||
#endif
|
||||
}
|
||||
|
||||
// NOTE: Setup logging
|
||||
DN_OS_EmitLogsWithOSPrintFunctions(os);
|
||||
|
||||
#if defined(DN_PLATFORM_WIN32)
|
||||
// NOTE: win32 bcrypt
|
||||
{
|
||||
os->arena = DN_Arena_InitFromOSVMem(DN_Megabytes(1), DN_Kilobytes(4), DN_ArenaFlags_NoAllocTrack);
|
||||
#if defined(DN_PLATFORM_WIN32)
|
||||
os->platform_context = DN_Arena_New(&os->arena, DN_W32Core, DN_ZeroMem_Yes);
|
||||
#elif defined(DN_PLATFORM_POSIX)
|
||||
os->platform_context = DN_Arena_New(&os->arena, DN_POSIXCore, DN_ZeroMem_Yes);
|
||||
#endif
|
||||
|
||||
#if defined(DN_PLATFORM_WIN32)
|
||||
DN_W32Core *w32 = DN_CAST(DN_W32Core *) os->platform_context;
|
||||
InitializeCriticalSection(&w32->sync_primitive_free_list_mutex);
|
||||
|
||||
QueryPerformanceFrequency(&w32->qpc_frequency);
|
||||
HMODULE module = LoadLibraryA("kernel32.dll");
|
||||
w32->set_thread_description = DN_CAST(DN_W32SetThreadDescriptionFunc *) GetProcAddress(module, "SetThreadDescription");
|
||||
FreeLibrary(module);
|
||||
|
||||
// NOTE: win32 bcrypt
|
||||
wchar_t const BCRYPT_ALGORITHM[] = L"RNG";
|
||||
long /*NTSTATUS*/ init_status = BCryptOpenAlgorithmProvider(&os->win32_bcrypt_rng_handle, BCRYPT_ALGORITHM, nullptr /*implementation*/, 0 /*flags*/);
|
||||
if (os->win32_bcrypt_rng_handle && init_status == 0)
|
||||
os->win32_bcrypt_init_success = true;
|
||||
long /*NTSTATUS*/ init_status = BCryptOpenAlgorithmProvider(&w32->bcrypt_rng_handle, BCRYPT_ALGORITHM, nullptr /*implementation*/, 0 /*flags*/);
|
||||
if (w32->bcrypt_rng_handle && init_status == 0)
|
||||
w32->bcrypt_init_success = true;
|
||||
else
|
||||
DN_LOG_ErrorF("Failed to initialise Windows secure random number generator, error: %d", init_status);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
// NOTE: Initialise tmem arenas which allocate memory and will be
|
||||
// recorded to the now initialised allocation table. The initialisation
|
||||
@@ -135,7 +152,6 @@ DN_API void DN_OS_Init(DN_OSCore *os, DN_OSInitArgs *args)
|
||||
#define DN_CPU_FEAT_XENTRY(label) g_dn_cpu_feature_decl[DN_CPUFeature_##label] = {DN_CPUFeature_##label, DN_STR8(#label)};
|
||||
DN_CPU_FEAT_XMACRO
|
||||
#undef DN_CPU_FEAT_XENTRY
|
||||
|
||||
DN_Assert(g_dn_os_core_);
|
||||
}
|
||||
|
||||
@@ -702,13 +718,13 @@ static void DN_OS_ThreadExecute_(void *user_context)
|
||||
|
||||
DN_API void DN_OS_ThreadSetName(DN_Str8 name)
|
||||
{
|
||||
DN_OSTLS *tls = DN_OS_TLSGet();
|
||||
DN_OSTLS *tls = DN_OS_TLSGet();
|
||||
tls->name_size = DN_CAST(uint8_t) DN_Min(name.size, sizeof(tls->name) - 1);
|
||||
DN_Memcpy(tls->name, name.data, tls->name_size);
|
||||
tls->name[tls->name_size] = 0;
|
||||
|
||||
#if defined(DN_PLATFORM_WIN32)
|
||||
DN_Win_ThreadSetName(name);
|
||||
DN_W32_ThreadSetName(name);
|
||||
#else
|
||||
DN_Posix_ThreadSetName(name);
|
||||
#endif
|
||||
@@ -717,7 +733,7 @@ DN_API void DN_OS_ThreadSetName(DN_Str8 name)
|
||||
// NOTE: DN_OSHttp /////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API void DN_OS_HttpRequestWait(DN_OSHttpResponse *response)
|
||||
{
|
||||
if (response && DN_OS_SemaphoreIsValid(&response->on_complete_semaphore))
|
||||
if (response && response->on_complete_semaphore.handle != 0)
|
||||
DN_OS_SemaphoreWait(&response->on_complete_semaphore, DN_OS_SEMAPHORE_INFINITE_TIMEOUT);
|
||||
}
|
||||
|
||||
|
||||
+34
-50
@@ -1,11 +1,13 @@
|
||||
#if !defined(DN_OS_H)
|
||||
#define DN_OS_H
|
||||
|
||||
#include <new> // operator new
|
||||
|
||||
#if defined(DN_PLATFORM_EMSCRIPTEN) || defined(DN_PLATFORM_POSIX) || defined(DN_PLATFORM_ARM64)
|
||||
#include "dn_os_posix.h"
|
||||
#elif defined(DN_PLATFORM_WIN32)
|
||||
#include "dn_os_windows.h"
|
||||
#include "dn_os_win32.h"
|
||||
#include "dn_os_w32.h"
|
||||
#else
|
||||
#error Please define a platform e.g. 'DN_PLATFORM_WIN32' to enable the correct implementation for platform APIs
|
||||
#endif
|
||||
@@ -38,10 +40,6 @@
|
||||
#include <emscripten/fetch.h> // emscripten_fetch (for DN_OSHttpResponse)
|
||||
#endif
|
||||
|
||||
#if defined(DN_PLATFORM_WIN32)
|
||||
typedef HRESULT DN_WinSetThreadDescriptionFunc(HANDLE hThread, PWSTR const lpThreadDescription);
|
||||
#endif
|
||||
|
||||
// NOTE: DN_OSDate /////////////////////////////////////////////////////////////////////////////////
|
||||
struct DN_OSDateTimeStr8
|
||||
{
|
||||
@@ -178,11 +176,11 @@ struct DN_OSExecAsyncHandle
|
||||
|
||||
struct DN_OSExecResult
|
||||
{
|
||||
bool finished;
|
||||
DN_Str8 stdout_text;
|
||||
DN_Str8 stderr_text;
|
||||
DN_U32 os_error_code;
|
||||
DN_U32 exit_code;
|
||||
bool finished;
|
||||
DN_Str8 stdout_text;
|
||||
DN_Str8 stderr_text;
|
||||
DN_U32 os_error_code;
|
||||
DN_U32 exit_code;
|
||||
};
|
||||
|
||||
struct DN_OSExecArgs
|
||||
@@ -192,18 +190,12 @@ struct DN_OSExecArgs
|
||||
DN_Slice<DN_Str8> environment;
|
||||
};
|
||||
|
||||
#if !defined(DN_NO_SEMAPHORE)
|
||||
// NOTE: DN_OSSemaphore ////////////////////////////////////////////////////////////////////////////
|
||||
DN_U32 const DN_OS_SEMAPHORE_INFINITE_TIMEOUT = UINT32_MAX;
|
||||
|
||||
struct DN_OSSemaphore
|
||||
{
|
||||
#if defined(DN_OS_WIN32) && !defined(DN_OS_WIN32_USE_PTHREADS)
|
||||
void *win32_handle;
|
||||
#else
|
||||
sem_t posix_handle;
|
||||
bool posix_init;
|
||||
#endif
|
||||
DN_U64 handle;
|
||||
};
|
||||
|
||||
enum DN_OSSemaphoreWaitResult
|
||||
@@ -212,35 +204,31 @@ enum DN_OSSemaphoreWaitResult
|
||||
DN_OSSemaphoreWaitResult_Success,
|
||||
DN_OSSemaphoreWaitResult_Timeout,
|
||||
};
|
||||
#endif // !defined(DN_NO_SEMAPHORE)
|
||||
|
||||
// NOTE: DN_OSMutex ////////////////////////////////////////////////////////////////////////////////
|
||||
struct DN_OSMutex
|
||||
{
|
||||
#if defined(DN_OS_WIN32) && !defined(DN_OS_WIN32_USE_PTHREADS)
|
||||
char win32_handle[48];
|
||||
#else
|
||||
pthread_mutex_t posix_handle;
|
||||
pthread_mutexattr_t posix_attribs;
|
||||
#endif
|
||||
DN_U64 handle;
|
||||
};
|
||||
|
||||
struct DN_OSConditionVariable
|
||||
{
|
||||
DN_U64 handle;
|
||||
};
|
||||
|
||||
// NOTE: DN_OSThread ///////////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DN_NO_THREAD) && !defined(DN_NO_SEMAPHORE)
|
||||
typedef int32_t(DN_OSThreadFunc)(struct DN_OSThread *);
|
||||
typedef DN_I32(DN_OSThreadFunc)(struct DN_OSThread *);
|
||||
|
||||
struct DN_OSThread
|
||||
{
|
||||
DN_FStr8<64> name;
|
||||
DN_OSTLS tls;
|
||||
DN_OSTLSInitArgs tls_init_args;
|
||||
DN_OSTLS tls;
|
||||
DN_OSTLSInitArgs tls_init_args;
|
||||
void *handle;
|
||||
DN_U64 thread_id;
|
||||
void *user_context;
|
||||
DN_OSThreadFunc *func;
|
||||
DN_OSSemaphore init_semaphore;
|
||||
};
|
||||
#endif // !defined(DN_NO_THREAD)
|
||||
|
||||
// NOTE: DN_OSHttp /////////////////////////////////////////////////////////////////////////////////
|
||||
enum DN_OSHttpRequestSecure
|
||||
@@ -272,9 +260,9 @@ struct DN_OSHttpResponse
|
||||
#if defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
emscripten_fetch_t *em_handle;
|
||||
#elif defined(DN_PLATFORM_WIN32)
|
||||
HINTERNET win32_request_session;
|
||||
HINTERNET win32_request_connection;
|
||||
HINTERNET win32_request_handle;
|
||||
HINTERNET w32_request_session;
|
||||
HINTERNET w32_request_connection;
|
||||
HINTERNET w32_request_handle;
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -300,6 +288,7 @@ struct DN_OSCore
|
||||
bool log_no_colour; // Disable colours in the logging output
|
||||
|
||||
// NOTE: OS //////////////////////////////////////////////////////////////////////////////////////
|
||||
DN_U32 logical_processor_count;
|
||||
DN_U32 page_size;
|
||||
DN_U32 alloc_granularity;
|
||||
|
||||
@@ -312,14 +301,8 @@ struct DN_OSCore
|
||||
DN_U64 mem_allocs_total;
|
||||
DN_U64 mem_allocs_frame; // Total OS heap allocs since the last 'DN_Core_FrameBegin' was invoked
|
||||
|
||||
// NOTE: Win32 /////////////////////////////////////////////////////////////////////////////////
|
||||
#if defined(DN_PLATFORM_WIN32)
|
||||
DN_WinSetThreadDescriptionFunc *win32_set_thread_description;
|
||||
LARGE_INTEGER win32_qpc_frequency;
|
||||
void * win32_bcrypt_rng_handle;
|
||||
bool win32_bcrypt_init_success;
|
||||
bool win32_sym_initialised;
|
||||
#endif
|
||||
DN_Arena arena;
|
||||
void *platform_context;
|
||||
};
|
||||
|
||||
struct DN_OSDiskSpace
|
||||
@@ -349,6 +332,8 @@ DN_API DN_OSDateTime DN_OS_DateLocalTimeNow ();
|
||||
DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8Now(char date_separator = '-', char hms_separator = ':');
|
||||
DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8 (DN_OSDateTime time, char date_separator = '-', char hms_separator = ':');
|
||||
DN_API DN_U64 DN_OS_DateUnixTimeNs ();
|
||||
#define DN_OS_DateUnixTimeUs() (DN_OS_DateUnixTimeNs() / 1000)
|
||||
#define DN_OS_DateUnixTimeMs() (DN_OS_DateUnixTimeNs() / 1000 * 1000)
|
||||
DN_API DN_U64 DN_OS_DateUnixTimeS ();
|
||||
DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate (DN_U64 time);
|
||||
DN_API DN_U64 DN_OS_DateLocalToUnixTimeS(DN_OSDateTime date);
|
||||
@@ -451,31 +436,30 @@ DN_API DN_OSExecResult DN_OS_Exec (DN_Slice<DN_Str8> c
|
||||
DN_API DN_OSExecResult DN_OS_ExecOrAbort (DN_Slice<DN_Str8> cmd_line, DN_OSExecArgs *args, DN_Arena *arena);
|
||||
#define DN_OS_ExecOrAbortFromTLS(...) DN_OS_ExecOrAbort(__VA_ARGS__, DN_OS_TLSTopArena())
|
||||
|
||||
// NOTE: DN_OSSemaphore ////////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DN_NO_SEMAPHORE)
|
||||
DN_API DN_OSSemaphore DN_OS_SemaphoreInit (DN_U32 initial_count);
|
||||
DN_API bool DN_OS_SemaphoreIsValid (DN_OSSemaphore *semaphore);
|
||||
DN_API void DN_OS_SemaphoreDeinit (DN_OSSemaphore *semaphore);
|
||||
DN_API void DN_OS_SemaphoreIncrement(DN_OSSemaphore *semaphore, DN_U32 amount);
|
||||
DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait (DN_OSSemaphore *semaphore, DN_U32 timeout_ms);
|
||||
#endif // !defined(DN_NO_SEMAPHORE)
|
||||
|
||||
// NOTE: DN_OSMutex ////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_OSMutex DN_OS_MutexInit ();
|
||||
DN_API void DN_OS_MutexDeinit(DN_OSMutex *mutex);
|
||||
DN_API void DN_OS_MutexLock (DN_OSMutex *mutex);
|
||||
DN_API void DN_OS_MutexUnlock(DN_OSMutex *mutex);
|
||||
#define DN_OS_Mutex(mutex) DN_DEFER_LOOP(DN_OS_MutexLock(mutex), DN_OS_MutexUnlock(mutex))
|
||||
#define DN_OS_MutexScope(mutex) DN_DeferLoop(DN_OS_MutexLock(mutex), DN_OS_MutexUnlock(mutex))
|
||||
|
||||
DN_API DN_OSConditionVariable DN_OS_ConditionVariableInit ();
|
||||
DN_API void DN_OS_ConditionVariableDeinit (DN_OSConditionVariable *cv);
|
||||
DN_API bool DN_OS_ConditionVariableWait (DN_OSConditionVariable *cv, DN_OSMutex *mutex, DN_U64 sleep_ms);
|
||||
DN_API bool DN_OS_ConditionVariableWaitUntil(DN_OSConditionVariable *cv, DN_OSMutex *mutex, DN_U64 end_ts_ms);
|
||||
DN_API void DN_OS_ConditionVariableSignal (DN_OSConditionVariable *cv);
|
||||
DN_API void DN_OS_ConditionVariableBroadcast(DN_OSConditionVariable *cv);
|
||||
|
||||
// NOTE: DN_OSThread ///////////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(DN_NO_THREAD) && !defined(DN_NO_SEMAPHORE)
|
||||
DN_API bool DN_OS_ThreadInit (DN_OSThread *thread, DN_OSThreadFunc *func, void *user_context);
|
||||
DN_API void DN_OS_ThreadDeinit(DN_OSThread *thread);
|
||||
DN_API DN_U32 DN_OS_ThreadID ();
|
||||
DN_API void DN_OS_ThreadSetName(DN_Str8 name);
|
||||
#endif // !defined(DN_NO_THREAD)
|
||||
|
||||
// NOTE: DN_OSHttp /////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response, DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers);
|
||||
DN_API void DN_OS_HttpRequestWait (DN_OSHttpResponse *response);
|
||||
DN_API void DN_OS_HttpRequestFree (DN_OSHttpResponse *response);
|
||||
|
||||
+186
-85
@@ -4,11 +4,11 @@
|
||||
#include <sys/statvfs.h>
|
||||
|
||||
// NOTE: DN_OSMem //////////////////////////////////////////////////////////////////////////////////
|
||||
static uint32_t DN_OS_MemConvertPageToOSFlags_(uint32_t protect)
|
||||
static DN_U32 DN_OS_MemConvertPageToOSFlags_(DN_U32 protect)
|
||||
{
|
||||
DN_Assert((protect & ~DN_MemPage_All) == 0);
|
||||
DN_Assert(protect != 0);
|
||||
uint32_t result = 0;
|
||||
DN_U32 result = 0;
|
||||
|
||||
if (protect & (DN_MemPage_NoAccess | DN_MemPage_Guard)) {
|
||||
result = PROT_NONE;
|
||||
@@ -21,7 +21,7 @@ static uint32_t DN_OS_MemConvertPageToOSFlags_(uint32_t protect)
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API void *DN_OS_MemReserve(DN_USize size, DN_MemCommit commit, uint32_t page_flags)
|
||||
DN_API void *DN_OS_MemReserve(DN_USize size, DN_MemCommit commit, DN_U32 page_flags)
|
||||
{
|
||||
unsigned long os_page_flags = DN_OS_MemConvertPageToOSFlags_(page_flags);
|
||||
|
||||
@@ -36,7 +36,7 @@ DN_API void *DN_OS_MemReserve(DN_USize size, DN_MemCommit commit, uint32_t page_
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_MemCommit(void *ptr, DN_USize size, uint32_t page_flags)
|
||||
DN_API bool DN_OS_MemCommit(void *ptr, DN_USize size, DN_U32 page_flags)
|
||||
{
|
||||
bool result = false;
|
||||
if (!ptr || size == 0)
|
||||
@@ -60,7 +60,7 @@ DN_API void DN_OS_MemRelease(void *ptr, DN_USize size)
|
||||
munmap(ptr, size);
|
||||
}
|
||||
|
||||
DN_API int DN_OS_MemProtect(void *ptr, DN_USize size, uint32_t page_flags)
|
||||
DN_API int DN_OS_MemProtect(void *ptr, DN_USize size, DN_U32 page_flags)
|
||||
{
|
||||
if (!ptr || size == 0)
|
||||
return 0;
|
||||
@@ -162,7 +162,7 @@ DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate(uint64_t time)
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_SecureRNGBytes(void *buffer, uint32_t size)
|
||||
DN_API bool DN_OS_SecureRNGBytes(void *buffer, DN_U32 size)
|
||||
{
|
||||
#if defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
(void)buffer;
|
||||
@@ -182,7 +182,7 @@ DN_API bool DN_OS_SecureRNGBytes(void *buffer, uint32_t size)
|
||||
// TODO(doyle):
|
||||
// https://github.com/jedisct1/libsodium/blob/master/src/libsodium/randombytes/sysrandom/randombytes_sysrandom.c
|
||||
// TODO(doyle): https://man7.org/linux/man-pages/man2/getrandom.2.html
|
||||
uint32_t read_bytes = 0;
|
||||
DN_U32 read_bytes = 0;
|
||||
do {
|
||||
read_bytes =
|
||||
getrandom(buffer, size, 0); // NOTE: EINTR can not be triggered if size <= 32 bytes
|
||||
@@ -211,7 +211,7 @@ DN_API DN_OSDiskSpace DN_OS_DiskSpace(DN_Str8 path)
|
||||
return result;
|
||||
|
||||
result.success = true;
|
||||
result.free = info.f_bavail * info.f_frsize;
|
||||
result.avail = info.f_bavail * info.f_frsize;
|
||||
result.size = info.f_blocks * info.f_frsize;
|
||||
return result;
|
||||
}
|
||||
@@ -275,7 +275,7 @@ DN_API void DN_OS_SleepMs(DN_UInt milliseconds)
|
||||
{
|
||||
struct timespec ts;
|
||||
ts.tv_sec = milliseconds / 1000;
|
||||
ts.tv_nsec = (milliseconds % 1000) * 1000000; // Convert remaining milliseconds to nanoseconds
|
||||
ts.tv_nsec = (milliseconds % 1000) * 1'000'000; // Convert remaining milliseconds to nanoseconds
|
||||
// nanosleep can fail if interrupted by a signal, so we loop until the full sleep time has passed
|
||||
while (nanosleep(&ts, &ts) == -1 && errno == EINTR)
|
||||
;
|
||||
@@ -916,8 +916,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice<DN_Str8> cmd_line,
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_ForIndexU(arg_index, cmd_line.size)
|
||||
{
|
||||
for (DN_ForIndexU(arg_index, cmd_line.size)) {
|
||||
DN_Str8 arg = cmd_line.data[arg_index];
|
||||
argv[arg_index] = DN_Str8_Copy(tmem.arena, arg).data; // NOTE: Copy string to guarantee it is null-terminated
|
||||
}
|
||||
@@ -990,7 +989,7 @@ DN_API DN_OSExecResult DN_OS_ExecPump(DN_OSExecAsyncHandle handle,
|
||||
size_t *stdout_size,
|
||||
char *stderr_buffer,
|
||||
size_t *stderr_size,
|
||||
uint32_t timeout_ms,
|
||||
DN_U32 timeout_ms,
|
||||
DN_OSErrSink *err)
|
||||
{
|
||||
DN_InvalidCodePath;
|
||||
@@ -998,75 +997,111 @@ DN_API DN_OSExecResult DN_OS_ExecPump(DN_OSExecAsyncHandle handle,
|
||||
return result;
|
||||
}
|
||||
|
||||
#if !defined(DN_NO_SEMAPHORE)
|
||||
// NOTE: DN_OSSemaphore ////////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_OSSemaphore DN_OS_SemaphoreInit(uint32_t initial_count)
|
||||
static DN_POSIXCore *DN_OS_GetPOSIXCore_()
|
||||
{
|
||||
DN_OSSemaphore result = {};
|
||||
int pshared = 0; // Share the semaphore across all threads in the process
|
||||
if (sem_init(&result.posix_handle, pshared, initial_count) == 0)
|
||||
result.posix_init = true;
|
||||
DN_Assert(g_dn_os_core_ && g_dn_os_core_->platform_context);
|
||||
DN_POSIXCore *result = DN_CAST(DN_POSIXCore *)g_dn_os_core_->platform_context;
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_SemaphoreIsValid(DN_OSSemaphore *semaphore)
|
||||
static DN_POSIXSyncPrimitive *DN_OS_U64ToPOSIXSyncPrimitive_(DN_U64 u64)
|
||||
{
|
||||
bool result = false;
|
||||
if (semaphore)
|
||||
result = semaphore->posix_init;
|
||||
DN_POSIXSyncPrimitive *result = nullptr;
|
||||
DN_Memcpy(&result, &u64, sizeof(u64));
|
||||
return result;
|
||||
}
|
||||
|
||||
static DN_U64 DN_POSIX_SyncPrimitiveToU64(DN_POSIXSyncPrimitive *primitive)
|
||||
{
|
||||
DN_U64 result = 0;
|
||||
static_assert(sizeof(result) == sizeof(primitive), "Pointer size mis-match");
|
||||
DN_Memcpy(&result, &primitive, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
static DN_POSIXSyncPrimitive *DN_POSIX_AllocSyncPrimitive_()
|
||||
{
|
||||
DN_POSIXCore *posix = DN_OS_GetPOSIXCore_();
|
||||
DN_POSIXSyncPrimitive *result = nullptr;
|
||||
pthread_mutex_lock(&posix->sync_primitive_free_list_mutex);
|
||||
{
|
||||
if (posix->sync_primitive_free_list) {
|
||||
result = posix->sync_primitive_free_list;
|
||||
posix->sync_primitive_free_list = posix->sync_primitive_free_list->next;
|
||||
result->next = nullptr;
|
||||
} else {
|
||||
DN_OSCore *os = g_dn_os_core_;
|
||||
result = DN_Arena_New(&os->arena, DN_POSIXSyncPrimitive, DN_ZeroMem_Yes);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&posix->sync_primitive_free_list_mutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void DN_POSIX_DeallocSyncPrimitive_(DN_POSIXSyncPrimitive *primitive)
|
||||
{
|
||||
if (primitive) {
|
||||
DN_POSIXCore *posix = DN_OS_GetPOSIXCore_();
|
||||
pthread_mutex_lock(&posix->sync_primitive_free_list_mutex);
|
||||
primitive->next = posix->sync_primitive_free_list;
|
||||
posix->sync_primitive_free_list = primitive;
|
||||
pthread_mutex_unlock(&posix->sync_primitive_free_list_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: DN_OSSemaphore ////////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_OSSemaphore DN_OS_SemaphoreInit(DN_U32 initial_count)
|
||||
{
|
||||
DN_POSIXCore *posix = g_dn_os_core->posix_context;
|
||||
DN_Assert(posix);
|
||||
|
||||
DN_OSSemaphore result = {};
|
||||
DN_POSIXSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_();
|
||||
if (primitive) {
|
||||
int pshared = 0; // Share the semaphore across all threads in the process
|
||||
if (sem_init(&primitive->sem, pshared, initial_count) == 0)
|
||||
result.handle = DN_POSIX_SyncPrimitiveToU64(primitive);
|
||||
else
|
||||
DN_POSIX_DeallocSyncPrimitive_(primitive);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API void DN_OS_SemaphoreDeinit(DN_OSSemaphore *semaphore)
|
||||
{
|
||||
if (!DN_OS_SemaphoreIsValid(semaphore))
|
||||
return;
|
||||
// TODO(doyle): Error handling?
|
||||
if (semaphore->posix_init)
|
||||
sem_destroy(&semaphore->posix_handle);
|
||||
*semaphore = {};
|
||||
if (semaphore.handle != 0) {
|
||||
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle);
|
||||
sem_destroy(&primitive->sem);
|
||||
DN_POSIX_DeallocSyncPrimitive_(posix_sem);
|
||||
*semaphore = {};
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: These functions don't need semaphore to be passed by pointer, **BUT**
|
||||
// the POSIX implementation disallows copies of sem_t. In particular:
|
||||
//
|
||||
// Source: The Open Group Base Specifications Issue 7, 2018 edition
|
||||
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_09_09
|
||||
//
|
||||
// 2.9.9 Synchronization Object Copies and Alternative Mappings
|
||||
//
|
||||
// For barriers, condition variables, mutexes, and read-write locks, [TSH]
|
||||
// [Option Start] if the process-shared attribute is set to
|
||||
// PTHREAD_PROCESS_PRIVATE, [Option End] only the synchronization object at the
|
||||
// address used to initialize it can be used for performing synchronization. The
|
||||
// effect of referring to another mapping of the same object when locking,
|
||||
// unlocking, or destroying the object is undefined. [...] The effect of
|
||||
// referring to a copy of the object when locking, unlocking, or destroying it
|
||||
// is undefined.
|
||||
|
||||
DN_API void DN_OS_SemaphoreIncrement(DN_OSSemaphore *semaphore, uint32_t amount)
|
||||
DN_API void DN_OS_SemaphoreIncrement(DN_OSSemaphore *semaphore, DN_U32 amount)
|
||||
{
|
||||
if (!DN_OS_SemaphoreIsValid(semaphore))
|
||||
return;
|
||||
#if defined(DN_OS_WIN32)
|
||||
sem_post_multiple(&semaphore->posix_handle, amount); // mingw extension
|
||||
#else
|
||||
DN_ForIndexU(index, amount)
|
||||
sem_post(&semaphore->posix_handle);
|
||||
#endif // !defined(DN_OS_WIN32)
|
||||
if (semaphore.handle != 0) {
|
||||
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle);
|
||||
#if defined(DN_OS_WIN32)
|
||||
sem_post_multiple(&primitive->sem, amount); // mingw extension
|
||||
#else
|
||||
for (DN_ForIndexU(index, amount))
|
||||
sem_post(&primitive->sem);
|
||||
#endif // !defined(DN_OS_WIN32)
|
||||
}
|
||||
}
|
||||
|
||||
DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait(DN_OSSemaphore *semaphore,
|
||||
uint32_t timeout_ms)
|
||||
DN_U32 timeout_ms)
|
||||
{
|
||||
DN_OSSemaphoreWaitResult result = {};
|
||||
if (!DN_OS_SemaphoreIsValid(semaphore))
|
||||
if (semaphore.handle == 0)
|
||||
return result;
|
||||
|
||||
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle);
|
||||
if (timeout_ms == DN_OS_SEMAPHORE_INFINITE_TIMEOUT) {
|
||||
int wait_result = 0;
|
||||
do {
|
||||
wait_result = sem_wait(&semaphore->posix_handle);
|
||||
wait_result = sem_wait(&primitive->sem);
|
||||
} while (wait_result == -1 && errno == EINTR);
|
||||
|
||||
if (wait_result == 0)
|
||||
@@ -1075,47 +1110,115 @@ DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait(DN_OSSemaphore *semaphore,
|
||||
struct timespec abs_timeout = {};
|
||||
abs_timeout.tv_sec = timeout_ms / 1000;
|
||||
abs_timeout.tv_nsec = (timeout_ms % 1000) * 1'000'000;
|
||||
if (sem_timedwait(&semaphore->posix_handle, &abs_timeout) == 0)
|
||||
if (sem_timedwait(&primitive->sem) == 0)
|
||||
result = DN_OSSemaphoreWaitResult_Success;
|
||||
else if (errno == ETIMEDOUT)
|
||||
result = DN_OSSemaphoreWaitResult_Timeout;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif // !defined(DN_NO_SEMAPHORE)
|
||||
|
||||
#if !defined(DN_NO_THREAD)
|
||||
// NOTE: DN_OSMutex ////////////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_OSMutex DN_OS_MutexInit()
|
||||
{
|
||||
DN_OSMutex result = {};
|
||||
if (pthread_mutexattr_init(&result.posix_attribs) != 0)
|
||||
return result;
|
||||
if (pthread_mutex_init(&result.posix_handle, &result.posix_attribs) != 0)
|
||||
return result;
|
||||
DN_W32SyncPrimitive *primitive = DN_W32_AllocSyncPrimitive_();
|
||||
DN_OSMutex result = {};
|
||||
if (primitive) {
|
||||
int pshared = 0; // Share the semaphore across all threads in the process
|
||||
if (pthread_mutex_init(mutex, pshared, nullptr) == 0)
|
||||
result.handle = DN_POSIX_SyncPrimitiveToU64(primitive);
|
||||
else
|
||||
DN_POSIX_DeallocSyncPrimitive_(primitive);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API void DN_OS_MutexDeinit(DN_OSMutex *mutex)
|
||||
{
|
||||
if (!mutex)
|
||||
return;
|
||||
pthread_mutexattr_destroy(&mutex->posix_attribs);
|
||||
pthread_mutex_destroy(&mutex->posix_handle);
|
||||
if (mutex && mutex->handle != 0) {
|
||||
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle);
|
||||
pthread_mutex_destroy(&primitive->mutex);
|
||||
DN_POSIX_DeallocSyncPrimitive_(primitive);
|
||||
*mutex = {};
|
||||
}
|
||||
}
|
||||
|
||||
DN_API void DN_OS_MutexLock(DN_OSMutex *mutex)
|
||||
{
|
||||
if (!mutex)
|
||||
return;
|
||||
pthread_mutex_lock(&mutex->posix_handle);
|
||||
if (mutex && mutex->handle != 0) {
|
||||
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle);
|
||||
pthread_mutex_lock(&primitive->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
DN_API void DN_OS_MutexUnlock(DN_OSMutex *mutex)
|
||||
{
|
||||
if (!mutex)
|
||||
return;
|
||||
pthread_mutex_unlock(&mutex->posix_handle);
|
||||
if (mutex && mutex->handle != 0) {
|
||||
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle);
|
||||
pthread_mutex_unlock(&primitive->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
DN_API DN_OSConditionVariable DN_OS_ConditionVariableInit()
|
||||
{
|
||||
DN_POSIXSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_();
|
||||
DN_OSConditionVariable result = {};
|
||||
if (primitive) {
|
||||
if (pthread_cond_init(&primitive->cv) == 0)
|
||||
result.handle = DN_POSIX_SyncPrimitiveToU64(primitive);
|
||||
else
|
||||
DN_POSIX_DeallocSyncPrimitive_(primitive);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_ConditionVariableDeinit(DN_OSConditionVariable *cv)
|
||||
{
|
||||
if (cv && cv->handle != 0) {
|
||||
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle);
|
||||
pthread_cond_destroy(&primitive->cv);
|
||||
DN_POSIX_DeallocSyncPrimitive_(primitive);
|
||||
*cv = {};
|
||||
}
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_ConditionVariableWaitUntil(DN_OSConditionVariable *cv, DN_OSMutex *mutex, DN_U64 end_ts_ms)
|
||||
{
|
||||
bool result = false;
|
||||
if (cv && mutex && mutex->handle != 0 && cv->handle != 0) {
|
||||
DN_POSIXSyncPrimitive *cv_primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle);
|
||||
DN_POSIXSyncPrimitive *mutex_primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle);
|
||||
|
||||
struct timespec time;
|
||||
time.tv_sec = end_ts_ms / 1'000;
|
||||
time.tv_nsec = 1'000'000 * (end_ts_ms - (end_ts_ms / 1'000) * 1'000);
|
||||
int wait_result = pthread_cond_timedwait(&cv_primitive->cv, &mutex_primitive->mutex, &time);
|
||||
result = (wait_result != ETIMEDOUT);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_ConditionVariableWait(DN_OSConditionVariable *cv, DN_OSMutex *mutex, DN_U64 sleep_ms)
|
||||
{
|
||||
DN_U64 end_ts_ms = DN_OS_DateUnixTimeMs() + sleep_ms;
|
||||
bool result = DN_OS_ConditionVariableWaitUntil(cv, mutex, end_ts_ms);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API void DN_OS_ConditionVariableSignal(DN_OSConditionVariable *cv)
|
||||
{
|
||||
if (cv && cv->handle != 0) {
|
||||
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle);
|
||||
pthread_cond_signal(&primitive->cv);
|
||||
}
|
||||
}
|
||||
|
||||
DN_API void DN_OS_ConditionVariableBroadcast(DN_OSConditionVariable *cv)
|
||||
{
|
||||
if (cv && cv->handle != 0) {
|
||||
DN_POSIXSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle);
|
||||
pthread_cond_broadcast(&primitive->cv);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: DN_OSThread ///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1181,11 +1284,11 @@ DN_API void DN_OS_ThreadDeinit(DN_OSThread *thread)
|
||||
thread->thread_id = {};
|
||||
}
|
||||
|
||||
DN_API uint32_t DN_OS_ThreadID()
|
||||
DN_API DN_U32 DN_OS_ThreadID()
|
||||
{
|
||||
pid_t result = gettid();
|
||||
DN_Assert(gettid() >= 0);
|
||||
return DN_CAST(uint32_t) result;
|
||||
return DN_CAST(DN_U32) result;
|
||||
}
|
||||
|
||||
DN_API void DN_Posix_ThreadSetName(DN_Str8 name)
|
||||
@@ -1195,7 +1298,6 @@ DN_API void DN_Posix_ThreadSetName(DN_Str8 name)
|
||||
pthread_t thread = pthread_self();
|
||||
pthread_setname_np(thread, (char *)copy.data);
|
||||
}
|
||||
#endif // !defined(DN_NO_THREAD)
|
||||
|
||||
DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus()
|
||||
{
|
||||
@@ -1230,7 +1332,7 @@ DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus()
|
||||
DN_Str8 status_buf = DN_Str8Builder_BuildFromTLS(&builder);
|
||||
DN_Slice<DN_Str8> lines = DN_Str8_SplitAllocFromTLS(status_buf, DN_STR8("\n"), DN_Str8SplitIncludeEmptyStrings_No);
|
||||
|
||||
DN_ForIt(line_it, DN_Str8, &lines) {
|
||||
for (DN_ForIt(line_it, DN_Str8, &lines)) {
|
||||
DN_Str8 line = DN_Str8_TrimWhitespaceAround(*line_it.data);
|
||||
if (DN_Str8_StartsWith(line, NAME, DN_Str8EqCase_Insensitive)) {
|
||||
DN_Str8 str8 = DN_Str8_TrimWhitespaceAround(DN_Str8_Slice(line, NAME.size, line.size));
|
||||
@@ -1312,7 +1414,7 @@ static void DN_OS_HttpRequestEMFetchOnSuccessCallback(emscripten_fetch_t *fetch)
|
||||
if (!DN_Check(response))
|
||||
return;
|
||||
|
||||
response->http_status = DN_CAST(uint32_t) fetch->status;
|
||||
response->http_status = DN_CAST(DN_U32) fetch->status;
|
||||
response->body = DN_Str8_Alloc(response->arena, fetch->numBytes, DN_ZeroMem_No);
|
||||
if (response->body.data)
|
||||
DN_Memcpy(response->body.data, fetch->data, fetch->numBytes);
|
||||
@@ -1327,7 +1429,7 @@ static void DN_OS_HttpRequestEMFetchOnErrorCallback(emscripten_fetch_t *fetch)
|
||||
if (!DN_Check(response))
|
||||
return;
|
||||
|
||||
response->http_status = DN_CAST(uint32_t) fetch->status;
|
||||
response->http_status = DN_CAST(DN_U32) fetch->status;
|
||||
response->body = DN_Str8_Alloc(response->arena, fetch->numBytes, DN_ZeroMem_No);
|
||||
if (response->body.size)
|
||||
DN_Memcpy(response->body.data, fetch->data, fetch->numBytes);
|
||||
@@ -1372,7 +1474,7 @@ DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response,
|
||||
DN_CheckF(method.size < sizeof(fetch_attribs.requestMethod),
|
||||
"%.*s",
|
||||
DN_STR_FMT(response->error_msg));
|
||||
response->error_code = DN_CAST(uint32_t) - 1;
|
||||
response->error_code = DN_CAST(DN_U32) - 1;
|
||||
DN_Atomic_AddU32(&response->done, 1);
|
||||
return;
|
||||
}
|
||||
@@ -1409,7 +1511,6 @@ DN_API void DN_OS_HttpRequestFree(DN_OSHttpResponse *response)
|
||||
#endif // #elif defined(DN_OS_WIN32)
|
||||
|
||||
DN_Arena_Deinit(&response->tmp_arena);
|
||||
if (DN_OS_SemaphoreIsValid(&response->on_complete_semaphore))
|
||||
DN_OS_SemaphoreDeinit(&response->on_complete_semaphore);
|
||||
DN_OS_SemaphoreDeinit(&response->on_complete_semaphore);
|
||||
*response = {};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -26,5 +29,47 @@ struct DN_POSIXProcSelfStatus
|
||||
DN_U32 vm_size;
|
||||
};
|
||||
|
||||
// NOTE: The POSIX implementation disallows copies of synchronisation objects in
|
||||
// general hence we have to dynamically allocate these primitives to maintain a
|
||||
// consistent address.
|
||||
//
|
||||
//
|
||||
// Source: The Open Group Base Specifications Issue 7, 2018 edition
|
||||
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_09_09
|
||||
//
|
||||
// 2.9.9 Synchronization Object Copies and Alternative Mappings
|
||||
//
|
||||
// For barriers, condition variables, mutexes, and read-write locks, [TSH]
|
||||
// [Option Start] if the process-shared attribute is set to
|
||||
// PTHREAD_PROCESS_PRIVATE, [Option End] only the synchronization object at the
|
||||
// address used to initialize it can be used for performing synchronization. The
|
||||
// effect of referring to another mapping of the same object when locking,
|
||||
// unlocking, or destroying the object is undefined. [...] The effect of
|
||||
// referring to a copy of the object when locking, unlocking, or destroying it
|
||||
// is undefined.
|
||||
|
||||
enum DN_POSIXSyncPrimitiveType
|
||||
{
|
||||
DN_OSPOSIXSyncPrimitiveType_Semaphore,
|
||||
DN_OSPOSIXSyncPrimitiveType_Mutex,
|
||||
DN_OSPOSIXSyncPrimitiveType_ConditionVariable,
|
||||
};
|
||||
|
||||
struct DN_POSIXSyncPrimitive
|
||||
{
|
||||
union
|
||||
{
|
||||
sem_t sem;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cv;
|
||||
};
|
||||
DN_POSIXSyncPrimitive *next;
|
||||
};
|
||||
|
||||
struct DN_POSIXCore
|
||||
{
|
||||
DN_POSIXSyncPrimitive *sync_primitive_free_list;
|
||||
};
|
||||
|
||||
DN_API void DN_Posix_ThreadSetName(DN_Str8 name);
|
||||
DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus();
|
||||
|
||||
+9
-11
@@ -35,9 +35,9 @@ DN_API void DN_OS_TLSInit(DN_OSTLS *tls, DN_OSTLSInitArgs args)
|
||||
// TODO: We shouldn't have the no alloc track flag here but the initial TLS
|
||||
// init on OS init happens before CORE init. CORE init is the one responsible
|
||||
// for setting up the alloc tracking data structures.
|
||||
DN_ForIndexU(index, DN_OSTLSArena_Count) {
|
||||
DN_Arena *arena = tls->arenas + index;
|
||||
switch (DN_CAST(DN_OSTLSArena) index) {
|
||||
for (DN_ForItCArray(it, DN_Arena, tls->arenas)) {
|
||||
DN_Arena *arena = it.data;
|
||||
switch (DN_CAST(DN_OSTLSArena) it.index) {
|
||||
default: *arena = DN_Arena_InitFromOSVMem(reserve, commit, DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_NoAllocTrack); break;
|
||||
case DN_OSTLSArena_ErrorSink: *arena = DN_Arena_InitFromOSVMem(err_sink_reserve, err_sink_commit, DN_ArenaFlags_AllocCanLeak | DN_ArenaFlags_NoAllocTrack); break;
|
||||
case DN_OSTLSArena_Count: DN_InvalidCodePath; break;
|
||||
@@ -54,10 +54,8 @@ DN_API void DN_OS_TLSDeinit(DN_OSTLS *tls)
|
||||
tls->init = false;
|
||||
tls->err_sink = {};
|
||||
tls->arena_stack_index = {};
|
||||
DN_ForIndexU(index, DN_OSTLSArena_Count) {
|
||||
DN_Arena *arena = tls->arenas + index;
|
||||
DN_Arena_Deinit(arena);
|
||||
}
|
||||
for (DN_ForItCArray(it, DN_Arena, tls->arenas))
|
||||
DN_Arena_Deinit(it.data);
|
||||
}
|
||||
|
||||
DN_THREAD_LOCAL DN_OSTLS *g_dn_curr_thread_tls;
|
||||
@@ -170,7 +168,7 @@ DN_API DN_OSErrSink *DN_OS_ErrSinkBegin_(DN_OSErrSinkMode mode, DN_CallSite call
|
||||
if (tls->err_sink.stack_size == DN_ArrayCountU(err->stack)) {
|
||||
DN_Str8Builder builder = DN_Str8Builder_InitFromTLS();
|
||||
DN_USize counter = 0;
|
||||
DN_ForItSize(it, DN_OSErrSinkNode, err->stack, err->stack_size) {
|
||||
for (DN_ForItSize(it, DN_OSErrSinkNode, err->stack, err->stack_size)) {
|
||||
DN_MSVC_WARNING_PUSH
|
||||
DN_MSVC_WARNING_DISABLE(6284) // Object passed as _Param_(4) when a string is required in call to 'DN_Str8Builder_AppendF' Actual type: 'struct DN_Str8'.
|
||||
DN_Str8Builder_AppendF(&builder, " [%04zu] %S:%u %S\n", counter++, it.data->call_site.file, it.data->call_site.line, it.data->call_site.function);
|
||||
@@ -185,9 +183,9 @@ DN_API DN_OSErrSink *DN_OS_ErrSinkBegin_(DN_OSErrSinkMode mode, DN_CallSite call
|
||||
}
|
||||
|
||||
DN_OSErrSinkNode *node = tls->err_sink.stack + tls->err_sink.stack_size++;
|
||||
node->arena_pos = arena_pos;
|
||||
node->mode = mode;
|
||||
node->call_site = call_site;
|
||||
node->arena_pos = arena_pos;
|
||||
node->mode = mode;
|
||||
node->call_site = call_site;
|
||||
DN_DLList_InitArena(node->msg_sentinel, DN_OSErrSinkMsg, result->arena);
|
||||
|
||||
// NOTE: Handle allocation error
|
||||
|
||||
+1843
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,71 @@
|
||||
#if !defined(DN_OS_WIN32_H)
|
||||
#define DN_OS_WIN32_H
|
||||
|
||||
struct DN_W32Error
|
||||
{
|
||||
unsigned long code;
|
||||
DN_Str8 msg;
|
||||
};
|
||||
|
||||
struct DN_W32FolderIteratorW
|
||||
{
|
||||
void *handle;
|
||||
DN_Str16 file_name;
|
||||
wchar_t file_name_buf[512];
|
||||
};
|
||||
|
||||
enum DN_W32SyncPrimitiveType
|
||||
{
|
||||
DN_OSW32SyncPrimitiveType_Semaphore,
|
||||
DN_OSW32SyncPrimitiveType_Mutex,
|
||||
DN_OSW32SyncPrimitiveType_ConditionVariable,
|
||||
};
|
||||
|
||||
struct DN_W32SyncPrimitive
|
||||
{
|
||||
union
|
||||
{
|
||||
void *sem;
|
||||
CRITICAL_SECTION mutex;
|
||||
CONDITION_VARIABLE cv;
|
||||
};
|
||||
|
||||
DN_W32SyncPrimitive *next;
|
||||
};
|
||||
|
||||
typedef HRESULT DN_W32SetThreadDescriptionFunc(HANDLE hThread, PWSTR const lpThreadDescription);
|
||||
struct DN_W32Core
|
||||
{
|
||||
DN_W32SetThreadDescriptionFunc *set_thread_description;
|
||||
LARGE_INTEGER qpc_frequency;
|
||||
void *bcrypt_rng_handle;
|
||||
bool bcrypt_init_success;
|
||||
bool sym_initialised;
|
||||
|
||||
CRITICAL_SECTION sync_primitive_free_list_mutex;
|
||||
DN_W32SyncPrimitive *sync_primitive_free_list;
|
||||
};
|
||||
|
||||
DN_API void DN_W32_ThreadSetName (DN_Str8 name);
|
||||
|
||||
DN_API DN_Str16 DN_W32_ErrorCodeToMsg16Alloc(uint32_t error_code);
|
||||
DN_API DN_W32Error DN_W32_ErrorCodeToMsg (DN_Arena *arena, uint32_t error_code);
|
||||
DN_API DN_W32Error DN_W32_ErrorCodeToMsgAlloc (uint32_t error_code);
|
||||
DN_API DN_W32Error DN_W32_LastError (DN_Arena *arena);
|
||||
DN_API DN_W32Error DN_W32_LastErrorAlloc ();
|
||||
DN_API void DN_W32_MakeProcessDPIAware ();
|
||||
|
||||
// NOTE: Windows Str8 <-> Str16 ////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_Str16 DN_W32_Str8ToStr16 (DN_Arena *arena, DN_Str8 src);
|
||||
DN_API int DN_W32_Str8ToStr16Buffer (DN_Str16 src, char *dest, int dest_size);
|
||||
DN_API DN_Str8 DN_W32_Str16ToStr8 (DN_Arena *arena, DN_Str16 src);
|
||||
DN_API int DN_W32_Str16ToStr8Buffer (DN_Str16 src, char *dest, int dest_size);
|
||||
DN_API DN_Str8 DN_W32_Str16ToStr8FromHeap(DN_Str16 src);
|
||||
|
||||
// NOTE: Path navigation ///////////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_Str16 DN_W32_EXEPathW (DN_Arena *arena);
|
||||
DN_API DN_Str16 DN_W32_EXEDirW (DN_Arena *arena);
|
||||
DN_API DN_Str8 DN_W32_WorkingDir (DN_Arena *arena, DN_Str8 suffix);
|
||||
DN_API DN_Str16 DN_W32_WorkingDirW (DN_Arena *arena, DN_Str16 suffix);
|
||||
DN_API bool DN_W32_DirWIterate (DN_Str16 path, DN_W32FolderIteratorW *it);
|
||||
#endif // !defined(DN_OS_WIN32)
|
||||
@@ -296,6 +296,10 @@
|
||||
WORD Identifier;
|
||||
} RTL_CRITICAL_SECTION_DEBUG, *PRTL_CRITICAL_SECTION_DEBUG, RTL_RESOURCE_DEBUG, *PRTL_RESOURCE_DEBUG;
|
||||
|
||||
typedef struct _RTL_CONDITION_VARIABLE {
|
||||
PVOID Ptr;
|
||||
} RTL_CONDITION_VARIABLE, *PRTL_CONDITION_VARIABLE;
|
||||
|
||||
#pragma pack(push, 8)
|
||||
typedef struct _RTL_CRITICAL_SECTION {
|
||||
PRTL_CRITICAL_SECTION_DEBUG DebugInfo;
|
||||
@@ -1065,8 +1069,15 @@
|
||||
}
|
||||
|
||||
// NOTE: um/synchapi.h /////////////////////////////////////////////////////////////////////////
|
||||
typedef RTL_CONDITION_VARIABLE CONDITION_VARIABLE, *PCONDITION_VARIABLE;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
__declspec(dllimport) VOID __stdcall InitializeConditionVariable (CONDITION_VARIABLE *ConditionVariable);
|
||||
__declspec(dllimport) VOID __stdcall WakeConditionVariable (CONDITION_VARIABLE *ConditionVariable);
|
||||
__declspec(dllimport) VOID __stdcall WakeAllConditionVariable (CONDITION_VARIABLE *ConditionVariable);
|
||||
__declspec(dllimport) BOOL __stdcall SleepConditionVariableCS (CONDITION_VARIABLE *ConditionVariable, CRITICAL_SECTION *CriticalSection, DWORD dwMilliseconds);
|
||||
|
||||
__declspec(dllimport) VOID __stdcall InitializeCriticalSection (CRITICAL_SECTION *lpCriticalSection);
|
||||
__declspec(dllimport) VOID __stdcall EnterCriticalSection (CRITICAL_SECTION *lpCriticalSection);
|
||||
__declspec(dllimport) VOID __stdcall LeaveCriticalSection (CRITICAL_SECTION *lpCriticalSection);
|
||||
@@ -1075,6 +1086,7 @@
|
||||
__declspec(dllimport) DWORD __stdcall SetCriticalSectionSpinCount (CRITICAL_SECTION *lpCriticalSection, DWORD dwSpinCount);
|
||||
__declspec(dllimport) BOOL __stdcall TryEnterCriticalSection (CRITICAL_SECTION *lpCriticalSection);
|
||||
__declspec(dllimport) VOID __stdcall DeleteCriticalSection (CRITICAL_SECTION *lpCriticalSection);
|
||||
|
||||
__declspec(dllimport) DWORD __stdcall WaitForSingleObject (HANDLE hHandle, DWORD dwMilliseconds);
|
||||
__declspec(dllimport) BOOL __stdcall ReleaseSemaphore (HANDLE hSemaphore, LONG lReleaseCount, LONG *lpPreviousCount);
|
||||
__declspec(dllimport) VOID __stdcall Sleep (DWORD dwMilliseconds);
|
||||
|
||||
Reference in New Issue
Block a user