RWMutex.inc revision 239462
1218885Sdim//= llvm/Support/Win32/Mutex.inc - Win32 Reader/Writer Mutual Exclusion Lock =// 2218885Sdim// 3218885Sdim// The LLVM Compiler Infrastructure 4218885Sdim// 5218885Sdim// This file is distributed under the University of Illinois Open Source 6218885Sdim// License. See LICENSE.TXT for details. 7218885Sdim// 8218885Sdim//===----------------------------------------------------------------------===// 9218885Sdim// 10218885Sdim// This file implements the Win32 specific (non-pthread) RWMutex class. 11218885Sdim// 12218885Sdim//===----------------------------------------------------------------------===// 13218885Sdim 14218885Sdim//===----------------------------------------------------------------------===// 15218885Sdim//=== WARNING: Implementation here must contain only generic Win32 code that 16218885Sdim//=== is guaranteed to work on *all* Win32 variants. 17218885Sdim//===----------------------------------------------------------------------===// 18218885Sdim 19218885Sdim#include "Windows.h" 20218885Sdim 21218885Sdimnamespace llvm { 22218885Sdimusing namespace sys; 23218885Sdim 24226633Sdim// Windows has slim read-writer lock support on Vista and higher, so we 25226633Sdim// will attempt to load the APIs. If they exist, we will use them, and 26226633Sdim// if not, we will fall back on critical sections. When we drop support 27226633Sdim// for XP, we can stop lazy-loading these APIs and just use them directly. 28226633Sdim#if defined(__MINGW32__) 29226633Sdim // Taken from WinNT.h 30226633Sdim typedef struct _RTL_SRWLOCK { 31226633Sdim PVOID Ptr; 32226633Sdim } RTL_SRWLOCK, *PRTL_SRWLOCK; 33226633Sdim 34226633Sdim // Taken from WinBase.h 35226633Sdim typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK; 36226633Sdim#endif 37226633Sdim 38226633Sdimstatic VOID (WINAPI *fpInitializeSRWLock)(PSRWLOCK lock) = NULL; 39226633Sdimstatic VOID (WINAPI *fpAcquireSRWLockExclusive)(PSRWLOCK lock) = NULL; 40226633Sdimstatic VOID (WINAPI *fpAcquireSRWLockShared)(PSRWLOCK lock) = NULL; 41226633Sdimstatic VOID (WINAPI *fpReleaseSRWLockExclusive)(PSRWLOCK lock) = NULL; 42226633Sdimstatic VOID (WINAPI *fpReleaseSRWLockShared)(PSRWLOCK lock) = NULL; 43226633Sdim 44226633Sdimstatic bool sHasSRW = false; 45226633Sdim 46226633Sdimstatic bool loadSRW() { 47226633Sdim static bool sChecked = false; 48226633Sdim if (!sChecked) { 49226633Sdim sChecked = true; 50226633Sdim 51226633Sdim HMODULE hLib = ::LoadLibrary(TEXT("Kernel32")); 52226633Sdim if (hLib) { 53226633Sdim fpInitializeSRWLock = 54226633Sdim (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib, 55226633Sdim "InitializeSRWLock"); 56226633Sdim fpAcquireSRWLockExclusive = 57226633Sdim (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib, 58226633Sdim "AcquireSRWLockExclusive"); 59226633Sdim fpAcquireSRWLockShared = 60226633Sdim (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib, 61226633Sdim "AcquireSRWLockShared"); 62226633Sdim fpReleaseSRWLockExclusive = 63226633Sdim (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib, 64226633Sdim "ReleaseSRWLockExclusive"); 65226633Sdim fpReleaseSRWLockShared = 66226633Sdim (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib, 67226633Sdim "ReleaseSRWLockShared"); 68226633Sdim ::FreeLibrary(hLib); 69226633Sdim 70239462Sdim if (fpInitializeSRWLock != NULL) { 71239462Sdim sHasSRW = true; 72239462Sdim } 73226633Sdim } 74226633Sdim } 75226633Sdim return sHasSRW; 76226633Sdim} 77226633Sdim 78218885SdimRWMutexImpl::RWMutexImpl() { 79226633Sdim if (loadSRW()) { 80226633Sdim data_ = calloc(1, sizeof(SRWLOCK)); 81226633Sdim fpInitializeSRWLock(static_cast<PSRWLOCK>(data_)); 82226633Sdim } else { 83226633Sdim data_ = calloc(1, sizeof(CRITICAL_SECTION)); 84226633Sdim InitializeCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); 85226633Sdim } 86218885Sdim} 87218885Sdim 88218885SdimRWMutexImpl::~RWMutexImpl() { 89226633Sdim if (sHasSRW) { 90226633Sdim // Nothing to do in the case of slim reader/writers 91226633Sdim } else { 92226633Sdim DeleteCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); 93226633Sdim free(data_); 94226633Sdim } 95218885Sdim} 96218885Sdim 97218885Sdimbool RWMutexImpl::reader_acquire() { 98226633Sdim if (sHasSRW) { 99226633Sdim fpAcquireSRWLockShared(static_cast<PSRWLOCK>(data_)); 100226633Sdim } else { 101226633Sdim EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); 102226633Sdim } 103218885Sdim return true; 104218885Sdim} 105218885Sdim 106218885Sdimbool RWMutexImpl::reader_release() { 107226633Sdim if (sHasSRW) { 108226633Sdim fpReleaseSRWLockShared(static_cast<PSRWLOCK>(data_)); 109226633Sdim } else { 110226633Sdim LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); 111226633Sdim } 112218885Sdim return true; 113218885Sdim} 114218885Sdim 115218885Sdimbool RWMutexImpl::writer_acquire() { 116226633Sdim if (sHasSRW) { 117226633Sdim fpAcquireSRWLockExclusive(static_cast<PSRWLOCK>(data_)); 118226633Sdim } else { 119226633Sdim EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); 120226633Sdim } 121218885Sdim return true; 122218885Sdim} 123218885Sdim 124218885Sdimbool RWMutexImpl::writer_release() { 125226633Sdim if (sHasSRW) { 126226633Sdim fpReleaseSRWLockExclusive(static_cast<PSRWLOCK>(data_)); 127226633Sdim } else { 128226633Sdim LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); 129226633Sdim } 130218885Sdim return true; 131218885Sdim} 132218885Sdim 133218885Sdim 134218885Sdim} 135