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.

179 lines
7.7 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. ntos\tdi\isn\fwd\rwlock.h
  5. Abstract:
  6. Reader-Writer lock macros
  7. Author:
  8. Vadim Eydelman
  9. Revision History:
  10. --*/
  11. #ifndef _IPXFWD_RWLOCK_
  12. #define _IPXFWD_RWLOCK_
  13. typedef volatile LONG VOLCTR, *PVOLCTR;
  14. typedef PVOLCTR RWCOOKIE, *PRWCOOKIE;
  15. // Reader- writer lock.
  16. // Allows no-lock access to the tables for readers - they merely
  17. // increment the counter to record their presence upon entrance
  18. // and decrement the same counter as they leave.
  19. // Writers are supposed to be serialized (externally) and their
  20. // actions are limited to ATOMIC insertions of new elements and
  21. // ATOMIC removals/replacements. The removals/replacements MUST
  22. // be followed by a wait for all potential readers who might still
  23. // be using the element that was removed/replaced
  24. typedef struct _RW_LOCK {
  25. KEVENT Event; // Event to release waiting writer
  26. VOLCTR Ctr1; // Two alternating
  27. VOLCTR Ctr2; // reader counters
  28. volatile PVOLCTR CurCtr; // Counter currently in use
  29. } RW_LOCK, *PRW_LOCK;
  30. /*++
  31. *******************************************************************
  32. I n i t i a l i z e R W L o c k
  33. Routine Description:
  34. Initializes RW lock
  35. Arguments:
  36. lock - pointer to lock to initialize
  37. Return Value:
  38. None
  39. *******************************************************************
  40. --*/
  41. //VOID
  42. //InitializeRWLock (
  43. // PRW_LOCK lock
  44. // );
  45. #define InitializeRWLock(lock) { \
  46. KeInitializeEvent (&(lock)->Event, \
  47. SynchronizationEvent, \
  48. FALSE); \
  49. (lock)->Ctr1 = (lock)->Ctr2 = 0; \
  50. (lock)->CurCtr = &(lock)->Ctr1; \
  51. }
  52. /*++
  53. *******************************************************************
  54. A c q u i r e R e a d e r A c c e s s
  55. Routine Description:
  56. Acquires reader access to resource protected by the lock
  57. Arguments:
  58. lock - pointer to lock
  59. cookie - pointer to buffer to store lock state for subsequent
  60. release operation
  61. Return Value:
  62. None
  63. *******************************************************************
  64. --*/
  65. //VOID
  66. //AcquireReaderAccess (
  67. // IN PRW_LOCK lock,
  68. // OUT RWCOOKIE cookie
  69. // );
  70. #define AcquireReaderAccess(lock,cookie) \
  71. do { \
  72. register LONG local,local1; \
  73. cookie = (lock)->CurCtr; /*Get current counter pointer*/ \
  74. local = *(cookie); /*Copy counter value*/ \
  75. local1 = local + 1; \
  76. if ((local>=0) /*If counter is valid*/ \
  77. /*and it hasn't changed while*/ \
  78. /*we were checking and trying*/ \
  79. /*to increment it,*/ \
  80. && (InterlockedCompareExchange ( \
  81. (PLONG)(cookie), \
  82. local1, \
  83. local) \
  84. ==local)) \
  85. break; /*then we obtained the access*/ \
  86. } while (1) /*otherwise, we have to do it again (possibly with*/\
  87. /*the other counter if writer switched it on us)*/
  88. /*++
  89. *******************************************************************
  90. R e l e a s e R e a d e r A c c e s s
  91. Routine Description:
  92. Releases reader access to resource protected by the lock
  93. Arguments:
  94. lock - pointer to lock
  95. cookie - lock state for subsequent stored during acquire operation
  96. Return Value:
  97. None
  98. *******************************************************************
  99. --*/
  100. //VOID
  101. //ReleaseReaderAccess (
  102. // IN PRW_LOCK lock,
  103. // IN RWCOOKIE cookie
  104. // );
  105. #define ReleaseReaderAccess(lock,cookie) { \
  106. /*If counter drops below 0, we have to signal the writer*/ \
  107. if (InterlockedDecrement((PLONG)cookie)<0) { \
  108. LONG res; \
  109. ASSERT (*(cookie)==-1); \
  110. res = KeSetEvent (&(lock)->Event, 0, FALSE); \
  111. ASSERT (res==0); \
  112. } \
  113. }
  114. /*++
  115. *******************************************************************
  116. W a i t F o r A l l R e a d e r s
  117. Routine Description:
  118. Waits for all readers that were accessing the resource prior
  119. to the call to exit (New readers are not included)
  120. Arguments:
  121. lock - pointer to lock
  122. Return Value:
  123. None
  124. *******************************************************************
  125. --*/
  126. //VOID
  127. //WaitForAllReaders (
  128. // PRW_LOCK lock
  129. // );
  130. #define WaitForAllReaders(lock) { \
  131. RWCOOKIE prevCtr = (lock)->CurCtr; \
  132. /*Switch the counter first*/ \
  133. if (prevCtr==&(lock)->Ctr1) { \
  134. (lock)->Ctr2 = 0; \
  135. (lock)->CurCtr = &(lock)->Ctr2; \
  136. } \
  137. else { \
  138. ASSERT (prevCtr==&(lock)->Ctr2); \
  139. (lock)->Ctr1 = 0; \
  140. (lock)->CurCtr = &(lock)->Ctr1; \
  141. } \
  142. /* If not all readers are gone, we'll have to wait for them*/ \
  143. if (InterlockedDecrement((PLONG)prevCtr)>=0) { \
  144. NTSTATUS status \
  145. = KeWaitForSingleObject ( \
  146. &(lock)->Event, \
  147. Executive, \
  148. ExGetPreviousMode(),\
  149. FALSE, \
  150. 0); \
  151. ASSERT (NT_SUCCESS(status)); \
  152. ASSERT (*prevCtr==-1); \
  153. } \
  154. }
  155. #endif