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.

394 lines
6.3 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. qlock.c
  5. Abstract:
  6. This module contains the code to emulate the operation of queued spin
  7. locks using ordinary spin locks interfaces.
  8. Author:
  9. David N. Cutler 13-Feb-2000
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. --*/
  14. #include "ki.h"
  15. #if defined(NT_UP)
  16. #undef KeAcquireQueuedSpinLockRaiseToSynch
  17. #undef KeAcquireQueuedSpinLock
  18. #undef KeReleaseQueuedSpinLock
  19. #undef KeTryToAcquireQueuedSpinLockRaiseToSynch
  20. #undef KeTryToAcquireQueuedSpinLock
  21. #undef KeAcquireQueuedSpinLockAtDpcLevel
  22. #undef KeReleaseQueuedSpinLockFromDpcLevel
  23. #endif
  24. VOID
  25. FASTCALL
  26. KeAcquireQueuedSpinLockAtDpcLevel (
  27. IN PKSPIN_LOCK_QUEUE LockQueue
  28. )
  29. /*++
  30. Routine Description:
  31. This function acquires a queued spin lock at DPC level.
  32. Arguments:
  33. LockQueue - Supplies a pointer to a lock queue entry in the PRCB.
  34. Return Value:
  35. None.
  36. --*/
  37. {
  38. KiAcquireSpinLock(LockQueue->Lock);
  39. return;
  40. }
  41. VOID
  42. FASTCALL
  43. KeReleaseQueuedSpinLockFromDpcLevel (
  44. IN PKSPIN_LOCK_QUEUE LockQueue
  45. )
  46. /*++
  47. Routine Description:
  48. This function releases a queued spin lock at DPC level.
  49. Arguments:
  50. LockQueue - Supplies a pointer to a lock queue entry in the PRCB.
  51. Return Value:
  52. None.
  53. --*/
  54. {
  55. KiReleaseSpinLock(LockQueue->Lock);
  56. return;
  57. }
  58. KIRQL
  59. FASTCALL
  60. KeAcquireQueuedSpinLock (
  61. IN KSPIN_LOCK_QUEUE_NUMBER Number
  62. )
  63. /*++
  64. Routine Description:
  65. This function acquires a queued spin lock and raises IRQL to DPC
  66. level.
  67. Arguments:
  68. Number - Supplies the lock queue number.
  69. Return Value:
  70. The previous IRQL is returned as the function value.
  71. --*/
  72. {
  73. PKSPIN_LOCK Lock;
  74. KIRQL OldIrql;
  75. //
  76. // N.B. It is safe to use any PRCB address since the backpointer
  77. // to the actual spinlock is always the same.
  78. //
  79. Lock = KeGetCurrentPrcb()->LockQueue[Number].Lock;
  80. KeAcquireSpinLock(Lock, &OldIrql);
  81. return OldIrql;
  82. }
  83. VOID
  84. FASTCALL
  85. KeReleaseQueuedSpinLock (
  86. IN KSPIN_LOCK_QUEUE_NUMBER Number,
  87. IN KIRQL OldIrql
  88. )
  89. /*++
  90. Routine Description:
  91. This function releases a queued spin lock and lowers IRQL to the
  92. previous level.
  93. Arguments:
  94. LockQueue - Supplies a pointer to a lock queue entry in the PRCB.
  95. Irql - Supplies the previos IRQL level.
  96. Return Value:
  97. None.
  98. --*/
  99. {
  100. PKSPIN_LOCK Lock;
  101. //
  102. // N.B. It is safe to use any PRCB address since the backpointer
  103. // to the actual spinlock is always the same.
  104. //
  105. Lock = KeGetCurrentPrcb()->LockQueue[Number].Lock;
  106. KeReleaseSpinLock(Lock, OldIrql);
  107. return;
  108. }
  109. LOGICAL
  110. FASTCALL
  111. KeTryToAcquireQueuedSpinLock(
  112. IN KSPIN_LOCK_QUEUE_NUMBER Number,
  113. IN PKIRQL OldIrql
  114. )
  115. /*++
  116. Routine Description:
  117. This function attempts to acquire a queued spin lock and raises IRQL
  118. to DPC level.
  119. Arguments:
  120. Number - Supplies the lock queue number.
  121. OldIrql - Supplies a pointer to a variable that receives the previous
  122. IRQL value.
  123. Return Value:
  124. A value of TRUE is returned if the spin lock is acquired. Otherwise,
  125. a value of FALSE is returned.
  126. --*/
  127. {
  128. PKSPIN_LOCK Lock;
  129. //
  130. // N.B. It is safe to use any PRCB address since the backpointer
  131. // to the actual spinlock is always the same.
  132. //
  133. Lock = KeGetCurrentPrcb()->LockQueue[Number].Lock;
  134. return KeTryToAcquireSpinLock(Lock, OldIrql);
  135. }
  136. KIRQL
  137. FASTCALL
  138. KeAcquireQueuedSpinLockRaiseToSynch (
  139. IN KSPIN_LOCK_QUEUE_NUMBER Number
  140. )
  141. /*++
  142. Routine Description:
  143. This function acquires a queued spin lock and raises IRQL to synch
  144. level.
  145. Arguments:
  146. Number - Supplies the lock queue number.
  147. Return Value:
  148. The previous IRQL is returned as the function value.
  149. --*/
  150. {
  151. PKSPIN_LOCK Lock;
  152. //
  153. // N.B. It is safe to use any PRCB address since the backpointer
  154. // to the actual spinlock is always the same.
  155. //
  156. Lock = KeGetCurrentPrcb()->LockQueue[Number].Lock;
  157. return KeAcquireSpinLockRaiseToSynch(Lock);
  158. }
  159. LOGICAL
  160. FASTCALL
  161. KeTryToAcquireQueuedSpinLockRaiseToSynch(
  162. IN KSPIN_LOCK_QUEUE_NUMBER Number,
  163. IN PKIRQL OldIrql
  164. )
  165. /*++
  166. Routine Description:
  167. This function attempts to acquire a queued spin lock and raises IRQL
  168. to synch level.
  169. Arguments:
  170. Number - Supplies the lock queue number.
  171. OldIrql - Supplies a pointer to a variable that receives the previous
  172. IRQL value.
  173. Return Value:
  174. A value of TRUE is returned if the spin lock is acquired. Otherwise,
  175. a value of FALSE is returned.
  176. --*/
  177. {
  178. PKSPIN_LOCK Lock;
  179. //
  180. // N.B. It is safe to use any PRCB address since the backpointer
  181. // to the actual spinlock is always the same.
  182. //
  183. Lock = KeGetCurrentPrcb()->LockQueue[Number].Lock;
  184. *OldIrql = KeAcquireSpinLockRaiseToSynch(Lock);
  185. return TRUE;
  186. }
  187. VOID
  188. KeAcquireInStackQueuedSpinLock (
  189. IN PKSPIN_LOCK SpinLock,
  190. IN PKLOCK_QUEUE_HANDLE LockHandle
  191. )
  192. {
  193. #if !defined(NT_UP)
  194. LockHandle->LockQueue.Next = NULL;
  195. LockHandle->LockQueue.Lock = SpinLock;
  196. #endif
  197. LockHandle->OldIrql = KeRaiseIrqlToDpcLevel();
  198. #if !defined(NT_UP)
  199. KeAcquireQueuedSpinLockAtDpcLevel(&LockHandle->LockQueue);
  200. #endif
  201. return;
  202. }
  203. VOID
  204. KeAcquireInStackQueuedSpinLockRaiseToSynch (
  205. IN PKSPIN_LOCK SpinLock,
  206. IN PKLOCK_QUEUE_HANDLE LockHandle
  207. )
  208. {
  209. #if !defined(NT_UP)
  210. LockHandle->LockQueue.Next = NULL;
  211. LockHandle->LockQueue.Lock = SpinLock;
  212. #endif
  213. LockHandle->OldIrql = KeRaiseIrqlToSynchLevel();
  214. #if !defined(NT_UP)
  215. KeAcquireQueuedSpinLockAtDpcLevel(&LockHandle->LockQueue);
  216. #endif
  217. return;
  218. }
  219. VOID
  220. KeReleaseInStackQueuedSpinLock (
  221. IN PKLOCK_QUEUE_HANDLE LockHandle
  222. )
  223. {
  224. #if !defined(NT_UP)
  225. KeReleaseQueuedSpinLockFromDpcLevel(&LockHandle->LockQueue);
  226. #endif
  227. KeLowerIrql(LockHandle->OldIrql);
  228. return;
  229. }
  230. VOID
  231. KeAcquireInStackQueuedSpinLockAtDpcLevel (
  232. IN PKSPIN_LOCK SpinLock,
  233. IN PKLOCK_QUEUE_HANDLE LockHandle
  234. )
  235. {
  236. #if !defined(NT_UP)
  237. LockHandle->LockQueue.Next = NULL;
  238. LockHandle->LockQueue.Lock = SpinLock;
  239. KeAcquireQueuedSpinLockAtDpcLevel(&LockHandle->LockQueue);
  240. #endif
  241. return;
  242. }
  243. VOID
  244. KeReleaseInStackQueuedSpinLockFromDpcLevel (
  245. IN PKLOCK_QUEUE_HANDLE LockHandle
  246. )
  247. {
  248. #if !defined(NT_UP)
  249. KeReleaseQueuedSpinLockFromDpcLevel(&LockHandle->LockQueue);
  250. #endif
  251. return;
  252. }