RWMutex.inc revision 263508
194541Sru//= llvm/Support/Win32/Mutex.inc - Win32 Reader/Writer Mutual Exclusion Lock  =//
294541Sru//
394541Sru//                     The LLVM Compiler Infrastructure
494541Sru//
594541Sru// This file is distributed under the University of Illinois Open Source
694541Sru// License. See LICENSE.TXT for details.
794541Sru//
894541Sru//===----------------------------------------------------------------------===//
994541Sru//
1094541Sru// This file implements the Win32 specific (non-pthread) RWMutex class.
1194541Sru//
1294541Sru//===----------------------------------------------------------------------===//
1394541Sru
1494541Sru//===----------------------------------------------------------------------===//
1594541Sru//=== WARNING: Implementation here must contain only generic Win32 code that
1694541Sru//===          is guaranteed to work on *all* Win32 variants.
1794541Sru//===----------------------------------------------------------------------===//
1894541Sru
1994541Sru#include "Windows.h"
2094541Sru
2194541Srunamespace llvm {
2294541Sruusing namespace sys;
2394541Sru
2494541Sru// Windows has slim read-writer lock support on Vista and higher, so we
2594541Sru// will attempt to load the APIs.  If they exist, we will use them, and
2694541Sru// if not, we will fall back on critical sections.  When we drop support
2794541Sru// for XP, we can stop lazy-loading these APIs and just use them directly.
2894541Sru#if defined(__MINGW32__)
2994541Sru  // Taken from WinNT.h
3094541Sru  typedef struct _RTL_SRWLOCK {
3194541Sru    PVOID Ptr;
3294541Sru  } RTL_SRWLOCK, *PRTL_SRWLOCK;
3394541Sru
3494541Sru  // Taken from WinBase.h
3594541Sru  typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK;
3694541Sru#endif
3794541Sru
3894541Srustatic VOID (WINAPI *fpInitializeSRWLock)(PSRWLOCK lock) = NULL;
3994541Srustatic VOID (WINAPI *fpAcquireSRWLockExclusive)(PSRWLOCK lock) = NULL;
4094541Srustatic VOID (WINAPI *fpAcquireSRWLockShared)(PSRWLOCK lock) = NULL;
4194541Srustatic VOID (WINAPI *fpReleaseSRWLockExclusive)(PSRWLOCK lock) = NULL;
4294541Srustatic VOID (WINAPI *fpReleaseSRWLockShared)(PSRWLOCK lock) = NULL;
4394541Sru
4494541Srustatic bool sHasSRW = false;
4594541Sru
4694541Srustatic bool loadSRW() {
4794541Sru  static bool sChecked = false;
4894541Sru  if (!sChecked) {
4994541Sru    sChecked = true;
5094541Sru
5194541Sru    if (HMODULE hLib = ::GetModuleHandleW(L"Kernel32.dll")) {
5294541Sru      fpInitializeSRWLock =
5394541Sru        (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
5494541Sru                                               "InitializeSRWLock");
5594541Sru      fpAcquireSRWLockExclusive =
5694541Sru        (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
5794541Sru                                               "AcquireSRWLockExclusive");
5894541Sru      fpAcquireSRWLockShared =
5994541Sru        (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
6094541Sru                                               "AcquireSRWLockShared");
6194541Sru      fpReleaseSRWLockExclusive =
6294541Sru        (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
6394541Sru                                               "ReleaseSRWLockExclusive");
6494541Sru      fpReleaseSRWLockShared =
6594541Sru        (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
6694541Sru                                               "ReleaseSRWLockShared");
6794541Sru
6894541Sru      if (fpInitializeSRWLock != NULL) {
6994541Sru        sHasSRW = true;
7094541Sru      }
7194541Sru    }
7294541Sru  }
7394541Sru  return sHasSRW;
7494541Sru}
7594541Sru
7694541SruRWMutexImpl::RWMutexImpl() {
7794541Sru  if (loadSRW()) {
7894541Sru    data_ = calloc(1, sizeof(SRWLOCK));
7994541Sru    fpInitializeSRWLock(static_cast<PSRWLOCK>(data_));
8094541Sru  } else {
8194541Sru    data_ = calloc(1, sizeof(CRITICAL_SECTION));
8294541Sru    InitializeCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
8394541Sru  }
8494541Sru}
8594541Sru
8694541SruRWMutexImpl::~RWMutexImpl() {
8794541Sru  if (sHasSRW) {
8894541Sru    // Nothing to do in the case of slim reader/writers
8994541Sru  } else {
9094541Sru    DeleteCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
9194541Sru    free(data_);
9294541Sru  }
9394541Sru}
9494541Sru
9594541Srubool RWMutexImpl::reader_acquire() {
9694541Sru  if (sHasSRW) {
9794541Sru    fpAcquireSRWLockShared(static_cast<PSRWLOCK>(data_));
9894541Sru  } else {
9994541Sru    EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
10094541Sru  }
10194541Sru  return true;
10294541Sru}
10394541Sru
10494541Srubool RWMutexImpl::reader_release() {
10594541Sru  if (sHasSRW) {
10694541Sru    fpReleaseSRWLockShared(static_cast<PSRWLOCK>(data_));
10794541Sru  } else {
10894541Sru    LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
10994541Sru  }
11094541Sru  return true;
11194541Sru}
11294541Sru
11394541Srubool RWMutexImpl::writer_acquire() {
11494541Sru  if (sHasSRW) {
11594541Sru    fpAcquireSRWLockExclusive(static_cast<PSRWLOCK>(data_));
11694541Sru  } else {
11794541Sru    EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
118  }
119  return true;
120}
121
122bool RWMutexImpl::writer_release() {
123  if (sHasSRW) {
124    fpReleaseSRWLockExclusive(static_cast<PSRWLOCK>(data_));
125  } else {
126    LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
127  }
128  return true;
129}
130
131
132}
133