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.

401 lines
9.9 KiB

  1. // TITLE("Fast Mutex Support")
  2. //++
  3. //
  4. // Module Name:
  5. //
  6. // fmutex.s
  7. //
  8. // Abstract:
  9. //
  10. // This module implements the code necessary to acquire and release fast
  11. // mutxes.
  12. //
  13. //
  14. // Author:
  15. //
  16. // William K. Cheung (wcheung) 02-Oct-1995
  17. //
  18. // Environment:
  19. //
  20. // Kernel mode only.
  21. //
  22. // Revision History:
  23. //
  24. // 08-Feb-96 Updated to EAS2.1
  25. //
  26. //--
  27. #include "ksia64.h"
  28. .file "fmutex.s"
  29. PublicFunction(KeWaitForSingleObject)
  30. PublicFunction(KeSetEventBoostPriority)
  31. PublicFunction(KiCheckForSoftwareInterrupt)
  32. //++
  33. //
  34. // VOID
  35. // ExAcquireFastMutex (
  36. // IN PFAST_MUTEX FastMutex
  37. // )
  38. //
  39. // Routine Description:
  40. //
  41. // This function acquires ownership of a fast mutex and raises IRQL to
  42. // APC Level. Must be called at IRQL < DISPATCH_LEVEL.
  43. //
  44. // Arguments:
  45. //
  46. // FastMutex (a0) - Supplies a pointer to a fast mutex.
  47. //
  48. // Return Value:
  49. //
  50. // None.
  51. //
  52. //--
  53. //
  54. // t0 -- Original value of Fmutex.FmCount
  55. // t1 -- Address of Fmutex.FmCount
  56. // t2 -- Address of Fmutex.FmOldIrql
  57. // t3 -- Address of KiPcr
  58. // t4 -- Address of Fmutex.FmContention
  59. // t8 -- Address of KiPcr.PcCurrentThread
  60. // r35 -- old IRQL
  61. //
  62. // t5 -- temp
  63. //
  64. NESTED_ENTRY(ExAcquireFastMutex)
  65. .regstk 1, 4, 5, 0
  66. .prologue 0xC, savedpfs
  67. alloc savedpfs = ar.pfs, 1, 4, 5, 0
  68. add loc3 = FmOwner, a0
  69. mov savedbrp = brp
  70. GET_IRQL (loc2) // Get old IRQL
  71. PROLOGUE_END
  72. mov t4 = APC_LEVEL
  73. add t1 = FmCount, a0
  74. add t2 = FmOldIrql, a0
  75. ;;
  76. SET_IRQL (t4) // change IRQL to APC_LEVEL
  77. ;;
  78. //
  79. // synchronize subsequent reads
  80. //
  81. fetchadd4.acq t0 = [t1], -1 // decrement mutex count
  82. add t4 = FmContention, a0
  83. add out0 = FmEvent, a0
  84. mov out1 = Executive // set reason for wait
  85. mov out2 = KernelMode // set mode of wait
  86. ;;
  87. cmp4.le pt7, pt8 = t0, zero // if le, mutex acq failed
  88. mov out3 = FALSE // set nonalertable wait
  89. mov out4 = zero // set NULL timeout pointer
  90. ;;
  91. (pt7) ld4 t5 = [t4] // load contention count
  92. (pt8) st8 [loc3] = sp // Save the SP so we can identify the owner.
  93. (pt8) st4 [t2] = loc2 // save old IRQL
  94. (pt8) br.ret.sptk.clr brp // return
  95. ;;
  96. Eafm10:
  97. (pt7) add t5 = 1, t5 // inc contention count
  98. ;;
  99. st4 [t4] = t5 // save contention count
  100. br.call.sptk.many brp = KeWaitForSingleObject
  101. add t2 = FmOldIrql, a0
  102. mov ar.pfs = savedpfs // restore pfs
  103. mov brp = savedbrp // restore brp
  104. ;;
  105. st4 [t2] = loc2 // save old IRQL
  106. st8 [loc3] = sp // Save the SP so we can identify the owner.
  107. br.ret.sptk.clr brp // return
  108. NESTED_EXIT(ExAcquireFastMutex)
  109. //++
  110. //
  111. // VOID
  112. // ExReleaseFastMutex (
  113. // IN PFAST_MUTEX FastMutex
  114. // )
  115. //
  116. // Routine Description:
  117. //
  118. // This function releases ownership to a fast mutex and lowers IRQL to
  119. // its previous level.
  120. //
  121. // Arguments:
  122. //
  123. // FastMutex (a0) - Supplies a pointer to a fast mutex.
  124. //
  125. // Return Value:
  126. //
  127. // None.
  128. //
  129. //--
  130. NESTED_ENTRY(ExReleaseFastMutex)
  131. NESTED_SETUP(1, 3, 2, 0)
  132. add t1 = FmCount, a0
  133. PROLOGUE_END
  134. //
  135. // Increment mutex count and release waiter if contention.
  136. //
  137. //
  138. // use release semantics to synchronize all previous writes
  139. //
  140. add t2 = FmOldIrql, a0
  141. ;;
  142. ld4 loc2 = [t2] // get old IRQL before releasing lock
  143. fetchadd4.rel t9 = [t1], 1 // increment mutex count
  144. add out0 = FmEvent, a0
  145. ;;
  146. cmp4.eq pt1, pt0 = zero, t9 // if eq, no waiter
  147. mov out1 = zero
  148. (pt0) br.call.spnt.many brp = KeSetEventBoostPriority
  149. ;;
  150. LOWER_IRQL (loc2)
  151. NESTED_RETURN
  152. NESTED_EXIT(ExReleaseFastMutex)
  153. //++
  154. //
  155. // BOOLEAN
  156. // ExTryToAcquireFastMutex (
  157. // IN PFAST_MUTEX FastMutex
  158. // )
  159. //
  160. // Routine Description:
  161. //
  162. // This function attempts to acquire ownership of a fast mutex, and if
  163. // successful, raises IRQL to APC level.
  164. //
  165. // Arguments:
  166. //
  167. // FastMutex (a0) - Supplies a pointer to a fast mutex.
  168. //
  169. // Return Value:
  170. //
  171. // If the fast mutex was successfully acquired, then a value of TRUE
  172. // is returned as the function value. Otherwise, a valye of FALSE is
  173. // returned.
  174. //
  175. //--
  176. LEAF_ENTRY(ExTryToAcquireFastMutex)
  177. mov t4 = APC_LEVEL
  178. add t1 = FmCount, a0
  179. add t2 = FmOldIrql, a0
  180. add t6 = FmOwner, a0
  181. GET_IRQL (t0) // get old IRQL
  182. SET_IRQL (t4) // change IRQL to APC_LEVEL
  183. ;;
  184. ld4 t4 = [t1]
  185. ;;
  186. mov ar.ccv = t4
  187. cmp4.le pt8, pt7 = t4, zero // if le, mutex acq failed
  188. add t5 = -1, t4
  189. mov v0 = TRUE // return TRUE by default
  190. (pt8) br.spnt.few Ettafm10
  191. ;;
  192. //
  193. // use acquire semantics to sychronize subsequent reads
  194. //
  195. cmpxchg4.acq t4 = [t1], t5, ar.ccv
  196. ;;
  197. cmp4.le pt8, pt7 = t4, zero // if le, mutex acq failed
  198. ;;
  199. Ettafm10:
  200. PSET_IRQL (pt8, t0) // restore IRQL
  201. (pt7) st4 [t2] = t0 // save old IRQL
  202. (pt8) mov v0 = FALSE // return FALSE
  203. (pt7) st8 [t6] = sp // Save the SP so we can identify the owner.
  204. br.ret.sptk.clr brp // return
  205. LEAF_EXIT(ExTryToAcquireFastMutex)
  206. //++
  207. //
  208. // VOID
  209. // ExAcquireFastMutexUnsafe (
  210. // IN PFAST_MUTEX FastMutex
  211. // )
  212. //
  213. // Routine Description:
  214. //
  215. // This function acquires ownership of a fast mutex, but does not raise
  216. // IRQL to APC Level.
  217. //
  218. // Arguments:
  219. //
  220. // FastMutex (a0) - Supplies a pointer to a fast mutex.
  221. //
  222. // Return Value:
  223. //
  224. // None.
  225. //
  226. //--
  227. NESTED_ENTRY(ExAcquireFastMutexUnsafe)
  228. NESTED_SETUP(1, 3, 5, 0)
  229. add t1 = FmCount, a0
  230. ;;
  231. PROLOGUE_END
  232. //
  233. // Use acquire semantics to synchronize subsequent reads
  234. //
  235. fetchadd4.acq t0 = [t1], -1 // decrement mutex count
  236. add out0 = FmEvent, a0
  237. add t3 = FmContention, a0
  238. add loc2 = FmOwner, a0
  239. mov out1 = Executive // set reason for wait
  240. mov out2 = KernelMode // set mode of wait
  241. ;;
  242. cmp4.le p0, pt8 = t0, zero // if le, contention
  243. mov out3 = FALSE // set nonalertable wait
  244. ;;
  245. (pt8) st8 [loc2] = sp // Save the SP so we can identify the owner.
  246. (pt8) br.ret.sptk.clr brp // return
  247. //
  248. // Increment the contention count and then call KeWaitForSingleObject().
  249. // The outgoing arguments have been set up ahead of time.
  250. //
  251. ld4 t4 = [t3] // get contention count
  252. ;;
  253. add t4 = 1, t4 // increment contention count
  254. mov out4 = 0 // set NULL timeout pointer
  255. ;;
  256. st4 [t3] = t4 // save contention count
  257. br.call.sptk.many brp = KeWaitForSingleObject
  258. mov ar.pfs = savedpfs // restore pfs
  259. mov brp = savedbrp // restore return link
  260. st8 [loc2] = sp // Save the sp of the owner
  261. br.ret.sptk.clr brp // return
  262. NESTED_EXIT(ExAcquireFastMutexUnsafe)
  263. //++
  264. //
  265. // VOID
  266. // ExReleaseFastMutexUnsafe (
  267. // IN PFAST_MUTEX FastMutex
  268. // )
  269. //
  270. // Routine Description:
  271. //
  272. // This function releases ownership to a fast mutex, and does not
  273. // restore IRQL to its previous level.
  274. //
  275. // Arguments:
  276. //
  277. // FastMutex (a0) - Supplies a pointer to a fast mutex.
  278. //
  279. // Return Value:
  280. //
  281. // None.
  282. //
  283. //--
  284. NESTED_ENTRY(ExReleaseFastMutexUnsafe)
  285. NESTED_SETUP(1, 2, 2, 0)
  286. add t1 = FmCount, a0
  287. ;;
  288. PROLOGUE_END
  289. //
  290. // Increment mutex count and release waiter if contention.
  291. //
  292. //
  293. // Use release semantics to syncrhonize all previous writes
  294. // before the mutext is released.
  295. //
  296. fetchadd4.rel t9 = [t1], 1 // increment mutex count
  297. ;;
  298. add out0 = FmEvent, a0
  299. cmp4.eq pt7, pt8 = zero, t9 // if eq, no waiter
  300. add out1 = zero, zero
  301. (pt7) br.ret.sptk.clr brp // return
  302. (pt8) br.call.spnt.many brp = KeSetEventBoostPriority
  303. mov ar.pfs = savedpfs
  304. mov brp = savedbrp
  305. br.ret.sptk.clr brp // return
  306. NESTED_EXIT(ExReleaseFastMutexUnsafe)
  307. //++
  308. //
  309. // BOOLEAN
  310. // ExTryToAcquireFastMutexUnsafe (
  311. // IN PFAST_MUTEX FastMutex
  312. // )
  313. //
  314. // Routine Description:
  315. //
  316. // This function attempts to acquire ownership of a fast mutex, and if
  317. // successful, does not raise IRQL to APC level.
  318. //
  319. // Arguments:
  320. //
  321. // FastMutex (a0) - Supplies a pointer to a fast mutex.
  322. //
  323. // Return Value:
  324. //
  325. // If the fast mutex was successfully acquired, then a value of TRUE
  326. // is returned as the function value. Otherwise, a valye of FALSE is
  327. // returned.
  328. //
  329. //--
  330. #if 0
  331. LEAF_ENTRY(ExTryToAcquireFastMutexUnsafe)
  332. LEAF_EXIT(ExTryToAcquireFastMutexUnsafe)
  333. #endif