2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/rtl/amd64/interlck.S
5 * PURPOSE: Rtl Interlocked Functions for amd64
6 * PROGRAMMERS: Timo Kreuzer
10 #include <ksamd64.inc>
13 typedef union DECLSPEC_ALIGN(16) _SLIST_HEADER
24 ULONGLONG NextEntry:39;
25 ULONGLONG HeaderType:1;
27 ULONGLONG Reserved:59;
33 ULONGLONG Sequence:48;
34 ULONGLONG HeaderType:1;
37 ULONGLONG NextEntry:60;
42 ULONGLONG Sequence:48;
43 ULONGLONG HeaderType:1;
45 ULONGLONG NextEntry:60;
47 } SLIST_HEADER, *PSLIST_HEADER;
50 #define SLIST8A_DEPTH_MASK HEX(000000000000FFFF)
51 #define SLIST8A_DEPTH_INC HEX(0000000000000001)
52 #define SLIST8A_SEQUENCE_MASK HEX(0000000001FF0000)
53 #define SLIST8A_SEQUENCE_INC HEX(0000000000010000)
54 #define SLIST8A_NEXTENTRY_MASK HEX(FFFFFFFFFE000000)
55 #define SLIST8A_NEXTENTRY_SHIFT 21
56 #define SLIST8B_HEADERTYPE_MASK HEX(0000000000000001)
57 #define SLIST8B_INIT_MASK HEX(0000000000000002)
58 #define SLIST8B_REGION_MASK HEX(E000000000000000)
59 #define SLIST8_POINTER_MASK HEX(000007FFFFFFFFFF)
61 #define SLIST16A_DEPTH_MASK HEX(000000000000FFFF)
62 #define SLIST16A_DEPTH_INC HEX(0000000000000001)
63 #define SLIST16A_SEQUENCE_MASK HEX(FFFFFFFFFFFF0000)
64 #define SLIST16A_SEQUENCE_INC HEX(0000000000010000)
65 #define SLIST16B_HEADERTYPE_MASK HEX(0000000000000001)
66 #define SLIST16B_INIT_MASK HEX(0000000000000002)
67 #define SLIST16B_NEXTENTRY_MASK HEX(FFFFFFFFFFFFFFF0)
70 /* FUNCTIONS ****************************************************************/
74 PUBLIC ExpInterlockedPopEntrySList
75 PUBLIC ExpInterlockedPopEntrySListResume
76 PUBLIC ExpInterlockedPopEntrySListFault
77 PUBLIC ExpInterlockedPopEntrySListEnd
78 PUBLIC ExpInterlockedPopEntrySListResume16
79 PUBLIC ExpInterlockedPopEntrySListFault16
80 PUBLIC ExpInterlockedPopEntrySListEnd16
81 PUBLIC ExpInterlockedPushEntrySList
82 PUBLIC ExpInterlockedFlushSList
84 PUBLIC RtlInterlockedFlushSList
85 PUBLIC RtlInterlockedPopEntrySList
86 PUBLIC RtlInterlockedPushEntrySList
90 * RtlInterlockedPopEntrySList(
91 * IN PSLIST_HEADER ListHead);
93 RtlInterlockedPopEntrySList:
94 ExpInterlockedPopEntrySList:
96 /* Load ListHead->Region into rdx */
99 /* Load ListHead->Alignment into rax */
102 /* Check what kind of header this is */
103 test rdx, SLIST8B_HEADERTYPE_MASK
104 jnz RtlInterlockedPopEntrySList16
106 /* We have an 8 byte header */
108 ExpInterlockedPopEntrySListResume:
110 /* Check if ListHead->NextEntry is NULL */
112 and r9, SLIST8A_NEXTENTRY_MASK
113 jz RtlInterlockedPopEntrySListEmpty
115 /* Copy Depth and Sequence number and adjust Depth */
116 lea r8, [rax - SLIST8A_DEPTH_INC]
117 and r8, (SLIST8A_SEQUENCE_MASK OR SLIST8A_DEPTH_MASK)
119 /* Create a pointer template from rcx in rdx */
120 mov rdx, (NOT SLIST8_POINTER_MASK)
123 /* Shift the NextEntry pointer */
124 shr r9, SLIST8A_NEXTENTRY_SHIFT
126 /* Combine to new pointer in rdx */
129 ExpInterlockedPopEntrySListFault:
131 /* Load the next NextEntry pointer to r9 */
134 /* Shift bits in place */
135 shl r9, SLIST8A_NEXTENTRY_SHIFT
137 /* Combine into r8 */
140 ExpInterlockedPopEntrySListEnd:
142 /* If [rcx] equals rax, exchange it with r8 */
143 lock cmpxchg [rcx], r8
145 /* If not equal, retry with rax, being the content of [rcx] now */
146 jne ExpInterlockedPopEntrySListResume
148 /* Shift the pointer bits in place */
149 and rax, SLIST8A_NEXTENTRY_MASK
150 shr rax, SLIST8A_NEXTENTRY_SHIFT
152 /* Use rcx as pointer template */
153 mov rdx, (NOT SLIST8_POINTER_MASK)
156 /* Combine result and return */
160 RtlInterlockedPopEntrySListEmpty:
164 RtlInterlockedPopEntrySList16:
165 /* This is a 16 byte header
167 rdx == ListHead->Region
168 rax == ListHead->Alignment */
173 /* Copy rcx to r8, as we need rcx for the exchange */
176 ExpInterlockedPopEntrySListResume16:
178 /* Set r9 = ListHead->NextEntry and check if it is NULL */
180 and r9, SLIST16B_NEXTENTRY_MASK
181 jz RtlInterlockedPopEntrySListEmpty16
183 ExpInterlockedPopEntrySListFault16:
185 /* Set NewListHead.Next = ListHead->NextEntry->Next */
188 /* Set NewListHead.HeaderType = 1 and NewListHead.Init = 1 */
189 or rcx, (SLIST16B_HEADERTYPE_MASK or SLIST16B_INIT_MASK)
191 /* Copy Depth and Sequence number and adjust Depth */
192 lea rbx, [rax - SLIST16A_DEPTH_INC]
194 ExpInterlockedPopEntrySListEnd16:
196 /* If [r8] equals rdx:rax, exchange it with rcx:rbx */
199 /* If not equal, retry with rdx:rax, being the content of [r8] now */
200 jne ExpInterlockedPopEntrySListResume16
202 /* Copy the old NextEntry pointer to rax */
204 and rax, SLIST16B_NEXTENTRY_MASK
210 RtlInterlockedPopEntrySListEmpty16:
218 * RtlInterlockedPushEntrySList(
219 * IN PSLIST_HEADER ListHead,
220 * IN PSLIST_ENTRY ListEntry);
222 RtlInterlockedPushEntrySList:
223 ExpInterlockedPushEntrySList:
226 /* Make sure the ListEntry is 16 bytes aligned */
228 jz ExpInterlockedPushEntrySListChecked
229 /* Not aligned, raise an assertion */
231 ExpInterlockedPushEntrySListChecked:
234 /* Load ListHead->Alignment into rax */
237 /* Load ListHead->Region into r9 */
240 /* Check what kind of header this is */
241 test r9, SLIST8B_HEADERTYPE_MASK
242 jnz RtlInterlockedPushEntrySList16
244 /* We have an 8 byte header */
246 RtlInterlockedPushEntrySListLoop:
248 /* Get ListHead->NextEntry */
250 and r8, SLIST8A_NEXTENTRY_MASK
251 jz RtlInterlockedPushEntrySListEmpty
253 /* Shift the NextEntry pointer */
254 shr r8, SLIST8A_NEXTENTRY_SHIFT
256 /* Create a pointer template from rcx in rdx */
257 mov r9, (NOT SLIST8_POINTER_MASK)
260 /* Combine to new pointer and save as ListEntry->NextEntry */
263 RtlInterlockedPushEntrySListEmpty:
264 /* Store the NextEntry pointer in the new ListEntry */
267 /* Shift and mask the new ListEntry pointer */
269 shl r8, SLIST8A_NEXTENTRY_SHIFT
270 and r8, SLIST8A_NEXTENTRY_MASK
272 /* Copy and adjust depth and sequence number */
273 lea r9, [rax + SLIST8A_DEPTH_INC + SLIST8A_SEQUENCE_INC]
274 and r9, SLIST8A_SEQUENCE_MASK OR SLIST8A_DEPTH_MASK
276 /* Combine to exchange value in r8 */
279 /* Save the NextEntry in r9 */
282 /* If [rcx] equals rax, exchange it with r8 */
283 lock cmpxchg [rcx], r8
285 /* If not equal, retry with rax, being the content of [rcx] now */
286 jne RtlInterlockedPushEntrySListLoop
288 /* Return the old NextEntry pointer */
292 RtlInterlockedPushEntrySList16:
293 /* This is a 16 byte header
296 rax = ListHead->Alignment
297 r9 = ListHead->Region */
302 /* Copy rcx/rdx to r8/r9, as we need rcx/rdx for the exchange */
306 /* Set NewListHead.NextEntry = ListEntry */
309 /* Set NewListHead.HeaderType = 1 and NewListHead.Init = 1 */
310 or rcx, (SLIST16B_HEADERTYPE_MASK or SLIST16B_INIT_MASK)
312 /* Set rdx = ListHead->Region */
315 RtlInterlockedPushEntrySListLoop16:
318 rax = ListHead->Alignment
319 rdx = ListHead->Region
322 /* Move ListHead->NextEntry to rbx */
324 and rbx, SLIST16B_NEXTENTRY_MASK
326 /* Store next pointer in ListEntry->Next */
329 /* Copy and increment Depth and Sequence number to rbx */
330 lea rbx, [rax + SLIST16A_DEPTH_INC + SLIST16A_SEQUENCE_INC]
332 /* If [r8] equals rdx:rax, exchange it with rcx:rbx */
335 /* If not equal, retry with rdx:rax, being the content of [r8] now */
336 jne RtlInterlockedPushEntrySListLoop16
338 /* Copy the old NextEntry pointer to rax */
340 and rax, SLIST16B_NEXTENTRY_MASK
349 * RtlInterlockedFlushSList(
350 * IN PSLIST_HEADER ListHead);
352 RtlInterlockedFlushSList:
353 ExpInterlockedFlushSList:
355 /* Load ListHead->Region into rdx */
358 /* Load ListHead->Alignment into rax */
361 /* Check what kind of header this is */
362 test rdx, SLIST8B_HEADERTYPE_MASK
363 jnz RtlInterlockedFlushSList16
365 /* We have an 8 byte header */
367 RtlInterlockedFlushSListLoop:
369 /* Zero NewListHead.Alignment */
372 /* If [rcx] equals rax, exchange it with r8 */
373 lock cmpxchg [rcx], r8
375 /* If not equal, retry with rax, being the content of [rcx] now */
376 jne RtlInterlockedFlushSListLoop
378 /* Create a pointer template from rcx in rdx */
379 mov rdx, (NOT SLIST8_POINTER_MASK)
382 /* Load the old NextEntry pointer into rax */
383 and rax, SLIST8A_NEXTENTRY_MASK
384 shr rax, SLIST8A_NEXTENTRY_SHIFT
386 /* Combine result and return */
390 RtlInterlockedFlushSList16:
391 /* We have a 16 byte header
393 rax = ListHead->Alignment
394 rdx = ListHead->Region
400 /* Load ListHead into r8, as we need rcx for the exchange */
403 /* Initialize an ampty NewListHead in rcx:rbx */
405 mov rcx, (SLIST16B_HEADERTYPE_MASK or SLIST16B_INIT_MASK)
407 RtlInterlockedFlushSListLoop16:
409 /* If [r8] equals rdx:rax, exchange it with rcx:rbx */
412 /* If not equal, retry with rdx:rax, being the content of [r8] now */
413 jne RtlInterlockedFlushSListLoop16
415 /* Copy the old NextEntry pointer to rax */
417 and rax, SLIST16B_NEXTENTRY_MASK