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.

280 lines
8.4 KiB

  1. // TITLE("Interlocked Increment and Decrement Support")
  2. //++
  3. //
  4. // Copyright (c) 1991 Microsoft Corporation
  5. // Copyright (c) 1992 Digital Equipment Corporation
  6. //
  7. // Module Name:
  8. //
  9. // critsect.s
  10. //
  11. // Abstract:
  12. //
  13. // This module implements functions to support user mode critical sections.
  14. // It contains some code from ntos\dll\alpha\critsect.s but without the Rtl
  15. // prefix.
  16. //
  17. // Author:
  18. //
  19. // David N. Cutler 29-Apr-1992
  20. //
  21. // Environment:
  22. //
  23. // Any mode.
  24. //
  25. // Revision History:
  26. //
  27. // Thomas Van Baak (tvb) 22-Jul-1992
  28. //
  29. // Adapted for Alpha AXP.
  30. //
  31. //--
  32. #include "ksalpha.h"
  33. SBTTL("Interlocked Increment")
  34. //++
  35. //
  36. // LONG
  37. // InterlockedIncrement(
  38. // IN PLONG Addend
  39. // )
  40. //
  41. // Routine Description:
  42. //
  43. // This function performs an interlocked increment on the addend variable.
  44. //
  45. // This function and its companion are assuming that the count will never
  46. // be incremented past 2**31 - 1.
  47. //
  48. // Arguments:
  49. //
  50. // Addend (a0) - Supplies a pointer to a variable whose value is to be
  51. // incremented.
  52. //
  53. // Return Value:
  54. //
  55. // A negative value is returned if the updated value is less than zero,
  56. // a zero value is returned if the updated value is zero, and a nonzero
  57. // positive value is returned if the updated value is greater than zero.
  58. //
  59. //--
  60. LEAF_ENTRY(InterlockedIncrement)
  61. 10: mb // synchronize memory access
  62. ldl_l v0, 0(a0) // get addend value - locked
  63. addl v0, 1, v0 // increment addend value
  64. mov v0, t0 // copy updated value to t0 for store
  65. stl_c t0, 0(a0) // store conditionally
  66. beq t0, 20f // if eq, conditional store failed
  67. mb // synchronize memory access
  68. ret zero, (ra) // return
  69. //
  70. // We expect the store conditional will usually succeed the first time so it
  71. // is faster to branch forward (predicted not taken) to here and then branch
  72. // backward (predicted taken) to where we wanted to go.
  73. //
  74. 20: br zero, 10b // go try load again
  75. .end InterlockedIncrement
  76. SBTTL("InterlockedDecrement")
  77. //++
  78. //
  79. // LONG
  80. // InterlockedDecrement(
  81. // IN PLONG Addend
  82. // )
  83. //
  84. // Routine Description:
  85. //
  86. // This function performs an interlocked decrement on the addend variable.
  87. //
  88. // This function and its companion are assuming that the count will never
  89. // be decremented past 2**31 - 1.
  90. //
  91. // Arguments:
  92. //
  93. // Addend (a0) - Supplies a pointer to a variable whose value is to be
  94. // decremented.
  95. //
  96. // Return Value:
  97. //
  98. // A negative value is returned if the updated value is less than zero,
  99. // a zero value is returned if the updated value is zero, and a nonzero
  100. // positive value is returned if the updated value is greater than zero.
  101. //
  102. //--
  103. LEAF_ENTRY(InterlockedDecrement)
  104. 10: mb // synchronize memory access
  105. ldl_l v0, 0(a0) // get addend value - locked
  106. subl v0, 1, v0 // decrement addend value
  107. mov v0, t0 // copy updated value to t0 for store
  108. stl_c t0, 0(a0) // store conditionally
  109. beq t0, 20f // if eq, conditional store failed
  110. mb // synchronize memory access
  111. ret zero, (ra) // return
  112. //
  113. // We expect the store conditional will usually succeed the first time so it
  114. // is faster to branch forward (predicted not taken) to here and then branch
  115. // backward (predicted taken) to where we wanted to go.
  116. //
  117. 20: br zero, 10b // go try load again
  118. .end InterlockedDecrement
  119. SBTTL("Interlocked Exchange")
  120. //++
  121. //
  122. // ULONG
  123. // InterlockedExchange (
  124. // IN PULONG Source,
  125. // IN ULONG Value
  126. // )
  127. //
  128. // Routine Description:
  129. //
  130. // This function performs an interlocked exchange of a longword value with
  131. // a longword in memory and returns the memory value.
  132. //
  133. // Arguments:
  134. //
  135. // Source (a0) - Supplies a pointer to a variable whose value is to be
  136. // exchanged.
  137. //
  138. // Value (a1) - Supplies the value to exchange with the source value.
  139. //
  140. // Return Value:
  141. //
  142. // The source value is returned as the function value.
  143. //
  144. //--
  145. LEAF_ENTRY(InterlockedExchange)
  146. 10: mb // synchronize memory access
  147. ldl_l v0,0(a0) // get current source value
  148. xor a1,zero,t0 // set exchange value
  149. stl_c t0,0(a0) // replace source value
  150. beq t0,20f // if eq, conditional store failed
  151. mb // synchronize memory access
  152. ret zero,(ra) // else/ return old value to caller
  153. //
  154. // We expect the store conditional will usually succeed the first time so it
  155. // is faster to branch forward (predicted not taken) to here and then branch
  156. // backward (predicted taken) to where we wanted to go.
  157. //
  158. 20: br zero,10b // go try spin lock again
  159. .end InterlockedExchange
  160. SBTTL("Interlocked Compare Exchange")
  161. //++
  162. //
  163. // LONG
  164. // InterlockedCompareExchange (
  165. // IN OUT PLONG *Destination,
  166. // IN LONG Exchange,
  167. // IN LONG Comperand
  168. // )
  169. //
  170. // Routine Description:
  171. //
  172. // This function performs an interlocked compare of the destination
  173. // value with the comperand value. If the destination value is equal
  174. // to the comperand value, then the exchange value is stored in the
  175. // destination. Otherwise, no opeation is performed.
  176. //
  177. // Arguments:
  178. //
  179. // Destination (a0) - Supplies a pointer to the destination value.
  180. //
  181. // Exchange (a1) - Supplies the exchange.
  182. //
  183. // Comperand (a2) - Supplies the comperand value.
  184. //
  185. // Return Value:
  186. //
  187. // The initial destination value is returned as the function value.
  188. //
  189. //--
  190. LEAF_ENTRY(InterlockedCompareExchange)
  191. 10: mb // synchronize memory accesss
  192. ldl_l v0, 0(a0) // get current addend value
  193. bis a1, zero, t0 // copy exchange value for store
  194. cmpeq v0, a2, t1 // check if operands match
  195. beq t1, 20f // if eq, operands mismatch
  196. stl_c t0, 0(a0) // store updated addend value
  197. beq t0,25f // if eq, store conditional failed
  198. mb // synchronize memory access
  199. 20: ret zero, (ra) // return
  200. //
  201. // We expect the store conditional will usually succeed the first time so it
  202. // is faster to branch forward (predicted not taken) to here and then branch
  203. // backward (predicted taken) to where we wanted to go.
  204. //
  205. 25: br zero, 10b // go try spin lock again
  206. .end InterlockedCompareExchange
  207. SBTTL("Interlocked Exchange Add")
  208. //++
  209. //
  210. // LONG
  211. // InterlockedExchangeAdd (
  212. // IN PLONG Addend,
  213. // IN ULONG Increment
  214. // )
  215. //
  216. // Routine Description:
  217. //
  218. // This function performs an interlocked add of an increment value to an
  219. // addend variable of type unsigned long. The initial value of the addend
  220. // variable is returned as the function value.
  221. //
  222. // Arguments:
  223. //
  224. // Addend (a0) - Supplies a pointer to a variable whose value is to be
  225. // adjusted by the increment value.
  226. //
  227. // Increment (a1) - Supplies the increment value to be added to the
  228. // addend variable.
  229. //
  230. // Return Value:
  231. //
  232. // The initial value of the addend variable.
  233. //
  234. //--
  235. LEAF_ENTRY(InterlockedExchangeAdd)
  236. 10: mb // synchronize memory access
  237. ldl_l v0, 0(a0) // get current addend value - locked
  238. addl v0, a1, t0 // increment addend value
  239. stl_c t0, 0(a0) // store updated value - conditionally
  240. beq t0, 20f // if eq, conditional store failed
  241. mb // synchronize memory access
  242. ret zero, (ra) // return
  243. //
  244. // We expect the store conditional will usually succeed the first time so it
  245. // is faster to branch forward (predicted not taken) to here and then branch
  246. // backward (predicted taken) to where we wanted to go.
  247. //
  248. 20: br zero, 10b // go try spin lock again
  249. .end InterlockedExchangeAdd