blob: 26b9bba9052c55ef6db3e78706ca67f7feb52dc8 [file] [log] [blame]
Charles Davis53ca1f32010-11-29 19:44:50 +00001//= llvm/Support/Win32/Mutex.inc - Win32 Reader/Writer Mutual Exclusion Lock =//
Michael J. Spencer1f6efa32010-11-29 18:16:10 +00002//
Owen Anderson2a8cf9a2009-06-16 20:19:28 +00003// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Michael J. Spencer1f6efa32010-11-29 18:16:10 +00007//
Owen Anderson2a8cf9a2009-06-16 20:19:28 +00008//===----------------------------------------------------------------------===//
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
Michael J. Spencer1f6efa32010-11-29 18:16:10 +000019#include "Windows.h"
Owen Anderson2a8cf9a2009-06-16 20:19:28 +000020
21namespace llvm {
22using namespace sys;
23
Michael J. Spencer7d2bc082011-10-13 23:10:56 +000024// 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
38static VOID (WINAPI *fpInitializeSRWLock)(PSRWLOCK lock) = NULL;
39static VOID (WINAPI *fpAcquireSRWLockExclusive)(PSRWLOCK lock) = NULL;
40static VOID (WINAPI *fpAcquireSRWLockShared)(PSRWLOCK lock) = NULL;
41static VOID (WINAPI *fpReleaseSRWLockExclusive)(PSRWLOCK lock) = NULL;
42static VOID (WINAPI *fpReleaseSRWLockShared)(PSRWLOCK lock) = NULL;
43
44static bool sHasSRW = false;
45
46static bool loadSRW() {
47 static bool sChecked = false;
48 if (!sChecked) {
49 sChecked = true;
50
51 HMODULE hLib = ::LoadLibrary(TEXT("Kernel32"));
52 if (hLib) {
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 ::FreeLibrary(hLib);
69
70 if (fpInitializeSRWLock != NULL) {
71 sHasSRW = true;
72 }
73 }
74 }
75 return sHasSRW;
76}
77
Owen Andersonb65e9ed2009-06-18 18:26:15 +000078RWMutexImpl::RWMutexImpl() {
Michael J. Spencer7d2bc082011-10-13 23:10:56 +000079 if (loadSRW()) {
80 data_ = calloc(1, sizeof(SRWLOCK));
81 fpInitializeSRWLock(static_cast<PSRWLOCK>(data_));
82 } else {
83 data_ = calloc(1, sizeof(CRITICAL_SECTION));
84 InitializeCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
85 }
Owen Andersonc9f8e8e2009-06-17 09:10:42 +000086}
Owen Anderson2a8cf9a2009-06-16 20:19:28 +000087
Owen Andersonb65e9ed2009-06-18 18:26:15 +000088RWMutexImpl::~RWMutexImpl() {
Michael J. Spencer7d2bc082011-10-13 23:10:56 +000089 if (sHasSRW) {
90 // Nothing to do in the case of slim reader/writers
91 } else {
92 DeleteCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
93 free(data_);
94 }
Owen Andersonc9f8e8e2009-06-17 09:10:42 +000095}
Owen Anderson2a8cf9a2009-06-16 20:19:28 +000096
Owen Andersonb65e9ed2009-06-18 18:26:15 +000097bool RWMutexImpl::reader_acquire() {
Michael J. Spencer7d2bc082011-10-13 23:10:56 +000098 if (sHasSRW) {
99 fpAcquireSRWLockShared(static_cast<PSRWLOCK>(data_));
100 } else {
101 EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
102 }
Owen Anderson2a8cf9a2009-06-16 20:19:28 +0000103 return true;
104}
105
Owen Andersonb65e9ed2009-06-18 18:26:15 +0000106bool RWMutexImpl::reader_release() {
Michael J. Spencer7d2bc082011-10-13 23:10:56 +0000107 if (sHasSRW) {
108 fpReleaseSRWLockShared(static_cast<PSRWLOCK>(data_));
109 } else {
110 LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
111 }
Owen Anderson2a8cf9a2009-06-16 20:19:28 +0000112 return true;
113}
114
Owen Andersonb65e9ed2009-06-18 18:26:15 +0000115bool RWMutexImpl::writer_acquire() {
Michael J. Spencer7d2bc082011-10-13 23:10:56 +0000116 if (sHasSRW) {
117 fpAcquireSRWLockExclusive(static_cast<PSRWLOCK>(data_));
118 } else {
119 EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
120 }
Owen Anderson2a8cf9a2009-06-16 20:19:28 +0000121 return true;
122}
123
Owen Andersonb65e9ed2009-06-18 18:26:15 +0000124bool RWMutexImpl::writer_release() {
Michael J. Spencer7d2bc082011-10-13 23:10:56 +0000125 if (sHasSRW) {
126 fpReleaseSRWLockExclusive(static_cast<PSRWLOCK>(data_));
127 } else {
128 LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
129 }
Owen Anderson2a8cf9a2009-06-16 20:19:28 +0000130 return true;
131}
132
133
134}