ntdll: Slist support.

Implemented ntdll's RtlInitializeSListHead, RtlQueryDepthSList,
RtlInterlockedFlushSList, RtlFirstEntrySList,
RtlInterlockedPushEntrySList, RtlInterlockedPopEntrySList, their
kernel32 equivalents, and tests.
oldstable
Damjan Jovanovic 2007-02-02 16:41:15 +02:00 committed by Alexandre Julliard
parent 7e7ff40769
commit 07db8882c2
4 changed files with 236 additions and 12 deletions

View File

@ -706,15 +706,15 @@
@ stdcall InitAtomTable(long)
@ stdcall InitializeCriticalSection(ptr)
@ stdcall InitializeCriticalSectionAndSpinCount(ptr long)
# @ stub InitializeSListHead ( -> ntdll.RtlInitializeSListHead)
@ stdcall InitializeSListHead(ptr) ntdll.RtlInitializeSListHead
@ stdcall InterlockedCompareExchange (ptr long long)
@ stdcall InterlockedDecrement(ptr)
@ stdcall InterlockedExchange(ptr long)
@ stdcall InterlockedExchangeAdd (ptr long )
# @ stub InterlockedFlushSList ( -> ntdll.RtlInterlockedFlushSList)
@ stdcall InterlockedFlushSList(ptr) ntdll.RtlInterlockedFlushSList
@ stdcall InterlockedIncrement(ptr)
# @ stub InterlockedPopEntrySList ( -> ntdll.RtlInterlockedPopEntrySList)
# @ stub InterlockedPushEntrySList ( -> ntdll.RtlInterlockedPushEntrySList)
@ stdcall InterlockedPopEntrySList(ptr) ntdll.RtlInterlockedPopEntrySList
@ stdcall InterlockedPushEntrySList(ptr ptr) ntdll.RtlInterlockedPushEntrySList
@ stub InvalidateConsoleDIBits
@ stdcall InvalidateNLSCache()
@ stdcall IsBadCodePtr(ptr)
@ -843,7 +843,7 @@
@ stdcall PurgeComm(long long)
@ stdcall -i386 -register QT_Thunk()
@ stdcall QueryActCtxW(long ptr ptr long ptr long ptr)
# @ stub QueryDepthSList ( -> ntdll.RtlQueryDepthSList)
@ stdcall QueryDepthSList(ptr) ntdll.RtlQueryDepthSList
@ stdcall QueryDosDeviceA(str ptr long)
@ stdcall QueryDosDeviceW(wstr ptr long)
@ stub QueryInformationJobObject

View File

@ -152,8 +152,102 @@ static void test_mutex(void)
CloseHandle(hCreated);
}
static void test_slist(void)
{
struct item
{
SLIST_ENTRY entry;
int value;
} item1, item2, item3, *pitem;
SLIST_HEADER slist_header, test_header;
PSLIST_ENTRY entry;
USHORT size;
VOID (WINAPI *pInitializeSListHead)(PSLIST_HEADER);
USHORT (WINAPI *pQueryDepthSList)(PSLIST_HEADER);
PSLIST_ENTRY (WINAPI *pInterlockedFlushSList)(PSLIST_HEADER);
PSLIST_ENTRY (WINAPI *pInterlockedPopEntrySList)(PSLIST_HEADER);
PSLIST_ENTRY (WINAPI *pInterlockedPushEntrySList)(PSLIST_HEADER,PSLIST_ENTRY);
HMODULE kernel32;
kernel32 = GetModuleHandle("KERNEL32.DLL");
pInitializeSListHead = (void*) GetProcAddress(kernel32, "InitializeSListHead");
pQueryDepthSList = (void*) GetProcAddress(kernel32, "QueryDepthSList");
pInterlockedFlushSList = (void*) GetProcAddress(kernel32, "InterlockedFlushSList");
pInterlockedPopEntrySList = (void*) GetProcAddress(kernel32, "InterlockedPopEntrySList");
pInterlockedPushEntrySList = (void*) GetProcAddress(kernel32, "InterlockedPushEntrySList");
if (pInitializeSListHead == NULL ||
pQueryDepthSList == NULL ||
pInterlockedFlushSList == NULL ||
pInterlockedPopEntrySList == NULL ||
pInterlockedPushEntrySList == NULL)
{
skip("some required slist entrypoints were not found, skipping tests\n");
return;
}
memset(&test_header, 0, sizeof(test_header));
memset(&slist_header, 0xFF, sizeof(slist_header));
pInitializeSListHead(&slist_header);
ok(memcmp(&test_header, &slist_header, sizeof(SLIST_HEADER)) == 0,
"InitializeSListHead didn't zero-fill list header");
size = pQueryDepthSList(&slist_header);
ok(size == 0, "initially created slist has size %d, expected 0\n", size);
item1.value = 1;
ok(pInterlockedPushEntrySList(&slist_header, &item1.entry) == NULL,
"previous entry in empty slist wasn't NULL\n");
size = pQueryDepthSList(&slist_header);
ok(size == 1, "slist with 1 item has size %d\n", size);
item2.value = 2;
entry = pInterlockedPushEntrySList(&slist_header, &item2.entry);
ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
if (entry != NULL)
{
pitem = (struct item*) entry;
ok(pitem->value == 1, "previous entry in slist wasn't the one added\n");
}
size = pQueryDepthSList(&slist_header);
ok(size == 2, "slist with 2 items has size %d\n", size);
item3.value = 3;
entry = pInterlockedPushEntrySList(&slist_header, &item3.entry);
ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
if (entry != NULL)
{
pitem = (struct item*) entry;
ok(pitem->value == 2, "previous entry in slist wasn't the one added\n");
}
size = pQueryDepthSList(&slist_header);
ok(size == 3, "slist with 3 items has size %d\n", size);
entry = pInterlockedPopEntrySList(&slist_header);
ok(entry != NULL, "entry shouldn't be NULL\n");
if (entry != NULL)
{
pitem = (struct item*) entry;
ok(pitem->value == 3, "unexpected entry removed\n");
}
size = pQueryDepthSList(&slist_header);
ok(size == 2, "slist with 2 items has size %d\n", size);
entry = pInterlockedFlushSList(&slist_header);
size = pQueryDepthSList(&slist_header);
ok(size == 0, "flushed slist should be empty, size is %d\n", size);
if (size == 0)
{
ok(pInterlockedPopEntrySList(&slist_header) == NULL,
"popping empty slist didn't return NULL\n");
}
ok(((struct item*)entry)->value == 2, "item 2 not in front of list\n");
ok(((struct item*)entry->Next)->value == 1, "item 1 not at the back of list\n");
}
START_TEST(sync)
{
test_signalandwait();
test_mutex();
test_slist();
}

View File

@ -592,7 +592,7 @@
@ stdcall RtlFindSetBits(ptr long long)
@ stdcall RtlFindSetBitsAndClear(ptr long long)
@ stdcall RtlFindSetRuns(ptr ptr long long)
@ stub RtlFirstEntrySList
@ stdcall RtlFirstEntrySList(ptr)
@ stdcall RtlFirstFreeAce(ptr ptr)
@ stub RtlFlushPropertySet
# @ stub RtlFlushSecureMemoryCache
@ -670,7 +670,7 @@
@ stub RtlInitializeRXact
# @ stub RtlInitializeRangeList
@ stdcall RtlInitializeResource(ptr)
# @ stub RtlInitializeSListHead
@ stdcall RtlInitializeSListHead(ptr)
@ stdcall RtlInitializeSid(ptr ptr long)
# @ stub RtlInitializeStackTraceDataBase
@ stub RtlInsertElementGenericTable
@ -678,10 +678,10 @@
@ stdcall RtlInt64ToUnicodeString(double long ptr)
@ stdcall RtlIntegerToChar(long long long ptr)
@ stdcall RtlIntegerToUnicodeString(long long ptr)
# @ stub RtlInterlockedFlushSList
# @ stub RtlInterlockedPopEntrySList
# @ stub RtlInterlockedPushEntrySList
# @ stub RtlInterlockedPushListSList
@ stdcall RtlInterlockedFlushSList(ptr)
@ stdcall RtlInterlockedPopEntrySList(ptr)
@ stdcall RtlInterlockedPushEntrySList(ptr ptr)
@ stdcall RtlInterlockedPushListSList(ptr ptr ptr long)
# @ stub RtlInvertRangeList
# @ stub RtlIpv4AddressToStringA
# @ stub RtlIpv4AddressToStringExA
@ -763,7 +763,7 @@
@ stub RtlProtectHeap
# @ stub RtlPushFrame
@ stdcall RtlQueryAtomInAtomTable(ptr long ptr ptr ptr ptr)
@ stub RtlQueryDepthSList
@ stdcall RtlQueryDepthSList(ptr)
@ stdcall RtlQueryEnvironmentVariable_U(ptr ptr ptr)
@ stub RtlQueryHeapInformation
@ stdcall RtlQueryInformationAcl(ptr ptr long long)

View File

@ -35,6 +35,7 @@
#include "windef.h"
#include "winternl.h"
#include "wine/debug.h"
#include "wine/exception.h"
#include "ntdll_misc.h"
WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
@ -922,3 +923,132 @@ PVOID WINAPI RtlDecodePointer( PVOID ptr )
DWORD_PTR ptrval = (DWORD_PTR) ptr;
return (PVOID)(ptrval ^ get_pointer_obfuscator());
}
VOID WINAPI RtlInitializeSListHead(volatile PSLIST_HEADER ListHeader)
{
TRACE("(%p)\n", ListHeader);
#if _WIN64
assert(0);
#else
ListHeader->Alignment = 0;
#endif
}
USHORT WINAPI RtlQueryDepthSList(volatile PSLIST_HEADER ListHeader)
{
TRACE("(%p)\n", ListHeader);
#if _WIN64
assert(0);
#else
return ListHeader->Depth;
#endif
}
PSLIST_ENTRY WINAPI RtlFirstEntrySList(volatile PSLIST_HEADER ListHeader)
{
TRACE("(%p)\n", ListHeader);
#if _WIN64
assert(0);
#else
return ListHeader->Next.Next;
#endif
}
PSLIST_ENTRY WINAPI RtlInterlockedFlushSList(volatile PSLIST_HEADER ListHeader)
{
SLIST_HEADER oldHeader, newHeader;
TRACE("(%p)\n", ListHeader);
#if _WIN64
assert(0);
#else
if (ListHeader->Depth == 0)
return NULL;
newHeader.Alignment = 0;
do
{
oldHeader = *ListHeader;
newHeader.Sequence = ListHeader->Sequence + 1;
} while (interlocked_cmpxchg64((__int64*)&ListHeader->Alignment,
newHeader.Alignment,
oldHeader.Alignment) != oldHeader.Alignment);
return oldHeader.Next.Next;
#endif
}
PSLIST_ENTRY WINAPI RtlInterlockedPushEntrySList(volatile PSLIST_HEADER ListHeader,
PSLIST_ENTRY ListEntry)
{
SLIST_HEADER oldHeader, newHeader;
TRACE("(%p, %p)\n", ListHeader, ListEntry);
#if _WIN64
assert(0);
#else
newHeader.Next.Next = ListEntry;
do
{
oldHeader = *ListHeader;
ListEntry->Next = ListHeader->Next.Next;
newHeader.Depth = ListHeader->Depth + 1;
newHeader.Sequence = ListHeader->Sequence + 1;
} while (interlocked_cmpxchg64((__int64*)&ListHeader->Alignment,
newHeader.Alignment,
oldHeader.Alignment) != oldHeader.Alignment);
return oldHeader.Next.Next;
#endif
}
PSLIST_ENTRY WINAPI RtlInterlockedPopEntrySList(volatile PSLIST_HEADER ListHeader)
{
SLIST_HEADER oldHeader, newHeader;
PSLIST_ENTRY entry;
TRACE("(%p)\n", ListHeader);
#if _WIN64
assert(0);
#else
do
{
oldHeader = *ListHeader;
entry = ListHeader->Next.Next;
if (entry == NULL)
return NULL;
/* entry could be deleted by another thread */
__TRY
{
newHeader.Next.Next = entry->Next;
newHeader.Depth = ListHeader->Depth - 1;
newHeader.Sequence = ListHeader->Sequence + 1;
}
__EXCEPT_PAGE_FAULT
{
}
__ENDTRY
} while (interlocked_cmpxchg64((__int64*)&ListHeader->Alignment,
newHeader.Alignment,
oldHeader.Alignment) != oldHeader.Alignment);
return entry;
#endif
}
PSLIST_ENTRY WINAPI RtlInterlockedPushListSList(volatile PSLIST_HEADER ListHeader,
PSLIST_ENTRY FirstEntry,
PSLIST_ENTRY LastEntry,
ULONG Count)
{
SLIST_HEADER oldHeader, newHeader;
TRACE("(%p, %p, %p, %d)\n", ListHeader, FirstEntry, LastEntry, Count);
#if _WIN64
assert(0);
#else
newHeader.Next.Next = FirstEntry;
do
{
oldHeader = *ListHeader;
newHeader.Depth = ListHeader->Depth + Count;
newHeader.Sequence = ListHeader->Sequence + 1;
LastEntry->Next = ListHeader->Next.Next;
} while (interlocked_cmpxchg64((__int64*)&ListHeader->Alignment,
newHeader.Alignment,
oldHeader.Alignment) != oldHeader.Alignment);
return oldHeader.Next.Next;
#endif
}