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