https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f4d4b31c61eadcb5916a929626aacc229c249083

commit f4d4b31c61eadcb5916a929626aacc229c249083
Author:     Timo Kreuzer <[email protected]>
AuthorDate: Mon Aug 8 09:26:39 2022 +0200
Commit:     Timo Kreuzer <[email protected]>
CommitDate: Thu Nov 24 21:17:58 2022 +0200

    [RTL] Implement x64 version of RtlInterlockedPushListSList
---
 sdk/lib/rtl/slist.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 72 insertions(+), 3 deletions(-)

diff --git a/sdk/lib/rtl/slist.c b/sdk/lib/rtl/slist.c
index 88ea519ef0a..b4625f15838 100644
--- a/sdk/lib/rtl/slist.c
+++ b/sdk/lib/rtl/slist.c
@@ -104,9 +104,78 @@ RtlInterlockedPushListSList(
     _In_ ULONG Count)
 {
 #ifdef _WIN64
-    UNIMPLEMENTED;
-    DbgBreakPoint();
-    return NULL;
+    SLIST_HEADER OldSListHead, NewSListHead;
+    PSLIST_ENTRY FirstEntry;
+
+    ASSERT(((ULONG_PTR)SListHead & 0xF) == 0);
+    ASSERT(((ULONG_PTR)List & 0xF) == 0);
+
+    if (RtlpUse16ByteSLists)
+    {
+         BOOLEAN exchanged;
+
+        do
+        {
+            /* Capture the current SListHead */
+            OldSListHead = *SListHead;
+
+            /* Link the last list entry */
+            FirstEntry = (PSLIST_ENTRY)(SListHead->Region & ~0xFLL);
+            ListEnd->Next = FirstEntry;
+
+            /* Set up new SListHead */
+            NewSListHead = OldSListHead;
+            NewSListHead.Header16.Depth += Count;
+            NewSListHead.Header16.Sequence++;
+            NewSListHead.Region = (ULONG64)List;
+            NewSListHead.Header16.HeaderType = 1;
+            NewSListHead.Header16.Init = 1;
+
+            /* Atomically exchange the SlistHead with the new one */
+            exchanged = _InterlockedCompareExchange128((PULONG64)SListHead,
+                                                       NewSListHead.Region,
+                                                       NewSListHead.Alignment,
+                                                       
(PULONG64)&OldSListHead);
+        } while (!exchanged);
+
+        return FirstEntry;
+    }
+    else
+    {
+        ULONG64 Compare;
+
+        /* ListHead and List must be in the same region */
+        ASSERT(((ULONG64)SListHead & 0xFFFFF80000000000ull) ==
+               ((ULONG64)List & 0xFFFFF80000000000ull));
+
+        /* Read the header */
+        OldSListHead = *SListHead;
+
+        do
+        {
+            /* Construct the address from the header bits and the list head 
pointer */
+            FirstEntry = (PSLIST_ENTRY)((OldSListHead.Header8.NextEntry << 4) |
+                                        ((ULONG64)SListHead & 
0xFFFFF80000000000ull));
+
+            /* Link the last list entry */
+            ListEnd->Next = FirstEntry;
+
+            /* Create a new header */
+            NewSListHead = OldSListHead;
+            NewSListHead.Header8.NextEntry = (ULONG64)List >> 4;
+            NewSListHead.Header8.Depth += Count;
+            NewSListHead.Header8.Sequence++;
+
+            /* Try to exchange atomically */
+            Compare = OldSListHead.Alignment;
+            OldSListHead.Alignment = 
InterlockedCompareExchange64((PLONG64)&SListHead->Alignment,
+                                                                  
NewSListHead.Alignment,
+                                                                  Compare);
+        } while (OldSListHead.Alignment != Compare);
+
+        /* Return the old first entry */
+        return FirstEntry;
+    }
 #else
     SLIST_HEADER OldHeader, NewHeader;
     ULONGLONG Compare;

Reply via email to