1 //= llvm/Support/Win32/Mutex.inc - Win32 Reader/Writer Mutual Exclusion Lock =//
3 // 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
7 //===----------------------------------------------------------------------===//
9 // This file implements the Win32 specific (non-pthread) RWMutex class.
11 //===----------------------------------------------------------------------===//
13 //===----------------------------------------------------------------------===//
14 //=== WARNING: Implementation here must contain only generic Win32 code that
15 //=== is guaranteed to work on *all* Win32 variants.
16 //===----------------------------------------------------------------------===//
18 #include "WindowsSupport.h"
22 // 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__)
28 typedef struct _RTL_SRWLOCK {
30 } RTL_SRWLOCK, *PRTL_SRWLOCK;
32 // Taken from WinBase.h
33 typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK;
36 static VOID (WINAPI *fpInitializeSRWLock)(PSRWLOCK lock) = NULL;
37 static VOID (WINAPI *fpAcquireSRWLockExclusive)(PSRWLOCK lock) = NULL;
38 static VOID (WINAPI *fpAcquireSRWLockShared)(PSRWLOCK lock) = NULL;
39 static VOID (WINAPI *fpReleaseSRWLockExclusive)(PSRWLOCK lock) = NULL;
40 static VOID (WINAPI *fpReleaseSRWLockShared)(PSRWLOCK lock) = NULL;
42 static bool sHasSRW = false;
44 static bool loadSRW() {
45 static bool sChecked = false;
49 if (HMODULE hLib = ::GetModuleHandleW(L"Kernel32.dll")) {
51 (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
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");
66 if (fpInitializeSRWLock != NULL) {
74 sys::RWMutexImpl::RWMutexImpl() {
76 data_ = safe_calloc(1, sizeof(SRWLOCK));
77 fpInitializeSRWLock(static_cast<PSRWLOCK>(data_));
79 data_ = safe_calloc(1, sizeof(CRITICAL_SECTION));
80 InitializeCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
84 sys::RWMutexImpl::~RWMutexImpl() {
86 DeleteCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
87 // Nothing to do in the case of slim reader/writers except free the memory.
91 bool sys::RWMutexImpl::reader_acquire() {
93 fpAcquireSRWLockShared(static_cast<PSRWLOCK>(data_));
95 EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
100 bool sys::RWMutexImpl::reader_release() {
102 fpReleaseSRWLockShared(static_cast<PSRWLOCK>(data_));
104 LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
109 bool sys::RWMutexImpl::writer_acquire() {
111 fpAcquireSRWLockExclusive(static_cast<PSRWLOCK>(data_));
113 EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
118 bool sys::RWMutexImpl::writer_release() {
120 fpReleaseSRWLockExclusive(static_cast<PSRWLOCK>(data_));
122 LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));