diff --git a/CMakeLists.txt b/CMakeLists.txt index 880415ed3..0a22a556b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1596,7 +1596,7 @@ elseif(WINDOWS) set(SDL_THREAD_WINDOWS 1) set(SOURCE_FILES ${SOURCE_FILES} ${SDL2_SOURCE_DIR}/src/thread/generic/SDL_syscond.c - ${SDL2_SOURCE_DIR}/src/thread/windows/SDL_syscond_srw.c + ${SDL2_SOURCE_DIR}/src/thread/windows/SDL_syscond_cv.c ${SDL2_SOURCE_DIR}/src/thread/windows/SDL_sysmutex.c ${SDL2_SOURCE_DIR}/src/thread/windows/SDL_syssem.c ${SDL2_SOURCE_DIR}/src/thread/windows/SDL_systhread.c diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj index d5deb7ebe..5cb8b0388 100644 --- a/VisualC/SDL/SDL.vcxproj +++ b/VisualC/SDL/SDL.vcxproj @@ -559,7 +559,7 @@ - + diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters index 8fa5c689b..4924e6cce 100644 --- a/VisualC/SDL/SDL.vcxproj.filters +++ b/VisualC/SDL/SDL.vcxproj.filters @@ -1201,7 +1201,7 @@ thread - + thread\windows diff --git a/include/SDL_hints.h b/include/SDL_hints.h index 2c4818c4c..fdfb7eee8 100644 --- a/include/SDL_hints.h +++ b/include/SDL_hints.h @@ -1547,9 +1547,6 @@ 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_cv.c similarity index 68% rename from src/thread/windows/SDL_syscond_srw.c rename to src/thread/windows/SDL_syscond_cv.c index 763a5465e..587a585bd 100644 --- a/src/thread/windows/SDL_syscond_srw.c +++ b/src/thread/windows/SDL_syscond_cv.c @@ -62,29 +62,32 @@ typedef struct CONDITION_VARIABLE { #define pWakeConditionVariable WakeConditionVariable #define pWakeAllConditionVariable WakeAllConditionVariable #define pSleepConditionVariableSRW SleepConditionVariableSRW +#define pSleepConditionVariableCS SleepConditionVariableCS #else typedef VOID(WINAPI *pfnWakeConditionVariable)(PCONDITION_VARIABLE); typedef VOID(WINAPI *pfnWakeAllConditionVariable)(PCONDITION_VARIABLE); typedef BOOL(WINAPI *pfnSleepConditionVariableSRW)(PCONDITION_VARIABLE, PSRWLOCK, DWORD, ULONG); +typedef BOOL(WINAPI* pfnSleepConditionVariableCS)(PCONDITION_VARIABLE, PCRITICAL_SECTION, DWORD); static pfnWakeConditionVariable pWakeConditionVariable = NULL; static pfnWakeAllConditionVariable pWakeAllConditionVariable = NULL; static pfnSleepConditionVariableSRW pSleepConditionVariableSRW = NULL; +static pfnSleepConditionVariableCS pSleepConditionVariableCS = NULL; #endif -typedef struct SDL_cond_srw +typedef struct SDL_cond_cv { CONDITION_VARIABLE cond; -} SDL_cond_srw; +} SDL_cond_cv; static SDL_cond * -SDL_CreateCond_srw(void) +SDL_CreateCond_cv(void) { - SDL_cond_srw *cond; + SDL_cond_cv *cond; /* Relies on CONDITION_VARIABLE_INIT == 0. */ - cond = (SDL_cond_srw *) SDL_calloc(1, sizeof(*cond)); + cond = (SDL_cond_cv *) SDL_calloc(1, sizeof(*cond)); if (!cond) { SDL_OutOfMemory(); } @@ -93,7 +96,7 @@ SDL_CreateCond_srw(void) } static void -SDL_DestroyCond_srw(SDL_cond * cond) +SDL_DestroyCond_cv(SDL_cond * cond) { if (cond) { /* There are no kernel allocated resources */ @@ -102,9 +105,9 @@ SDL_DestroyCond_srw(SDL_cond * cond) } static int -SDL_CondSignal_srw(SDL_cond * _cond) +SDL_CondSignal_cv(SDL_cond * _cond) { - SDL_cond_srw *cond = (SDL_cond_srw *)_cond; + SDL_cond_cv *cond = (SDL_cond_cv *)_cond; if (!cond) { return SDL_SetError("Passed a NULL condition variable"); } @@ -115,9 +118,9 @@ SDL_CondSignal_srw(SDL_cond * _cond) } static int -SDL_CondBroadcast_srw(SDL_cond * _cond) +SDL_CondBroadcast_cv(SDL_cond * _cond) { - SDL_cond_srw *cond = (SDL_cond_srw *)_cond; + SDL_cond_cv *cond = (SDL_cond_cv *)_cond; if (!cond) { return SDL_SetError("Passed a NULL condition variable"); } @@ -128,65 +131,82 @@ SDL_CondBroadcast_srw(SDL_cond * _cond) } static int -SDL_CondWaitTimeout_srw(SDL_cond * _cond, SDL_mutex * _mutex, Uint32 ms) +SDL_CondWaitTimeout_cv(SDL_cond * _cond, SDL_mutex * _mutex, Uint32 ms) { - SDL_cond_srw *cond = (SDL_cond_srw *)_cond; - SDL_mutex_srw *mutex = (SDL_mutex_srw *)_mutex; + SDL_cond_cv *cond = (SDL_cond_cv *)_cond; DWORD timeout; int ret; if (!cond) { return SDL_SetError("Passed a NULL condition variable"); } - if (!mutex) { + if (!_mutex) { return SDL_SetError("Passed a NULL mutex"); } - if (mutex->count != 1 || mutex->owner != GetCurrentThreadId()) { - return SDL_SetError("Passed mutex is not locked or locked recursively"); - } - if (ms == SDL_MUTEX_MAXWAIT) { timeout = INFINITE; } else { timeout = (DWORD) ms; } - /* The mutex must be updated to the released state */ - mutex->count = 0; - mutex->owner = 0; + if (SDL_mutex_impl_active.Type == SDL_MUTEX_SRW) { + SDL_mutex_srw *mutex = (SDL_mutex_srw *)_mutex; - if (pSleepConditionVariableSRW(&cond->cond, &mutex->srw, timeout, 0) == FALSE) { - if (GetLastError() == ERROR_TIMEOUT) { - ret = SDL_MUTEX_TIMEDOUT; - } else { - ret = SDL_SetError("SleepConditionVariableSRW() failed"); + if (mutex->count != 1 || mutex->owner != GetCurrentThreadId()) { + return SDL_SetError("Passed mutex is not locked or locked recursively"); } - } else { - ret = 0; - } - /* The mutex is owned by us again, regardless of status of the wait */ - SDL_assert(mutex->count == 0 && mutex->owner == 0); - mutex->count = 1; - mutex->owner = GetCurrentThreadId(); + /* The mutex must be updated to the released state */ + mutex->count = 0; + mutex->owner = 0; + + if (pSleepConditionVariableSRW(&cond->cond, &mutex->srw, timeout, 0) == FALSE) { + if (GetLastError() == ERROR_TIMEOUT) { + ret = SDL_MUTEX_TIMEDOUT; + } else { + ret = SDL_SetError("SleepConditionVariableSRW() failed"); + } + } else { + ret = 0; + } + + /* The mutex is owned by us again, regardless of status of the wait */ + SDL_assert(mutex->count == 0 && mutex->owner == 0); + mutex->count = 1; + mutex->owner = GetCurrentThreadId(); + } else { + SDL_mutex_cs *mutex = (SDL_mutex_cs *)_mutex; + + SDL_assert(SDL_mutex_impl_active.Type == SDL_MUTEX_CS); + + if (pSleepConditionVariableCS(&cond->cond, &mutex->cs, timeout) == FALSE) { + if (GetLastError() == ERROR_TIMEOUT) { + ret = SDL_MUTEX_TIMEDOUT; + } else { + ret = SDL_SetError("SleepConditionVariableCS() failed"); + } + } else { + ret = 0; + } + } return ret; } static int -SDL_CondWait_srw(SDL_cond * cond, SDL_mutex * mutex) { - return SDL_CondWaitTimeout_srw(cond, mutex, SDL_MUTEX_MAXWAIT); +SDL_CondWait_cv(SDL_cond * cond, SDL_mutex * mutex) { + return SDL_CondWaitTimeout_cv(cond, mutex, SDL_MUTEX_MAXWAIT); } -static const SDL_cond_impl_t SDL_cond_impl_srw = +static const SDL_cond_impl_t SDL_cond_impl_cv = { - &SDL_CreateCond_srw, - &SDL_DestroyCond_srw, - &SDL_CondSignal_srw, - &SDL_CondBroadcast_srw, - &SDL_CondWait_srw, - &SDL_CondWaitTimeout_srw, + &SDL_CreateCond_cv, + &SDL_DestroyCond_cv, + &SDL_CondSignal_cv, + &SDL_CondBroadcast_cv, + &SDL_CondWait_cv, + &SDL_CondWaitTimeout_cv, }; /** @@ -222,27 +242,24 @@ SDL_CreateCond(void) 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; + /* Link statically on this platform */ + impl = &SDL_cond_impl_cv; #else + { HMODULE kernel32 = GetModuleHandle(TEXT("kernel32.dll")); if (kernel32) { pWakeConditionVariable = (pfnWakeConditionVariable) GetProcAddress(kernel32, "WakeConditionVariable"); pWakeAllConditionVariable = (pfnWakeAllConditionVariable) GetProcAddress(kernel32, "WakeAllConditionVariable"); pSleepConditionVariableSRW = (pfnSleepConditionVariableSRW) GetProcAddress(kernel32, "SleepConditionVariableSRW"); - if (pWakeConditionVariable && pWakeAllConditionVariable && pSleepConditionVariableSRW) { + pSleepConditionVariableCS = (pfnSleepConditionVariableCS) GetProcAddress(kernel32, "SleepConditionVariableCS"); + if (pWakeConditionVariable && pWakeAllConditionVariable && pSleepConditionVariableSRW && pSleepConditionVariableCS) { /* Use the Windows provided API */ - impl = &SDL_cond_impl_srw; + impl = &SDL_cond_impl_cv; } } - 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 } +#endif SDL_memcpy(&SDL_cond_impl_active, impl, sizeof(SDL_cond_impl_active)); } diff --git a/src/thread/windows/SDL_sysmutex.c b/src/thread/windows/SDL_sysmutex.c index 6bf9f83c2..e4918ded0 100644 --- a/src/thread/windows/SDL_sysmutex.c +++ b/src/thread/windows/SDL_sysmutex.c @@ -169,11 +169,6 @@ static const SDL_mutex_impl_t SDL_mutex_impl_srw = * Fallback Mutex implementation using Critical Sections (before Win 7) */ -typedef struct SDL_mutex_cs -{ - CRITICAL_SECTION cs; -} SDL_mutex_cs; - /* Create a mutex */ static SDL_mutex * SDL_CreateMutex_cs(void) diff --git a/src/thread/windows/SDL_sysmutex_c.h b/src/thread/windows/SDL_sysmutex_c.h index 6480e9421..1367ca635 100644 --- a/src/thread/windows/SDL_sysmutex_c.h +++ b/src/thread/windows/SDL_sysmutex_c.h @@ -66,4 +66,9 @@ typedef struct SDL_mutex_srw DWORD owner; } SDL_mutex_srw; +typedef struct SDL_mutex_cs +{ + CRITICAL_SECTION cs; +} SDL_mutex_cs; + /* vi: set ts=4 sw=4 expandtab: */