https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f4d4b31c61eadcb5916a92...
commit f4d4b31c61eadcb5916a929626aacc229c249083 Author: Timo Kreuzer timo.kreuzer@reactos.org AuthorDate: Mon Aug 8 09:26:39 2022 +0200 Commit: Timo Kreuzer timo.kreuzer@reactos.org 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;