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.

298 lines
5.3 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 retval = FALSE;
  52. HANDLE hSemaphore = NULL;
  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. // Create a semaphore with maximum count as 1, which means
  63. // that only one thread can own it
  64. hSemaphore = psr->WriterSemaphore = CreateSemaphore(NULL, 1, 1, NULL);
  65. }
  66. __finally {
  67. if (brr && hSemaphore) {
  68. retval = TRUE;
  69. psr->Valid = TRUE;
  70. }
  71. else {
  72. if (brr)
  73. DeleteCriticalSection(&psr->ReaderMutex);
  74. if (hSemaphore)
  75. CloseHandle(psr->WriterSemaphore);
  76. psr->Valid = FALSE;
  77. }
  78. }
  79. // Initialize Readers
  80. psr->Readers = 0;
  81. return retval;
  82. }
  83. VOID
  84. AcquireResourceShared(
  85. IN PSHAREDRESOURCE psr
  86. )
  87. /*++
  88. Routine Description:
  89. This routine acquires a resource for shared access.
  90. Arguments:
  91. psr - Pointer to SHAREDRESOURCE which has been initialized.
  92. Return Value:
  93. None.
  94. --*/
  95. {
  96. ASSERT(psr->Valid);
  97. EnterCriticalSection(&psr->ReaderMutex);
  98. psr->Readers += 1;
  99. if (psr->Readers == 1)
  100. WaitForSingleObject(psr->WriterSemaphore, INFINITE);
  101. LeaveCriticalSection(&psr->ReaderMutex);
  102. }
  103. VOID
  104. ReleaseResourceShared(
  105. IN PSHAREDRESOURCE psr
  106. )
  107. /*++
  108. Routine Description:
  109. This routine releases a resource's shared access.
  110. Arguments:
  111. psr - Pointer to SHAREDRESOURCE which has been initialized and which has
  112. shared (read) access.
  113. Return Value:
  114. None.
  115. --*/
  116. {
  117. ASSERT(psr->Valid);
  118. EnterCriticalSection(&psr->ReaderMutex);
  119. ASSERT(psr->Readers != 0);
  120. psr->Readers -= 1;
  121. if (psr->Readers == 0)
  122. ReleaseSemaphore(psr->WriterSemaphore, 1, NULL);
  123. LeaveCriticalSection(&psr->ReaderMutex);
  124. }
  125. VOID
  126. AcquireResourceExclusive(
  127. IN PSHAREDRESOURCE psr
  128. )
  129. /*++
  130. Routine Description:
  131. This routine acquires a resource for exclusive (write) access.
  132. Arguments:
  133. psr - Pointer to SHAREDRESOURCE which has been initialized.
  134. Return Value:
  135. None.
  136. --*/
  137. {
  138. ASSERT(psr->Valid);
  139. WaitForSingleObject(psr->WriterSemaphore, INFINITE);
  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. ReleaseSemaphore(psr->WriterSemaphore, 1, NULL);
  157. }
  158. VOID
  159. FreeSharedResource(
  160. IN OUT PSHAREDRESOURCE psr
  161. )
  162. /*++
  163. Routine Description:
  164. This routine frees resources taken up by a shared resource object allocated
  165. by InitializeSharedResource. It does not free the memory.
  166. Arguments:
  167. psr - Pointer to SHAREDRESOURCE whose resources should be freed.
  168. Return Value:
  169. None.
  170. --*/
  171. {
  172. ASSERT(psr->Valid);
  173. ASSERT(psr->Readers == 0);
  174. DeleteCriticalSection(&psr->ReaderMutex);
  175. CloseHandle(psr->WriterSemaphore);
  176. psr->Readers = 0;
  177. psr->Valid = FALSE;
  178. }
  179. BOOL
  180. VerifyNoSharedAccess(
  181. IN PSHAREDRESOURCE psr
  182. )
  183. /*++
  184. Routine Description:
  185. This routine verifies that the critical section does not currently have any
  186. shared accessors.
  187. Arugments:
  188. psr - Pointer to SHAREDRESOURCE to verify.
  189. Return Value:
  190. TRUE - if there are no shared accessors.
  191. FALSE - if there are shared accessors.
  192. --*/
  193. {
  194. ASSERT(psr->Valid);
  195. return (psr->Readers == 0);
  196. }