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.

382 lines
7.6 KiB

  1. if NT_INST
  2. else
  3. TITLE "Spin Locks"
  4. ;++
  5. ;
  6. ; Copyright (c) 1989 Microsoft Corporation
  7. ;
  8. ; Module Name:
  9. ;
  10. ; spinlock.asm
  11. ;
  12. ; Abstract:
  13. ;
  14. ; This module implements stubbed x86 spinlock functions for
  15. ; any HAL. Some HALs may implement these function directly
  16. ; to minimize the amount of code required to perform a spinlock.
  17. ; (ie, out Raise & Lower irql in the fall through path)
  18. ;
  19. ; Author:
  20. ;
  21. ; Bryan Willman (bryanwi) 13 Dec 89
  22. ;
  23. ; Environment:
  24. ;
  25. ; Kernel mode only.
  26. ;
  27. ; Revision History:
  28. ;
  29. ; Ken Reneris (kenr) 22-Jan-1991
  30. ;--
  31. PAGE
  32. .486p
  33. include callconv.inc ; calling convention macros
  34. include i386\kimacro.inc
  35. include hal386.inc
  36. include mac386.inc
  37. EXTRNP KfRaiseIrql,1,,FASTCALL
  38. EXTRNP KfLowerIrql,1,,FASTCALL
  39. EXTRNP _KeBugCheck,1,IMPORT
  40. EXTRNP _KeSetEventBoostPriority, 2, IMPORT
  41. EXTRNP _KeWaitForSingleObject,5, IMPORT
  42. ifdef NT_UP
  43. LOCK_ADD equ add
  44. LOCK_DEC equ dec
  45. else
  46. LOCK_ADD equ lock add
  47. LOCK_DEC equ lock dec
  48. endif
  49. _TEXT SEGMENT PARA PUBLIC 'CODE'
  50. ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING
  51. PAGE
  52. SUBTTL "Acquire Kernel Spin Lock"
  53. ;++
  54. ;
  55. ; KIRQL
  56. ; FASTCALL
  57. ; KfAcquireSpinLock (
  58. ; IN PKSPIN_LOCK SpinLock
  59. ; )
  60. ;
  61. ; Routine Description:
  62. ;
  63. ; This function raises to DISPATCH_LEVEL and then acquires a the
  64. ; kernel spin lock.
  65. ;
  66. ; Arguments:
  67. ;
  68. ; (ecx) = SpinLock - Supplies a pointer to an kernel spin lock.
  69. ;
  70. ; Return Value:
  71. ;
  72. ; OldIrql - pointer to place old irql
  73. ;
  74. ;--
  75. align 16
  76. cPublicFastCall KfAcquireSpinLock ,1
  77. cPublicFpo 0,0
  78. ;
  79. ; On a MP build we raise to dispatch_level
  80. ; and then acquire the spinlock
  81. ;
  82. push ecx ; Save address of spinlock
  83. mov ecx, DISPATCH_LEVEL
  84. fstCall KfRaiseIrql ; (al) = OldIrql
  85. pop ecx ; (ecx) -> spinlock
  86. ;
  87. ; Attempt to assert the lock
  88. ;
  89. sl10: ACQUIRE_SPINLOCK ecx,<short sl20>
  90. fstRET KfAcquireSpinLock
  91. ;
  92. ; Lock is owned, spin till it looks free, then go get it again.
  93. ;
  94. sl20: SPIN_ON_SPINLOCK ecx,sl10
  95. fstENDP KfAcquireSpinLock
  96. PAGE
  97. SUBTTL "Acquire Synch Kernel Spin Lock"
  98. ;++
  99. ;
  100. ; KIRQL
  101. ; FASTCALL
  102. ; KeAcquireSpinLockRaiseToSynch (
  103. ; IN PKSPIN_LOCK SpinLock
  104. ; )
  105. ;
  106. ; Routine Description:
  107. ;
  108. ; This function acquires the SpinLock at SYNCH_LEVEL. The function
  109. ; is optmized for hoter locks (the lock is tested before acquired,
  110. ; any spin should occur at OldIrql)
  111. ;
  112. ; Arguments:
  113. ;
  114. ; (ecx) = SpinLock - Supplies a pointer to an kernel spin lock.
  115. ;
  116. ; Return Value:
  117. ;
  118. ; OldIrql - pointer to place old irql
  119. ;
  120. ;--
  121. align 16
  122. cPublicFastCall KeAcquireSpinLockRaiseToSynch,1
  123. cPublicFpo 0,0
  124. ;
  125. ; Disable interrupts
  126. ;
  127. sls10: cli
  128. ;
  129. ; Try to obtain spinlock. Use non-lock operation first
  130. ;
  131. TEST_SPINLOCK ecx,<short sls20>
  132. ACQUIRE_SPINLOCK ecx,<short sls20>
  133. ;
  134. ; Got the lock, raise to SYNCH_LEVEL
  135. ;
  136. mov ecx, SYNCH_LEVEL
  137. fstCall KfRaiseIrql ; (al) = OldIrql
  138. ;
  139. ; Enable interrupts and return
  140. ;
  141. sti
  142. fstRET KeAcquireSpinLockRaiseToSynch
  143. ;
  144. ; Lock is owned, spin till it looks free, then go get it again.
  145. ;
  146. sls20: sti
  147. SPIN_ON_SPINLOCK ecx,sls10
  148. fstENDP KeAcquireSpinLockRaiseToSynch
  149. PAGE
  150. SUBTTL "Release Kernel Spin Lock"
  151. ;++
  152. ;
  153. ; VOID
  154. ; FASTCALL
  155. ; KfReleaseSpinLock (
  156. ; IN PKSPIN_LOCK SpinLock,
  157. ; IN KIRQL NewIrql
  158. ; )
  159. ;
  160. ; Routine Description:
  161. ;
  162. ; This function releases a kernel spin lock and lowers to the new irql
  163. ;
  164. ; Arguments:
  165. ;
  166. ; (ecx) = SpinLock - Supplies a pointer to an executive spin lock.
  167. ; (dl) = NewIrql - New irql value to set
  168. ;
  169. ; Return Value:
  170. ;
  171. ; None.
  172. ;
  173. ;--
  174. align 16
  175. cPublicFastCall KfReleaseSpinLock ,2
  176. cPublicFpo 0,0
  177. ifndef NT_UP
  178. RELEASE_SPINLOCK ecx ; release it
  179. endif
  180. mov ecx, edx ; (ecx) = NewIrql
  181. jmp @KfLowerIrql@4 ; to KeLowerIrql
  182. fstENDP KfReleaseSpinLock
  183. ;++
  184. ;
  185. ; VOID
  186. ; FASTCALL
  187. ; ExAcquireFastMutex (
  188. ; IN PFAST_MUTEX FastMutex
  189. ; )
  190. ;
  191. ; Routine description:
  192. ;
  193. ; This function acquire ownership of the FastMutex
  194. ;
  195. ; Arguments:
  196. ;
  197. ; (ecx) = FastMutex - Supplies a pointer to the fast mutex
  198. ;
  199. ; Return Value:
  200. ;
  201. ; None.
  202. ;
  203. ;--
  204. cPublicFastCall ExAcquireFastMutex,1
  205. cPublicFpo 0,1
  206. push ecx ; Push FAST_MUTEX addr
  207. mov ecx, APC_LEVEL
  208. fstCall KfRaiseIrql
  209. pop ecx ; (ecx) = Fast Mutex
  210. cPublicFpo 0,0
  211. LOCK_DEC dword ptr [ecx].FmCount ; Get count
  212. jz short afm_ret ; The owner? Yes, Done
  213. inc dword ptr [ecx].FmContention
  214. cPublicFpo 0,1
  215. push ecx
  216. push eax
  217. add ecx, FmEvent ; Wait on Event
  218. stdCall _KeWaitForSingleObject,<ecx,WrExecutive,0,0,0>
  219. pop eax
  220. pop ecx
  221. cPublicFpo 0,0
  222. afm_ret:
  223. mov byte ptr [ecx].FmOldIrql, al
  224. fstRet ExAcquireFastMutex
  225. fstENDP ExAcquireFastMutex
  226. ;++
  227. ;
  228. ; BOOLEAN
  229. ; FASTCALL
  230. ; ExTryToAcquireFastMutex (
  231. ; IN PFAST_MUTEX FastMutex
  232. ; )
  233. ;
  234. ; Routine description:
  235. ;
  236. ; This function acquire ownership of the FastMutex
  237. ;
  238. ; Arguments:
  239. ;
  240. ; (ecx) = FastMutex - Supplies a pointer to the fast mutex
  241. ;
  242. ; Return Value:
  243. ;
  244. ; Returns TRUE if the FAST_MUTEX was acquired; otherwise false
  245. ;
  246. ;--
  247. cPublicFastCall ExTryToAcquireFastMutex,1
  248. cPublicFpo 0,0
  249. ;
  250. ; Try to acquire
  251. ;
  252. cmp dword ptr [ecx].FmCount, 1 ; Busy?
  253. jne short tam25 ; Yes, abort
  254. cPublicFpo 0,1
  255. push ecx ; Push FAST_MUTEX
  256. mov ecx, APC_LEVEL
  257. fstCall KfRaiseIrql ; (al) = OldIrql
  258. mov ecx, [esp] ; Restore FAST_MUTEX
  259. mov [esp], eax ; Save OldIrql
  260. mov eax, 1 ; Value to compare against
  261. mov edx, 0 ; Value to set
  262. lock cmpxchg dword ptr [ecx].FmCount, edx ; Attempt to acquire
  263. jnz short tam20 ; got it?
  264. cPublicFpo 0,0
  265. pop edx ; (edx) = OldIrql
  266. mov eax, 1 ; return TRUE
  267. mov byte ptr [ecx].FmOldIrql, dl ; Store OldIrql
  268. fstRet ExTryToAcquireFastMutex
  269. tam20: pop ecx ; (ecx) = OldIrql
  270. fstCall KfLowerIrql ; restore OldIrql
  271. tam25: xor eax, eax ; return FALSE
  272. fstRet ExTryToAcquireFastMutex ; all done
  273. fstENDP ExTryToAcquireFastMutex
  274. ;++
  275. ;
  276. ; VOID
  277. ; FASTCALL
  278. ; ExReleaseFastMutex (
  279. ; IN PFAST_MUTEX FastMutex
  280. ; )
  281. ;
  282. ; Routine description:
  283. ;
  284. ; This function releases ownership of the FastMutex
  285. ;
  286. ; Arguments:
  287. ;
  288. ; (ecx) FastMutex - Supplies a pointer to the fast mutex
  289. ;
  290. ; Return Value:
  291. ;
  292. ; None.
  293. ;
  294. ;--
  295. cPublicFastCall ExReleaseFastMutex,1
  296. cPublicFpo 0,0
  297. mov al, byte ptr [ecx].FmOldIrql ; (cl) = OldIrql
  298. LOCK_ADD dword ptr [ecx].FmCount, 1 ; Remove our count
  299. xchg ecx, eax ; (cl) = OldIrql
  300. js short rfm05 ; if < 0, set event
  301. jnz @KfLowerIrql@4 ; if != 0, don't set event
  302. rfm05: add eax, FmEvent
  303. push ecx
  304. stdCall _KeSetEventBoostPriority, <eax, 0>
  305. pop ecx
  306. jmp @KfLowerIrql@4
  307. fstENDP ExReleaseFastMutex
  308. _TEXT ends
  309. ENDIF ; NT_INST
  310. end