1//= llvm/Support/Win32/Mutex.inc - Win32 Reader/Writer Mutual Exclusion Lock =// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file implements the Win32 specific (non-pthread) RWMutex class. 11// 12//===----------------------------------------------------------------------===// 13 14//===----------------------------------------------------------------------===// 15//=== WARNING: Implementation here must contain only generic Win32 code that 16//=== is guaranteed to work on *all* Win32 variants. 17//===----------------------------------------------------------------------===// 18 19#include "WindowsSupport.h" 20 21namespace llvm { 22 23// Windows has slim read-writer lock support on Vista and higher, so we 24// will attempt to load the APIs. If they exist, we will use them, and 25// if not, we will fall back on critical sections. When we drop support 26// for XP, we can stop lazy-loading these APIs and just use them directly. 27#if defined(__MINGW32__) 28 // Taken from WinNT.h 29 typedef struct _RTL_SRWLOCK { 30 PVOID Ptr; 31 } RTL_SRWLOCK, *PRTL_SRWLOCK; 32 33 // Taken from WinBase.h 34 typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK; 35#endif 36 37static VOID (WINAPI *fpInitializeSRWLock)(PSRWLOCK lock) = NULL; 38static VOID (WINAPI *fpAcquireSRWLockExclusive)(PSRWLOCK lock) = NULL; 39static VOID (WINAPI *fpAcquireSRWLockShared)(PSRWLOCK lock) = NULL; 40static VOID (WINAPI *fpReleaseSRWLockExclusive)(PSRWLOCK lock) = NULL; 41static VOID (WINAPI *fpReleaseSRWLockShared)(PSRWLOCK lock) = NULL; 42 43static bool sHasSRW = false; 44 45static bool loadSRW() { 46 static bool sChecked = false; 47 if (!sChecked) { 48 sChecked = true; 49 50 if (HMODULE hLib = ::GetModuleHandleW(L"Kernel32.dll")) { 51 fpInitializeSRWLock = 52 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib, 53 "InitializeSRWLock"); 54 fpAcquireSRWLockExclusive = 55 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib, 56 "AcquireSRWLockExclusive"); 57 fpAcquireSRWLockShared = 58 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib, 59 "AcquireSRWLockShared"); 60 fpReleaseSRWLockExclusive = 61 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib, 62 "ReleaseSRWLockExclusive"); 63 fpReleaseSRWLockShared = 64 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib, 65 "ReleaseSRWLockShared"); 66 67 if (fpInitializeSRWLock != NULL) { 68 sHasSRW = true; 69 } 70 } 71 } 72 return sHasSRW; 73} 74 75sys::RWMutexImpl::RWMutexImpl() { 76 if (loadSRW()) { 77 data_ = safe_calloc(1, sizeof(SRWLOCK)); 78 fpInitializeSRWLock(static_cast<PSRWLOCK>(data_)); 79 } else { 80 data_ = safe_calloc(1, sizeof(CRITICAL_SECTION)); 81 InitializeCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); 82 } 83} 84 85sys::RWMutexImpl::~RWMutexImpl() { 86 if (!sHasSRW) 87 DeleteCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); 88 // Nothing to do in the case of slim reader/writers except free the memory. 89 free(data_); 90} 91 92bool sys::RWMutexImpl::reader_acquire() { 93 if (sHasSRW) { 94 fpAcquireSRWLockShared(static_cast<PSRWLOCK>(data_)); 95 } else { 96 EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); 97 } 98 return true; 99} 100 101bool sys::RWMutexImpl::reader_release() { 102 if (sHasSRW) { 103 fpReleaseSRWLockShared(static_cast<PSRWLOCK>(data_)); 104 } else { 105 LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); 106 } 107 return true; 108} 109 110bool sys::RWMutexImpl::writer_acquire() { 111 if (sHasSRW) { 112 fpAcquireSRWLockExclusive(static_cast<PSRWLOCK>(data_)); 113 } else { 114 EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); 115 } 116 return true; 117} 118 119bool sys::RWMutexImpl::writer_release() { 120 if (sHasSRW) { 121 fpReleaseSRWLockExclusive(static_cast<PSRWLOCK>(data_)); 122 } else { 123 LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); 124 } 125 return true; 126} 127 128 129} 130