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.

439 lines
13 KiB

  1. title "Interlocked Support"
  2. ;++
  3. ;
  4. ; Copyright (c) 2000 Microsoft Corporation
  5. ;
  6. ; Module Name:
  7. ;
  8. ; slist.asm
  9. ;
  10. ; Abstract:
  11. ;
  12. ; This module implements functions to support interlocked S-List
  13. ; operations.
  14. ;
  15. ; Author:
  16. ;
  17. ; David N. Cutler (davec) 23-Jun-2000
  18. ;
  19. ; Environment:
  20. ;
  21. ; Any mode.
  22. ;
  23. ;--
  24. include ksamd64.inc
  25. altentry ExpInterlockedFlushSList
  26. altentry ExpInterlockedPopEntrySList
  27. altentry ExpInterlockedPopEntrySListEnd
  28. altentry ExpInterlockedPopEntrySListFault
  29. altentry ExpInterlockedPopEntrySListResume
  30. altentry ExpInterlockedPushEntrySList
  31. subttl "First Entry SList"
  32. ;++
  33. ;
  34. ; PSINGLE_LIST_ENTRY
  35. ; FirstEntrySList (
  36. ; IN PSLIST_HEADER SListHead
  37. ; )
  38. ;
  39. ; Routine Description:
  40. ;
  41. ; This function returns the address of the fisrt entry in the SLIST or
  42. ; NULL.
  43. ;
  44. ; Arguments:
  45. ;
  46. ; ListHead (rcx) - Supplies a pointer to the sequenced listhead from
  47. ; which the first entry address is to be computed.
  48. ;
  49. ; Return Value:
  50. ;
  51. ; The address of the first entry is the specified, or NULL if the list is
  52. ; empty.
  53. ;
  54. ;--
  55. LEAF_ENTRY FirstEntrySList, _TEXT$00
  56. mov rax, [rcx] ; get address, sequence, and depth
  57. and rax, 0fe000000H ; isolate packed address
  58. ;
  59. ; The following code takes advantage of the fact that the high order bit
  60. ; for user mode addresses is zero and for system addresses is one.
  61. ;
  62. ifdef NTOS_KERNEL_RUNTIME
  63. cmp rax, 1 ; set carry if address is zero
  64. cmc ; set carry if address is not zero
  65. rcr rax, 1 ; rotate carry into high bit
  66. sar rax, 63 - 43 ; extract first entry address
  67. else
  68. shr rax, 63 - 42 ; extract first entry address
  69. endif
  70. ret ; return
  71. LEAF_END FirstEntrySList, _TEXT$00
  72. subttl "Interlocked Pop Entry Sequenced List"
  73. ;++
  74. ;
  75. ; PSINGLE_LIST_ENTRY
  76. ; RtlpInterlockedPopEntrySList (
  77. ; IN PSINGLE_LIST_ENTRY ListHead
  78. ; )
  79. ;
  80. ; Routine Description:
  81. ;
  82. ; This function removes an entry from the front of a sequenced singly
  83. ; linked list so that access to the list is synchronized in an MP system.
  84. ; If there are no entries in the list, then a value of NULL is returned.
  85. ; Otherwise, the address of the entry that is removed is returned as the
  86. ; function value.
  87. ;
  88. ; Arguments:
  89. ;
  90. ; ListHead (rcx) - Supplies a pointer to the sequenced listhead from
  91. ; which an entry is to be removed.
  92. ;
  93. ; Return Value:
  94. ;
  95. ; The address of the entry removed from the list, or NULL if the list is
  96. ; empty.
  97. ;
  98. ;--
  99. LEAF_ENTRY RtlpInterlockedPopEntrySList, _TEXT$00
  100. ALTERNATE_ENTRY ExpInterlockedPopEntrySList
  101. ;
  102. ; N.B. The following code is the continuation address should a fault occur
  103. ; in the rare case described below.
  104. ;
  105. ALTERNATE_ENTRY ExpInterlockedPopEntrySListResume
  106. mov rax, [rcx] ; get address, sequence, and depth
  107. Pop10: mov rdx, rax ; make a copy
  108. and rdx, 0fe000000H ; isolate packed address
  109. jz short Pop20 ; if z, list is empty
  110. ;
  111. ; The following code takes advantage of the fact that the high order bit
  112. ; for user mode addresses is zero and for system addresses is one.
  113. ;
  114. ifdef NTOS_KERNEL_RUNTIME
  115. or rdx, 01fffffh ; sign-extend resultant address
  116. endif
  117. ror rdx, 63 - 42 ; extract next entry address
  118. ;
  119. ; N.B. It is possible for the following instruction to fault in the rare
  120. ; case where the first entry in the list is allocated on another
  121. ; processor and free between the time the free pointer is read above
  122. ; and the following instruction. When this happens, the access fault
  123. ; code continues execution by skipping the following instruction.
  124. ; This results in the compare failing and the entire operation is
  125. ; retried.
  126. ;
  127. ALTERNATE_ENTRY ExpInterlockedPopEntrySListFault
  128. mov r8, [rdx] ; get address of successor entry
  129. shl r8, 63 - 42 ; shift address into position
  130. mov r9, rax ; adjust depth but not sequence
  131. dec r9w ;
  132. and r9, 01ffffffh ; isolate sequence and depth
  133. or r8, r9 ; merge address, sequence, and depth
  134. ALTERNATE_ENTRY ExpInterlockedPopEntrySListEnd
  135. ifndef NT_UP
  136. lock cmpxchg [rcx], r8 ; compare and exchange
  137. else
  138. cmpxchg [rcx], r8 ; compare and exchange
  139. endif
  140. jnz short Pop10 ; if nz, exchange failed
  141. Pop20: mov rax, rdx ; set address of next entry
  142. ret ;
  143. LEAF_END RtlpInterlockedPopEntrySList, _TEXT$00
  144. subttl "Interlocked Push Entry Sequenced List"
  145. ;++
  146. ;
  147. ; PSINGLE_LIST_ENTRY
  148. ; RtlpInterlockedPushEntrySList (
  149. ; IN PSINGLE_LIST_ENTRY ListHead,
  150. ; IN PSINGLE_LIST_ENTRY ListEntry
  151. ; )
  152. ;
  153. ; Routine Description:
  154. ;
  155. ; This function inserts an entry at the head of a sequenced singly linked
  156. ; list so that access to the list is synchronized in an MP system.
  157. ;
  158. ; Arguments:
  159. ;
  160. ; ListHead (rcx) - Supplies a pointer to the sequenced listhead into which
  161. ; an entry is to be inserted.
  162. ;
  163. ; ListEntry (rdx) - Supplies a pointer to the entry to be inserted at the
  164. ; head of the list.
  165. ;
  166. ; Return Value:
  167. ;
  168. ; Previous contents of list head. NULL implies list went from empty to not
  169. ; empty.
  170. ;
  171. ;--
  172. LEAF_ENTRY RtlpInterlockedPushEntrySList, _TEXT$00
  173. ALTERNATE_ENTRY ExpInterlockedPushEntrySList
  174. mov r9, rdx ; make copy of list entry pointer
  175. shl r9, 63 - 42 ; shift address into position
  176. mov rax, [rcx] ; get address, sequence, and depth
  177. if DBG
  178. test dl, 0fh ; test if entry 16-byte aligned
  179. jz short Push10 ; if z, entry is 16-byte aligned
  180. int 3 ; break into debugger
  181. endif
  182. Push10: mov r8, rax ; make copy
  183. and r8, 0fe000000h ; isolate packed address
  184. ;
  185. ; The following code takes advantage of the fact that the high order bit
  186. ; for user mode addresses is zero and for system addresses is one.
  187. ;
  188. ifdef NTOS_KERNEL_RUNTIME
  189. cmp r8, 1 ; set carry if address is zero
  190. cmc ; set carry if address is not zero
  191. rcr r8, 1 ; rotate carry into high bit
  192. sar r8, 63 - 43 ; extract next entry address
  193. else
  194. shr r8, 63 - 42 ; extract next entry address
  195. endif
  196. mov [rdx], r8 ; set next entry to previous first
  197. mov r10, rax ;
  198. inc r10w ; increment depth field
  199. add r10d, 010000h ; increment sequence field
  200. and r10, 01ffffffh ; isolate sequence and depth
  201. or r10, r9 ; merge address, sequence, and depth
  202. ifndef NT_UP
  203. lock cmpxchg [rcx], r10 ; compare and exchange
  204. else
  205. cmpxchg [rcx], r10 ; compare and exchange
  206. endif
  207. jnz short Push10 ; if nz, exchange failed
  208. mov rax, r8 ; set address of first entry
  209. ret ; return
  210. LEAF_END RtlpInterlockedPushEntrySList, _TEXT$00
  211. subttl "Interlocked Flush Sequenced List"
  212. ;++
  213. ;
  214. ; PSINGLE_LIST_ENTRY
  215. ; RtlpInterlockedFlushSList (
  216. ; IN PSINGLE_LIST_ENTRY ListHead
  217. ; )
  218. ;
  219. ; Routine Description:
  220. ;
  221. ; This function removes the entire list from a sequenced singly
  222. ; linked list so that access to the list is synchronized in an MP system.
  223. ; If there are no entries in the list, then a value of NULL is returned.
  224. ; Otherwise, the address of the entry at the top of the list is removed
  225. ; and returned as the function value and the list header is set to point
  226. ; to NULL.
  227. ;
  228. ; Arguments:
  229. ;
  230. ; ListHead (rcx) - Supplies a pointer to the sequenced listhead from
  231. ; which the list is to be flushed.
  232. ;
  233. ; Return Value:
  234. ;
  235. ; The address of the entire current list, or NULL if the list is
  236. ; empty.
  237. ;
  238. ;--
  239. LEAF_ENTRY RtlpInterlockedFlushSList, _TEXT$00
  240. ALTERNATE_ENTRY ExpInterlockedFlushSList
  241. mov rax, [rcx] ; get address, sequence, and depth
  242. Fl10: mov rdx, rax ; make copy
  243. and rdx, 0fe000000h ; isolate packed address
  244. jz short Fl20 ; if z, list is empty
  245. ;
  246. ; The following code takes advantage of the fact that the high order bit
  247. ; for user mode addresses is zero and for system addresses is one.
  248. ;
  249. ifdef NTOS_KERNEL_RUNTIME
  250. or rdx, 01fffffh ; sign-extend resultant address
  251. endif
  252. ror rdx, 63 - 42 ; extract next entry address
  253. mov r8, rax ; isolate sequence number
  254. and r8, 01ff0000h ;
  255. ifndef NT_UP
  256. lock cmpxchg [rcx], r8 ; compare and exchange
  257. else
  258. cmpxchg [rcx], r8 ; compare and exchange
  259. endif
  260. jnz short Fl10 ; if nz, exchange failed
  261. Fl20: mov rax, rdx ; set address of first entry
  262. ret ; return
  263. LEAF_END RtlpInterlockedFlushSList, _TEXT$00
  264. subttl "Interlocked Push List Sequenced List"
  265. ;++
  266. ;
  267. ; PSINGLE_LIST_ENTRY
  268. ; InterlockedPushListSList (
  269. ; IN PSLIST_HEADER ListHead,
  270. ; IN PSINGLE_LIST_ENTRY List,
  271. ; IN PSINGLE_LIST_ENTRY ListEnd,
  272. ; IN ULONG Count
  273. ; )
  274. ;
  275. ; Routine Description:
  276. ;
  277. ; This function pushes the specified singly linked list onto the front of
  278. ; a sequenced list.
  279. ;
  280. ; Arguments:
  281. ;
  282. ; ListHead (rcx) - Supplies a pointer to the sequenced listhead into which
  283. ; the specified list is inserted.
  284. ;
  285. ; List (rdx) - Supplies a pointer to the first entry in the list to be
  286. ; pushed onto the front of the specified sequenced list.
  287. ;
  288. ; ListEnd (r8) - Supplies a pointer to the last entry in the list to be
  289. ; pushed onto the front of the specified sequence list.
  290. ;
  291. ; Count (r9) - Supplies the number of entries in the list.
  292. ;
  293. ; Return Value:
  294. ;
  295. ; Previous contents of list head. NULL implies list went from empty to not
  296. ; empty.
  297. ;
  298. ;--
  299. NESTED_ENTRY InterlockedPushListSList, _TEX$00
  300. push_reg rsi ; save nonvolatile register
  301. END_PROLOGUE
  302. mov rax, [rcx] ; get address, sequence, and depth
  303. if DBG
  304. test dl, 0fh ; test if entry 16-byte aligned
  305. jnz short Pshl10 ; if nz, entry not 16-byte aligned
  306. test r8b, 0fh ; test if entry 16-byte aligned
  307. jz short Pshl20 ; if z, entry is 16-byte aligned
  308. Pshl10: int 3 ; break into debugger
  309. endif
  310. Pshl20: shl rdx, 63 - 42 ; shift first address into position
  311. Pshl30: mov r10, rax ; make a copy
  312. and r10, 0fe000000H ; isolate packed address
  313. ;
  314. ; The following code takes advantage of the fact that the high order bit
  315. ; for user mode addresses is zero and for system addresses is one.
  316. ;
  317. ifdef NTOS_KERNEL_RUNTIME
  318. cmp r10, 1 ; set carry if address is zero
  319. cmc ; set carry if address is not zero
  320. rcr r10, 1 ; rotate carry into high bit
  321. sar r10, 63 - 43 ; extract next entry address
  322. else
  323. shr r10, 63 - 42 ; extract next entry address
  324. endif
  325. mov [r8], r10 ; link old first to last in list
  326. lea r11d, [rax][r9] ; add length of list to depth
  327. and r11d, 0ffffh ; wrap depth if overlfow
  328. lea esi, 010000h[rax] ; increment sequence
  329. and esi, 01ff0000h ; wrap sequence if overflow
  330. or rsi, r11 ; merge address, sequence, and depth
  331. or rsi, rdx ;
  332. ifndef NT_UP
  333. lock cmpxchg [rcx], rsi ; compare and exchange
  334. else
  335. cmpxchg [rcx], rsi ; compare and exchange
  336. endif
  337. jnz short Pshl30 ; if nz, exchange failed
  338. mov rax, r10 ; set address of first entry
  339. pop rsi ; restore volatile register
  340. ret ; return
  341. NESTED_END InterlockedPushListSList, _TEX$00
  342. end