Atlas - SDL_sysrwlock_srw.c

Home / ext / SDL / src / thread / windows Lines: 1 | Size: 7972 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "SDL_internal.h" 22 23/** 24 * Implementation based on Slim Reader/Writer (SRW) Locks for Win 7 and newer. 25 */ 26 27// This header makes sure SRWLOCK is actually declared, even on ancient WinSDKs. 28#include "SDL_sysmutex_c.h" 29 30typedef VOID (WINAPI *pfnInitializeSRWLock)(PSRWLOCK); 31typedef VOID (WINAPI *pfnReleaseSRWLockShared)(PSRWLOCK); 32typedef VOID (WINAPI *pfnAcquireSRWLockShared)(PSRWLOCK); 33typedef BOOLEAN (WINAPI *pfnTryAcquireSRWLockShared)(PSRWLOCK); 34typedef VOID (WINAPI *pfnReleaseSRWLockExclusive)(PSRWLOCK); 35typedef VOID (WINAPI *pfnAcquireSRWLockExclusive)(PSRWLOCK); 36typedef BOOLEAN (WINAPI *pfnTryAcquireSRWLockExclusive)(PSRWLOCK); 37 38static pfnInitializeSRWLock pInitializeSRWLock = NULL; 39static pfnReleaseSRWLockShared pReleaseSRWLockShared = NULL; 40static pfnAcquireSRWLockShared pAcquireSRWLockShared = NULL; 41static pfnTryAcquireSRWLockShared pTryAcquireSRWLockShared = NULL; 42static pfnReleaseSRWLockExclusive pReleaseSRWLockExclusive = NULL; 43static pfnAcquireSRWLockExclusive pAcquireSRWLockExclusive = NULL; 44static pfnTryAcquireSRWLockExclusive pTryAcquireSRWLockExclusive = NULL; 45 46typedef SDL_RWLock *(*pfnSDL_CreateRWLock)(void); 47typedef void (*pfnSDL_DestroyRWLock)(SDL_RWLock *); 48typedef void (*pfnSDL_LockRWLockForReading)(SDL_RWLock *); 49typedef void (*pfnSDL_LockRWLockForWriting)(SDL_RWLock *); 50typedef bool (*pfnSDL_TryLockRWLockForReading)(SDL_RWLock *); 51typedef bool (*pfnSDL_TryLockRWLockForWriting)(SDL_RWLock *); 52typedef void (*pfnSDL_UnlockRWLock)(SDL_RWLock *); 53 54typedef struct SDL_rwlock_impl_t 55{ 56 pfnSDL_CreateRWLock Create; 57 pfnSDL_DestroyRWLock Destroy; 58 pfnSDL_LockRWLockForReading LockForReading; 59 pfnSDL_LockRWLockForWriting LockForWriting; 60 pfnSDL_TryLockRWLockForReading TryLockForReading; 61 pfnSDL_TryLockRWLockForWriting TryLockForWriting; 62 pfnSDL_UnlockRWLock Unlock; 63} SDL_rwlock_impl_t; 64 65// Implementation will be chosen at runtime based on available Kernel features 66static SDL_rwlock_impl_t SDL_rwlock_impl_active = { 0 }; 67 68// rwlock implementation using Win7+ slim read/write locks (SRWLOCK) 69 70typedef struct SDL_rwlock_srw 71{ 72 SRWLOCK srw; 73 SDL_ThreadID write_owner; 74} SDL_rwlock_srw; 75 76static SDL_RWLock *SDL_CreateRWLock_srw(void) 77{ 78 SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *)SDL_calloc(1, sizeof(*rwlock)); 79 if (rwlock) { 80 pInitializeSRWLock(&rwlock->srw); 81 } 82 return (SDL_RWLock *)rwlock; 83} 84 85static void SDL_DestroyRWLock_srw(SDL_RWLock *_rwlock) 86{ 87 SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *) _rwlock; 88 // There are no kernel allocated resources 89 SDL_free(rwlock); 90} 91 92static void SDL_LockRWLockForReading_srw(SDL_RWLock *_rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes 93{ 94 SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *) _rwlock; 95 pAcquireSRWLockShared(&rwlock->srw); 96} 97 98static void SDL_LockRWLockForWriting_srw(SDL_RWLock *_rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes 99{ 100 SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *) _rwlock; 101 pAcquireSRWLockExclusive(&rwlock->srw); 102 rwlock->write_owner = SDL_GetCurrentThreadID(); 103} 104 105static bool SDL_TryLockRWLockForReading_srw(SDL_RWLock *_rwlock) 106{ 107 SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *) _rwlock; 108 return pTryAcquireSRWLockShared(&rwlock->srw); 109} 110 111static bool SDL_TryLockRWLockForWriting_srw(SDL_RWLock *_rwlock) 112{ 113 SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *) _rwlock; 114 if (pTryAcquireSRWLockExclusive(&rwlock->srw)) { 115 rwlock->write_owner = SDL_GetCurrentThreadID(); 116 return true; 117 } else { 118 return false; 119 } 120} 121 122static void SDL_UnlockRWLock_srw(SDL_RWLock *_rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes 123{ 124 SDL_rwlock_srw *rwlock = (SDL_rwlock_srw *) _rwlock; 125 if (rwlock->write_owner == SDL_GetCurrentThreadID()) { 126 rwlock->write_owner = 0; 127 pReleaseSRWLockExclusive(&rwlock->srw); 128 } else { 129 pReleaseSRWLockShared(&rwlock->srw); 130 } 131} 132 133static const SDL_rwlock_impl_t SDL_rwlock_impl_srw = { 134 &SDL_CreateRWLock_srw, 135 &SDL_DestroyRWLock_srw, 136 &SDL_LockRWLockForReading_srw, 137 &SDL_LockRWLockForWriting_srw, 138 &SDL_TryLockRWLockForReading_srw, 139 &SDL_TryLockRWLockForWriting_srw, 140 &SDL_UnlockRWLock_srw 141}; 142 143 144#include "../generic/SDL_sysrwlock_c.h" 145 146// Generic rwlock implementation using SDL_Mutex, SDL_Condition, and SDL_AtomicInt 147static const SDL_rwlock_impl_t SDL_rwlock_impl_generic = { 148 &SDL_CreateRWLock_generic, 149 &SDL_DestroyRWLock_generic, 150 &SDL_LockRWLockForReading_generic, 151 &SDL_LockRWLockForWriting_generic, 152 &SDL_TryLockRWLockForReading_generic, 153 &SDL_TryLockRWLockForWriting_generic, 154 &SDL_UnlockRWLock_generic 155}; 156 157SDL_RWLock *SDL_CreateRWLock(void) 158{ 159 if (!SDL_rwlock_impl_active.Create) { 160 // Default to generic implementation, works with all mutex implementations 161 const SDL_rwlock_impl_t *impl = &SDL_rwlock_impl_generic; 162 { 163 HMODULE kernel32 = GetModuleHandle(TEXT("kernel32.dll")); 164 if (kernel32) { 165 bool okay = true; 166 #define LOOKUP_SRW_SYM(sym) if (okay) { if ((p##sym = (pfn##sym)GetProcAddress(kernel32, #sym)) == NULL) { okay = false; } } 167 LOOKUP_SRW_SYM(InitializeSRWLock); 168 LOOKUP_SRW_SYM(ReleaseSRWLockShared); 169 LOOKUP_SRW_SYM(AcquireSRWLockShared); 170 LOOKUP_SRW_SYM(TryAcquireSRWLockShared); 171 LOOKUP_SRW_SYM(ReleaseSRWLockExclusive); 172 LOOKUP_SRW_SYM(AcquireSRWLockExclusive); 173 LOOKUP_SRW_SYM(TryAcquireSRWLockExclusive); 174 #undef LOOKUP_SRW_SYM 175 if (okay) { 176 impl = &SDL_rwlock_impl_srw; // Use the Windows provided API instead of generic fallback 177 } 178 } 179 } 180 181 SDL_copyp(&SDL_rwlock_impl_active, impl); 182 } 183 return SDL_rwlock_impl_active.Create(); 184} 185 186void SDL_DestroyRWLock(SDL_RWLock *rwlock) 187{ 188 if (rwlock) { 189 SDL_rwlock_impl_active.Destroy(rwlock); 190 } 191} 192 193void SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes 194{ 195 if (rwlock) { 196 SDL_rwlock_impl_active.LockForReading(rwlock); 197 } 198} 199 200void SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes 201{ 202 if (rwlock) { 203 SDL_rwlock_impl_active.LockForWriting(rwlock); 204 } 205} 206 207bool SDL_TryLockRWLockForReading(SDL_RWLock *rwlock) 208{ 209 bool result = true; 210 if (rwlock) { 211 result = SDL_rwlock_impl_active.TryLockForReading(rwlock); 212 } 213 return result; 214} 215 216bool SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock) 217{ 218 bool result = true; 219 if (rwlock) { 220 result = SDL_rwlock_impl_active.TryLockForWriting(rwlock); 221 } 222 return result; 223} 224 225void SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_NO_THREAD_SAFETY_ANALYSIS // clang doesn't know about NULL mutexes 226{ 227 if (rwlock) { 228 SDL_rwlock_impl_active.Unlock(rwlock); 229 } 230} 231 232
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.