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 24226890Sdim// Windows has slim read-writer lock support on Vista and higher, so we 25226890Sdim// will attempt to load the APIs. If they exist, we will use them, and 26226890Sdim// if not, we will fall back on critical sections. When we drop support 27226890Sdim// for XP, we can stop lazy-loading these APIs and just use them directly. 28226890Sdim#if defined(__MINGW32__) 29226890Sdim // Taken from WinNT.h 30226890Sdim typedef struct _RTL_SRWLOCK { 31226890Sdim PVOID Ptr; 32226890Sdim } RTL_SRWLOCK, *PRTL_SRWLOCK; 33226890Sdim 34226890Sdim // Taken from WinBase.h 35226890Sdim typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK; 36226890Sdim#endif 37226890Sdim 38226890Sdimstatic VOID (WINAPI *fpInitializeSRWLock)(PSRWLOCK lock) = NULL; 39226890Sdimstatic VOID (WINAPI *fpAcquireSRWLockExclusive)(PSRWLOCK lock) = NULL; 40226890Sdimstatic VOID (WINAPI *fpAcquireSRWLockShared)(PSRWLOCK lock) = NULL; 41226890Sdimstatic VOID (WINAPI *fpReleaseSRWLockExclusive)(PSRWLOCK lock) = NULL; 42226890Sdimstatic VOID (WINAPI *fpReleaseSRWLockShared)(PSRWLOCK lock) = NULL; 43226890Sdim 44226890Sdimstatic bool sHasSRW = false; 45226890Sdim 46226890Sdimstatic bool loadSRW() { 47226890Sdim static bool sChecked = false; 48226890Sdim if (!sChecked) { 49226890Sdim sChecked = true; 50226890Sdim 51263509Sdim if (HMODULE hLib = ::GetModuleHandleW(L"Kernel32.dll")) { 52226890Sdim fpInitializeSRWLock = 53226890Sdim (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib, 54226890Sdim "InitializeSRWLock"); 55226890Sdim fpAcquireSRWLockExclusive = 56226890Sdim (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib, 57226890Sdim "AcquireSRWLockExclusive"); 58226890Sdim fpAcquireSRWLockShared = 59226890Sdim (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib, 60226890Sdim "AcquireSRWLockShared"); 61226890Sdim fpReleaseSRWLockExclusive = 62226890Sdim (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib, 63226890Sdim "ReleaseSRWLockExclusive"); 64226890Sdim fpReleaseSRWLockShared = 65226890Sdim (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib, 66226890Sdim "ReleaseSRWLockShared"); 67226890Sdim 68245431Sdim if (fpInitializeSRWLock != NULL) { 69245431Sdim sHasSRW = true; 70245431Sdim } 71226890Sdim } 72226890Sdim } 73226890Sdim return sHasSRW; 74226890Sdim} 75226890Sdim 76218885SdimRWMutexImpl::RWMutexImpl() { 77226890Sdim if (loadSRW()) { 78226890Sdim data_ = calloc(1, sizeof(SRWLOCK)); 79226890Sdim fpInitializeSRWLock(static_cast<PSRWLOCK>(data_)); 80226890Sdim } else { 81226890Sdim data_ = calloc(1, sizeof(CRITICAL_SECTION)); 82226890Sdim InitializeCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); 83226890Sdim } 84218885Sdim} 85218885Sdim 86218885SdimRWMutexImpl::~RWMutexImpl() { 87226890Sdim if (sHasSRW) { 88226890Sdim // Nothing to do in the case of slim reader/writers 89226890Sdim } else { 90226890Sdim DeleteCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); 91226890Sdim free(data_); 92226890Sdim } 93218885Sdim} 94218885Sdim 95218885Sdimbool RWMutexImpl::reader_acquire() { 96226890Sdim if (sHasSRW) { 97226890Sdim fpAcquireSRWLockShared(static_cast<PSRWLOCK>(data_)); 98226890Sdim } else { 99226890Sdim EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); 100226890Sdim } 101218885Sdim return true; 102218885Sdim} 103218885Sdim 104218885Sdimbool RWMutexImpl::reader_release() { 105226890Sdim if (sHasSRW) { 106226890Sdim fpReleaseSRWLockShared(static_cast<PSRWLOCK>(data_)); 107226890Sdim } else { 108226890Sdim LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); 109226890Sdim } 110218885Sdim return true; 111218885Sdim} 112218885Sdim 113218885Sdimbool RWMutexImpl::writer_acquire() { 114226890Sdim if (sHasSRW) { 115226890Sdim fpAcquireSRWLockExclusive(static_cast<PSRWLOCK>(data_)); 116226890Sdim } else { 117226890Sdim EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); 118226890Sdim } 119218885Sdim return true; 120218885Sdim} 121218885Sdim 122218885Sdimbool RWMutexImpl::writer_release() { 123226890Sdim if (sHasSRW) { 124226890Sdim fpReleaseSRWLockExclusive(static_cast<PSRWLOCK>(data_)); 125226890Sdim } else { 126226890Sdim LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); 127226890Sdim } 128218885Sdim return true; 129218885Sdim} 130218885Sdim 131218885Sdim 132218885Sdim} 133