Leaked source code of windows server 2003
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.

956 lines
27 KiB

  1. title "Interlocked Support"
  2. ;++
  3. ;
  4. ; Copyright (c) 1989 Microsoft Corporation
  5. ;
  6. ; Module Name:
  7. ;
  8. ; intrlock.asm
  9. ;
  10. ; Abstract:
  11. ;
  12. ; This module implements functions to support interlocked operations.
  13. ; Interlocked operations can only operate on nonpaged data.
  14. ;
  15. ; Author:
  16. ;
  17. ; Shie-Lin Tzong (shielint) 12-Feb-1990
  18. ;
  19. ; Environment:
  20. ;
  21. ; Any mode.
  22. ;
  23. ; Revision History:
  24. ;
  25. ; bryanwi 1-aug-90 Clean up and fix stuff.
  26. ; bryanwi 3-aug-90 Add ExInterlockedIncrementLlong,...
  27. ;
  28. ;--
  29. .386p
  30. .xlist
  31. include ks386.inc
  32. include callconv.inc ; calling convention macros
  33. include mac386.inc
  34. .list
  35. _TEXT$00 SEGMENT DWORD PUBLIC 'CODE'
  36. ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
  37. ;++
  38. ;
  39. ; General Notes on Interlocked Procedures:
  40. ;
  41. ; These procedures assume that neither their code, nor any of
  42. ; the data they touch, will cause a page fault.
  43. ;
  44. ; They use spinlocks to achieve MP atomicity, iff it's an MP machine.
  45. ; (The spinlock macros generate zilch if NT_UP = 1, and
  46. ; we if out some aux code here as well.)
  47. ;
  48. ; They turn off interrupts so that they can be used for synchronization
  49. ; between ISRs and driver code. Flags are preserved so they can
  50. ; be called in special code (Like IPC interrupt handlers) that
  51. ; may have interrupts off.
  52. ;
  53. ;--
  54. ;; align 512
  55. page ,132
  56. subttl "ExInterlockedAddLargeInteger"
  57. ;++
  58. ;
  59. ; LARGE_INTEGER
  60. ; ExInterlockedAddLargeInteger (
  61. ; IN PLARGE_INTEGER Addend,
  62. ; IN LARGE_INTEGER Increment,
  63. ; IN PKSPIN_LOCK Lock
  64. ; )
  65. ;
  66. ; Routine Description:
  67. ;
  68. ; This function performs an interlocked add of an increment value to an
  69. ; addend variable of type unsigned large integer. The initial value of
  70. ; the addend variable is returned as the function value.
  71. ;
  72. ; Arguments:
  73. ;
  74. ; (TOS+4) = Addend - a pointer to the addend value
  75. ; (TOS+8) = Increment - the increment value
  76. ; (TOS+16) = Lock - a pointer to a pointer to a spin lock
  77. ;
  78. ; Return Value:
  79. ;
  80. ; The initial value of the addend variable is stored in eax:edx
  81. ;
  82. ;--
  83. EiulAddend equ [ebp + 8]
  84. EiulIncrement equ [ebp + 12]
  85. EiulLock equ [ebp + 20]
  86. EiulRetval equ [ebp - 8]
  87. cPublicProc _ExInterlockedAddLargeInteger, 4
  88. push ebp
  89. mov ebp,esp
  90. sub esp, 8
  91. ifndef NT_UP
  92. mov eax,EiulLock ; (eax) -> KSPIN_LOCK
  93. endif
  94. eiul10: pushfd
  95. cli ; disable interrupts
  96. ACQUIRE_SPINLOCK eax,<short eiul20>
  97. mov eax,EiulAddend ; (eax)-> addend variable
  98. mov ecx,[eax] ; (ecx)= low part of addend value
  99. mov edx,[eax]+4 ; (edx)= high part of addend value
  100. mov EiulRetVal,ecx ; set low part of return value
  101. mov EiulRetVal+4,edx ; set high part of return value
  102. add ecx,EiulIncrement ; add low parts of large integer
  103. adc edx,EiulIncrement+4 ; add high parts of large integer and carry
  104. mov eax,EiulAddend ; RELOAD (eax)-> addend variable
  105. mov [eax],ecx ; store low part of result
  106. mov [eax]+4,edx ; store high part of result
  107. ifndef NT_UP
  108. mov eax,EiulLock
  109. RELEASE_SPINLOCK eax ; NOTHING if NT_UP = 1
  110. endif
  111. popfd ; restore flags including interrupts
  112. mov eax, EiulRetval ; calling convention
  113. mov edx, EiulRetval+4 ; calling convention
  114. mov esp, ebp
  115. pop ebp
  116. stdRET _ExInterlockedAddLargeInteger
  117. ifndef NT_UP
  118. eiul20: popfd
  119. SPIN_ON_SPINLOCK eax, eiul10
  120. endif
  121. stdENDP _ExInterlockedAddLargeInteger
  122. page , 132
  123. subttl "Interlocked Add Unsigned Long"
  124. ;++
  125. ;
  126. ; ULONG
  127. ; ExInterlockedAddUlong (
  128. ; IN PULONG Addend,
  129. ; IN ULONG Increment,
  130. ; IN PKSPIN_LOCK Lock
  131. ; )
  132. ;
  133. ; Routine Description:
  134. ;
  135. ; This function performs an interlocked add of an increment value to an
  136. ; addend variable of type unsinged long. The initial value of the addend
  137. ; variable is returned as the function value.
  138. ;
  139. ; It is NOT possible to mix ExInterlockedDecrementLong and
  140. ; ExInterlockedIncrementong with ExInterlockedAddUlong.
  141. ;
  142. ;
  143. ; Arguments:
  144. ;
  145. ; Addend - Supplies a pointer to a variable whose value is to be
  146. ; adjusted by the increment value.
  147. ;
  148. ; Increment - Supplies the increment value to be added to the
  149. ; addend variable.
  150. ;
  151. ; Lock - Supplies a pointer to a spin lock to be used to synchronize
  152. ; access to the addend variable.
  153. ;
  154. ; Return Value:
  155. ;
  156. ; The initial value of the addend variable.
  157. ;
  158. ;--
  159. EialAddend equ [esp + 8]
  160. EialIncrement equ [esp + 12]
  161. EialLock equ [esp + 16]
  162. ; end of arguments
  163. cPublicProc _ExInterlockedAddUlong , 3
  164. cPublicFpo 3, 1
  165. ifdef NT_UP
  166. ;
  167. ; UP version of ExInterlockedAddUlong
  168. ;
  169. pushfd
  170. cli ; disable interrupts
  171. mov ecx, EialAddend ; (ecx)->initial addend value
  172. mov edx, [ecx] ; (edx)= initial addend value
  173. mov eax, edx ; (eax)= initial addend value
  174. add edx, EialIncrement ; (edx)=adjusted value
  175. mov [ecx], edx ; [ecx]=adjusted value
  176. popfd ; restore flags including ints
  177. stdRET _ExInterlockedAddUlong ; cRetURN
  178. else
  179. ;
  180. ; MP version of ExInterlockedAddUlong
  181. ;
  182. pushfd
  183. mov edx,EialLock ; (edx)-> KSPIN_LOCK
  184. Eial10: cli ; disable interrupts
  185. ACQUIRE_SPINLOCK edx, <short Eial20>
  186. mov ecx, EialAddend ; (ecx)->initial addend value
  187. mov eax, [ecx] ; (eax)=initial addend value
  188. add eax, EialIncrement ; (eax)=adjusted value
  189. mov [ecx], eax ; [ecx]=adjusted value
  190. sub eax, EialIncrement ; (eax)=initial addend value
  191. RELEASE_SPINLOCK edx
  192. popfd
  193. stdRET _ExInterlockedAddUlong ; cRetURN
  194. Eial20: popfd
  195. pushfd
  196. SPIN_ON_SPINLOCK edx, <short Eial10>
  197. endif
  198. stdENDP _ExInterlockedAddUlong
  199. page , 132
  200. subttl "Interlocked Insert Head List"
  201. ;++
  202. ;
  203. ; PLIST_ENTRY
  204. ; ExInterlockedInsertHeadList (
  205. ; IN PLIST_ENTRY ListHead,
  206. ; IN PLIST_ENTRY ListEntry,
  207. ; IN PKSPIN_LOCK Lock
  208. ; )
  209. ;
  210. ; Routine Description:
  211. ;
  212. ; This function inserts an entry at the head of a doubly linked list
  213. ; so that access to the list is synchronized in a multiprocessor system.
  214. ;
  215. ; N.B. The pages of data which this routine operates on MUST be
  216. ; present. No page fault is allowed in this routine.
  217. ;
  218. ; Arguments:
  219. ;
  220. ; ListHead - Supplies a pointer to the head of the doubly linked
  221. ; list into which an entry is to be inserted.
  222. ;
  223. ; ListEntry - Supplies a pointer to the entry to be inserted at the
  224. ; head of the list.
  225. ;
  226. ; Lock - Supplies a pointer to a spin lock to be used to synchronize
  227. ; access to the list.
  228. ;
  229. ; Return Value:
  230. ;
  231. ; Pointer to entry that was at the head of the list or NULL if the list
  232. ; was empty.
  233. ;
  234. ;--
  235. EiihListHead equ [esp + 8]
  236. EiihListEntry equ [esp + 12]
  237. EiihLock equ [esp + 16]
  238. ; end arguments
  239. cPublicProc _ExInterlockedInsertHeadList , 3
  240. cPublicFpo 3, 1
  241. ifndef NT_UP
  242. mov edx, EiihLock - 4 ; (edx)->KSPIN_LOCK
  243. endif
  244. Eiih10: pushfd
  245. cli
  246. ACQUIRE_SPINLOCK edx,<short Eiih20>
  247. mov eax, EiihListHead ; (eax)->head of linked list
  248. mov ecx, EiihListEntry ; (ecx)->entry to be inserted
  249. mov edx, LsFlink[eax] ; (edx)->next entry in the list
  250. mov [ecx]+LsFlink, edx ; store next link in entry
  251. mov [ecx]+LsBlink, eax ; store previous link in entry
  252. mov [eax]+LsFlink, ecx ; store next link in head
  253. mov [edx]+LsBlink, ecx ; store previous link in next
  254. ifndef NT_UP
  255. mov ecx, EiihLock ; (ecx)->KSPIN_LOCK
  256. RELEASE_SPINLOCK ecx
  257. endif
  258. cPublicFpo 3, 0
  259. popfd ; restore flags including interrupts
  260. xor eax,edx ; return null if list was empty
  261. jz short Eiih15
  262. mov eax,edx ; otherwise return prev. entry at head
  263. Eiih15:
  264. stdRET _ExInterlockedInsertHeadList
  265. ifndef NT_UP
  266. align 4
  267. Eiih20: popfd
  268. SPIN_ON_SPINLOCK edx, <short Eiih10>
  269. endif
  270. stdENDP _ExInterlockedInsertHeadList
  271. page , 132
  272. subttl "Interlocked Insert Tail List"
  273. ;++
  274. ;
  275. ; PLIST_ENTRY
  276. ; ExInterlockedInsertTailList (
  277. ; IN PLIST_ENTRY ListHead,
  278. ; IN PLIST_ENTRY ListEntry,
  279. ; IN PKSPIN_LOCK Lock
  280. ; )
  281. ;
  282. ; Routine Description:
  283. ;
  284. ; This function inserts an entry at the tail of a doubly linked list
  285. ; so that access to the list is synchronized in a multiprocessor system.
  286. ;
  287. ; N.B. The pages of data which this routine operates on MUST be
  288. ; present. No page fault is allowed in this routine.
  289. ;
  290. ; Arguments:
  291. ;
  292. ; ListHead - Supplies a pointer to the head of the doubly linked
  293. ; list into which an entry is to be inserted.
  294. ;
  295. ; ListEntry - Supplies a pointer to the entry to be inserted at the
  296. ; tail of the list.
  297. ;
  298. ; Lock - Supplies a pointer to a spin lock to be used to synchronize
  299. ; access to the list.
  300. ;
  301. ; Return Value:
  302. ;
  303. ; Pointer to entry that was at the tail of the list or NULL if the list
  304. ; was empty.
  305. ;
  306. ;--
  307. EiitListHead equ [esp + 8]
  308. EiitListEntry equ [esp + 12]
  309. EiitLock equ [esp + 16]
  310. ; end arguments
  311. cPublicProc _ExInterlockedInsertTailList , 3
  312. cPublicFpo 3, 1
  313. ifndef NT_UP
  314. mov edx,EiitLock - 4 ; (edx)->KSPIN_LOCK
  315. endif
  316. Eiit10: pushfd
  317. cli ; disable interrupts
  318. ACQUIRE_SPINLOCK edx, <short Eiit20>
  319. mov eax, EiihListHead ; (eax)->head of linked list
  320. mov ecx, EiihListEntry ; (ecx)->entry to be inserted
  321. mov edx, LsBlink[eax] ; (edx)->previous entry in the list
  322. mov [ecx]+LsFlink, eax ; store next link in entry
  323. mov [ecx]+LsBlink, edx ; store previous link in entry
  324. mov [eax]+LsBlink, ecx ; store previous link in head
  325. mov [edx]+LsFlink, ecx ; store next link in next
  326. ifndef NT_UP
  327. mov ecx,EiitLock ; (ecx)->KSPIN_LOCK
  328. RELEASE_SPINLOCK ecx
  329. endif
  330. cPublicFpo 3,0
  331. popfd ; restore flags including interrupts
  332. xor eax,edx ; return null if list was empty
  333. jz short Eiit15
  334. mov eax,edx ; otherwise return prev. entry at tail
  335. Eiit15:
  336. stdRET _ExInterlockedInsertTailList
  337. ifndef NT_UP
  338. align 4
  339. Eiit20: popfd
  340. SPIN_ON_SPINLOCK edx, <short Eiit10>
  341. endif
  342. stdENDP _ExInterlockedInsertTailList
  343. page , 132
  344. subttl "Interlocked Remove Head List"
  345. ;++
  346. ;
  347. ; PLIST_ENTRY
  348. ; ExInterlockedRemoveHeadList (
  349. ; IN PLIST_ENTRY ListHead,
  350. ; IN PKSPIN_LOCK Lock
  351. ; )
  352. ;
  353. ; Routine Description:
  354. ;
  355. ; This function removes an entry from the head of a doubly linked list
  356. ; so that access to the list is synchronized in a multiprocessor system.
  357. ; If there are no entries in the list, then a value of NULL is returned.
  358. ; Otherwise, the address of the entry that is removed is returned as the
  359. ; function value.
  360. ;
  361. ; N.B. The pages of data which this routine operates on MUST be
  362. ; present. No page fault is allowed in this routine.
  363. ;
  364. ; Arguments:
  365. ;
  366. ; ListHead - Supplies a pointer to the head of the doubly linked
  367. ; list from which an entry is to be removed.
  368. ;
  369. ; Lock - Supplies a pointer to a spin lock to be used to synchronize
  370. ; access to the list.
  371. ;
  372. ; Return Value:
  373. ;
  374. ; The address of the entry removed from the list, or NULL if the list is
  375. ; empty.
  376. ;
  377. ;--
  378. EirhListHead equ [esp + 8]
  379. EirhLock equ [esp + 12]
  380. ; end of arguments
  381. cPublicProc _ExInterlockedRemoveHeadList , 2
  382. cPublicFpo 2, 1
  383. ifndef NT_UP
  384. mov edx, EirhLock - 4 ; (edx)-> KSPIN_LOCK
  385. endif
  386. Eirh10: pushfd
  387. cli
  388. ACQUIRE_SPINLOCK edx, <Eirh30>
  389. mov edx, EirhListHead ; (edx)-> head of list
  390. mov eax, [edx]+LsFlink ; (eax)-> next entry
  391. cmp eax, edx ; Is list empty?
  392. je short Eirh20 ; if e, list is empty, go Eirh20
  393. mov ecx, [eax]+LsFlink ; (ecx)-> next entry(after deletion)
  394. mov [edx]+LsFlink, ecx ; store address of next in head
  395. mov [ecx]+LsBlink, edx ; store address of previous in next
  396. if DBG
  397. mov [eax]+LsFlink, 0baddd0ffh
  398. mov [eax]+LsBlink, 0baddd0ffh
  399. endif
  400. ifndef NT_UP
  401. mov edx, EirhLock ; (edx)-> KSPIN_LOCK
  402. RELEASE_SPINLOCK edx
  403. endif
  404. cPublicFpo 2, 0
  405. popfd ; restore flags including interrupts
  406. stdRET _ExInterlockedRemoveHeadList ; cReturn entry
  407. align 4
  408. Eirh20:
  409. ifndef NT_UP
  410. mov edx, EirhLock ; (edx)-> KSPIN_LOCK
  411. RELEASE_SPINLOCK edx
  412. endif
  413. popfd
  414. xor eax,eax ; (eax) = null for empty list
  415. stdRET _ExInterlockedRemoveHeadList ; cReturn NULL
  416. ifndef NT_UP
  417. align 4
  418. Eirh30: popfd
  419. SPIN_ON_SPINLOCK edx, Eirh10
  420. endif
  421. stdENDP _ExInterlockedRemoveHeadList
  422. page , 132
  423. subttl "Interlocked Pop Entry List"
  424. ;++
  425. ;
  426. ; PSINGLE_LIST_ENTRY
  427. ; ExInterlockedPopEntryList (
  428. ; IN PSINGLE_LIST_ENTRY ListHead,
  429. ; IN PKSPIN_LOCK Lock
  430. ; )
  431. ;
  432. ; Routine Description:
  433. ;
  434. ; This function removes an entry from the front of a singly linked list
  435. ; so that access to the list is synchronized in a multiprocessor system.
  436. ; If there are no entries in the list, then a value of NULL is returned.
  437. ; Otherwise, the address of the entry that is removed is returned as the
  438. ; function value.
  439. ;
  440. ; Arguments:
  441. ;
  442. ; ListHead - Supplies a pointer to the head of the singly linked
  443. ; list from which an entry is to be removed.
  444. ;
  445. ; Lock - Supplies a pointer to a spin lock to be used to synchronize
  446. ; access to the list.
  447. ;
  448. ; Return Value:
  449. ;
  450. ; The address of the entry removed from the list, or NULL if the list is
  451. ; empty.
  452. ;
  453. ;--
  454. ; end of arguments
  455. cPublicProc _ExInterlockedPopEntryList , 2
  456. cPublicFpo 2,1
  457. ifndef NT_UP
  458. mov edx, [esp+8] ; (edx)-> KSPIN_LOCK
  459. endif
  460. Eipe10: pushfd
  461. cli ; disable interrupts
  462. ACQUIRE_SPINLOCK edx, <short Eipe30>
  463. mov ecx, [esp+8] ; (ecx)-> head of list
  464. mov eax, [ecx] ; (eax)-> next entry
  465. or eax, eax ; Is it empty?
  466. je short Eipe20 ; if e, empty list, go Eipe20
  467. mov edx, [eax] ; (edx)->next entry (after deletion)
  468. mov [ecx], edx ; store address of next in head
  469. if DBG
  470. mov [eax], 0baddd0ffh
  471. endif
  472. ifndef NT_UP
  473. mov edx, [esp+12] ; (edx)-> KSPIN_LOCK
  474. endif
  475. Eipe15: RELEASE_SPINLOCK edx
  476. cPublicFpo 2,0
  477. popfd ; restore flags including interrupts
  478. stdRET _ExInterlockedPopEntryList ; cReturn (eax)->removed entry
  479. Eipe20: xor eax, eax ; return NULL for empty list
  480. jmp short Eipe15 ; continue in common exit
  481. ifndef NT_UP
  482. Eipe30: popfd
  483. SPIN_ON_SPINLOCK edx, Eipe10
  484. endif
  485. stdENDP _ExInterlockedPopEntryList
  486. page , 132
  487. subttl "Interlocked Push Entry List"
  488. ;++
  489. ;
  490. ; PSINGLE_LIST_ENTRY
  491. ; ExInterlockedPushEntryList (
  492. ; IN PSINGLE_LIST_ENTRY ListHead,
  493. ; IN PSINGLE_LIST_ENTRY ListEntry,
  494. ; IN PKSPIN_LOCK Lock
  495. ; )
  496. ;
  497. ; Routine Description:
  498. ;
  499. ; This function inserts an entry at the head of a singly linked list
  500. ; so that access to the list is synchronized in a multiprocessor system.
  501. ;
  502. ; Arguments:
  503. ;
  504. ; ListHead - Supplies a pointer to the head of the singly linked
  505. ; list into which an entry is to be inserted.
  506. ;
  507. ; ListEntry - Supplies a pointer to the entry to be inserted at the
  508. ; head of the list.
  509. ;
  510. ; Lock - Supplies a pointer to a spin lock to be used to synchronize
  511. ; access to the list.
  512. ;
  513. ; Return Value:
  514. ;
  515. ; Previous contents of ListHead. NULL implies list went from empty
  516. ; to not empty.
  517. ;
  518. ;--
  519. ; end of arguments
  520. cPublicProc _ExInterlockedPushEntryList , 3
  521. cPublicFpo 3,1
  522. ifndef NT_UP
  523. mov edx, [esp+12] ; (edx)->KSPIN_LOCK
  524. endif
  525. Eipl10: pushfd
  526. cli
  527. ACQUIRE_SPINLOCK edx, <short Eipl20>
  528. mov edx, [esp+8] ; (edx)-> Head of list
  529. mov eax, [edx] ; (eax)-> next entry (return value also)
  530. mov ecx, [esp+12] ; (ecx)-> Entry to be pushed
  531. mov [ecx], eax ; store address of next in new entry
  532. mov [edx], ecx ; set address of next in head
  533. ifndef NT_UP
  534. mov edx, [esp+16] ; (edx)->KSPIN_LOCK
  535. RELEASE_SPINLOCK edx
  536. endif
  537. cPublicFpo 3,0
  538. popfd ; restore flags including interrupts
  539. stdRET _ExInterlockedPushEntryList
  540. ifndef NT_UP
  541. align 4
  542. Eipl20: popfd
  543. SPIN_ON_SPINLOCK edx, <short Eipl10>
  544. endif
  545. stdENDP _ExInterlockedPushEntryList
  546. page , 132
  547. subttl "Interlocked Increment Long"
  548. ;++
  549. ;
  550. ; INTERLOCKED_RESULT
  551. ; ExInterlockedIncrementLong (
  552. ; IN PLONG Addend,
  553. ; IN PKSPIN_LOCK Lock
  554. ; )
  555. ;
  556. ; Routine Description:
  557. ;
  558. ; This function atomically increments Addend, returning an ennumerated
  559. ; type which indicates what interesting transitions in the value of
  560. ; Addend occurred due the operation.
  561. ;
  562. ; It is NOT possible to mix ExInterlockedDecrementLong and
  563. ; ExInterlockedIncrementong with ExInterlockedAddUlong.
  564. ;
  565. ;
  566. ; Arguments:
  567. ;
  568. ; Addend (esp+4) - Pointer to variable to increment.
  569. ;
  570. ; Lock (esp+8) - Spinlock used to implement atomicity.
  571. ; (not actually used on x86)
  572. ;
  573. ; Return Value:
  574. ;
  575. ; An ennumerated type:
  576. ;
  577. ; ResultNegative if Addend is < 0 after increment.
  578. ; ResultZero if Addend is = 0 after increment.
  579. ; ResultPositive if Addend is > 0 after increment.
  580. ;
  581. ;--
  582. cPublicProc _ExInterlockedIncrementLong , 2
  583. cPublicFpo 2, 0
  584. mov eax, [esp+4] ; (eax) -> addend
  585. ifdef NT_UP
  586. add dword ptr [eax],1
  587. else
  588. lock add dword ptr [eax],1
  589. endif
  590. lahf ; (ah) = flags
  591. and eax,EFLAG_SELECT ; clear all but sign and zero flags
  592. stdRET _ExInterlockedIncrementLong
  593. stdENDP _ExInterlockedIncrementLong
  594. page , 132
  595. subttl "Interlocked Decrement Long"
  596. ;++
  597. ;
  598. ; INTERLOCKED_RESULT
  599. ; ExInterlockedDecrementLong (
  600. ; IN PLONG Addend,
  601. ; IN PKSPIN_LOCK Lock
  602. ; )
  603. ;
  604. ; Routine Description:
  605. ;
  606. ; This function atomically decrements Addend, returning an ennumerated
  607. ; type which indicates what interesting transitions in the value of
  608. ; Addend occurred due the operation.
  609. ;
  610. ; It is NOT possible to mix ExInterlockedDecrementLong and
  611. ; ExInterlockedIncrementong with ExInterlockedAddUlong.
  612. ;
  613. ; Arguments:
  614. ;
  615. ; Addend (esp+4) - Pointer to variable to decrement.
  616. ;
  617. ; Lock (esp+8) - Spinlock used to implement atomicity.
  618. ; (not actually used on x86)
  619. ;
  620. ; Return Value:
  621. ;
  622. ; An ennumerated type:
  623. ;
  624. ; ResultNegative if Addend is < 0 after decrement.
  625. ; ResultZero if Addend is = 0 after decrement.
  626. ; ResultPositive if Addend is > 0 after decrement.
  627. ;
  628. ;--
  629. cPublicProc _ExInterlockedDecrementLong , 2
  630. cPublicFpo 2, 0
  631. mov eax, [esp+4] ; (eax) -> addend
  632. ifdef NT_UP
  633. sub dword ptr [eax], 1
  634. else
  635. lock sub dword ptr [eax], 1
  636. endif
  637. lahf ; (ah) = flags
  638. and eax, EFLAG_SELECT ; clear all but sign and zero flags
  639. stdRET _ExInterlockedDecrementLong
  640. stdENDP _ExInterlockedDecrementLong
  641. page , 132
  642. subttl "Interlocked Exchange Ulong"
  643. ;++
  644. ;
  645. ; ULONG
  646. ; ExInterlockedExchangeUlong (
  647. ; IN PULONG Target,
  648. ; IN ULONG Value,
  649. ; IN PKSPIN_LOCK Lock
  650. ; )
  651. ;
  652. ; Routine Description:
  653. ;
  654. ; This function atomically exchanges the Target and Value, returning
  655. ; the prior contents of Target
  656. ;
  657. ; This function does not necessarily synchronize with the Lock.
  658. ;
  659. ; Arguments:
  660. ;
  661. ; Target - Address of ULONG to exchange
  662. ; Value - New value of ULONG
  663. ; Lock - SpinLock used to implement atomicity.
  664. ;
  665. ; Return Value:
  666. ;
  667. ; The prior value of Source
  668. ;--
  669. cPublicProc _ExInterlockedExchangeUlong, 3
  670. cPublicFpo 3,0
  671. ifndef NT_UP
  672. mov edx, [esp+4] ; (edx) = Target
  673. mov eax, [esp+8] ; (eax) = Value
  674. xchg [edx], eax ; make the exchange
  675. else
  676. mov edx, [esp+4] ; (edx) = Target
  677. mov ecx, [esp+8] ; (eax) = Value
  678. pushfd
  679. cli
  680. mov eax, [edx] ; get current value
  681. mov [edx], ecx ; store new value
  682. popfd
  683. endif
  684. stdRET _ExInterlockedExchangeUlong
  685. stdENDP _ExInterlockedExchangeUlong
  686. page , 132
  687. subttl "Interlocked i386 Increment Long"
  688. ;++
  689. ;
  690. ; INTERLOCKED_RESULT
  691. ; Exi386InterlockedIncrementLong (
  692. ; IN PLONG Addend
  693. ; )
  694. ;
  695. ; Routine Description:
  696. ;
  697. ; This function atomically increments Addend, returning an ennumerated
  698. ; type which indicates what interesting transitions in the value of
  699. ; Addend occurred due the operation.
  700. ;
  701. ; See ExInterlockedIncrementLong. This function is the i386
  702. ; architectural specific version of ExInterlockedIncrementLong.
  703. ; No source directly calls this function, instead
  704. ; ExInterlockedIncrementLong is called and when built on x86 these
  705. ; calls are macroed to the i386 optimized version.
  706. ;
  707. ; Arguments:
  708. ;
  709. ; Addend (esp+4) - Pointer to variable to increment.
  710. ;
  711. ; Lock (esp+8) - Spinlock used to implement atomicity.
  712. ; (not actually used on x86)
  713. ;
  714. ; Return Value:
  715. ;
  716. ; An ennumerated type:
  717. ;
  718. ; ResultNegative if Addend is < 0 after increment.
  719. ; ResultZero if Addend is = 0 after increment.
  720. ; ResultPositive if Addend is > 0 after increment.
  721. ;
  722. ;--
  723. cPublicProc _Exi386InterlockedIncrementLong , 1
  724. cPublicFpo 1, 0
  725. mov eax, [esp+4] ; (eax) -> addend
  726. ifdef NT_UP
  727. add dword ptr [eax],1
  728. else
  729. lock add dword ptr [eax],1
  730. endif
  731. lahf ; (ah) = flags
  732. and eax,EFLAG_SELECT ; clear all but sign and zero flags
  733. stdRET _Exi386InterlockedIncrementLong
  734. stdENDP _Exi386InterlockedIncrementLong
  735. page , 132
  736. subttl "Interlocked i386 Decrement Long"
  737. ;++
  738. ;
  739. ; INTERLOCKED_RESULT
  740. ; ExInterlockedDecrementLong (
  741. ; IN PLONG Addend,
  742. ; IN PKSPIN_LOCK Lock
  743. ; )
  744. ;
  745. ; Routine Description:
  746. ;
  747. ; This function atomically decrements Addend, returning an ennumerated
  748. ; type which indicates what interesting transitions in the value of
  749. ; Addend occurred due the operation.
  750. ;
  751. ; See Exi386InterlockedDecrementLong. This function is the i386
  752. ; architectural specific version of ExInterlockedDecrementLong.
  753. ; No source directly calls this function, instead
  754. ; ExInterlockedDecrementLong is called and when built on x86 these
  755. ; calls are macroed to the i386 optimized version.
  756. ;
  757. ; Arguments:
  758. ;
  759. ; Addend (esp+4) - Pointer to variable to decrement.
  760. ;
  761. ; Lock (esp+8) - Spinlock used to implement atomicity.
  762. ; (not actually used on x86)
  763. ;
  764. ; Return Value:
  765. ;
  766. ; An ennumerated type:
  767. ;
  768. ; ResultNegative if Addend is < 0 after decrement.
  769. ; ResultZero if Addend is = 0 after decrement.
  770. ; ResultPositive if Addend is > 0 after decrement.
  771. ;
  772. ;--
  773. cPublicProc _Exi386InterlockedDecrementLong , 1
  774. cPublicFpo 1, 0
  775. mov eax, [esp+4] ; (eax) -> addend
  776. ifdef NT_UP
  777. sub dword ptr [eax], 1
  778. else
  779. lock sub dword ptr [eax], 1
  780. endif
  781. lahf ; (ah) = flags
  782. and eax, EFLAG_SELECT ; clear all but sign and zero flags
  783. stdRET _Exi386InterlockedDecrementLong
  784. stdENDP _Exi386InterlockedDecrementLong
  785. page , 132
  786. subttl "Interlocked i386 Exchange Ulong"
  787. ;++
  788. ;
  789. ; ULONG
  790. ; Exi386InterlockedExchangeUlong (
  791. ; IN PULONG Target,
  792. ; IN ULONG Value,
  793. ; IN PKSPIN_LOCK Lock
  794. ; )
  795. ;
  796. ; Routine Description:
  797. ;
  798. ; This function atomically exchanges the Target and Value, returning
  799. ; the prior contents of Target
  800. ;
  801. ; See Exi386InterlockedExchangeUlong. This function is the i386
  802. ; architectural specific version of ExInterlockedDecrementLong.
  803. ; No source directly calls this function, instead
  804. ; ExInterlockedDecrementLong is called and when built on x86 these
  805. ; calls are macroed to the i386 optimized version.
  806. ;
  807. ; Arguments:
  808. ;
  809. ; Source - Address of ULONG to exchange
  810. ; Value - New value of ULONG
  811. ; Lock - SpinLock used to implement atomicity.
  812. ;
  813. ; Return Value:
  814. ;
  815. ; The prior value of Source
  816. ;--
  817. cPublicProc _Exi386InterlockedExchangeUlong, 2
  818. cPublicFpo 2,0
  819. ifndef NT_UP
  820. mov edx, [esp+4] ; (edx) = Target
  821. mov eax, [esp+8] ; (eax) = Value
  822. xchg [edx], eax ; make the exchange
  823. else
  824. mov edx, [esp+4] ; (edx) = Target
  825. mov ecx, [esp+8] ; (eax) = Value
  826. pushfd
  827. cli
  828. mov eax, [edx] ; get current value
  829. mov [edx], ecx ; store new value
  830. popfd
  831. endif
  832. stdRET _Exi386InterlockedExchangeUlong
  833. stdENDP _Exi386InterlockedExchangeUlong
  834. _TEXT$00 ends
  835. end