]>
Commit | Line | Data |
---|---|---|
1 | //= llvm/Support/Win32/Mutex.inc - Win32 Reader/Writer Mutual Exclusion Lock =// | |
2 | // | |
3 | // The LLVM Compiler Infrastructure | |
4 | // | |
5 | // This file is distributed under the University of Illinois Open Source | |
6 | // License. See LICENSE.TXT for details. | |
7 | // | |
8 | //===----------------------------------------------------------------------===// | |
9 | // | |
10 | // This file implements the Win32 specific (non-pthread) RWMutex class. | |
11 | // | |
12 | //===----------------------------------------------------------------------===// | |
13 | ||
14 | //===----------------------------------------------------------------------===// | |
15 | //=== WARNING: Implementation here must contain only generic Win32 code that | |
16 | //=== is guaranteed to work on *all* Win32 variants. | |
17 | //===----------------------------------------------------------------------===// | |
18 | ||
19 | #include "WindowsSupport.h" | |
20 | ||
21 | namespace llvm { | |
22 | using namespace sys; | |
23 | ||
24 | // Windows has slim read-writer lock support on Vista and higher, so we | |
25 | // will attempt to load the APIs. If they exist, we will use them, and | |
26 | // if not, we will fall back on critical sections. When we drop support | |
27 | // for XP, we can stop lazy-loading these APIs and just use them directly. | |
28 | #if defined(__MINGW32__) | |
29 | // Taken from WinNT.h | |
30 | typedef struct _RTL_SRWLOCK { | |
31 | PVOID Ptr; | |
32 | } RTL_SRWLOCK, *PRTL_SRWLOCK; | |
33 | ||
34 | // Taken from WinBase.h | |
35 | typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK; | |
36 | #endif | |
37 | ||
38 | static VOID (WINAPI *fpInitializeSRWLock)(PSRWLOCK lock) = NULL; | |
39 | static VOID (WINAPI *fpAcquireSRWLockExclusive)(PSRWLOCK lock) = NULL; | |
40 | static VOID (WINAPI *fpAcquireSRWLockShared)(PSRWLOCK lock) = NULL; | |
41 | static VOID (WINAPI *fpReleaseSRWLockExclusive)(PSRWLOCK lock) = NULL; | |
42 | static VOID (WINAPI *fpReleaseSRWLockShared)(PSRWLOCK lock) = NULL; | |
43 | ||
44 | static bool sHasSRW = false; | |
45 | ||
46 | static bool loadSRW() { | |
47 | static bool sChecked = false; | |
48 | if (!sChecked) { | |
49 | sChecked = true; | |
50 | ||
51 | if (HMODULE hLib = ::GetModuleHandleW(L"Kernel32.dll")) { | |
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 | ||
68 | if (fpInitializeSRWLock != NULL) { | |
69 | sHasSRW = true; | |
70 | } | |
71 | } | |
72 | } | |
73 | return sHasSRW; | |
74 | } | |
75 | ||
76 | RWMutexImpl::RWMutexImpl() { | |
77 | if (loadSRW()) { | |
78 | data_ = calloc(1, sizeof(SRWLOCK)); | |
79 | fpInitializeSRWLock(static_cast<PSRWLOCK>(data_)); | |
80 | } else { | |
81 | data_ = calloc(1, sizeof(CRITICAL_SECTION)); | |
82 | InitializeCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); | |
83 | } | |
84 | } | |
85 | ||
86 | RWMutexImpl::~RWMutexImpl() { | |
87 | if (!sHasSRW) | |
88 | DeleteCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); | |
89 | // Nothing to do in the case of slim reader/writers except free the memory. | |
90 | free(data_); | |
91 | } | |
92 | ||
93 | bool RWMutexImpl::reader_acquire() { | |
94 | if (sHasSRW) { | |
95 | fpAcquireSRWLockShared(static_cast<PSRWLOCK>(data_)); | |
96 | } else { | |
97 | EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); | |
98 | } | |
99 | return true; | |
100 | } | |
101 | ||
102 | bool RWMutexImpl::reader_release() { | |
103 | if (sHasSRW) { | |
104 | fpReleaseSRWLockShared(static_cast<PSRWLOCK>(data_)); | |
105 | } else { | |
106 | LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); | |
107 | } | |
108 | return true; | |
109 | } | |
110 | ||
111 | bool RWMutexImpl::writer_acquire() { | |
112 | if (sHasSRW) { | |
113 | fpAcquireSRWLockExclusive(static_cast<PSRWLOCK>(data_)); | |
114 | } else { | |
115 | EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); | |
116 | } | |
117 | return true; | |
118 | } | |
119 | ||
120 | bool RWMutexImpl::writer_release() { | |
121 | if (sHasSRW) { | |
122 | fpReleaseSRWLockExclusive(static_cast<PSRWLOCK>(data_)); | |
123 | } else { | |
124 | LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_)); | |
125 | } | |
126 | return true; | |
127 | } | |
128 | ||
129 | ||
130 | } |