1 #ifdef _WIN32 2 3 #include "lldb/Host/ProcessRunLock.h" 4 #include "lldb/Host/windows/windows.h" 5 6 namespace 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 { 25 long int readlockcount; 26 HANDLE writable; 27 CRITICAL_SECTION writelock; 28 long int writelocked; 29 } 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 242