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