blob: 25d034b605ea954f93caac90725783f499d94997 [file] [log] [blame]
Virgile Bellob2f1fb22013-08-23 12:44:05 +00001#ifdef _WIN32
2
3#include "lldb/Host/ProcessRunLock.h"
Virgile Bello0a3b1512013-09-04 13:56:11 +00004#include "lldb/Host/windows/windows.h"
Virgile Bellob2f1fb22013-08-23 12:44:05 +00005
6namespace lldb_private {
7
8 // Windows has slim read-writer lock support on Vista and higher, so we
9 // will attempt to load the APIs. If they exist, we will use them, and
10 // if not, we will fall back on critical sections. When we drop support
11 // for XP, we can stop lazy-loading these APIs and just use them directly.
12#if defined(__MINGW32__)
13 // Taken from WinNT.h
14 typedef struct _RTL_SRWLOCK {
15 PVOID Ptr;
16 } RTL_SRWLOCK, *PRTL_SRWLOCK;
17
18 // Taken from WinBase.h
19 typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK;
20#endif
21
22
23 typedef struct Win32RWLOCK
24 {
Hafiz Abid Qadeera1b42ec2014-03-13 10:47:49 +000025 long int readlockcount;
Virgile Bellob2f1fb22013-08-23 12:44:05 +000026 HANDLE writable;
27 CRITICAL_SECTION writelock;
Hafiz Abid Qadeera1b42ec2014-03-13 10:47:49 +000028 long int writelocked;
Virgile Bellob2f1fb22013-08-23 12:44:05 +000029 } Win32RWLOCK;
30
31 typedef Win32RWLOCK* PWin32RWLOCK;
32
33 static VOID (WINAPI *fpInitializeSRWLock)(PSRWLOCK lock) = NULL;
34 static VOID (WINAPI *fpAcquireSRWLockExclusive)(PSRWLOCK lock) = NULL;
35 static VOID (WINAPI *fpAcquireSRWLockShared)(PSRWLOCK lock) = NULL;
36 static VOID (WINAPI *fpReleaseSRWLockExclusive)(PSRWLOCK lock) = NULL;
37 static VOID (WINAPI *fpReleaseSRWLockShared)(PSRWLOCK lock) = NULL;
38 static BOOL (WINAPI *fpTryAcquireSRWLockExclusive)(PSRWLOCK lock) = NULL;
39 static BOOL (WINAPI *fpTryAcquireSRWLockShared)(PSRWLOCK lock) = NULL;
40
41 static bool sHasSRW = false;
42
43 static bool loadSRW()
44 {
45 static bool sChecked = false;
46 if (!sChecked)
47 {
48 sChecked = true;
49 return false;
50
51 HMODULE hLib = ::LoadLibrary(TEXT("Kernel32"));
52 if (hLib)
53 {
54 fpInitializeSRWLock =
55 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
56 "InitializeSRWLock");
57 fpAcquireSRWLockExclusive =
58 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
59 "AcquireSRWLockExclusive");
60 fpAcquireSRWLockShared =
61 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
62 "AcquireSRWLockShared");
63 fpReleaseSRWLockExclusive =
64 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
65 "ReleaseSRWLockExclusive");
66 fpReleaseSRWLockShared =
67 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
68 "ReleaseSRWLockShared");
69 fpTryAcquireSRWLockExclusive =
70 (BOOL (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
71 "TryAcquireSRWLockExclusive");
72 fpTryAcquireSRWLockShared =
73 (BOOL (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
74 "TryAcquireSRWLockShared");
75
76 ::FreeLibrary(hLib);
77
78 if (fpInitializeSRWLock != NULL) {
79 sHasSRW = true;
80 }
81 }
82 }
83 return sHasSRW;
84 }
85
86 ProcessRunLock::ProcessRunLock ()
87 : m_running(false)
88 {
89 if (loadSRW())
90 {
91 m_rwlock = calloc(1, sizeof(SRWLOCK));
92 fpInitializeSRWLock(static_cast<PSRWLOCK>(m_rwlock));
93 }
94 else
95 {
96 m_rwlock = calloc(1, sizeof(Win32RWLOCK));
97 static_cast<PWin32RWLOCK>(m_rwlock)->readlockcount = 0;
98 static_cast<PWin32RWLOCK>(m_rwlock)->writable = CreateEvent(NULL, true, true, NULL);
99 InitializeCriticalSection(&static_cast<PWin32RWLOCK>(m_rwlock)->writelock);
100 }
101 }
102
103 ProcessRunLock::~ProcessRunLock ()
104 {
105 if (!sHasSRW)
106 {
107 CloseHandle(static_cast<PWin32RWLOCK>(m_rwlock)->writable);
108 DeleteCriticalSection(&static_cast<PWin32RWLOCK>(m_rwlock)->writelock);
109 }
110 free(m_rwlock);
111 }
112
113 bool ReadLock (lldb::rwlock_t rwlock)
114 {
115 if (sHasSRW)
116 {
117 fpAcquireSRWLockShared(static_cast<PSRWLOCK>(rwlock));
118 return true;
119 }
120 else
121 {
122 EnterCriticalSection(&static_cast<PWin32RWLOCK>(rwlock)->writelock);
123 InterlockedIncrement(&static_cast<PWin32RWLOCK>(rwlock)->readlockcount);
124 ResetEvent(static_cast<PWin32RWLOCK>(rwlock)->writable);
125 LeaveCriticalSection(&static_cast<PWin32RWLOCK>(rwlock)->writelock);
126 return true;
127 }
128 }
129
130 bool ProcessRunLock::ReadTryLock ()
131 {
132 ReadLock(m_rwlock);
133 if (m_running == false)
134 return true;
135 ReadUnlock();
136 return false;
137 }
138
139 bool ProcessRunLock::ReadUnlock ()
140 {
141 if (sHasSRW)
142 {
143 fpReleaseSRWLockShared(static_cast<PSRWLOCK>(m_rwlock));
144 return true;
145 }
146 else
147 {
148 unsigned long int value = InterlockedDecrement(&static_cast<PWin32RWLOCK>(m_rwlock)->readlockcount);
149 assert(((int)value) >= 0);
150 if (value == 0)
151 SetEvent(static_cast<PWin32RWLOCK>(m_rwlock)->writable);
152 return true;
153 }
154 }
155
156 bool WriteLock(lldb::rwlock_t rwlock)
157 {
158 if (sHasSRW)
159 {
160 fpAcquireSRWLockExclusive(static_cast<PSRWLOCK>(rwlock));
161 return true;
162 }
163 else
164 {
165 EnterCriticalSection(&static_cast<PWin32RWLOCK>(rwlock)->writelock);
166 WaitForSingleObject(static_cast<PWin32RWLOCK>(rwlock)->writable, INFINITE);
167 int res = InterlockedExchange(&static_cast<PWin32RWLOCK>(rwlock)->writelocked, 1);
168 assert(res == 0);
169 return true;
170 }
171 }
172
173 bool WriteTryLock(lldb::rwlock_t rwlock)
174 {
175 if (sHasSRW)
176 {
177 return fpTryAcquireSRWLockExclusive(static_cast<PSRWLOCK>(rwlock)) != 0;
178 }
179 else
180 {
181 if (TryEnterCriticalSection(&static_cast<PWin32RWLOCK>(rwlock)->writelock)) {
182 if (WaitForSingleObject(static_cast<PWin32RWLOCK>(rwlock)->writable, 0)) {
183 LeaveCriticalSection(&static_cast<PWin32RWLOCK>(rwlock)->writelock);
184 return false;
185 }
186 int res = InterlockedExchange(&static_cast<PWin32RWLOCK>(rwlock)->writelocked, 1);
187 assert(res == 0);
188 return true;
189 }
190 return false;
191 }
192 }
193
194 bool WriteUnlock(lldb::rwlock_t rwlock)
195 {
196 if (sHasSRW)
197 {
198 fpReleaseSRWLockExclusive(static_cast<PSRWLOCK>(rwlock));
199 return true;
200 }
201 else
202 {
203 int res = InterlockedExchange(&static_cast<PWin32RWLOCK>(rwlock)->writelocked, 0);
204 if (res == 1) {
205 LeaveCriticalSection(&static_cast<PWin32RWLOCK>(rwlock)->writelock);
206 return true;
207 }
208 return false;
209 }
210 }
211
212 bool ProcessRunLock::SetRunning ()
213 {
214 WriteLock(m_rwlock);
215 m_running = true;
216 WriteUnlock(m_rwlock);
217 return true;
218 }
219
220 bool ProcessRunLock::TrySetRunning ()
221 {
222 if (WriteTryLock(m_rwlock))
223 {
224 bool r = !m_running;
225 m_running = true;
226 WriteUnlock(m_rwlock);
227 return r;
228 }
229 return false;
230 }
231
232 bool ProcessRunLock::SetStopped ()
233 {
234 WriteLock(m_rwlock);
235 m_running = false;
236 WriteUnlock(m_rwlock);
237 return true;
238 }
239}
240
241#endif