RWMutex.inc 4.1 KB

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