Windows NT 4.0 source code leak
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.

261 lines
6.8 KiB

4 years ago
  1. // TITLE("Interlocked Increment and Decrement Support")
  2. //++
  3. //
  4. // Copyright (c) 1993 IBM Corporation
  5. //
  6. // Module Name:
  7. //
  8. // critsect.c
  9. //
  10. // Abstract:
  11. //
  12. // This module implements Win32 functions to support user mode
  13. // critical sections
  14. //
  15. // Author:
  16. //
  17. // Curtis R. Fawcett 22-Sept-1993
  18. //
  19. // Environment:
  20. //
  21. // Any mode.
  22. //
  23. // Revision History:
  24. //
  25. // Curtis R. Fawcett 19-Jan-1994 Removed register names
  26. // as requested
  27. // Curtis R. Fawcett 04-Nov-1994 Cleaned up enter/leave
  28. // critical section functs
  29. //--
  30. #include <ksppc.h>
  31. //
  32. // Define local values
  33. //
  34. .struct 0
  35. .space StackFrameHeaderLength
  36. EcAddr: .space 4 // Saved critical section address
  37. EcClient: .space 4 // Saved ClientId
  38. EcLR: .space 4 // Saved Return address
  39. .align 3 // Ensure 8 byte alignment
  40. EcFrameLength: // Frame length
  41. //
  42. // Define external routines
  43. //
  44. .extern ..RtlpWaitForCriticalSection
  45. .extern ..RtlpNotOwnerCriticalSection
  46. .extern ..RtlpUnWaitCriticalSection
  47. //
  48. SBTTL("Interlocked Decrement")
  49. //++
  50. //
  51. // LONG
  52. // InterlockedDecrement(
  53. // IN PLONG Addend
  54. // )
  55. //
  56. // Routine Description:
  57. //
  58. // This function performs an interlocked increment on the addend
  59. // variable.
  60. //
  61. // This function and its companion are assuming that the count will
  62. // never be incremented past 2**31 - 1.
  63. //
  64. // Arguments:
  65. //
  66. // Addend (r.3) - Supplies a pointer to a variable whose value is to
  67. // be incremented.
  68. //
  69. // Return Value:
  70. //
  71. // A negative value is returned if the updated value is less than
  72. // zero, a zero value is returned if the updated value is zero, and
  73. // a nonzero positive value is returned if the updated value is
  74. // greater than zero.
  75. //
  76. //--
  77. LEAF_ENTRY(InterlockedIncrement)
  78. //
  79. IntlckIncLp:
  80. lwarx r.5,0,r.3 // Get addend Value
  81. addi r.5,r.5,1 // Increment addend value
  82. stwcx. r.5,0,r.3 // Store conditionally
  83. bne- IntlckIncLp // Jump if store failed
  84. //
  85. // Exit the routine
  86. //
  87. mr r.3,r.5 // Set exit status
  88. LEAF_EXIT(InterlockedIncrement)
  89. //
  90. SBTTL("InterlockedDecrement")
  91. //++
  92. //
  93. // LONG
  94. // InterlockedDecrement(
  95. // IN PLONG Addend
  96. // )
  97. //
  98. // Routine Description:
  99. //
  100. // This function performs an interlocked decrement on the addend
  101. // variable.
  102. //
  103. // This function and its companion are assuming that the count will
  104. // never be decremented past 2**31 - 1.
  105. //
  106. // Arguments:
  107. //
  108. // Addend (r.3) - Supplies a pointer to a variable whose value is to
  109. // be decremented.
  110. //
  111. // Return Value:
  112. //
  113. // A negative value is returned if the updated value is less than
  114. // zero, a zero value is returned if the updated value is zero, and
  115. // a nonzero positive value is returned if the updated value is
  116. // greater than zero.
  117. //
  118. //--
  119. LEAF_ENTRY(InterlockedDecrement)
  120. IntlckDecLp:
  121. lwarx r.5,0,r.3 // Get addend Value
  122. subi r.5,r.5,1 // Decrement addend value
  123. stwcx. r.5,0,r.3 // Store conditionally
  124. bne- IntlckDecLp // Jump if store failed
  125. //
  126. // Exit the routine
  127. //
  128. mr r.3,r.5 // Set exit status
  129. LEAF_EXIT(InterlockedDecrement)
  130. SBTTL("Interlocked Exchange Long")
  131. //++
  132. //
  133. // LONG
  134. // InterlockedExchangeUlong (
  135. // IN OUT LPLONG Target,
  136. // IN LONG Value
  137. // )
  138. //
  139. // Routine Description:
  140. //
  141. // This function performs an interlocked exchange of a longword
  142. // value with a longword in memory and returns the memory value.
  143. //
  144. // Arguments:
  145. //
  146. // Target (r.3) - Supplies a pointer to a variable whose value is
  147. // to be exchanged.
  148. //
  149. // Value (r.4) - Supplies the value to exchange with source value
  150. //
  151. // Return Value:
  152. //
  153. // The target value is returned as the function value.
  154. //
  155. //--
  156. LEAF_ENTRY(InterlockedExchange)
  157. IntlckExLp:
  158. lwarx r.5,0,r.3 // Get current source value
  159. stwcx. r.4,0,r.3 // Set new source value
  160. bne- IntlckExLp // Jump if store failed
  161. //
  162. // Exit the routine
  163. //
  164. mr r.3,r.5 // return old value
  165. LEAF_EXIT(InterlockedExchange)
  166. //
  167. SBTTL("Interlocked Compare Exchange")
  168. //++
  169. //
  170. // PVOID
  171. // InterlockedCompareExchange (
  172. // IN OUT PVOID *Destination,
  173. // IN PVOID Exchange,
  174. // IN PVOID Comperand
  175. // )
  176. //
  177. // Routine Description:
  178. //
  179. // This function performs an interlocked compare of the destination
  180. // value with the comperand value. If the destination value is equal
  181. // to the comperand value, then the exchange value is stored in the
  182. // destination. Otherwise, no opeation is performed.
  183. //
  184. // Arguments:
  185. //
  186. // Destination (r3) - Supplies a pointer to the destination value.
  187. //
  188. // Exchange (r4) - Supplies the exchange.
  189. //
  190. // Comperand (r5) - Supplies the comperand value.
  191. //
  192. // Return Value:
  193. //
  194. // The initial destination value is returned as the function value.
  195. //
  196. //--
  197. LEAF_ENTRY(InterlockedCompareExchange)
  198. ice10:
  199. lwarx r6, 0, r3 // get current addend value
  200. cmpw r6, r5 // compare
  201. bne- ice20 // if ne, operands mismatch
  202. stwcx. r4, 0, r3 // store updated addend value
  203. bne- ice10 // loop if store failed
  204. ice20:
  205. mr r3, r6 // return original value
  206. LEAF_EXIT(InterlockedCompareExchange) // return
  207. // SBTTL("Interlocked Exchange Add")
  208. //++
  209. //
  210. // LONG
  211. // InterlockedExchangeAdd (
  212. // IN PLONG Addend,
  213. // IN LONG 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 (r.3) - Supplies a pointer to a variable whose value is to be
  225. // adjusted by the increment value.
  226. //
  227. // Increment (r.4) - 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. add1failed:
  237. lwarx r.5,0,r.3 // get current addend value
  238. add r.6,r.5,r.4 // increment addend value
  239. stwcx. r.6,0,r.3 // set new addend value
  240. bne- add1failed // if ne, store conditional failed
  241. mr r.3,r.5 // return result
  242. LEAF_EXIT(InterlockedExchangeAdd) // return