[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