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.

156 lines
4.3 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. tcpip\ip\ipmlock.h
  5. Abstract:
  6. Reader Writer lock primitives for the IP Multicasting
  7. Author:
  8. Amritansh Raghav
  9. Revision History:
  10. AmritanR Created
  11. Notes:
  12. --*/
  13. //
  14. // Need to include "debug.h" before this file is included because
  15. // RT_LOCK is defined there
  16. //
  17. //
  18. // A reader writer lock for kernel mode.
  19. //
  20. typedef struct _RW_LOCK
  21. {
  22. RT_LOCK rlReadLock;
  23. RT_LOCK rlWriteLock;
  24. LONG lReaderCount;
  25. }RW_LOCK, *PRW_LOCK;
  26. //
  27. // VOID
  28. // InitRwLock(
  29. // PRW_LOCK pLock
  30. // )
  31. //
  32. // Initializes the spin locks and the reader count
  33. //
  34. #define InitRwLock(l) \
  35. RtInitializeSpinLock(&((l)->rlReadLock)); \
  36. RtInitializeSpinLock(&((l)->rlWriteLock)); \
  37. (l)->lReaderCount = 0
  38. //
  39. // VOID
  40. // EnterReader(
  41. // PRW_LOCK pLock,
  42. // PKIRQL pCurrIrql
  43. // )
  44. //
  45. // Acquires the Reader Spinlock (now thread is at DPC).
  46. // InterlockedIncrements the reader count (interlocked because the reader
  47. // lock is not taken when the count is decremented in ExitReader())
  48. // If the thread is the first reader, also acquires the Writer Spinlock (at
  49. // DPC to be more efficient) to block writers
  50. // Releases the Reader Spinlock from DPC, so that it remains at DPC
  51. // for the duration of the lock being held
  52. //
  53. // If a writer is in the code, the first reader will wait on the Writer
  54. // Spinlock and all subsequent readers will wait on the Reader Spinlock
  55. // If a reader is in the code and is executing the EnterReader, then a new
  56. // reader will wait for sometime on the Reader Spinlock, and then proceed
  57. // on to the code (at DPC)
  58. //
  59. #define EnterReader(l, q) \
  60. RtAcquireSpinLock(&((l)->rlReadLock), (q)); \
  61. if(InterlockedIncrement(&((l)->lReaderCount)) == 1) \
  62. RtAcquireSpinLockAtDpcLevel(&((l)->rlWriteLock)); \
  63. RtReleaseSpinLockFromDpcLevel(&((l)->rlReadLock))
  64. #define EnterReaderAtDpcLevel(l) \
  65. RtAcquireSpinLockAtDpcLevel(&((l)->rlReadLock)); \
  66. if(InterlockedIncrement(&((l)->lReaderCount)) == 1) \
  67. RtAcquireSpinLockAtDpcLevel(&((l)->rlWriteLock)); \
  68. RtReleaseSpinLockFromDpcLevel(&((l)->rlReadLock))
  69. //
  70. // VOID
  71. // ExitReader(
  72. // PRW_LOCK pLock,
  73. // KIRQL kiOldIrql
  74. // )
  75. //
  76. // InterlockedDec the reader count.
  77. // If this is the last reader, then release the Writer Spinlock to let
  78. // other writers in
  79. // Otherwise, just lower the irql to what was before the lock was
  80. // acquired. Either way, the irql is down to original irql
  81. //
  82. #define ExitReader(l, q) \
  83. if(InterlockedDecrement(&((l)->lReaderCount)) == 0) \
  84. RtReleaseSpinLock(&((l)->rlWriteLock), q); \
  85. else \
  86. KeLowerIrql(q)
  87. #define ExitReaderFromDpcLevel(l) \
  88. if(InterlockedDecrement(&((l)->lReaderCount)) == 0) \
  89. RtReleaseSpinLockFromDpcLevel(&((l)->rlWriteLock))
  90. //
  91. // EnterWriter(
  92. // PRW_LOCK pLock,
  93. // PKIRQL pCurrIrql
  94. // )
  95. //
  96. // Acquire the reader and then the writer spin lock
  97. // If there are readers in the code, the first writer will wait
  98. // on the Writer Spinlock. All other writers will wait (with readers)
  99. // on the Reader Spinlock
  100. // If there is a writer in the code then a new writer will wait on
  101. // the Reader Spinlock
  102. #define EnterWriter(l, q) \
  103. RtAcquireSpinLock(&((l)->rlReadLock), (q)); \
  104. RtAcquireSpinLockAtDpcLevel(&((l)->rlWriteLock))
  105. #define EnterWriterAtDpcLevel(l) \
  106. RtAcquireSpinLockAtDpcLevel(&((l)->rlReadLock)); \
  107. RtAcquireSpinLockAtDpcLevel(&((l)->rlWriteLock))
  108. //
  109. // ExitWriter(
  110. // PRW_LOCK pLock,
  111. // KIRQL kiOldIrql
  112. // )
  113. //
  114. // Release both the locks
  115. //
  116. #define ExitWriter(l, q) \
  117. RtReleaseSpinLockFromDpcLevel(&((l)->rlWriteLock)); \
  118. RtReleaseSpinLock(&((l)->rlReadLock), q)
  119. #define ExitWriterFromDpcLevel(l) \
  120. RtReleaseSpinLockFromDpcLevel(&((l)->rlWriteLock)); \
  121. RtReleaseSpinLockFromDpcLevel(&((l)->rlReadLock))