Commit 32f72989 authored by Sebastian Lackner's avatar Sebastian Lackner Committed by Alexandre Julliard

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

parent 38d0690a
......@@ -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();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment