Source code of Windows XP (NT5)
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.

300 lines
4.9 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. synch.c
  5. Abstract:
  6. This module contains routines for shared reader/writer locks for Session
  7. Directory. These reader/writer locks can starve writers, so the assumption
  8. is that there is not a lot of constant reading activity.
  9. Author:
  10. Trevor Foucher (trevorfo) 01-Feb-2001
  11. Environment:
  12. User mode.
  13. Revision History:
  14. 01-Feb-2001 trevorfo
  15. Created
  16. --*/
  17. #include "synch.h"
  18. #if DBG
  19. NTSYSAPI
  20. VOID
  21. NTAPI
  22. RtlAssert(
  23. PVOID FailedAssertion,
  24. PVOID FileName,
  25. ULONG LineNumber,
  26. PCHAR Message
  27. );
  28. #define ASSERT( exp ) \
  29. ((!(exp)) ? \
  30. (RtlAssert( #exp, __FILE__, __LINE__, NULL ),FALSE) : \
  31. TRUE)
  32. #else
  33. #define ASSERT( exp ) ((void) 0)
  34. #endif
  35. BOOL
  36. InitializeSharedResource(
  37. IN OUT PSHAREDRESOURCE psr
  38. )
  39. /*++
  40. Routine Description:
  41. This routine initializes a shared resource object. Call FreeSharedResource
  42. to free.
  43. Arguments:
  44. psr - Pointer to SHAREDRESOURCE to initialize. Must point to a valid block
  45. of memory, and the psr->Valid field must be FALSE.
  46. Return Value:
  47. TRUE if the function succeeds, FALSE if it fails.
  48. --*/
  49. {
  50. BOOL brr = FALSE;
  51. BOOL bwr = FALSE;
  52. BOOL retval = FALSE;
  53. ASSERT(!IsBadReadPtr(psr, sizeof(psr)));
  54. ASSERT(psr->Valid == FALSE);
  55. // Initialize Reader Mutex, Writer Mutex.
  56. __try {
  57. // Initialize the critical section to preallocate the event
  58. // and spin 4096 times on each try (since we don't spend very
  59. // long in our critical section).
  60. brr = InitializeCriticalSectionAndSpinCount(&psr->ReaderMutex,
  61. 0x80001000);
  62. bwr = InitializeCriticalSectionAndSpinCount(&psr->WriterMutex,
  63. 0x80001000);
  64. }
  65. __finally {
  66. if (brr && bwr) {
  67. retval = TRUE;
  68. psr->Valid = TRUE;
  69. }
  70. else {
  71. if (brr)
  72. DeleteCriticalSection(&psr->ReaderMutex);
  73. if (bwr)
  74. DeleteCriticalSection(&psr->WriterMutex);
  75. psr->Valid = FALSE;
  76. }
  77. }
  78. // Initialize Readers
  79. psr->Readers = 0;
  80. return retval;
  81. }
  82. VOID
  83. AcquireResourceShared(
  84. IN PSHAREDRESOURCE psr
  85. )
  86. /*++
  87. Routine Description:
  88. This routine acquires a resource for shared access.
  89. Arguments:
  90. psr - Pointer to SHAREDRESOURCE which has been initialized.
  91. Return Value:
  92. None.
  93. --*/
  94. {
  95. ASSERT(psr->Valid);
  96. EnterCriticalSection(&psr->ReaderMutex);
  97. psr->Readers += 1;
  98. if (psr->Readers == 1)
  99. EnterCriticalSection(&psr->WriterMutex);
  100. LeaveCriticalSection(&psr->ReaderMutex);
  101. }
  102. VOID
  103. ReleaseResourceShared(
  104. IN PSHAREDRESOURCE psr
  105. )
  106. /*++
  107. Routine Description:
  108. This routine releases a resource's shared access.
  109. Arguments:
  110. psr - Pointer to SHAREDRESOURCE which has been initialized and which has
  111. shared (read) access.
  112. Return Value:
  113. None.
  114. --*/
  115. {
  116. ASSERT(psr->Valid);
  117. EnterCriticalSection(&psr->ReaderMutex);
  118. ASSERT(psr->Readers != 0);
  119. psr->Readers -= 1;
  120. if (psr->Readers == 0)
  121. LeaveCriticalSection(&psr->WriterMutex);
  122. LeaveCriticalSection(&psr->ReaderMutex);
  123. }
  124. VOID
  125. AcquireResourceExclusive(
  126. IN PSHAREDRESOURCE psr
  127. )
  128. /*++
  129. Routine Description:
  130. This routine acquires a resource for exclusive (write) access.
  131. Arguments:
  132. psr - Pointer to SHAREDRESOURCE which has been initialized.
  133. Return Value:
  134. None.
  135. --*/
  136. {
  137. ASSERT(psr->Valid);
  138. EnterCriticalSection(&psr->WriterMutex);
  139. ASSERT(psr->Readers == 0);
  140. }
  141. VOID
  142. ReleaseResourceExclusive(
  143. IN PSHAREDRESOURCE psr
  144. )
  145. /*++
  146. Routine Description:
  147. This routine releases a resource for which we have exclusive (write) access.
  148. Arguments:
  149. psr - Pointer to SHAREDRESOURCE which has been initialized and which has
  150. write access.
  151. Return Value:
  152. None.
  153. --*/
  154. {
  155. ASSERT(psr->Valid);
  156. ASSERT(psr->Readers == 0);
  157. LeaveCriticalSection(&psr->WriterMutex);
  158. }
  159. VOID
  160. FreeSharedResource(
  161. IN OUT PSHAREDRESOURCE psr
  162. )
  163. /*++
  164. Routine Description:
  165. This routine frees resources taken up by a shared resource object allocated
  166. by InitializeSharedResource. It does not free the memory.
  167. Arguments:
  168. psr - Pointer to SHAREDRESOURCE whose resources should be freed.
  169. Return Value:
  170. None.
  171. --*/
  172. {
  173. ASSERT(psr->Valid);
  174. ASSERT(psr->Readers == 0);
  175. DeleteCriticalSection(&psr->ReaderMutex);
  176. DeleteCriticalSection(&psr->WriterMutex);
  177. psr->Readers = 0;
  178. psr->Valid = FALSE;
  179. }
  180. BOOL
  181. VerifyNoSharedAccess(
  182. IN PSHAREDRESOURCE psr
  183. )
  184. /*++
  185. Routine Description:
  186. This routine verifies that the critical section does not currently have any
  187. shared accessors.
  188. Arugments:
  189. psr - Pointer to SHAREDRESOURCE to verify.
  190. Return Value:
  191. TRUE - if there are no shared accessors.
  192. FALSE - if there are shared accessors.
  193. --*/
  194. {
  195. ASSERT(psr->Valid);
  196. return (psr->Readers == 0);
  197. }