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
6.8 KiB

  1. //
  2. // Copyright (c) 1995 Microsoft Corporation
  3. //
  4. // Module Name:
  5. //
  6. // atomic.s
  7. //
  8. // Abstract:
  9. //
  10. // This module implements atomic operations such as InterlockedOr,
  11. // InterlockedAnd and the MrswFetch...() functions used for
  12. // Multiple Reader Single Writer (mrsw) synchronization.
  13. //
  14. // Author:
  15. //
  16. // Dave Hastings (daveh) creation-date 05-Jan-1996
  17. // from ..\mips\atomic.s
  18. //
  19. // Notes:
  20. //
  21. // Mrsw Counter is: WriterCount : 16
  22. // ReaderCount : 16
  23. //
  24. // Revision History:
  25. #include "kxalpha.h"
  26. SBTTL("MrswFetchAndIncrementWriter")
  27. //++
  28. //
  29. // MRSWCOUNTERS
  30. // MrswFetchAndIncrementWriter(
  31. // PMRSWCOUNTERS pCounters
  32. // )
  33. //
  34. // Routine Description:
  35. //
  36. // Atomically increment Writer counter and return the new reader/writer
  37. // counts (the values AFTER the increment).
  38. //
  39. // Arguments:
  40. //
  41. // pCounters (a0) - pointer to reader/writer counters
  42. //
  43. // Return Value:
  44. //
  45. // MRSWCOUNTERS - value of both counters AFTER writer count was incremented
  46. //
  47. //--
  48. LEAF_ENTRY(MrswFetchAndIncrementWriter)
  49. PROLOGUE_END
  50. //
  51. // Increment the writer count and load both reader and writer accounts
  52. // atomically.
  53. //
  54. fiw10: ldl_l v0, (a0) // Get both reader and write counts
  55. addl v0, 1, v0 // increment the writer count
  56. bis v0, zero, t0
  57. stl_c t0, (a0)
  58. beq t0, fiw20 // atomic update failed?
  59. mb // insure that updates of the data
  60. // being protected are synch'ed
  61. ret zero, (ra)
  62. fiw20: br zero, fiw10
  63. .end MrswFetchAndIncrementWriter
  64. //++
  65. //
  66. // MRSWCOUNTERS
  67. // MrswFetchAndIncrementReader(
  68. // PMRSWCOUNTERS pCounters
  69. // )
  70. //
  71. // Routine Description:
  72. //
  73. // Atomically: Get WriterCount. If WriterCount zero, increment ReaderCount
  74. // and return the value AFTER the increment. Else, return right away.
  75. //
  76. // Arguments:
  77. //
  78. // pCounters (a0) - pointer to reader/writer counters
  79. //
  80. // Return Value:
  81. //
  82. // MRSWCOUNTERS
  83. //
  84. //--
  85. LEAF_ENTRY(MrswFetchAndIncrementReader)
  86. PROLOGUE_END
  87. //
  88. // Increment the waiting reader count and load both reader and writer accounts
  89. // atomically.
  90. //
  91. fir10: ldah t2, 1(zero) // Load increment value for Reader count
  92. ldl_l v0, (a0) // get both counters
  93. and v0, 0xffff, t1 // isolate writer count
  94. bne t1, fir20 // exit if there is already a writer
  95. addl v0, t2, v0 // increment reader count
  96. bis v0, zero, t0
  97. stl_c t0, (a0)
  98. beq t0, fir30
  99. mb // insure that updates of the data
  100. // being protected are synch'ed
  101. fir20: ret zero, (ra)
  102. fir30: br zero, fir10
  103. .end MrswFetchAndIncrementReader
  104. SBTTL("MrswFetchAndDecrementWriter")
  105. //++
  106. //
  107. // MRSWCOUNTERS
  108. // MrswFetchAndDecrementWriter(
  109. // PMRSWCOUNTERS pCounters
  110. // )
  111. //
  112. // Routine Description:
  113. //
  114. // Atomically decrement Writer counter and return the new reader/writer
  115. // counts (the values AFTER the decrement).
  116. //
  117. // Arguments:
  118. //
  119. // pCounters (a0) - pointer to reader/writer counters
  120. //
  121. // Return Value:
  122. //
  123. // MRSWCOUNTERS - value of both counters AFTER writer count was decremented
  124. //
  125. //--
  126. LEAF_ENTRY(MrswFetchAndDecrementWriter)
  127. PROLOGUE_END
  128. mb // insure that updates of the data
  129. // being protected are synch'ed
  130. //
  131. // Decrement the writer count and load both reader and writer accounts
  132. // atomically.
  133. //
  134. fdw10: ldl_l v0, (a0) // get both counters
  135. subl v0, 1, v0 // decrement writer count
  136. bis v0, zero, t0
  137. stl_c t0, (a0)
  138. beq t0, fdw20
  139. ret zero, (ra)
  140. fdw20: br zero, fdw10
  141. .end MrswFetchAndDecrementWriter
  142. //++
  143. //
  144. // MRSWCOUNTERS
  145. // MrswFetchAndDecrementReader(
  146. // PMRSWCOUNTERS pCounters
  147. // )
  148. //
  149. // Routine Description:
  150. //
  151. // Atomically decrement Active Reader counter and return the new reader/writer
  152. // counts (the values AFTER the decrement).
  153. //
  154. // Arguments:
  155. //
  156. // pCounters (a0) - pointer to reader/writer counters
  157. //
  158. // Return Value:
  159. //
  160. // MRSWCOUNTERS - value of both counters AFTER writer count was decremented
  161. //
  162. //
  163. // Notes:
  164. //
  165. // No MB is used, because the readers don't write into the data, and this
  166. // function is called when a thread is DONE reading
  167. //
  168. //--
  169. LEAF_ENTRY(MrswFetchAndDecrementReader)
  170. PROLOGUE_END
  171. //
  172. // Decrement the active reader count and load both reader and writer accounts
  173. // atomically.
  174. //
  175. fdr10: ldah t1, 1(zero) // decrement value to dec reader count
  176. ldl_l v0, (a0) // get both counters
  177. subl v0, t1, v0
  178. bis v0, zero, t0
  179. stl_c t0, (a0)
  180. beq t0, fdr20
  181. ret zero, (ra)
  182. fdr20: br zero, fdr10
  183. .end MrswFetchAndDecrementReader
  184. //++
  185. //
  186. // DWORD
  187. // InterlockedAnd(
  188. // DWORD *pDWORD, // ptr to DWORD to bitwise AND a value into
  189. // DWORD AndValue // value to bitwise OR into *pDWORD
  190. // )
  191. //
  192. // Routine Description:
  193. //
  194. // Atomically grabs the value of *pDWORD and clears the bits in *pDWORD
  195. // specified by Mask. ie. implements atomically: temp = *pDWORD;
  196. // *pDWORD &= Mask;
  197. // return temp;
  198. //
  199. // Arguments:
  200. //
  201. // pDWORD - ptr to DWORD to modify
  202. // Mask - value to bitwise AND into *pDWORD
  203. //
  204. // Return Value:
  205. //
  206. // Value of *pDWORD before the AND operation.
  207. //
  208. //--
  209. LEAF_ENTRY(InterlockedAnd)
  210. PROLOGUE_END
  211. ia10: ldl_l v0, (a0)
  212. and v0, a1, t0
  213. stl_c t0, (a0)
  214. beq t0, ia20
  215. ret zero, (ra)
  216. ia20: br zero, ia10
  217. .end InterlockedAnd
  218. //++
  219. //
  220. // DWORD
  221. // InterlockedOr(
  222. // DWORD *pDWORD, // ptr to DWORD to bitwise OR a value into
  223. // DWORD OrValue // value to bitwise OR into *pDWORD
  224. // )
  225. //
  226. // Routine Description:
  227. //
  228. // Atomically grabs the value of *pDWORD and bitwise ORs in OrValue.
  229. //
  230. // Arguments:
  231. //
  232. // pDWORD - ptr to DWORD to modify
  233. // OrValue - value to bitwise OR into *pDWORD
  234. //
  235. // Return Value:
  236. //
  237. // Value of *pDWORD before the OR operation.
  238. //
  239. //--
  240. LEAF_ENTRY(InterlockedOr)
  241. PROLOGUE_END
  242. io10: ldl_l v0, (a0)
  243. bis v0, a1, t0
  244. stl_c t0, (a0)
  245. beq t0, io20
  246. ret zero, (ra)
  247. io20: br zero, io10
  248. .end InterlockedOr