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.

524 lines
14 KiB

  1. // TITLE("Alpha Fast Mutex Support")
  2. //++
  3. //
  4. // Copyright (c) 1994 Microsoft Corporation
  5. //
  6. // Module Name:
  7. //
  8. // fmutex.s
  9. //
  10. // Abstract:
  11. //
  12. // This module implements the code necessary to acquire and release fast
  13. // mutxes.
  14. //
  15. //
  16. // Author:
  17. //
  18. // John Vert (jvert) 14-Apr-1994
  19. //
  20. // Environment:
  21. //
  22. // Kernel mode only.
  23. //
  24. // Revision History:
  25. //
  26. //--
  27. #include "ksalpha.h"
  28. SBTTL("Acquire Fast Mutex")
  29. //++
  30. //
  31. // VOID
  32. // ExAcquireFastMutex (
  33. // IN PFAST_MUTEX FastMutex
  34. // )
  35. //
  36. // Routine Description:
  37. //
  38. // This function acquires ownership of a fast mutex and raises IRQL to
  39. // APC Level.
  40. //
  41. // Arguments:
  42. //
  43. // FastMutex (a0) - Supplies a pointer to a fast mutex.
  44. //
  45. // Return Value:
  46. //
  47. // None.
  48. //
  49. //--
  50. .struct 0
  51. FmA0: .space 8 // saved fast mutex address
  52. FmIrql: .space 4 // old IRQL value
  53. .space 4 // fill
  54. FmRa: .space 8 // saved return address
  55. .space 8 // fill
  56. FastMutexFrameLength: // frame length
  57. NESTED_ENTRY(ExAcquireFastMutex, FastMutexFrameLength, zero)
  58. lda sp, -FastMutexFrameLength(sp) // allocate stack frame
  59. stq ra, FmRa(sp) // save return address
  60. PROLOGUE_END
  61. //
  62. // Raise IRQL to APC_LEVEL
  63. //
  64. bis a0, zero, t0 // save address of fast mutex
  65. bis zero, APC_LEVEL, a0 // set new IRQL level
  66. SWAP_IRQL // raise IRQL
  67. //
  68. // Decrement ownership count.
  69. //
  70. 10: ldl_l t4, FmCount(t0) // get ownership count
  71. subl t4, 1, t5 // decrement ownership count
  72. stl_c t5, FmCount(t0) // conditionally store ownership count
  73. beq t5, 15f // if eq, conditional store failed
  74. ble t4, 20f // if le, mutex is already owned
  75. #if !defined(NT_UP)
  76. mb // synchronize memory access
  77. #endif
  78. stl v0, FmOldIrql(t0) // save previous IRQL
  79. GET_CURRENT_THREAD // get current thread address
  80. STP v0, FmOwner(t0) // set owner thread address
  81. lda sp, FastMutexFrameLength(sp) // deallocate stack frame
  82. ret zero, (ra) // return
  83. //
  84. // Store conditional attempt failed.
  85. //
  86. 15: br zero, 10b // retry
  87. //
  88. // Fast mutex is currently owned by another thread. Increment the contention
  89. // count and wait for ownership.
  90. //
  91. 20: stl v0, FmIrql(sp) // save previous IRQL
  92. STP t0, FmA0(sp) // save address of fast mutex
  93. ldl t1, FmContention(t0) // increment contention count
  94. addl t1, 1, t2 //
  95. stl t2, FmContention(t0) //
  96. bis zero, zero, a4 // set NULL timeout pointer
  97. bis zero, FALSE, a3 // set nonalertable wait
  98. bis zero, KernelMode, a2 // set mode of wait
  99. bis zero, Executive, a1 // set reason for wait
  100. ADDP t0, FmEvent, a0 // compute address of event
  101. bsr ra, KeWaitForSingleObject // wait for ownership
  102. LDP t0, FmA0(sp) // get address of fast mutex
  103. ldl a1, FmIrql(sp) // get old IRQL value
  104. stl a1, FmOldIrql(t0) // save old IRQL value in fast mutex
  105. GET_CURRENT_THREAD // get current thread address
  106. STP v0, FmOwner(t0) // set owner thread address
  107. ldq ra, FmRa(sp) // restore return address
  108. lda sp, FastMutexFrameLength(sp) // deallocate stack frame
  109. ret zero, (ra) // return
  110. .end ExAcquireFastMutex
  111. SBTTL("Release Fast Mutex")
  112. //++
  113. //
  114. // VOID
  115. // ExReleaseFastMutex (
  116. // IN PFAST_MUTEX FastMutex
  117. // )
  118. //
  119. // Routine Description:
  120. //
  121. // This function releases ownership to a fast mutex and lowers IRQL to
  122. // its previous level.
  123. //
  124. // Arguments:
  125. //
  126. // FastMutex (a0) - Supplies a pointer to a fast mutex.
  127. //
  128. // Return Value:
  129. //
  130. // None.
  131. //
  132. //--
  133. NESTED_ENTRY(ExReleaseFastMutex, FastMutexFrameLength, zero)
  134. lda sp, -FastMutexFrameLength(sp) // allocate stack frame
  135. stq ra, FmRa(sp) // save return address
  136. PROLOGUE_END
  137. ldl a1, FmOldIrql(a0) // get old IRQL value
  138. STP zero, FmOwner(a0) // clear owner thread address
  139. //
  140. // Synchronize all previous writes before the mutex is released.
  141. //
  142. #if !defined(NT_UP)
  143. mb // synchronize memory access
  144. #endif
  145. //
  146. // Increment ownership count and release waiter if contention.
  147. //
  148. 10: ldl_l t0, FmCount(a0) // get ownership count
  149. addl t0, 1, t1 // increment ownership count
  150. stl_c t1, FmCount(a0) // conditionally store ownership count
  151. beq t1, 15f // if eq, store conditional failed
  152. bne t0, 30f // if ne, a waiter is present
  153. //
  154. // Lower IRQL to its previous value.
  155. //
  156. bis a1, zero, a0 // set IRQL level
  157. 20: SWAP_IRQL // lower IRQL
  158. lda sp, FastMutexFrameLength(sp) // deallocate stack frame
  159. ret zero, (ra) // return
  160. //
  161. // There is contention for the fast mutex. Wake up a waiting thread and
  162. // boost its priority to the priority of the current thread.
  163. //
  164. 30: stl a1, FmIrql(sp) // save old IRQL value
  165. ADDP a0, FmEvent, a0 // compute address of event
  166. bis zero, zero, a1 // set optional parameter
  167. bsr ra, KeSetEventBoostPriority // set event and boost priority
  168. ldl a0, FmIrql(sp) // restore old IRQL value
  169. ldq ra, FmRa(sp) // restore return address
  170. br zero, 20b // lower IRQL and return
  171. //
  172. // Conditional store attempt failed.
  173. //
  174. 15: br zero, 10b // retry
  175. .end ExReleaseFastMutex
  176. SBTTL("Try To Acquire Fast Mutex")
  177. //++
  178. //
  179. // BOOLEAN
  180. // ExTryToAcquireFastMutex (
  181. // IN PFAST_MUTEX FastMutex
  182. // )
  183. //
  184. // Routine Description:
  185. //
  186. // This function attempts to acquire ownership of a fast mutex, and if
  187. // successful, raises IRQL to APC level.
  188. //
  189. // Arguments:
  190. //
  191. // FastMutex (a0) - Supplies a pointer to a fast mutex.
  192. //
  193. // Return Value:
  194. //
  195. // If the fast mutex was successfully acquired, then a value of TRUE
  196. // is returned as the function value. Otherwise, a valye of FALSE is
  197. // returned.
  198. //
  199. //--
  200. LEAF_ENTRY(ExTryToAcquireFastMutex)
  201. //
  202. // Raise IRQL to APC_LEVEL.
  203. //
  204. bis a0, zero, t0 // save fast mutex address
  205. bis zero, APC_LEVEL, a0 // set new IRQL level
  206. SWAP_IRQL // raise IRQL
  207. bis v0, zero, a0 // save previous IRQL
  208. //
  209. // Decrement ownership count if and only if fast mutex is not currently
  210. // owned.
  211. //
  212. 10: ldl_l t4, FmCount(t0) // get ownership count
  213. subl t4, 1, v0 // decrement ownership count
  214. ble t4, 20f // if le, mutex is already owned
  215. stl_c v0, FmCount(t0) // conditionally store ownership count
  216. beq v0, 15f // if ne, conditional store failed
  217. #if !defined(NT_UP)
  218. mb // synchronize memory access
  219. #endif
  220. stl a0, FmOldIrql(t0) // set previous IRQL
  221. GET_CURRENT_THREAD // get current thread address
  222. STP v0, FmOwner(t0) // set owner thread address
  223. bis zero, TRUE, v0 // set return value
  224. ret zero, (ra) // return
  225. //
  226. // Conditional store attempt failed.
  227. //
  228. 15: br zero, 10b // retry
  229. //
  230. // Fast mutex is currently owned by another thread. Restore IRQL to its
  231. // previous valye and return false.
  232. //
  233. 20: SWAP_IRQL // lower IRQL
  234. bis zero, zero, v0 // set return value
  235. ret zero, (ra) // return
  236. .end ExTrytoAcquireFastMutex
  237. SBTTL("Acquire Fast Mutex Unsafe")
  238. //++
  239. //
  240. // VOID
  241. // ExAcquireFastMutexUnsafe (
  242. // IN PFAST_MUTEX FastMutex
  243. // )
  244. //
  245. // Routine Description:
  246. //
  247. // This function acquires ownership of a fast mutex, but does not raise
  248. // IRQL to APC Level.
  249. //
  250. // Arguments:
  251. //
  252. // FastMutex (a0) - Supplies a pointer to a fast mutex.
  253. //
  254. // Return Value:
  255. //
  256. // None.
  257. //
  258. //--
  259. NESTED_ENTRY(ExAcquireFastMutexUnsafe, FastMutexFrameLength, zero)
  260. lda sp, -FastMutexFrameLength(sp) // allocate stack frame
  261. stq ra, FmRa(sp) // save return address
  262. PROLOGUE_END
  263. //
  264. // Decrement ownership count.
  265. //
  266. bis a0, zero, t0 // save fast mutex address
  267. 10: ldl_l t4, FmCount(t0) // get ownership count
  268. subl t4, 1, t5 // decrement ownership count
  269. stl_c t5, FmCount(t0) // conditionally store ownership count
  270. beq t5, 15f // if eq, conditional store failed
  271. ble t4, 20f // if le zero, mutex is already owned
  272. #if !defined(NT_UP)
  273. mb // synchronize memory access
  274. #endif
  275. GET_CURRENT_THREAD // get current thread address
  276. STP v0, FmOwner(t0) // store owning thread
  277. lda sp, FastMutexFrameLength(sp) // deallocate stack frame
  278. ret zero, (ra) // return
  279. //
  280. // Conditional store attempt failed.
  281. //
  282. 15: br zero, 10b // retry
  283. //
  284. // Fast mutex is currently owned by another thread. Increment the contention
  285. // count and wait for ownership.
  286. //
  287. 20: STP t0, FmA0(sp) // save address of fast mutex
  288. ldl t1, FmContention(t0) // increment contention count
  289. addl t1, 1, t2 //
  290. stl t2, FmContention(t0) //
  291. bis zero, zero, a4 // set NULL timeout pointer
  292. bis zero, FALSE, a3 // set nonalertable wait
  293. bis zero, KernelMode, a2 // set mode of wait
  294. bis zero, Executive, a1 // set reason for wait
  295. ADDP t0, FmEvent, a0 // compute address of event
  296. bsr ra, KeWaitForSingleObject // wait for ownership
  297. LDP t0, FmA0(sp) // get address of fast mutex
  298. GET_CURRENT_THREAD // get current thread address
  299. STP v0, FmOwner(t0) // set owner thread address
  300. ldq ra, FmRa(sp) // restore return address
  301. lda sp, FastMutexFrameLength(sp) // deallocate stack frame
  302. ret zero, (ra) //
  303. .end ExAcquireFastMutexUnsafe
  304. SBTTL("Release Fast Mutex Unsafe")
  305. //++
  306. //
  307. // VOID
  308. // ExReleaseFastMutexUnsafe (
  309. // IN PFAST_MUTEX FastMutex
  310. // )
  311. //
  312. // Routine Description:
  313. //
  314. // This function releases ownership to a fast mutex, and does not
  315. // restore IRQL to its previous level.
  316. //
  317. // Arguments:
  318. //
  319. // FastMutex (a0) - Supplies a pointer to a fast mutex.
  320. //
  321. // Return Value:
  322. //
  323. // None.
  324. //
  325. //--
  326. NESTED_ENTRY(ExReleaseFastMutexUnsafe, FastMutexFrameLength, zero)
  327. lda sp, -FastMutexFrameLength(sp) // allocate stack frame
  328. stq ra, FmRa(sp) // save return address
  329. PROLOGUE_END
  330. //
  331. // Synchronize all previous writes before the mutex is released.
  332. //
  333. #if !defined(NT_UP)
  334. mb // synchronize memory access
  335. #endif
  336. //
  337. // Increment ownership count and release waiter if contention.
  338. //
  339. STP zero, FmOwner(a0) // clear owner thread address
  340. 10: ldl_l t0, FmCount(a0) // get ownership count
  341. addl t0, 1, t1 // increment ownership count
  342. stl_c t1, FmCount(a0) // conditionally store ownership count
  343. beq t1, 15f // if eq, store conditional failed
  344. beq t0, 20f // if ne, a waiter is present
  345. //
  346. // There is contention for the fast mutex. Wake up a waiting thread and
  347. // boost its priority to the priority of the current thread.
  348. //
  349. ADDP a0, FmEvent, a0 // compute address of event
  350. bis zero, zero, a1 // set optional parameter
  351. bsr ra, KeSetEventBoostPriority // set event and boost priority
  352. ldq ra, FmRa(sp) // restore return address
  353. 20: lda sp, FastMutexFrameLength(sp) // deallocate stack frame
  354. ret zero, (ra) // return
  355. //
  356. // Conditional store attempt failed.
  357. 15: br zero, 10b // retry
  358. .end ExReleaseFastMutexUnsafe
  359. SBTTL("Try To Acquire Fast Mutex Unsafe")
  360. //++
  361. //
  362. // BOOLEAN
  363. // ExTryToAcquireFastMutexUnsafe (
  364. // IN PFAST_MUTEX FastMutex
  365. // )
  366. //
  367. // Routine Description:
  368. //
  369. // This function attempts to acquire ownership of a fast mutex, and if
  370. // successful, does not raise IRQL to APC level.
  371. //
  372. // Arguments:
  373. //
  374. // FastMutex (a0) - Supplies a pointer to a fast mutex.
  375. //
  376. // Return Value:
  377. //
  378. // If the fast mutex was successfully acquired, then a value of TRUE
  379. // is returned as the function value. Otherwise, a valye of FALSE is
  380. // returned.
  381. //
  382. //--
  383. #if 0
  384. LEAF_ENTRY(ExTryToAcquireFastMutexUnsafe)
  385. //
  386. // Decrement ownership count if and only if fast mutex is not currently
  387. // owned.
  388. //
  389. bis a0, zero, t0 // save fast mutex address
  390. 10: ldl_l t4, FmCount(t0) // get ownership count
  391. subl t4, 1, v0 // decrement ownership count
  392. ble t4, 20f // if le zero, mutex is already owned
  393. stl_c v0, FmCount(t0) // conditionally store ownership count
  394. beq v0, 15f // if eq, conditional store failed
  395. #if !defined(NT_UP)
  396. mb // synchronize memory access
  397. #endif
  398. GET_CURRENT_THREAD // get current thread address
  399. STP v0, FmOwner(t0) // set owner thread address
  400. ret zero, (ra) // return
  401. //
  402. // Conditional store attempt failed.
  403. 15: br zero, 10b // retry
  404. //
  405. // Fast mutex is currently owned by another thread. Restore IRQL to its
  406. // previous value and return false.
  407. //
  408. 20: bis zero, zero, v0 // set return value
  409. ret zero, (ra) // return
  410. .end ExTrytoAcquireFastMutexUnsafe
  411. #endif