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.

568 lines
15 KiB

  1. title "Critical Section Support"
  2. ;++
  3. ;
  4. ; Copyright (c) 1991 Microsoft Corporation
  5. ;
  6. ; Module Name:
  7. ;
  8. ; critsect.asm
  9. ;
  10. ; Abstract:
  11. ;
  12. ; This module implements functions to support user mode interlocked operations.
  13. ;
  14. ; Author:
  15. ;
  16. ; Bryan M. Willman (bryanwi) 2-Oct-91
  17. ;
  18. ; Environment:
  19. ;
  20. ; Any mode.
  21. ;
  22. ; Revision History:
  23. ;
  24. ;
  25. ; WARNING!!!!!!!!!! Some of this code is duplicated in
  26. ; ntos\dll\i386\critsect.asm
  27. ;
  28. ; Some day we should put it in a .inc file that both include.
  29. ;
  30. ;--
  31. .486p
  32. .xlist
  33. include ks386.inc
  34. include callconv.inc
  35. .list
  36. _DATA SEGMENT DWORD PUBLIC 'DATA'
  37. public _BasepLockPrefixTable
  38. _BasepLockPrefixTable label dword
  39. dd offset FLAT:Lock1
  40. dd offset FLAT:Lock2
  41. dd offset FLAT:Lock3
  42. dd offset FLAT:Lock4
  43. dd offset FLAT:Lock5
  44. dd 0
  45. _DATA ENDS
  46. _TEXT SEGMENT PARA PUBLIC 'CODE'
  47. ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
  48. Addend equ [esp + 4]
  49. FlagMask equ 0c0000000H
  50. FlagShift equ 24
  51. FlagSelect equ 30
  52. page , 132
  53. subttl "InterlockedIncrement"
  54. ;++
  55. ;
  56. ; LONG
  57. ; InterlockedIncrement(
  58. ; IN PLONG Addend
  59. ; )
  60. ;
  61. ; Routine Description:
  62. ;
  63. ; This function performs an interlocked add of one to the addend variable.
  64. ;
  65. ; No checking is done for overflow.
  66. ;
  67. ; Arguments:
  68. ;
  69. ; Addend - Supplies a pointer to a variable whose value is to be
  70. ; incremented by one.
  71. ;
  72. ; Return Value:
  73. ;
  74. ; (eax) - the incremented value.
  75. ;
  76. ;--
  77. cPublicProc _InterlockedIncrement,1
  78. cPublicFpo 1,0
  79. mov ecx,Addend ; get pointer to addend variable
  80. mov eax,1 ; set increment value
  81. Lock1:
  82. lock xadd [ecx],eax ; interlocked increment
  83. inc eax ; adjust return value
  84. stdRET _InterlockedIncrement ;
  85. stdENDP _InterlockedIncrement
  86. page , 132
  87. subttl "InterlockedDecrment"
  88. ;++
  89. ;
  90. ; LONG
  91. ; InterlockedDecrement(
  92. ; IN PLONG Addend
  93. ; )
  94. ;
  95. ; Routine Description:
  96. ;
  97. ; This function performs an interlocked add of -1 to the addend variable.
  98. ;
  99. ; No checking is done for overflow
  100. ;
  101. ; Arguments:
  102. ;
  103. ; Addend - Supplies a pointer to a variable whose value is to be
  104. ; decremented by one.
  105. ;
  106. ; Return Value:
  107. ;
  108. ; (eax) - The decremented value.
  109. ;
  110. ;--
  111. cPublicProc _InterlockedDecrement,1
  112. cPublicFpo 1,0
  113. mov ecx,Addend ; get pointer to addend variable
  114. mov eax,-1 ; set decrement value
  115. Lock2:
  116. lock xadd [ecx],eax ; interlocked decrement
  117. dec eax ; adjust return value
  118. stdRET _InterlockedDecrement ;
  119. stdENDP _InterlockedDecrement
  120. page , 132
  121. subttl "Interlocked Exchange"
  122. ;++
  123. ;
  124. ; LONG
  125. ; InterlockedExchange(
  126. ; IN OUT LPLONG Target,
  127. ; IN LONG Value
  128. ; )
  129. ;
  130. ; Routine Description:
  131. ;
  132. ; This function atomically exchanges the Target and Value, returning
  133. ; the prior contents of Target
  134. ;
  135. ; Arguments:
  136. ;
  137. ; Target - Address of LONG to exchange
  138. ; Value - New value of LONG
  139. ;
  140. ; Return Value:
  141. ;
  142. ; (eax) - The prior value of target.
  143. ;--
  144. cPublicProc _InterlockedExchange, 2
  145. cPublicFpo 2,0
  146. mov ecx, [esp+4] ; (ecx) = Target
  147. mov edx, [esp+8] ; (edx) = Value
  148. mov eax, [ecx] ; get comperand value
  149. Ixchg:
  150. Lock5:
  151. lock cmpxchg [ecx], edx ; compare and swap
  152. jnz Ixchg ; if nz, exchange failed
  153. stdRET _InterlockedExchange
  154. stdENDP _InterlockedExchange
  155. page , 132
  156. subttl "Interlocked Compare Exchange"
  157. ;++
  158. ;
  159. ; PVOID
  160. ; InterlockedCompareExchange (
  161. ; IN OUT PVOID *Destination,
  162. ; IN PVOID Exchange,
  163. ; IN PVOID Comperand
  164. ; )
  165. ;
  166. ; Routine Description:
  167. ;
  168. ; This function performs an interlocked compare of the destination
  169. ; value with the comperand value. If the destination value is equal
  170. ; to the comperand value, then the exchange value is stored in the
  171. ; destination. Otherwise, no operation is performed.
  172. ;
  173. ; Arguments:
  174. ;
  175. ; Destination - Supplies a pointer to destination value.
  176. ;
  177. ; Exchange - Supplies the exchange value.
  178. ;
  179. ; Comperand - Supplies the comperand value.
  180. ;
  181. ; Return Value:
  182. ;
  183. ; (eax) - The initial destination value.
  184. ;
  185. ;--
  186. cPublicProc _InterlockedCompareExchange, 3
  187. cPublicFpo 3,0
  188. mov ecx, [esp + 4] ; get destination address
  189. mov edx, [esp + 8] ; get exchange value
  190. mov eax, [esp + 12] ; get comperand value
  191. Lock3:
  192. lock cmpxchg [ecx], edx ; compare and exchange
  193. stdRET _InterlockedCompareExchange
  194. stdENDP _InterlockedCompareExchange
  195. page , 132
  196. subttl "Interlocked Exchange Add"
  197. ;++
  198. ;
  199. ; LONG
  200. ; InterlockedExchangeAdd (
  201. ; IN OUT PLONG Addend,
  202. ; IN LONG Increment
  203. ; )
  204. ;
  205. ; Routine Description:
  206. ;
  207. ; This function performs an interlocked add of an increment value to an
  208. ; addend variable of type unsinged long. The initial value of the addend
  209. ; variable is returned as the function value.
  210. ;
  211. ; It is NOT possible to mix ExInterlockedDecrementLong and
  212. ; ExInterlockedIncrementong with ExInterlockedAddUlong.
  213. ;
  214. ;
  215. ; Arguments:
  216. ;
  217. ; Addend - Supplies a pointer to a variable whose value is to be
  218. ; adjusted by the increment value.
  219. ;
  220. ; Increment - Supplies the increment value to be added to the
  221. ; addend variable.
  222. ;
  223. ; Return Value:
  224. ;
  225. ; (eax) - The initial value of the addend.
  226. ;
  227. ;--
  228. cPublicProc _InterlockedExchangeAdd, 2
  229. cPublicFpo 2,0
  230. mov ecx, [esp + 4] ; get addend address
  231. mov eax, [esp + 8] ; get increment value
  232. Lock4:
  233. lock xadd [ecx], eax ; exchange add
  234. stdRET _InterlockedExchangeAdd
  235. stdENDP _InterlockedExchangeAdd
  236. page , 132
  237. subttl "Multiply and Divide"
  238. ;++
  239. ;
  240. ; LONG
  241. ; MulDiv(
  242. ; IN LONG nNumber,
  243. ; IN LONG nNumerator,
  244. ; IN LONG nDenominator
  245. ; )
  246. ;
  247. ; Routine Description:
  248. ;
  249. ; This function multiples two 32-bit numbers forming a 64-bit product.
  250. ; The 64-bit product is rounded and then divided by a 32-bit divisor
  251. ; yielding a 32-bit result.
  252. ;
  253. ; Arguments:
  254. ;
  255. ; nNumber - Supllies the multiplier.
  256. ;
  257. ; nNumerator - Supplies the multiplicand.
  258. ;
  259. ; nDenominator - Supplies the divisor.
  260. ;
  261. ; Return Value:
  262. ;
  263. ; If the divisor is zero or an overflow occurs, then a value of -1 is
  264. ; returned as the function value. Otherwise, the rounded quotient is
  265. ; returned as the funtion value.
  266. ;
  267. ;--
  268. nNumber equ [esp + 4]
  269. nNumerator equ [esp + 8]
  270. nDenominator equ DWORD PTR [esp + 12]
  271. cPublicProc _MulDiv, 3
  272. cPublicFpo 3,0
  273. mov eax, nNumber ; get multiplier absolute value
  274. or eax, eax ;
  275. js short MD32_First ; if s, multiplier is negative
  276. ;
  277. ; The multiplier is positive.
  278. ;
  279. mov edx, nNumerator ; get multiplicand absolute value
  280. or edx, edx ;
  281. js MD32_Second ; if s, multiplicand is negative
  282. ;
  283. ; The multiplicand is positive.
  284. ;
  285. mul edx ; compute 64-bit product
  286. mov ecx, nDenominator ; get denominator absolute value
  287. or ecx, ecx ;
  288. js MD32_Third ; if s, divisor is negative
  289. ;
  290. ; The divisor is positive.
  291. ;
  292. sar ecx, 1 ; compute rounding value
  293. add eax, ecx ; round the 64-bit produce by the
  294. adc edx, 0 ; divisor / 2
  295. cmp edx, nDenominator ; check for overflow
  296. jae short MD32_error ; if ae, overflow or divide by 0
  297. div nDenominator ; compute quotient
  298. ;
  299. ; The result is postive.
  300. ;
  301. or eax, eax ; check for overflow
  302. js short MD32_error ; if s, overlfow has occured
  303. stdRET _MulDiv
  304. MD32_error:
  305. xor eax, eax ; set return value to - 1
  306. dec eax ;
  307. stdRET _MulDiv
  308. ;
  309. ; The multiplier is negative.
  310. ;
  311. MD32_First: ;
  312. neg eax ; negate multiplier
  313. mov edx, nNumerator ; get multiplicand absolute value
  314. or edx, edx ;
  315. js short MD32_First10 ; if s, multiplicand is negative
  316. ;
  317. ; The multiplicand is positive.
  318. ;
  319. mul edx ; compute 64-bit product
  320. mov ecx, nDenominator ; get denominator absolute value
  321. or ecx, ecx ;
  322. js short MD32_First20 ; if s, divisor is negative
  323. ;
  324. ; The divisor is positive.
  325. ;
  326. sar ecx, 1 ; compute rounding value
  327. add eax, ecx ; round the 64-bit produce by the
  328. adc edx, 0 ; divisor / 2
  329. cmp edx, nDenominator ; check for overflow
  330. jae short MD32_error10 ; if ae, overflow or divide by 0
  331. div nDenominator ; compute quotient
  332. ;
  333. ; The result is negative.
  334. ;
  335. neg eax ; negate result
  336. jg short MD32_error10 ; if g, overlfow has occured
  337. stdRET _MulDiv
  338. ;
  339. ; The multiplier is negative and the multiplicand is negative.
  340. ;
  341. MD32_First10: ;
  342. neg edx ; negate multiplicand
  343. mul edx ; compute 64-bit product
  344. mov ecx, nDenominator ; get denominator absolute value
  345. or ecx, ecx ;
  346. js short MD32_First30 ; if s, divisor is negative
  347. ;
  348. ; The divisor is positive.
  349. ;
  350. sar ecx, 1 ; compute rounding value
  351. add eax, ecx ; round the 64-bit produce by the
  352. adc edx, 0 ; divisor / 2
  353. cmp edx, nDenominator ; check for overflow
  354. jae short MD32_error10 ; if ae, overflow or divide by 0
  355. div nDenominator ; compute quotient
  356. ;
  357. ; The result is positive.
  358. ;
  359. or eax, eax ; check for overflow
  360. js short MD32_error10 ; if s, overlfow has occured
  361. stdRET _MulDiv
  362. MD32_error10: ;
  363. xor eax, eax ; set return value to - 1
  364. dec eax ;
  365. stdRET _MulDiv
  366. ;
  367. ; The multiplier is negative, the multiplicand is positive, and the
  368. ; divisor is negative.
  369. ;
  370. MD32_First20: ;
  371. neg ecx ; negate divisor
  372. push ecx ; save absolute value of divisor
  373. sar ecx, 1 ; compute rounding value
  374. add eax, ecx ; round the 64-bit produce by the
  375. adc edx, 0 ; divisor / 2
  376. pop ecx ; restore divisor
  377. cmp edx, ecx ; check for overflow
  378. jae short MD32_error10 ; if ae, overflow or divide by 0
  379. div ecx ; compute quotient
  380. ;
  381. ; The result is postive.
  382. ;
  383. or eax, eax ; check for overflow
  384. js short MD32_error10 ; if s, overlfow has occured
  385. stdRET _MulDiv
  386. ;
  387. ; The multiplier is negative, the multiplier is negative, and the divisor
  388. ; is negative.
  389. ;
  390. MD32_First30: ;
  391. neg ecx ; negate divisor
  392. push ecx ; save absolute value of divisor
  393. sar ecx, 1 ; compute rounding value
  394. add eax, ecx ; round the 64-bit produce by the
  395. adc edx, 0 ; divisor / 2
  396. pop ecx ; restore divisor
  397. cmp edx, ecx ; check for overflow
  398. jae short MD32_error10 ; if ae, overflow or divide by 0
  399. div ecx ; compute quotient
  400. ;
  401. ; The result is negative.
  402. ;
  403. neg eax ; negate result
  404. jg short MD32_error10 ; if g, overlfow has occured
  405. stdRET _MulDiv
  406. ;
  407. ; The multiplier is positive and the multiplicand is negative.
  408. ;
  409. MD32_Second: ;
  410. neg edx ; negate multiplicand
  411. mul edx ; compute 64-bit product
  412. mov ecx, nDenominator ; get denominator absolute value
  413. or ecx, ecx ;
  414. js short MD32_Second10 ; if s, divisor is negative
  415. ;
  416. ; The divisor is positive.
  417. ;
  418. sar ecx, 1 ; compute rounding value
  419. add eax, ecx ; round the 64-bit produce by the
  420. adc edx, 0 ; divisor / 2
  421. cmp edx, nDenominator ; check for overflow
  422. jae short MD32_error20 ; if ae, overflow or divide by 0
  423. div nDenominator ; compute quotient
  424. ;
  425. ; The result is negative.
  426. ;
  427. neg eax ; check for overflow
  428. jg short MD32_error20 ; if g, overlfow has occured
  429. stdRET _MulDiv
  430. MD32_error20: ;
  431. xor eax, eax ; set return value to - 1
  432. dec eax ;
  433. stdRET _MulDiv
  434. ;
  435. ; The multiplier is positive, the multiplicand is negative, and the divisor
  436. ; is negative.
  437. ;
  438. MD32_Second10: ;
  439. neg ecx ; negate divisor
  440. push ecx ; save absolute value of divisor
  441. sar ecx, 1 ; compute rounding value
  442. add eax, ecx ; round the 64-bit produce by the
  443. adc edx, 0 ; divisor / 2
  444. pop ecx ; restore divisor
  445. cmp edx, ecx ; check for overflow
  446. jae short MD32_error20 ; if ae, overflow or divide by 0
  447. div ecx ; compute quotient
  448. ;
  449. ; The result is positive.
  450. ;
  451. or eax, eax ; check for overflow
  452. js short MD32_error10 ; if s, overlfow has occured
  453. stdRET _MulDiv
  454. ;
  455. ; The multiplier is positive, the multiplicand is positive, the divisor
  456. ; is negative.
  457. ;
  458. MD32_Third: ;
  459. neg ecx ; negate divisor
  460. push ecx ; save absolute value of divisor
  461. sar ecx, 1 ; compute rounding value
  462. add eax, ecx ; round the 64-bit produce by the
  463. adc edx, 0 ; divisor / 2
  464. pop ecx ; restore divisor
  465. cmp edx, ecx ; check for overflow
  466. jae short MD32_error20 ; if ae, overflow or divide by 0
  467. div ecx ; compute quotient
  468. ;
  469. ; The result is negative.
  470. ;
  471. neg eax ; negate result
  472. jg short MD32_error20 ; if g, overflow has occured
  473. stdRET _MulDiv
  474. stdENDP _MulDiv
  475. _TEXT ends
  476. end