blob: 8df9bc394160338ee3d4a76c0fe4ad48f3a27379 [file] [log] [blame]
Charles Davis54c9eb62010-11-29 19:44:50 +00001//= llvm/Support/Win32/Mutex.inc - Win32 Reader/Writer Mutual Exclusion Lock =//
Michael J. Spencer447762d2010-11-29 18:16:10 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Michael J. Spencer447762d2010-11-29 18:16:10 +00006//
Owen Anderson324f94c2009-06-16 20:19:28 +00007//===----------------------------------------------------------------------===//
8//
9// This file implements the Win32 specific (non-pthread) RWMutex class.
10//
11//===----------------------------------------------------------------------===//
12
13//===----------------------------------------------------------------------===//
14//=== WARNING: Implementation here must contain only generic Win32 code that
15//=== is guaranteed to work on *all* Win32 variants.
16//===----------------------------------------------------------------------===//
17
Reid Klecknerd59e2fa2014-02-12 21:26:20 +000018#include "WindowsSupport.h"
Owen Anderson324f94c2009-06-16 20:19:28 +000019
20namespace llvm {
Owen Anderson324f94c2009-06-16 20:19:28 +000021
Michael J. Spencer00846152011-10-13 23:10:56 +000022// Windows has slim read-writer lock support on Vista and higher, so we
23// will attempt to load the APIs. If they exist, we will use them, and
24// if not, we will fall back on critical sections. When we drop support
25// for XP, we can stop lazy-loading these APIs and just use them directly.
26#if defined(__MINGW32__)
27 // Taken from WinNT.h
28 typedef struct _RTL_SRWLOCK {
29 PVOID Ptr;
30 } RTL_SRWLOCK, *PRTL_SRWLOCK;
31
32 // Taken from WinBase.h
33 typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK;
34#endif
35
36static VOID (WINAPI *fpInitializeSRWLock)(PSRWLOCK lock) = NULL;
37static VOID (WINAPI *fpAcquireSRWLockExclusive)(PSRWLOCK lock) = NULL;
38static VOID (WINAPI *fpAcquireSRWLockShared)(PSRWLOCK lock) = NULL;
39static VOID (WINAPI *fpReleaseSRWLockExclusive)(PSRWLOCK lock) = NULL;
40static VOID (WINAPI *fpReleaseSRWLockShared)(PSRWLOCK lock) = NULL;
41
42static bool sHasSRW = false;
43
44static bool loadSRW() {
45 static bool sChecked = false;
46 if (!sChecked) {
47 sChecked = true;
48
David Majnemer7af18572013-10-14 00:06:58 +000049 if (HMODULE hLib = ::GetModuleHandleW(L"Kernel32.dll")) {
Michael J. Spencer00846152011-10-13 23:10:56 +000050 fpInitializeSRWLock =
51 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
52 "InitializeSRWLock");
53 fpAcquireSRWLockExclusive =
54 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
55 "AcquireSRWLockExclusive");
56 fpAcquireSRWLockShared =
57 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
58 "AcquireSRWLockShared");
59 fpReleaseSRWLockExclusive =
60 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
61 "ReleaseSRWLockExclusive");
62 fpReleaseSRWLockShared =
63 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
64 "ReleaseSRWLockShared");
Michael J. Spencer00846152011-10-13 23:10:56 +000065
Bill Wendling2b079652012-07-19 00:06:06 +000066 if (fpInitializeSRWLock != NULL) {
67 sHasSRW = true;
68 }
Michael J. Spencer00846152011-10-13 23:10:56 +000069 }
70 }
71 return sHasSRW;
72}
73
Kristof Beylsa11dbf22017-03-31 14:26:44 +000074sys::RWMutexImpl::RWMutexImpl() {
Michael J. Spencer00846152011-10-13 23:10:56 +000075 if (loadSRW()) {
Serge Pavlov76d8cce2018-02-20 05:41:26 +000076 data_ = safe_calloc(1, sizeof(SRWLOCK));
Michael J. Spencer00846152011-10-13 23:10:56 +000077 fpInitializeSRWLock(static_cast<PSRWLOCK>(data_));
78 } else {
Serge Pavlov76d8cce2018-02-20 05:41:26 +000079 data_ = safe_calloc(1, sizeof(CRITICAL_SECTION));
Michael J. Spencer00846152011-10-13 23:10:56 +000080 InitializeCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
81 }
Owen Anderson74af4ee2009-06-17 09:10:42 +000082}
Owen Anderson324f94c2009-06-16 20:19:28 +000083
Kristof Beylsa11dbf22017-03-31 14:26:44 +000084sys::RWMutexImpl::~RWMutexImpl() {
David Blaikiedf951532014-10-21 00:34:39 +000085 if (!sHasSRW)
Michael J. Spencer00846152011-10-13 23:10:56 +000086 DeleteCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
David Blaikiedf951532014-10-21 00:34:39 +000087 // Nothing to do in the case of slim reader/writers except free the memory.
88 free(data_);
Owen Anderson74af4ee2009-06-17 09:10:42 +000089}
Owen Anderson324f94c2009-06-16 20:19:28 +000090
Kristof Beylsa11dbf22017-03-31 14:26:44 +000091bool sys::RWMutexImpl::reader_acquire() {
Michael J. Spencer00846152011-10-13 23:10:56 +000092 if (sHasSRW) {
93 fpAcquireSRWLockShared(static_cast<PSRWLOCK>(data_));
94 } else {
95 EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
96 }
Owen Anderson324f94c2009-06-16 20:19:28 +000097 return true;
98}
99
Kristof Beylsa11dbf22017-03-31 14:26:44 +0000100bool sys::RWMutexImpl::reader_release() {
Michael J. Spencer00846152011-10-13 23:10:56 +0000101 if (sHasSRW) {
102 fpReleaseSRWLockShared(static_cast<PSRWLOCK>(data_));
103 } else {
104 LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
105 }
Owen Anderson324f94c2009-06-16 20:19:28 +0000106 return true;
107}
108
Kristof Beylsa11dbf22017-03-31 14:26:44 +0000109bool sys::RWMutexImpl::writer_acquire() {
Michael J. Spencer00846152011-10-13 23:10:56 +0000110 if (sHasSRW) {
111 fpAcquireSRWLockExclusive(static_cast<PSRWLOCK>(data_));
112 } else {
113 EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
114 }
Owen Anderson324f94c2009-06-16 20:19:28 +0000115 return true;
116}
117
Kristof Beylsa11dbf22017-03-31 14:26:44 +0000118bool sys::RWMutexImpl::writer_release() {
Michael J. Spencer00846152011-10-13 23:10:56 +0000119 if (sHasSRW) {
120 fpReleaseSRWLockExclusive(static_cast<PSRWLOCK>(data_));
121 } else {
122 LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
123 }
Owen Anderson324f94c2009-06-16 20:19:28 +0000124 return true;
125}
126
127
128}