[3/4] kernel32/tests: Add tests for RtlInterlockedPushListSList[Ex].

Sebastian Lackner sebastian at fds-team.de
Wed Feb 10 20:53:49 CST 2016


Signed-off-by: Sebastian Lackner <sebastian at fds-team.de>
---
 dlls/kernel32/tests/sync.c |  126 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 126 insertions(+)

diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c
index e2aa3a1..325e1ff 100644
--- a/dlls/kernel32/tests/sync.c
+++ b/dlls/kernel32/tests/sync.c
@@ -28,6 +28,9 @@
 
 #include "wine/test.h"
 
+#undef __fastcall
+#define __fastcall __stdcall
+
 static BOOL   (WINAPI *pChangeTimerQueueTimer)(HANDLE, HANDLE, ULONG, ULONG);
 static HANDLE (WINAPI *pCreateTimerQueue)(void);
 static BOOL   (WINAPI *pCreateTimerQueueTimer)(PHANDLE, HANDLE, WAITORTIMERCALLBACK,
@@ -61,6 +64,48 @@ static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG, SIZE_
 static NTSTATUS (WINAPI *pNtFreeVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG);
 static NTSTATUS (WINAPI *pNtWaitForSingleObject)(HANDLE, BOOLEAN, const LARGE_INTEGER *);
 static NTSTATUS (WINAPI *pNtWaitForMultipleObjects)(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*);
+static PSLIST_ENTRY (__fastcall *pRtlInterlockedPushListSList)(PSLIST_HEADER list, PSLIST_ENTRY first,
+                                                               PSLIST_ENTRY last, ULONG count);
+static PSLIST_ENTRY (WINAPI *pRtlInterlockedPushListSListEx)(PSLIST_HEADER list, PSLIST_ENTRY first,
+                                                             PSLIST_ENTRY last, ULONG count);
+
+#ifdef __i386__
+
+#include "pshpack1.h"
+struct fastcall_thunk
+{
+    BYTE pop_edx;   /* popl %edx            (ret addr) */
+    BYTE pop_eax;   /* popl %eax            (func) */
+    BYTE pop_ecx;   /* popl %ecx            (param 1) */
+    BYTE xchg[3];   /* xchgl (%esp),%edx    (param 2) */
+    WORD jmp_eax;   /* jmp  *%eax */
+};
+#include "poppack.h"
+
+static void * (WINAPI *call_fastcall_func4)(void *func, const void *a, const void *b, const void *c, const void *d);
+
+static void init_fastcall_thunk(void)
+{
+    struct fastcall_thunk *thunk = VirtualAlloc(NULL, sizeof(*thunk), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+    thunk->pop_edx = 0x5a;      /* popl  %edx */
+    thunk->pop_eax = 0x58;      /* popl  %eax */
+    thunk->pop_ecx = 0x59;      /* popl  %ecx */
+    thunk->xchg[0] = 0x87;      /* xchgl (%esp),%edx */
+    thunk->xchg[1] = 0x14;
+    thunk->xchg[2] = 0x24;
+    thunk->jmp_eax = 0xe0ff;    /* jmp *%eax */
+    call_fastcall_func4 = (void *)thunk;
+}
+
+#define call_func4(func, a, b, c, d) call_fastcall_func4(func, (const void *)(a), \
+        (const void *)(b), (const void *)(c), (const void *)(d))
+
+#else  /* __i386__ */
+
+#define init_fastcall_thunk() do { } while(0)
+#define call_func4(func, a, b, c, d) func(a, b, c, d)
+
+#endif /* __i386__ */
 
 static void test_signalandwait(void)
 {
@@ -276,6 +321,7 @@ static void test_slist(void)
     size = QueryDepthSList(&slist_header);
     ok(size == 0, "Expected size == 0, got %u\n", size);
 
+    /* test PushEntry, PopEntry and Flush */
     entry = InterlockedPushEntrySList(&slist_header, &item1.entry);
     ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
     size = QueryDepthSList(&slist_header);
@@ -313,6 +359,83 @@ static void test_slist(void)
     entry = InterlockedPopEntrySList(&slist_header);
     ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
 
+    /* test RtlInterlockedPushListSList */
+    entry = InterlockedPushEntrySList(&slist_header, &item3.entry);
+    ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
+    entry = call_func4(pRtlInterlockedPushListSList, &slist_header, &item2.entry, &item1.entry, 42);
+    ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
+    item = CONTAINING_RECORD(entry, struct item, entry);
+    ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value);
+    size = QueryDepthSList(&slist_header);
+    ok(size == 43, "Expected size == 43, got %u\n", size);
+
+    entry = InterlockedPopEntrySList(&slist_header);
+    ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
+    item = CONTAINING_RECORD(entry, struct item, entry);
+    ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value);
+    size = QueryDepthSList(&slist_header);
+    ok(size == 42, "Expected size == 42, got %u\n", size);
+
+    entry = InterlockedPopEntrySList(&slist_header);
+    ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
+    item = CONTAINING_RECORD(entry, struct item, entry);
+    ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value);
+    size = QueryDepthSList(&slist_header);
+    ok(size == 41, "Expected size == 41, got %u\n", size);
+
+    entry = InterlockedPopEntrySList(&slist_header);
+    ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
+    item = CONTAINING_RECORD(entry, struct item, entry);
+    ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value);
+    size = QueryDepthSList(&slist_header);
+    ok(size == 40, "Expected size == 40, got %u\n", size);
+
+    entry = InterlockedPopEntrySList(&slist_header);
+    ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
+    size = QueryDepthSList(&slist_header);
+    ok(size == 40, "Expected size == 40, got %u\n", size);
+
+    entry = InterlockedFlushSList(&slist_header);
+    ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
+    size = QueryDepthSList(&slist_header);
+    ok(size == 40 || broken(size == 0) /* >= Win 8 */, "Expected size == 40, got %u\n", size);
+
+    entry = InterlockedPushEntrySList(&slist_header, &item1.entry);
+    ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
+    entry = InterlockedFlushSList(&slist_header);
+    ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
+    item = CONTAINING_RECORD(entry, struct item, entry);
+    ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value);
+    size = QueryDepthSList(&slist_header);
+    ok(size == 0, "Expected size == 0, got %u\n", size);
+
+    /* test RtlInterlockedPushListSListEx */
+    if (pRtlInterlockedPushListSListEx)
+    {
+        entry = InterlockedPushEntrySList(&slist_header, &item3.entry);
+        ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
+        entry = pRtlInterlockedPushListSListEx(&slist_header, &item2.entry, &item1.entry, 42);
+        ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
+        item = CONTAINING_RECORD(entry, struct item, entry);
+        ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value);
+        size = QueryDepthSList(&slist_header);
+        ok(size == 43, "Expected size == 43, got %u\n", size);
+
+        entry = InterlockedFlushSList(&slist_header);
+        ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
+        item = CONTAINING_RECORD(entry, struct item, entry);
+        ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value);
+        item = CONTAINING_RECORD(item->entry.Next, struct item, entry);
+        ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value);
+        item = CONTAINING_RECORD(item->entry.Next, struct item, entry);
+        ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value);
+        size = QueryDepthSList(&slist_header);
+        ok(size == 0, "Expected size == 0, got %u\n", size);
+    }
+    else
+        win_skip("RtlInterlockedPushListSListEx not available, skipping tests\n");
+
+    /* test with a lot of items */
     for (i = 0; i < 65536; i++)
     {
         item = HeapAlloc(GetProcessHeap(), 0, sizeof(*item));
@@ -2561,6 +2684,8 @@ START_TEST(sync)
     pNtFreeVirtualMemory = (void *)GetProcAddress(hntdll, "NtFreeVirtualMemory");
     pNtWaitForSingleObject = (void *)GetProcAddress(hntdll, "NtWaitForSingleObject");
     pNtWaitForMultipleObjects = (void *)GetProcAddress(hntdll, "NtWaitForMultipleObjects");
+    pRtlInterlockedPushListSList = (void *)GetProcAddress(hntdll, "RtlInterlockedPushListSList");
+    pRtlInterlockedPushListSListEx = (void *)GetProcAddress(hntdll, "RtlInterlockedPushListSListEx");
 
     argc = winetest_get_mainargs( &argv );
     if (argc >= 3)
@@ -2572,6 +2697,7 @@ START_TEST(sync)
         return;
     }
 
+    init_fastcall_thunk();
     test_signalandwait();
     test_mutex();
     test_slist();
-- 
2.7.1



More information about the wine-patches mailing list