Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

241 lines
5.1 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. mrswlock.c
  5. Abstract:
  6. This module contains multiple readers / single writer implementation.
  7. Author:
  8. abhisheV 18-October-2001
  9. Environment
  10. User Level: Win32
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. DWORD
  15. InitializeRWLock(
  16. PWZC_RW_LOCK pWZCRWLock
  17. )
  18. {
  19. DWORD dwError = 0;
  20. SECURITY_ATTRIBUTES SecurityAttributes;
  21. memset(pWZCRWLock, 0, sizeof(WZC_RW_LOCK));
  22. __try {
  23. InitializeCriticalSection(&(pWZCRWLock->csExclusive));
  24. pWZCRWLock->bInitExclusive = TRUE;
  25. }
  26. __except (EXCEPTION_EXECUTE_HANDLER) {
  27. dwError = GetExceptionCode();
  28. BAIL_ON_WIN32_ERROR(dwError);
  29. }
  30. __try {
  31. InitializeCriticalSection(&(pWZCRWLock->csShared));
  32. pWZCRWLock->bInitShared = TRUE;
  33. }
  34. __except (EXCEPTION_EXECUTE_HANDLER) {
  35. dwError = GetExceptionCode();
  36. BAIL_ON_WIN32_ERROR(dwError);
  37. }
  38. memset(&SecurityAttributes, 0, sizeof(SECURITY_ATTRIBUTES));
  39. SecurityAttributes.nLength = sizeof(SecurityAttributes);
  40. SecurityAttributes.lpSecurityDescriptor = NULL;
  41. SecurityAttributes.bInheritHandle = TRUE;
  42. pWZCRWLock->hReadDone = CreateEvent(
  43. &SecurityAttributes,
  44. TRUE,
  45. FALSE,
  46. NULL
  47. );
  48. if (!pWZCRWLock->hReadDone) {
  49. dwError = GetLastError();
  50. BAIL_ON_WIN32_ERROR(dwError);
  51. }
  52. SetEvent(pWZCRWLock->hReadDone);
  53. return (dwError);
  54. error:
  55. DestroyRWLock(pWZCRWLock);
  56. return (dwError);
  57. }
  58. VOID
  59. DestroyRWLock(
  60. PWZC_RW_LOCK pWZCRWLock
  61. )
  62. {
  63. if (pWZCRWLock->hReadDone) {
  64. CloseHandle(pWZCRWLock->hReadDone);
  65. }
  66. if (pWZCRWLock->bInitShared == TRUE) {
  67. DeleteCriticalSection(&(pWZCRWLock->csShared));
  68. pWZCRWLock->bInitShared = FALSE;
  69. }
  70. if (pWZCRWLock->bInitExclusive == TRUE) {
  71. DeleteCriticalSection(&(pWZCRWLock->csExclusive));
  72. pWZCRWLock->bInitExclusive = FALSE;
  73. }
  74. memset(pWZCRWLock, 0, sizeof(WZC_RW_LOCK));
  75. return;
  76. }
  77. VOID
  78. AcquireSharedLock(
  79. PWZC_RW_LOCK pWZCRWLock
  80. )
  81. {
  82. //
  83. // Claim the exclusive critical section. This call blocks if there's
  84. // an active writer or if there's a writer waiting for active readers
  85. // to complete.
  86. //
  87. EnterCriticalSection(&(pWZCRWLock->csExclusive));
  88. //
  89. // Claim access to the reader count. If this blocks, it's only for a
  90. // brief moment while other reader threads go through to increment or
  91. // decrement the reader count.
  92. //
  93. EnterCriticalSection(&(pWZCRWLock->csShared));
  94. //
  95. // Increment the reader count. If this is the first reader then reset
  96. // the read done event so that the next writer blocks.
  97. //
  98. if ((pWZCRWLock->lReaders)++ == 0) {
  99. ResetEvent(pWZCRWLock->hReadDone);
  100. }
  101. //
  102. // Release access to the reader count.
  103. //
  104. LeaveCriticalSection(&(pWZCRWLock->csShared));
  105. //
  106. // Release access to the exclusive critical section. This enables
  107. // other readers to come through and the next write to wait for
  108. // active readers to complete which in turn prevents new readers
  109. // from entering.
  110. //
  111. LeaveCriticalSection(&(pWZCRWLock->csExclusive));
  112. return;
  113. }
  114. VOID
  115. AcquireExclusiveLock(
  116. PWZC_RW_LOCK pWZCRWLock
  117. )
  118. {
  119. DWORD dwStatus = 0;
  120. //
  121. // Claim the exclusive critical section. This not only prevents other
  122. // threads from claiming the write lock, but also prevents any new
  123. // threads from claiming the read lock.
  124. //
  125. EnterCriticalSection(&(pWZCRWLock->csExclusive));
  126. pWZCRWLock->dwCurExclusiveOwnerThreadId = GetCurrentThreadId();
  127. //
  128. // Wait for the active readers to release their read locks.
  129. //
  130. dwStatus = WaitForSingleObject(pWZCRWLock->hReadDone, INFINITE);
  131. ASSERT(dwStatus == WAIT_OBJECT_0);
  132. return;
  133. }
  134. VOID
  135. ReleaseSharedLock(
  136. PWZC_RW_LOCK pWZCRWLock
  137. )
  138. {
  139. //
  140. // Claim access to the reader count. If this blocks, it's only for a
  141. // brief moment while other reader threads go through to increment or
  142. // decrement the reader count.
  143. //
  144. EnterCriticalSection(&(pWZCRWLock->csShared));
  145. //
  146. // Decrement the reader count. If this is the last reader, set read
  147. // done event, which allows the first waiting writer to proceed.
  148. //
  149. if (--(pWZCRWLock->lReaders) == 0) {
  150. SetEvent(pWZCRWLock->hReadDone);
  151. }
  152. //
  153. // Release access to the reader count.
  154. //
  155. LeaveCriticalSection(&(pWZCRWLock->csShared));
  156. return;
  157. }
  158. VOID
  159. ReleaseExclusiveLock(
  160. PWZC_RW_LOCK pWZCRWLock
  161. )
  162. {
  163. //
  164. // Make the exclusive critical section available to one other writer
  165. // or to the first reader.
  166. //
  167. pWZCRWLock->dwCurExclusiveOwnerThreadId = 0;
  168. LeaveCriticalSection(&(pWZCRWLock->csExclusive));
  169. return;
  170. }