LLVM API Documentation
00001 //= llvm/Support/Win32/Mutex.inc - Win32 Reader/Writer Mutual Exclusion Lock =// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the Win32 specific (non-pthread) RWMutex class. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 //===----------------------------------------------------------------------===// 00015 //=== WARNING: Implementation here must contain only generic Win32 code that 00016 //=== is guaranteed to work on *all* Win32 variants. 00017 //===----------------------------------------------------------------------===// 00018 00019 #include "WindowsSupport.h" 00020 00021 namespace llvm { 00022 using namespace sys; 00023 00024 // Windows has slim read-writer lock support on Vista and higher, so we 00025 // will attempt to load the APIs. If they exist, we will use them, and 00026 // if not, we will fall back on critical sections. When we drop support 00027 // for XP, we can stop lazy-loading these APIs and just use them directly. 00028 #if defined(__MINGW32__) 00029 // Taken from WinNT.h 00030 typedef struct _RTL_SRWLOCK { 00031 PVOID Ptr; 00032 } RTL_SRWLOCK, *PRTL_SRWLOCK; 00033 00034 // Taken from WinBase.h 00035 typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK; 00036 #endif 00037 00038 static VOID (WINAPI *fpInitializeSRWLock)(PSRWLOCK lock) = NULL; 00039 static VOID (WINAPI *fpAcquireSRWLockExclusive)(PSRWLOCK lock) = NULL; 00040 static VOID (WINAPI *fpAcquireSRWLockShared)(PSRWLOCK lock) = NULL; 00041 static VOID (WINAPI *fpReleaseSRWLockExclusive)(PSRWLOCK lock) = NULL; 00042 static VOID (WINAPI *fpReleaseSRWLockShared)(PSRWLOCK lock) = NULL; 00043 00044 static bool sHasSRW = false; 00045 00046 static bool loadSRW() { 00047 static bool sChecked = false; 00048 if (!sChecked) { 00049 sChecked = true; 00050 00051 if (HMODULE hLib = ::GetModuleHandleW(L"Kernel32.dll")) { 00052 fpInitializeSRWLock = 00053 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib, 00054 "InitializeSRWLock"); 00055 fpAcquireSRWLockExclusive = 00056 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib, 00057 "AcquireSRWLockExclusive"); 00058 fpAcquireSRWLockShared = 00059 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib, 00060 "AcquireSRWLockShared"); 00061 fpReleaseSRWLockExclusive = 00062 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib, 00063 "ReleaseSRWLockExclusive"); 00064 fpReleaseSRWLockShared = 00065 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib, 00066 "ReleaseSRWLockShared"); 00067 00068 if (fpInitializeSRWLock != NULL) { 00069 sHasSRW = true; 00070 } 00071 } 00072 } 00073 return sHasSRW; 00074 } 00075 00076 RWMutexImpl::RWMutexImpl() { 00077 if (loadSRW()) { 00078 data_ = calloc(1, sizeof(SRWLOCK)); 00079 fpInitializeSRWLock(static_cast<PSRWLOCK>(data_)); 00080 } else { 00081 data_ = calloc(1, sizeof(CRITICAL_SECTION)); 00082 InitializeCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); 00083 } 00084 } 00085 00086 RWMutexImpl::~RWMutexImpl() { 00087 if (sHasSRW) { 00088 // Nothing to do in the case of slim reader/writers 00089 } else { 00090 DeleteCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); 00091 free(data_); 00092 } 00093 } 00094 00095 bool RWMutexImpl::reader_acquire() { 00096 if (sHasSRW) { 00097 fpAcquireSRWLockShared(static_cast<PSRWLOCK>(data_)); 00098 } else { 00099 EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); 00100 } 00101 return true; 00102 } 00103 00104 bool RWMutexImpl::reader_release() { 00105 if (sHasSRW) { 00106 fpReleaseSRWLockShared(static_cast<PSRWLOCK>(data_)); 00107 } else { 00108 LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); 00109 } 00110 return true; 00111 } 00112 00113 bool RWMutexImpl::writer_acquire() { 00114 if (sHasSRW) { 00115 fpAcquireSRWLockExclusive(static_cast<PSRWLOCK>(data_)); 00116 } else { 00117 EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); 00118 } 00119 return true; 00120 } 00121 00122 bool RWMutexImpl::writer_release() { 00123 if (sHasSRW) { 00124 fpReleaseSRWLockExclusive(static_cast<PSRWLOCK>(data_)); 00125 } else { 00126 LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); 00127 } 00128 return true; 00129 } 00130 00131 00132 }