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