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.

494 lines
7.4 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. spinlock.c
  5. Abstract:
  6. This module implements the platform specific functions for acquiring
  7. and releasing spin locks.
  8. Author:
  9. David N. Cutler (davec) 12-Jun-2000
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. --*/
  14. #include "ki.h"
  15. __forceinline
  16. VOID
  17. KxAcquireSpinLock (
  18. IN PKSPIN_LOCK SpinLock
  19. )
  20. /*++
  21. Routine Description:
  22. This function acquires a spin lock at the current IRQL.
  23. Arguments:
  24. SpinLock - Supplies a pointer to an spin lock.
  25. Return Value:
  26. None.
  27. --*/
  28. {
  29. PKTHREAD Thread;
  30. //
  31. // Acquire the specified spin lock at the current IRQL.
  32. //
  33. #if !defined(NT_UP)
  34. #if DBG
  35. Thread = KeGetCurrentThread();
  36. while (InterlockedCompareExchange64((PLONGLONG)SpinLock,
  37. (LONGLONG)Thread,
  38. 0) != 0) {
  39. #else
  40. while (InterlockedExchange64((PLONGLONG)SpinLock,
  41. (LONGLONG)SpinLock) != 0) {
  42. #endif // DBG
  43. do {
  44. } while (*(volatile LONGLONG *)SpinLock != 0);
  45. }
  46. #endif // !defined(NT_UP)
  47. return;
  48. }
  49. __forceinline
  50. BOOLEAN
  51. KxTryToAcquireSpinLock (
  52. IN PKSPIN_LOCK SpinLock
  53. )
  54. /*++
  55. Routine Description:
  56. This function attempts acquires a spin lock at the current IRQL. If
  57. the spinlock is already owned, then FALSE is returned. Otherwise,
  58. TRUE is returned.
  59. Arguments:
  60. SpinLock - Supplies a pointer to a spin lock.
  61. Return Value:
  62. If the spin lock is acquired a value TRUE is returned. Otherwise, FALSE
  63. is returned as the function value.
  64. --*/
  65. {
  66. PKTHREAD Thread;
  67. //
  68. // Try to acquire the specified spin lock at the current IRQL.
  69. //
  70. #if !defined(NT_UP)
  71. if (*(volatile ULONGLONG *)SpinLock == 0) {
  72. #if DBG
  73. Thread = KeGetCurrentThread();
  74. return InterlockedCompareExchange64((PLONGLONG)SpinLock,
  75. (LONGLONG)Thread,
  76. 0) == 0;
  77. #else
  78. return InterlockedExchange64((PLONGLONG)SpinLock,
  79. (LONGLONG)SpinLock) == 0;
  80. #endif // DBG
  81. } else {
  82. return FALSE;
  83. }
  84. #else
  85. return TRUE;
  86. #endif // !defined(NT_UP)
  87. }
  88. __forceinline
  89. VOID
  90. KxReleaseSpinLock (
  91. IN PKSPIN_LOCK SpinLock
  92. )
  93. /*++
  94. Routine Description:
  95. This function releases the specified spin lock at the current IRQL.
  96. Arguments:
  97. SpinLock - Supplies a pointer to a spin lock.
  98. Return Value:
  99. None.
  100. --*/
  101. {
  102. #if !defined(NT_UP)
  103. #if DBG
  104. ASSERT(*(volatile ULONGLONG *)SpinLock == (ULONGLONG)KeGetCurrentThread());
  105. #endif // DBG
  106. *(volatile ULONGLONG *)SpinLock = 0;
  107. #endif // !defined(NT_UP)
  108. return;
  109. }
  110. VOID
  111. KeInitializeSpinLock (
  112. IN PKSPIN_LOCK SpinLock
  113. )
  114. /*++
  115. Routine Description:
  116. This function initializes a spin lock.
  117. Arguments:
  118. SpinLock - Supplies a pointer to a spin lock.
  119. Return Value:
  120. None.
  121. --*/
  122. {
  123. *(volatile ULONGLONG *)SpinLock = 0;
  124. return;
  125. }
  126. KIRQL
  127. KeAcquireSpinLockRaiseToDpc (
  128. IN PKSPIN_LOCK SpinLock
  129. )
  130. /*++
  131. Routine Description:
  132. This function raises IRQL to DISPATCH_LEVEL and acquires the specified
  133. spin lock.
  134. Arguments:
  135. SpinLock - Supplies a pointer to a spin lock.
  136. Return Value:
  137. The previous IRQL is returned.
  138. --*/
  139. {
  140. KIRQL OldIrql;
  141. //
  142. // Raise IRQL to DISPATCH_LEVEL and acquire the specified spin lock.
  143. //
  144. OldIrql = KfRaiseIrql(DISPATCH_LEVEL);
  145. KxAcquireSpinLock(SpinLock);
  146. return OldIrql;
  147. }
  148. KIRQL
  149. KeAcquireSpinLockRaiseToSynch (
  150. IN PKSPIN_LOCK SpinLock
  151. )
  152. /*++
  153. Routine Description:
  154. This function raises IRQL to SYNCH_LEVEL and acquires the specified
  155. spin lock.
  156. Arguments:
  157. SpinLock - Supplies a pointer to a spin lock.
  158. Return Value:
  159. The previous IRQL is returned as the function value.
  160. --*/
  161. {
  162. KIRQL OldIrql;
  163. //
  164. // Raise IRQL to SYNCH_LEVEL and acquire the specified spin lock.
  165. //
  166. OldIrql = KfRaiseIrql(SYNCH_LEVEL);
  167. KxAcquireSpinLock(SpinLock);
  168. return OldIrql;
  169. }
  170. VOID
  171. KeAcquireSpinLockAtDpcLevel (
  172. IN PKSPIN_LOCK SpinLock
  173. )
  174. /*++
  175. Routine Description:
  176. This function acquires a spin lock at the current IRQL.
  177. Arguments:
  178. SpinLock - Supplies a pointer to an spin lock.
  179. Return Value:
  180. None.
  181. --*/
  182. {
  183. //
  184. // Acquired the specified spin lock at the current IRQL.
  185. //
  186. KxAcquireSpinLock(SpinLock);
  187. return;
  188. }
  189. BOOLEAN
  190. KeTryToAcquireSpinLock (
  191. IN PKSPIN_LOCK SpinLock,
  192. OUT PKIRQL OldIrql
  193. )
  194. /*++
  195. Routine Description:
  196. This function raises IRQL to DISPATCH level and attempts to acquire a
  197. spin lock. If the spin lock is already owned, then IRQL is restored to
  198. its previous value and FALSE is returned. Otherwise, the spin lock is
  199. acquired and TRUE is returned.
  200. Arguments:
  201. SpinLock - Supplies a pointer to a spin lock.
  202. OldIrql - Supplies a pointer to a variable that receives the old IRQL.
  203. Return Value:
  204. If the spin lock is acquired a value TRUE is returned. Otherwise, FALSE
  205. is returned.
  206. --*/
  207. {
  208. //
  209. // Raise IRQL to DISPATCH level and attempt to acquire the specified
  210. // spin lock.
  211. //
  212. *OldIrql = KfRaiseIrql(DISPATCH_LEVEL);
  213. if (KxTryToAcquireSpinLock(SpinLock) == FALSE) {
  214. KeLowerIrql(*OldIrql);
  215. return FALSE;
  216. }
  217. return TRUE;
  218. }
  219. BOOLEAN
  220. KeTryToAcquireSpinLockAtDpcLevel (
  221. IN PKSPIN_LOCK SpinLock
  222. )
  223. /*++
  224. Routine Description:
  225. This function attempts acquires a spin lock at the current IRQL. If
  226. the spinlock is already owned, then FALSE is returned. Otherwise,
  227. TRUE is returned.
  228. Arguments:
  229. SpinLock - Supplies a pointer to a spin lock.
  230. Return Value:
  231. If the spin lock is acquired a value TRUE is returned. Otherwise, FALSE
  232. is returned as the function value.
  233. --*/
  234. {
  235. //
  236. // Try to acquire the specified spin lock at the current IRQL.
  237. //
  238. return KxTryToAcquireSpinLock(SpinLock);
  239. }
  240. VOID
  241. KeReleaseSpinLock (
  242. IN PKSPIN_LOCK SpinLock,
  243. IN KIRQL OldIrql
  244. )
  245. /*++
  246. Routine Description:
  247. This function releases the specified spin lock and lowers IRQL to a
  248. previous value.
  249. Arguments:
  250. SpinLock - Supplies a pointer to a spin lock.
  251. OldIrql - Supplies the previous IRQL value.
  252. Return Value:
  253. None.
  254. --*/
  255. {
  256. //
  257. // Release the specified spin lock and lower IRQL.
  258. //
  259. KxReleaseSpinLock(SpinLock);
  260. KeLowerIrql(OldIrql);
  261. return;
  262. }
  263. VOID
  264. KeReleaseSpinLockFromDpcLevel (
  265. IN PKSPIN_LOCK SpinLock
  266. )
  267. /*++
  268. Routine Description:
  269. This function releases a spin lock at the current IRQL.
  270. Arguments:
  271. SpinLock - Supplies a pointer to a spin lock.
  272. Return Value:
  273. None.
  274. --*/
  275. {
  276. //
  277. // Release the specified spin lock.
  278. //
  279. KxReleaseSpinLock(SpinLock);
  280. return;
  281. }
  282. #if defined(KeTestSpinLock)
  283. #undef KeTestSpinLock
  284. #endif
  285. BOOLEAN
  286. KeTestSpinLock (
  287. IN PKSPIN_LOCK SpinLock
  288. )
  289. /*++
  290. Routine Description:
  291. This function tests a spin lock to determine if it is currently owned.
  292. If the spinlock is already owned, then FALSE is returned. Otherwise,
  293. TRUE is returned.
  294. Arguments:
  295. SpinLock - Supplies a pointer to a spin lock.
  296. Return Value:
  297. If the spin lock is currently owned, then a value of FALSE is returned.
  298. Otherwise, a value of TRUE is returned.
  299. --*/
  300. {
  301. #if !defined(NT_UP)
  302. return (*(volatile ULONGLONG *)SpinLock == 0);
  303. #else
  304. return TRUE;
  305. #endif // !defined(NT_UP)
  306. }