summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Linn <jl@conductive.de>2020-12-28 11:43:11 -0800
committerJoel Linn <jl@conductive.de>2020-12-28 11:43:11 -0800
commitef55169b72ab348b3156efed622be2338f63ccae (patch)
tree2a6d681bb0094f56891ab722207d58dc03f2c835
parentf34d3cad2e30eb65704b4b7f7db1fe612b1adbba (diff)
downloadsdl-ef55169b72ab348b3156efed622be2338f63ccae.tar.gz
Add SDL_cond implementation using Windows Condition Variables
Is automatically used when the SRW SDL_mutex implementation is active. Otherwise falls back to the generic implementation. v2: - Rebase onto master b69400b305a5
-rw-r--r--VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj1
-rw-r--r--VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj.filters3
-rw-r--r--VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj1
-rw-r--r--VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj.filters3
-rw-r--r--VisualC/SDL/SDL.vcxproj1
-rw-r--r--VisualC/SDL/SDL.vcxproj.filters1
-rw-r--r--include/SDL_hints.h3
-rw-r--r--src/thread/windows/SDL_syscond_srw.c169
-rw-r--r--src/thread/windows/SDL_sysmutex.c36
-rw-r--r--src/thread/windows/SDL_sysmutex_c.h69
10 files changed, 254 insertions, 33 deletions
diff --git a/VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj b/VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj
index d684c8e23..61060211c 100644
--- a/VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj
+++ b/VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj
@@ -133,6 +133,7 @@
<ClInclude Include="..\..\src\thread\SDL_systhread.h" />
<ClInclude Include="..\..\src\thread\SDL_thread_c.h" />
<ClInclude Include="..\..\src\thread\generic\SDL_syscond_c.h" />
+ <ClInclude Include="..\..\src\thread\windows\SDL_sysmutex_c.h" />
<ClInclude Include="..\..\src\thread\windows\SDL_systhread_c.h" />
<ClInclude Include="..\..\src\timer\SDL_timer_c.h" />
<ClInclude Include="..\..\src\video\dummy\SDL_nullevents_c.h" />
diff --git a/VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj.filters b/VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj.filters
index 0019ae0f1..c041cac46 100644
--- a/VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj.filters
+++ b/VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj.filters
@@ -384,6 +384,9 @@
<ClInclude Include="..\..\src\thread\generic\SDL_syscond_c.h">
<Filter>Source Files</Filter>
</ClInclude>
+ <ClInclude Include="..\..\src\thread\windows\SDL_sysmutex_c.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
<ClInclude Include="..\..\src\thread\windows\SDL_systhread_c.h">
<Filter>Source Files</Filter>
</ClInclude>
diff --git a/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj b/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj
index 3d756ceab..e774d6720 100644
--- a/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj
+++ b/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj
@@ -147,6 +147,7 @@
<ClInclude Include="..\..\src\sensor\SDL_syssensor.h" />
<ClInclude Include="..\..\src\thread\SDL_thread_c.h" />
<ClInclude Include="..\..\src\thread\generic\SDL_syscond_c.h" />
+ <ClInclude Include="..\..\src\thread\windows\SDL_sysmutex_c.h" />
<ClInclude Include="..\..\src\thread\windows\SDL_systhread_c.h" />
<ClInclude Include="..\..\src\timer\SDL_timer_c.h" />
<ClInclude Include="..\..\src\video\dummy\SDL_nullevents_c.h" />
diff --git a/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj.filters b/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj.filters
index aa52d8a5c..56db7083a 100644
--- a/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj.filters
+++ b/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj.filters
@@ -393,6 +393,9 @@
<ClInclude Include="..\..\src\thread\generic\SDL_syscond_c.h">
<Filter>Source Files</Filter>
</ClInclude>
+ <ClInclude Include="..\..\src\thread\windows\SDL_sysmutex_c.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
<ClInclude Include="..\..\src\thread\windows\SDL_systhread_c.h">
<Filter>Source Files</Filter>
</ClInclude>
diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj
index c5739535d..9915d0dcf 100644
--- a/VisualC/SDL/SDL.vcxproj
+++ b/VisualC/SDL/SDL.vcxproj
@@ -360,6 +360,7 @@
<ClInclude Include="..\..\src\thread\SDL_systhread.h" />
<ClInclude Include="..\..\src\thread\SDL_thread_c.h" />
<ClInclude Include="..\..\src\thread\generic\SDL_syscond_c.h" />
+ <ClInclude Include="..\..\src\thread\windows\SDL_sysmutex_c.h" />
<ClInclude Include="..\..\src\thread\windows\SDL_systhread_c.h" />
<ClInclude Include="..\..\src\timer\SDL_timer_c.h" />
<ClInclude Include="..\..\src\video\dummy\SDL_nullevents_c.h" />
diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters
index d7cddb140..c7ec35c08 100644
--- a/VisualC/SDL/SDL.vcxproj.filters
+++ b/VisualC/SDL/SDL.vcxproj.filters
@@ -302,6 +302,7 @@
<ClInclude Include="..\..\src\thread\SDL_systhread.h" />
<ClInclude Include="..\..\src\thread\SDL_thread_c.h" />
<ClInclude Include="..\..\src\thread\generic\SDL_syscond_c.h" />
+ <ClInclude Include="..\..\src\thread\windows\SDL_sysmutex_c.h" />
<ClInclude Include="..\..\src\thread\windows\SDL_systhread_c.h" />
<ClInclude Include="..\..\src\timer\SDL_timer_c.h" />
<ClInclude Include="..\..\src\video\dummy\SDL_nullevents_c.h" />
diff --git a/include/SDL_hints.h b/include/SDL_hints.h
index bac14a736..80b572bdb 100644
--- a/include/SDL_hints.h
+++ b/include/SDL_hints.h
@@ -1202,6 +1202,9 @@ extern "C" {
* They offer better performance, allocate no kernel ressources and
* use less memory. SDL will fall back to Critical Sections on older
* OS versions or if forced to by this hint.
+ * This also affects Condition Variables. When SRW mutexes are used,
+ * SDL will use Windows Condition Variables as well. Else, a generic
+ * SDL_cond implementation will be used that works with all mutexes.
*
* This variable can be set to the following values:
* "0" - Use SRW Locks when available. If not, fall back to Critical Sections. (default)
diff --git a/src/thread/windows/SDL_syscond_srw.c b/src/thread/windows/SDL_syscond_srw.c
index ef8c802f3..e2093c91a 100644
--- a/src/thread/windows/SDL_syscond_srw.c
+++ b/src/thread/windows/SDL_syscond_srw.c
@@ -24,6 +24,7 @@
#include "SDL_thread.h"
#include "../generic/SDL_syscond_c.h"
+#include "SDL_sysmutex_c.h"
typedef SDL_cond * (*pfnSDL_CreateCond)(void);
typedef void (*pfnSDL_DestroyCond)(SDL_cond *);
@@ -45,6 +46,136 @@ typedef struct SDL_cond_impl_t
/* Implementation will be chosen at runtime based on available Kernel features */
static SDL_cond_impl_t SDL_cond_impl_active = {0};
+
+/**
+ * Native Windows Condition Variable (SRW Locks)
+ */
+
+#ifndef CONDITION_VARIABLE_INIT
+#define CONDITION_VARIABLE_INIT {0}
+typedef struct CONDITION_VARIABLE {
+ PVOID Ptr;
+} CONDITION_VARIABLE, *PCONDITION_VARIABLE;
+#endif
+
+#if __WINRT__
+#define pWakeConditionVariable WakeConditionVariable
+#define pWakeAllConditionVariable WakeAllConditionVariable
+#define pSleepConditionVariableSRW SleepConditionVariableSRW
+#else
+typedef VOID(WINAPI *pfnWakeConditionVariable)(PCONDITION_VARIABLE);
+typedef VOID(WINAPI *pfnWakeAllConditionVariable)(PCONDITION_VARIABLE);
+typedef BOOL(WINAPI *pfnSleepConditionVariableSRW)(PCONDITION_VARIABLE, PSRWLOCK, DWORD, ULONG);
+
+static pfnWakeConditionVariable pWakeConditionVariable = NULL;
+static pfnWakeAllConditionVariable pWakeAllConditionVariable = NULL;
+static pfnSleepConditionVariableSRW pSleepConditionVariableSRW = NULL;
+#endif
+
+typedef struct SDL_cond_srw
+{
+ CONDITION_VARIABLE cond;
+} SDL_cond_srw;
+
+
+static SDL_cond *
+SDL_CreateCond_srw(void)
+{
+ SDL_cond_srw *cond;
+
+ /* Relies on CONDITION_VARIABLE_INIT == 0. */
+ cond = (SDL_cond_srw *) SDL_calloc(1, sizeof(*cond));
+ if (!cond) {
+ SDL_OutOfMemory();
+ }
+
+ return (SDL_cond *)cond;
+}
+
+static void
+SDL_DestroyCond_srw(SDL_cond * cond)
+{
+ if (cond) {
+ /* There are no kernel allocated resources */
+ SDL_free(cond);
+ }
+}
+
+static int
+SDL_CondSignal_srw(SDL_cond * _cond)
+{
+ SDL_cond_srw *cond = (SDL_cond_srw *)_cond;
+ if (!cond) {
+ return SDL_SetError("Passed a NULL condition variable");
+ }
+
+ pWakeConditionVariable(&cond->cond);
+
+ return 0;
+}
+
+static int
+SDL_CondBroadcast_srw(SDL_cond * _cond)
+{
+ SDL_cond_srw *cond = (SDL_cond_srw *)_cond;
+ if (!cond) {
+ return SDL_SetError("Passed a NULL condition variable");
+ }
+
+ pWakeAllConditionVariable(&cond->cond);
+
+ return 0;
+}
+
+static int
+SDL_CondWaitTimeout_srw(SDL_cond * _cond, SDL_mutex * _mutex, Uint32 ms)
+{
+ SDL_cond_srw *cond = (SDL_cond_srw *)_cond;
+ SDL_mutex_srw *mutex = (SDL_mutex_srw *)_mutex;
+ DWORD timeout;
+
+ if (!cond) {
+ return SDL_SetError("Passed a NULL condition variable");
+ }
+ if (!mutex) {
+ return SDL_SetError("Passed a NULL mutex");
+ }
+
+ if (mutex->count != 1) {
+ return SDL_SetError("Passed mutex is not locked or locked recursively");
+ }
+
+ if (ms == SDL_MUTEX_MAXWAIT) {
+ timeout = INFINITE;
+ } else {
+ timeout = (DWORD) ms;
+ }
+
+ if (pSleepConditionVariableSRW(&cond->cond, &mutex->srw, timeout, 0) == FALSE) {
+ if (GetLastError() == ERROR_TIMEOUT) {
+ return SDL_MUTEX_TIMEDOUT;
+ }
+ return SDL_SetError("SleepConditionVariableSRW() failed");
+ }
+
+ return 0;
+}
+
+static int
+SDL_CondWait_srw(SDL_cond * cond, SDL_mutex * mutex) {
+ return SDL_CondWaitTimeout_srw(cond, mutex, SDL_MUTEX_MAXWAIT);
+}
+
+static const SDL_cond_impl_t SDL_cond_impl_srw =
+{
+ &SDL_CreateCond_srw,
+ &SDL_DestroyCond_srw,
+ &SDL_CondSignal_srw,
+ &SDL_CondBroadcast_srw,
+ &SDL_CondWait_srw,
+ &SDL_CondWaitTimeout_srw,
+};
+
/**
* Generic Condition Variable implementation using SDL_mutex and SDL_sem
*/
@@ -64,7 +195,43 @@ SDL_cond *
SDL_CreateCond(void)
{
if (SDL_cond_impl_active.Create == NULL) {
- SDL_memcpy(&SDL_cond_impl_active, &SDL_cond_impl_generic, sizeof(SDL_cond_impl_active));
+ /* Default to generic implementation, works with all mutex implementations */
+ const SDL_cond_impl_t * impl = &SDL_cond_impl_generic;
+
+ if (SDL_mutex_impl_active.Type == SDL_MUTEX_INVALID) {
+ /* The mutex implementation isn't decided yet, trigger it */
+ SDL_mutex *mutex = SDL_CreateMutex();
+ if (!mutex) {
+ return NULL;
+ }
+ SDL_DestroyMutex(mutex);
+
+ SDL_assert(SDL_mutex_impl_active.Type != SDL_MUTEX_INVALID);
+ }
+
+ /* It is required SRW Locks are used */
+ if (SDL_mutex_impl_active.Type == SDL_MUTEX_SRW) {
+#if __WINRT__
+ /* Link statically on this platform */
+ impl = &SDL_cond_impl_srw;
+#else
+ HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll");
+ if (kernel32) {
+ pWakeConditionVariable = (pfnWakeConditionVariable) GetProcAddress(kernel32, "WakeConditionVariable");
+ pWakeAllConditionVariable = (pfnWakeAllConditionVariable) GetProcAddress(kernel32, "WakeAllConditionVariable");
+ pSleepConditionVariableSRW = (pfnSleepConditionVariableSRW) GetProcAddress(kernel32, "SleepConditionVariableSRW");
+ if (pWakeConditionVariable && pWakeAllConditionVariable && pSleepConditionVariableSRW) {
+ /* Use the Windows provided API */
+ impl = &SDL_cond_impl_srw;
+ }
+ }
+ if (!(kernel32 && pWakeConditionVariable && pWakeAllConditionVariable && pSleepConditionVariableSRW)) {
+ SDL_LogWarn(SDL_LOG_CATEGORY_SYSTEM, "Could not load required imports for SRW Condition Variables although SRW Locks are used!");
+ }
+#endif
+ }
+
+ SDL_memcpy(&SDL_cond_impl_active, impl, sizeof(SDL_cond_impl_active));
}
return SDL_cond_impl_active.Create();
}
diff --git a/src/thread/windows/SDL_sysmutex.c b/src/thread/windows/SDL_sysmutex.c
index eb4df31ae..8d5dd3591 100644
--- a/src/thread/windows/SDL_sysmutex.c
+++ b/src/thread/windows/SDL_sysmutex.c
@@ -31,41 +31,19 @@
*/
-#include "../../core/windows/SDL_windows.h"
-
#include "SDL_hints.h"
-#include "SDL_mutex.h"
-typedef SDL_mutex * (*pfnSDL_CreateMutex)(void);
-typedef int (*pfnSDL_LockMutex)(SDL_mutex *);
-typedef int (*pfnSDL_TryLockMutex)(SDL_mutex *);
-typedef int (*pfnSDL_UnlockMutex)(SDL_mutex *);
-typedef void (*pfnSDL_DestroyMutex)(SDL_mutex *);
+#include "SDL_sysmutex_c.h"
-typedef struct SDL_mutex_impl_t
-{
- pfnSDL_CreateMutex Create;
- pfnSDL_DestroyMutex Destroy;
- pfnSDL_LockMutex Lock;
- pfnSDL_TryLockMutex TryLock;
- pfnSDL_UnlockMutex Unlock;
-} SDL_mutex_impl_t;
/* Implementation will be chosen at runtime based on available Kernel features */
-static SDL_mutex_impl_t SDL_mutex_impl_active = {0};
+SDL_mutex_impl_t SDL_mutex_impl_active = {0};
/**
* Implementation based on Slim Reader/Writer (SRW) Locks for Win 7 and newer.
*/
-#ifndef SRWLOCK_INIT
-#define SRWLOCK_INIT {0}
-typedef struct _SRWLOCK {
- PVOID Ptr;
-} SRWLOCK, *PSRWLOCK;
-#endif
-
#if __WINRT__
/* Functions are guaranteed to be available */
#define pReleaseSRWLockExclusive ReleaseSRWLockExclusive
@@ -80,14 +58,6 @@ static pfnAcquireSRWLockExclusive pAcquireSRWLockExclusive = NULL;
static pfnTryAcquireSRWLockExclusive pTryAcquireSRWLockExclusive = NULL;
#endif
-typedef struct SDL_mutex_srw
-{
- SRWLOCK srw;
- /* SRW Locks are not recursive, that has to be handled by SDL: */
- DWORD count;
- DWORD owner;
-} SDL_mutex_srw;
-
static SDL_mutex *
SDL_CreateMutex_srw(void)
{
@@ -189,6 +159,7 @@ static const SDL_mutex_impl_t SDL_mutex_impl_srw =
&SDL_LockMutex_srw,
&SDL_TryLockMutex_srw,
&SDL_UnlockMutex_srw,
+ SDL_MUTEX_SRW,
};
@@ -283,6 +254,7 @@ static const SDL_mutex_impl_t SDL_mutex_impl_cs =
&SDL_LockMutex_cs,
&SDL_TryLockMutex_cs,
&SDL_UnlockMutex_cs,
+ SDL_MUTEX_CS,
};
diff --git a/src/thread/windows/SDL_sysmutex_c.h b/src/thread/windows/SDL_sysmutex_c.h
new file mode 100644
index 000000000..ddd519669
--- /dev/null
+++ b/src/thread/windows/SDL_sysmutex_c.h
@@ -0,0 +1,69 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#include "../../core/windows/SDL_windows.h"
+
+#include "SDL_mutex.h"
+
+typedef SDL_mutex * (*pfnSDL_CreateMutex)(void);
+typedef int (*pfnSDL_LockMutex)(SDL_mutex *);
+typedef int (*pfnSDL_TryLockMutex)(SDL_mutex *);
+typedef int (*pfnSDL_UnlockMutex)(SDL_mutex *);
+typedef void (*pfnSDL_DestroyMutex)(SDL_mutex *);
+
+typedef enum
+{
+ SDL_MUTEX_INVALID = 0,
+ SDL_MUTEX_SRW,
+ SDL_MUTEX_CS,
+} SDL_MutexType;
+
+typedef struct SDL_mutex_impl_t
+{
+ pfnSDL_CreateMutex Create;
+ pfnSDL_DestroyMutex Destroy;
+ pfnSDL_LockMutex Lock;
+ pfnSDL_TryLockMutex TryLock;
+ pfnSDL_UnlockMutex Unlock;
+ /* Needed by SDL_cond: */
+ SDL_MutexType Type;
+} SDL_mutex_impl_t;
+
+extern SDL_mutex_impl_t SDL_mutex_impl_active;
+
+
+#ifndef SRWLOCK_INIT
+#define SRWLOCK_INIT {0}
+typedef struct _SRWLOCK {
+ PVOID Ptr;
+} SRWLOCK, *PSRWLOCK;
+#endif
+
+typedef struct SDL_mutex_srw
+{
+ SRWLOCK srw;
+ /* SRW Locks are not recursive, that has to be handled by SDL: */
+ DWORD count;
+ DWORD owner;
+} SDL_mutex_srw;
+
+/* vi: set ts=4 sw=4 expandtab: */