diff --git a/Source/OS/dn_os.h b/Source/OS/dn_os.h index 90d9a88..9957ded 100644 --- a/Source/OS/dn_os.h +++ b/Source/OS/dn_os.h @@ -174,6 +174,11 @@ struct DN_OSSemaphore DN_U64 handle; }; +struct DN_OSBarrier +{ + DN_U64 handle; +}; + enum DN_OSSemaphoreWaitResult { DN_OSSemaphoreWaitResult_Failed, @@ -384,11 +389,14 @@ DN_API DN_OSExecResult DN_OS_Exec (D DN_API DN_OSExecResult DN_OS_ExecOrAbort (DN_Slice cmd_line, DN_OSExecArgs *args, DN_Arena *arena); 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); +DN_API DN_OSBarrier DN_OS_BarrierInit (DN_U32 thread_count); +DN_API void DN_OS_BarrierDeinit (DN_OSBarrier *barrier); +DN_API void DN_OS_BarrierWait (DN_OSBarrier *barrier); + 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); diff --git a/Source/OS/dn_os_posix.cpp b/Source/OS/dn_os_posix.cpp index 323d249..3a44846 100644 --- a/Source/OS/dn_os_posix.cpp +++ b/Source/OS/dn_os_posix.cpp @@ -1033,14 +1033,14 @@ DN_API DN_OSExecResult DN_OS_ExecPump(DN_OSExecAsyncHandle handle, return result; } -static DN_OSPosixSyncPrimitive *DN_OS_U64ToPOSIXSyncPrimitive_(DN_U64 u64) +static DN_OSPosixSyncPrimitive *DN_OS_PosixU64ToSyncPrimitive_(DN_U64 u64) { DN_OSPosixSyncPrimitive *result = nullptr; DN_Memcpy(&result, &u64, sizeof(result)); return result; } -static DN_U64 DN_POSIX_SyncPrimitiveToU64(DN_OSPosixSyncPrimitive *primitive) +static DN_U64 DN_OS_PosixSyncPrimitiveToU64(DN_OSPosixSyncPrimitive *primitive) { DN_U64 result = 0; static_assert(sizeof(result) >= sizeof(primitive), "Pointer size mis-match"); @@ -1067,7 +1067,7 @@ static DN_OSPosixSyncPrimitive *DN_POSIX_AllocSyncPrimitive_() return result; } -static void DN_POSIX_DeallocSyncPrimitive_(DN_OSPosixSyncPrimitive *primitive) +static void DN_OS_PosixDeallocSyncPrimitive_(DN_OSPosixSyncPrimitive *primitive) { if (primitive) { DN_OSPosixCore *posix = DN_OS_GetPOSIXCore_(); @@ -1078,7 +1078,7 @@ static void DN_POSIX_DeallocSyncPrimitive_(DN_OSPosixSyncPrimitive *primitive) } } -// NOTE: DN_OSSemaphore //////////////////////////////////////////////////////////////////////////// +// NOTE: DN_OSSemaphore DN_API DN_OSSemaphore DN_OS_SemaphoreInit(DN_U32 initial_count) { DN_OSSemaphore result = {}; @@ -1086,9 +1086,9 @@ DN_API DN_OSSemaphore DN_OS_SemaphoreInit(DN_U32 initial_count) 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); + result.handle = DN_OS_PosixSyncPrimitiveToU64(primitive); else - DN_POSIX_DeallocSyncPrimitive_(primitive); + DN_OS_PosixDeallocSyncPrimitive_(primitive); } return result; } @@ -1096,9 +1096,9 @@ DN_API DN_OSSemaphore DN_OS_SemaphoreInit(DN_U32 initial_count) DN_API void DN_OS_SemaphoreDeinit(DN_OSSemaphore *semaphore) { if (semaphore && semaphore->handle != 0) { - DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle); + DN_OSPosixSyncPrimitive *primitive = DN_OS_PosixU64ToSyncPrimitive_(semaphore->handle); sem_destroy(&primitive->sem); - DN_POSIX_DeallocSyncPrimitive_(primitive); + DN_OS_PosixDeallocSyncPrimitive_(primitive); *semaphore = {}; } } @@ -1106,7 +1106,7 @@ DN_API void DN_OS_SemaphoreDeinit(DN_OSSemaphore *semaphore) DN_API void DN_OS_SemaphoreIncrement(DN_OSSemaphore *semaphore, DN_U32 amount) { if (semaphore && semaphore->handle != 0) { - DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle); + DN_OSPosixSyncPrimitive *primitive = DN_OS_PosixU64ToSyncPrimitive_(semaphore->handle); #if defined(DN_OS_WIN32) sem_post_multiple(&primitive->sem, amount); // mingw extension #else @@ -1123,7 +1123,7 @@ DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait(DN_OSSemaphore *semaphore, if (!semaphore || semaphore->handle == 0) return result; - DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(semaphore->handle); + DN_OSPosixSyncPrimitive *primitive = DN_OS_PosixU64ToSyncPrimitive_(semaphore->handle); if (timeout_ms == DN_OS_SEMAPHORE_INFINITE_TIMEOUT) { int wait_result = 0; do { @@ -1147,16 +1147,49 @@ DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait(DN_OSSemaphore *semaphore, return result; } -// NOTE: DN_OSMutex //////////////////////////////////////////////////////////////////////////////// +DN_API DN_OSBarrier DN_OS_BarrierInit(DN_U32 thread_count) +{ + DN_OSPosixSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_(); + DN_OSBarrier result = {}; + if (primitive) { + int init_result = pthread_barrier_init(&primitive->barrier, /*attr*/ NULL, thread_count); + if (init_result == 0) { + result.handle = DN_OS_PosixSyncPrimitiveToU64(primitive); + } else { + DN_OS_PosixDeallocSyncPrimitive_(primitive); + } + } + return result; +} + +DN_API void DN_OS_BarrierDeinit(DN_OSBarrier *barrier) +{ + if (barrier && barrier->handle != 0) { + DN_OSPosixSyncPrimitive *primitive = DN_OS_PosixU64ToSyncPrimitive_(barrier->handle); + int del_result = pthread_barrier_destroy(&primitive->barrier); + DN_Assert(del_result == 0); + DN_OS_PosixDeallocSyncPrimitive_(primitive); + } +} + +DN_API void DN_OS_BarrierWait(DN_OSBarrier *barrier) +{ + if (barrier && barrier->handle != 0) { + DN_OSPosixSyncPrimitive *primitive = DN_OS_PosixU64ToSyncPrimitive_(barrier->handle); + pthread_barrier_wait(&primitive->barrier); + } +} + +// NOTE: DN_OSMutex DN_API DN_OSMutex DN_OS_MutexInit() { DN_OSPosixSyncPrimitive *primitive = DN_POSIX_AllocSyncPrimitive_(); - DN_OSMutex result = {}; + DN_OSMutex result = {}; if (primitive) { if (pthread_mutex_init(&primitive->mutex, nullptr) == 0) - result.handle = DN_POSIX_SyncPrimitiveToU64(primitive); + result.handle = DN_OS_PosixSyncPrimitiveToU64(primitive); else - DN_POSIX_DeallocSyncPrimitive_(primitive); + DN_OS_PosixDeallocSyncPrimitive_(primitive); } return result; } @@ -1164,9 +1197,9 @@ DN_API DN_OSMutex DN_OS_MutexInit() DN_API void DN_OS_MutexDeinit(DN_OSMutex *mutex) { if (mutex && mutex->handle != 0) { - DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle); + DN_OSPosixSyncPrimitive *primitive = DN_OS_PosixU64ToSyncPrimitive_(mutex->handle); pthread_mutex_destroy(&primitive->mutex); - DN_POSIX_DeallocSyncPrimitive_(primitive); + DN_OS_PosixDeallocSyncPrimitive_(primitive); *mutex = {}; } } @@ -1174,7 +1207,7 @@ DN_API void DN_OS_MutexDeinit(DN_OSMutex *mutex) DN_API void DN_OS_MutexLock(DN_OSMutex *mutex) { if (mutex && mutex->handle != 0) { - DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle); + DN_OSPosixSyncPrimitive *primitive = DN_OS_PosixU64ToSyncPrimitive_(mutex->handle); pthread_mutex_lock(&primitive->mutex); } } @@ -1182,7 +1215,7 @@ DN_API void DN_OS_MutexLock(DN_OSMutex *mutex) DN_API void DN_OS_MutexUnlock(DN_OSMutex *mutex) { if (mutex && mutex->handle != 0) { - DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle); + DN_OSPosixSyncPrimitive *primitive = DN_OS_PosixU64ToSyncPrimitive_(mutex->handle); pthread_mutex_unlock(&primitive->mutex); } } @@ -1193,9 +1226,9 @@ DN_API DN_OSConditionVariable DN_OS_ConditionVariableInit() DN_OSConditionVariable result = {}; if (primitive) { if (pthread_cond_init(&primitive->cv, nullptr) == 0) - result.handle = DN_POSIX_SyncPrimitiveToU64(primitive); + result.handle = DN_OS_PosixSyncPrimitiveToU64(primitive); else - DN_POSIX_DeallocSyncPrimitive_(primitive); + DN_OS_PosixDeallocSyncPrimitive_(primitive); } return result; } @@ -1203,9 +1236,9 @@ DN_API DN_OSConditionVariable DN_OS_ConditionVariableInit() DN_API void DN_OS_ConditionVariableDeinit(DN_OSConditionVariable *cv) { if (cv && cv->handle != 0) { - DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle); + DN_OSPosixSyncPrimitive *primitive = DN_OS_PosixU64ToSyncPrimitive_(cv->handle); pthread_cond_destroy(&primitive->cv); - DN_POSIX_DeallocSyncPrimitive_(primitive); + DN_OS_PosixDeallocSyncPrimitive_(primitive); *cv = {}; } } @@ -1214,8 +1247,8 @@ DN_API bool DN_OS_ConditionVariableWaitUntil(DN_OSConditionVariable *cv, DN_OSMu { bool result = false; if (cv && mutex && mutex->handle != 0 && cv->handle != 0) { - DN_OSPosixSyncPrimitive *cv_primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle); - DN_OSPosixSyncPrimitive *mutex_primitive = DN_OS_U64ToPOSIXSyncPrimitive_(mutex->handle); + DN_OSPosixSyncPrimitive *cv_primitive = DN_OS_PosixU64ToSyncPrimitive_(cv->handle); + DN_OSPosixSyncPrimitive *mutex_primitive = DN_OS_PosixU64ToSyncPrimitive_(mutex->handle); struct timespec time = {}; time.tv_sec = end_ts_ms / 1'000; @@ -1236,7 +1269,7 @@ DN_API bool DN_OS_ConditionVariableWait(DN_OSConditionVariable *cv, DN_OSMutex * DN_API void DN_OS_ConditionVariableSignal(DN_OSConditionVariable *cv) { if (cv && cv->handle != 0) { - DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle); + DN_OSPosixSyncPrimitive *primitive = DN_OS_PosixU64ToSyncPrimitive_(cv->handle); pthread_cond_signal(&primitive->cv); } } @@ -1244,12 +1277,12 @@ DN_API void DN_OS_ConditionVariableSignal(DN_OSConditionVariable *cv) DN_API void DN_OS_ConditionVariableBroadcast(DN_OSConditionVariable *cv) { if (cv && cv->handle != 0) { - DN_OSPosixSyncPrimitive *primitive = DN_OS_U64ToPOSIXSyncPrimitive_(cv->handle); + DN_OSPosixSyncPrimitive *primitive = DN_OS_PosixU64ToSyncPrimitive_(cv->handle); pthread_cond_broadcast(&primitive->cv); } } -// NOTE: DN_OSThread /////////////////////////////////////////////////////////////////////////////// +// NOTE: DN_OSThread static void *DN_OS_ThreadFunc_(void *user_context) { DN_OS_ThreadExecute_(user_context); diff --git a/Source/OS/dn_os_posix.h b/Source/OS/dn_os_posix.h index 75eeb95..8ff9c7c 100644 --- a/Source/OS/dn_os_posix.h +++ b/Source/OS/dn_os_posix.h @@ -46,9 +46,10 @@ struct DN_OSPosixSyncPrimitive { union { - sem_t sem; - pthread_mutex_t mutex; - pthread_cond_t cv; + sem_t sem; + pthread_mutex_t mutex; + pthread_cond_t cv; + pthread_barrier_t barrier; }; DN_OSPosixSyncPrimitive *next; }; diff --git a/Source/OS/dn_os_w32.cpp b/Source/OS/dn_os_w32.cpp index 1c890b6..7611538 100644 --- a/Source/OS/dn_os_w32.cpp +++ b/Source/OS/dn_os_w32.cpp @@ -1019,7 +1019,7 @@ static DN_OSW32SyncPrimitive *DN_OS_U64ToW32SyncPrimitive_(DN_U64 u64) return result; } -static DN_U64 DN_OSW32SyncPrimitiveToU64(DN_OSW32SyncPrimitive *primitive) +static DN_U64 DN_OS_W32SyncPrimitiveToU64(DN_OSW32SyncPrimitive *primitive) { DN_U64 result = 0; static_assert(sizeof(result) == sizeof(primitive), "Pointer size mis-match"); @@ -1057,16 +1057,16 @@ static void DN_OS_W32DeallocSyncPrimitive_(DN_OSW32SyncPrimitive *primitive) } } -// NOTE: DN_OSSemaphore //////////////////////////////////////////////////////////////////////////// +// NOTE: DN_OSSemaphore DN_API DN_OSSemaphore DN_OS_SemaphoreInit(DN_U32 initial_count) { - DN_OSSemaphore result = {}; + DN_OSSemaphore result = {}; DN_OSW32SyncPrimitive *primitive = DN_OS_W32AllocSyncPrimitive_(); if (primitive) { SECURITY_ATTRIBUTES security_attribs = {}; primitive->sem = CreateSemaphoreA(&security_attribs, initial_count, INT32_MAX, nullptr /*name*/); if (primitive->sem) - result.handle = DN_OSW32SyncPrimitiveToU64(primitive); + result.handle = DN_OS_W32SyncPrimitiveToU64(primitive); if (!primitive->sem) DN_OS_W32DeallocSyncPrimitive_(primitive); } @@ -1106,14 +1106,48 @@ DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait(DN_OSSemaphore *semaphore, D return result; } -// NOTE: DN_OSMutex //////////////////////////////////////////////////////////////////////////////// +// NOTE: DN_OSBarrier +DN_API DN_OSBarrier DN_OS_BarrierInit(DN_U32 thread_count) +{ + DN_OSBarrier result = {}; + DN_OSW32SyncPrimitive *primitive = DN_OS_W32AllocSyncPrimitive_(); + if (primitive) { + BOOL init_result = InitializeSynchronizationBarrier(&primitive->barrier, thread_count, /*lSpinCount=*/-1); + if (init_result) { + result.handle = DN_OS_W32SyncPrimitiveToU64(primitive); + } else { + DN_OS_W32DeallocSyncPrimitive_(primitive); + } + } + return result; +} + +DN_API void DN_OS_BarrierDeinit(DN_OSBarrier *barrier) +{ + if (barrier && barrier->handle != 0) { + DN_OSW32SyncPrimitive *primitive = DN_OS_U64ToW32SyncPrimitive_(barrier->handle); + bool result = DeleteSynchronizationBarrier(&primitive->barrier); + DN_Assert(result); + DN_OS_W32DeallocSyncPrimitive_(primitive); + } +} + +DN_API void DN_OS_BarrierWait(DN_OSBarrier *barrier) +{ + if (barrier && barrier->handle != 0) { + DN_OSW32SyncPrimitive *primitive = DN_OS_U64ToW32SyncPrimitive_(barrier->handle); + EnterSynchronizationBarrier(&primitive->barrier, /*dwFlags=*/ 0); + } +} + +// NOTE: DN_OSMutex DN_API DN_OSMutex DN_OS_MutexInit() { DN_OSW32SyncPrimitive *primitive = DN_OS_W32AllocSyncPrimitive_(); if (primitive) InitializeCriticalSection(&primitive->mutex); DN_OSMutex result = {}; - result.handle = DN_OSW32SyncPrimitiveToU64(primitive); + result.handle = DN_OS_W32SyncPrimitiveToU64(primitive); return result; } @@ -1150,7 +1184,7 @@ DN_API DN_OSConditionVariable DN_OS_ConditionVariableInit() if (primitive) InitializeConditionVariable(&primitive->cv); DN_OSConditionVariable result = {}; - result.handle = DN_OSW32SyncPrimitiveToU64(primitive); + result.handle = DN_OS_W32SyncPrimitiveToU64(primitive); return result; } diff --git a/Source/OS/dn_os_w32.h b/Source/OS/dn_os_w32.h index 387246e..d226a9e 100644 --- a/Source/OS/dn_os_w32.h +++ b/Source/OS/dn_os_w32.h @@ -25,15 +25,17 @@ enum DN_OSW32SyncPrimitiveType DN_OSW32SyncPrimitiveType_Semaphore, DN_OSW32SyncPrimitiveType_Mutex, DN_OSW32SyncPrimitiveType_ConditionVariable, + DN_OSW32SyncPrimitiveType_Barrier, }; struct DN_OSW32SyncPrimitive { union { - void *sem; - CRITICAL_SECTION mutex; - CONDITION_VARIABLE cv; + void *sem; + CRITICAL_SECTION mutex; + CONDITION_VARIABLE cv; + SYNCHRONIZATION_BARRIER barrier; }; DN_OSW32SyncPrimitive *next; diff --git a/Source/OS/dn_os_windows.h b/Source/OS/dn_os_windows.h index fcb5f69..217f92e 100644 --- a/Source/OS/dn_os_windows.h +++ b/Source/OS/dn_os_windows.h @@ -329,6 +329,14 @@ DWORD flags; // options } MODLOAD_DATA, *PMODLOAD_DATA; + typedef struct _RTL_BARRIER { + DWORD Reserved1; + DWORD Reserved2; + ULONG_PTR Reserved3[2]; + DWORD Reserved4; + DWORD Reserved5; + } RTL_BARRIER, *PRTL_BARRIER; + #define SLMFLAG_VIRTUAL 0x1 #define SLMFLAG_ALT_INDEX 0x2 #define SLMFLAG_NO_SYMBOLS 0x4 @@ -1076,6 +1084,14 @@ // NOTE: um/synchapi.h ///////////////////////////////////////////////////////////////////////// typedef RTL_CONDITION_VARIABLE CONDITION_VARIABLE, *PCONDITION_VARIABLE; + typedef RTL_BARRIER SYNCHRONIZATION_BARRIER; + typedef PRTL_BARRIER PSYNCHRONIZATION_BARRIER; + typedef PRTL_BARRIER LPSYNCHRONIZATION_BARRIER; + + #define SYNCHRONIZATION_BARRIER_FLAGS_SPIN_ONLY 0x01 + #define SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY 0x02 + #define SYNCHRONIZATION_BARRIER_FLAGS_NO_DELETE 0x04 + extern "C" { __declspec(dllimport) VOID __stdcall InitializeConditionVariable (CONDITION_VARIABLE *ConditionVariable); @@ -1095,6 +1111,10 @@ __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); + + __declspec(dllimport) BOOL __stdcall EnterSynchronizationBarrier (SYNCHRONIZATION_BARRIER *lpBarrier, DWORD dwFlags); + __declspec(dllimport) BOOL __stdcall InitializeSynchronizationBarrier (SYNCHRONIZATION_BARRIER *lpBarrier, LONG lTotalThreads, LONG lSpinCount); + __declspec(dllimport) BOOL __stdcall DeleteSynchronizationBarrier (SYNCHRONIZATION_BARRIER *lpBarrier); } // NOTE: um/profileapi.h ///////////////////////////////////////////////////////////////////////