llvm.org GIT mirror llvm / 7d2bc08
Support/Windows: Add efficent RW mutex on Windows. Patch by Aaron Ballman! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141907 91177308-0d34-0410-b5e6-96231b3b80d8 Michael J. Spencer 8 years ago
1 changed file(s) with 87 addition(s) and 11 deletion(s). Raw diff Collapse all Expand all
1717
1818 #include "Windows.h"
1919
20 // FIXME: Windows does not have reader-writer locks pre-Vista. If you want
21 // real reader-writer locks, you a threads implementation for Windows.
22
2320 namespace llvm {
2421 using namespace sys;
2522
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
37 static VOID (WINAPI *fpInitializeSRWLock)(PSRWLOCK lock) = NULL;
38 static VOID (WINAPI *fpAcquireSRWLockExclusive)(PSRWLOCK lock) = NULL;
39 static VOID (WINAPI *fpAcquireSRWLockShared)(PSRWLOCK lock) = NULL;
40 static VOID (WINAPI *fpReleaseSRWLockExclusive)(PSRWLOCK lock) = NULL;
41 static VOID (WINAPI *fpReleaseSRWLockShared)(PSRWLOCK lock) = NULL;
42
43 static bool sHasSRW = false;
44
45 static bool loadSRW() {
46 static bool sChecked = false;
47 if (!sChecked) {
48 sChecked = true;
49
50 HMODULE hLib = ::LoadLibrary(TEXT("Kernel32"));
51 if (hLib) {
52 fpInitializeSRWLock =
53 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
54 "InitializeSRWLock");
55 fpAcquireSRWLockExclusive =
56 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
57 "AcquireSRWLockExclusive");
58 fpAcquireSRWLockShared =
59 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
60 "AcquireSRWLockShared");
61 fpReleaseSRWLockExclusive =
62 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
63 "ReleaseSRWLockExclusive");
64 fpReleaseSRWLockShared =
65 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
66 "ReleaseSRWLockShared");
67 ::FreeLibrary(hLib);
68
69 if (fpInitializeSRWLock != NULL) {
70 sHasSRW = true;
71 }
72 }
73 }
74 return sHasSRW;
75 }
76
2677 RWMutexImpl::RWMutexImpl() {
27 data_ = calloc(1, sizeof(CRITICAL_SECTION));
28 InitializeCriticalSection(static_cast(data_));
78 if (loadSRW()) {
79 data_ = calloc(1, sizeof(SRWLOCK));
80 fpInitializeSRWLock(static_cast(data_));
81 } else {
82 data_ = calloc(1, sizeof(CRITICAL_SECTION));
83 InitializeCriticalSection(static_cast(data_));
84 }
2985 }
3086
3187 RWMutexImpl::~RWMutexImpl() {
32 DeleteCriticalSection(static_cast(data_));
33 free(data_);
88 if (sHasSRW) {
89 // Nothing to do in the case of slim reader/writers
90 } else {
91 DeleteCriticalSection(static_cast(data_));
92 free(data_);
93 }
3494 }
3595
3696 bool RWMutexImpl::reader_acquire() {
37 EnterCriticalSection(static_cast(data_));
97 if (sHasSRW) {
98 fpAcquireSRWLockShared(static_cast(data_));
99 } else {
100 EnterCriticalSection(static_cast(data_));
101 }
38102 return true;
39103 }
40104
41105 bool RWMutexImpl::reader_release() {
42 LeaveCriticalSection(static_cast(data_));
106 if (sHasSRW) {
107 fpReleaseSRWLockShared(static_cast(data_));
108 } else {
109 LeaveCriticalSection(static_cast(data_));
110 }
43111 return true;
44112 }
45113
46114 bool RWMutexImpl::writer_acquire() {
47 EnterCriticalSection(static_cast(data_));
115 if (sHasSRW) {
116 fpAcquireSRWLockExclusive(static_cast(data_));
117 } else {
118 EnterCriticalSection(static_cast(data_));
119 }
48120 return true;
49121 }
50122
51123 bool RWMutexImpl::writer_release() {
52 LeaveCriticalSection(static_cast(data_));
124 if (sHasSRW) {
125 fpReleaseSRWLockExclusive(static_cast(data_));
126 } else {
127 LeaveCriticalSection(static_cast(data_));
128 }
53129 return true;
54130 }
55131