[1/3] kernel32/tests: Add basic tests for SRWLock commands

Sebastian Lackner sebastian at fds-team.de
Fri Jan 10 21:17:50 CST 2014


This series of patches implements the Rtl*SRWLock* functions using keyed
events. The fifth and missing command (RtlSleepConditionVariableSRW)
will be implemented later as a separate patch.

Patch 1 and 2 first introduce some tests to verify how the functions
behave on Windows. Patch 3 is the actual implementation of the SRWLock.

---
 dlls/kernel32/tests/sync.c |  260
++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 260 insertions(+)
-------------- next part --------------
>From c379958c988e21c7d608db550b60f5b618cc2a08 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian at fds-team.de>
Date: Fri, 10 Jan 2014 23:02:52 +0100
Subject: kernel32/tests: Add basic tests for SRWLock commands

---
 dlls/kernel32/tests/sync.c |  260 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 260 insertions(+)

diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c
index d76aa16..79e045d 100644
--- a/dlls/kernel32/tests/sync.c
+++ b/dlls/kernel32/tests/sync.c
@@ -47,6 +47,12 @@ static BOOL   (WINAPI *pSleepConditionVariableCS)(PCONDITION_VARIABLE,PCRITICAL_
 static VOID   (WINAPI *pWakeAllConditionVariable)(PCONDITION_VARIABLE);
 static VOID   (WINAPI *pWakeConditionVariable)(PCONDITION_VARIABLE);
 
+static VOID   (WINAPI *pInitializeSRWLock)(PSRWLOCK);
+static VOID   (WINAPI *pAcquireSRWLockExclusive)(PSRWLOCK);
+static VOID   (WINAPI *pAcquireSRWLockShared)(PSRWLOCK);
+static VOID   (WINAPI *pReleaseSRWLockExclusive)(PSRWLOCK);
+static VOID   (WINAPI *pReleaseSRWLockShared)(PSRWLOCK);
+
 static void test_signalandwait(void)
 {
     DWORD (WINAPI *pSignalObjectAndWait)(HANDLE, HANDLE, DWORD, BOOL);
@@ -1664,6 +1670,254 @@ static void test_condvars_base(void) {
     WaitForSingleObject(hc, 100);
 }
 
+static LONG srwlock_seq = 0;
+static SRWLOCK srwlock_base;
+static struct
+{
+    LONG wrong_execution_order;
+    LONG samethread_excl_excl;
+    LONG samethread_excl_shared;
+    LONG samethread_shared_excl;
+    LONG multithread_excl_excl;
+    LONG excl_not_preferred;
+} srwlock_base_errors;
+
+/* Sequence of acquire/release to check boundary conditions:
+ *  0: init
+ *
+ *  1: thread2 acquires an exclusive lock and tries to acquire a second exclusive lock
+ *  2: thread1 expects a deadlock and releases the waiting lock
+ *     thread2 releases the lock again
+ *
+ *  3: thread2 acquires an exclusive lock and tries to acquire a shared lock
+ *  4: thread1 expects a deadlock and releases the waiting lock
+ *     thread2 releases the lock again
+ *
+ *  5: thread2 acquires a shared lock and tries to acquire an exclusive lock
+ *  6: thread1 expects a deadlock and releases the waiting lock
+ *     thread2 releases the lock again
+ *
+ *  7: thread2 acquires and releases two nested shared locks
+ *
+ *  8: thread1 acquires an exclusive lock
+ *  9: thread2 tries to acquire the exclusive lock, too
+ *     thread1 releases the exclusive lock again
+ * 10: thread2 enters the exclusive lock and leaves it immediately again
+ *
+ * 11: thread1 acquires a shared lock
+ * 12: thread2 acquires and releases a shared lock
+ *     thread1 releases the lock again
+ *
+ * 13: thread1 acquires a shared lock
+ * 14: thread2 tries to acquire an exclusive lock
+ * 15: thread3 tries to acquire a shared lock
+ * 16: thread1 releases the shared lock
+ * 17: thread2 wakes up and releases the exclusive lock
+ * 18: thread3 wakes up and releases the shared lock
+ *
+ * 19: end
+ */
+
+static DWORD WINAPI srwlock_base_thread1(LPVOID x)
+{
+    /* seq 2 */
+    while (srwlock_seq < 2) Sleep(1);
+    Sleep(100);
+    if (InterlockedIncrement(&srwlock_seq) != 3)
+        InterlockedIncrement(&srwlock_base_errors.samethread_excl_excl);
+    pReleaseSRWLockExclusive(&srwlock_base);
+
+    /* seq 4 */
+    while (srwlock_seq < 4) Sleep(1);
+    Sleep(100);
+    if (InterlockedIncrement(&srwlock_seq) != 5)
+        InterlockedIncrement(&srwlock_base_errors.samethread_excl_shared);
+    pReleaseSRWLockExclusive(&srwlock_base);
+
+    /* seq 6 */
+    while (srwlock_seq < 6) Sleep(1);
+    Sleep(100);
+    if (InterlockedIncrement(&srwlock_seq) != 7)
+        InterlockedIncrement(&srwlock_base_errors.samethread_shared_excl);
+    pReleaseSRWLockShared(&srwlock_base);
+
+    /* seq 8 */
+    while (srwlock_seq < 8) Sleep(1);
+    pAcquireSRWLockExclusive(&srwlock_base);
+    if (InterlockedIncrement(&srwlock_seq) != 9)
+        InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
+    Sleep(100);
+    if (InterlockedIncrement(&srwlock_seq) != 10)
+        InterlockedIncrement(&srwlock_base_errors.multithread_excl_excl);
+    pReleaseSRWLockExclusive(&srwlock_base);
+
+    /* seq 11 */
+    while (srwlock_seq < 11) Sleep(1);
+    pAcquireSRWLockShared(&srwlock_base);
+    if (InterlockedIncrement(&srwlock_seq) != 12)
+        InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
+
+    /* seq 13 */
+    while (srwlock_seq < 13) Sleep(1);
+    pReleaseSRWLockShared(&srwlock_base);
+    pAcquireSRWLockShared(&srwlock_base);
+    if (InterlockedIncrement(&srwlock_seq) != 14)
+        InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
+
+    /* seq 16 */
+    while (srwlock_seq < 16) Sleep(1);
+    Sleep(50); /* ensure that both the exclusive and shared access thread are queued */
+    if (InterlockedIncrement(&srwlock_seq) != 17)
+        InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
+    pReleaseSRWLockShared(&srwlock_base);
+
+    return 0;
+}
+
+static DWORD WINAPI srwlock_base_thread2(LPVOID x)
+{
+    /* seq 1 */
+    while (srwlock_seq < 1) Sleep(1);
+    pAcquireSRWLockExclusive(&srwlock_base);
+    if (InterlockedIncrement(&srwlock_seq) != 2)
+        InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
+
+    /* seq 3 */
+    pAcquireSRWLockExclusive(&srwlock_base);
+    if (srwlock_seq != 3)
+        InterlockedIncrement(&srwlock_base_errors.samethread_excl_excl);
+    pReleaseSRWLockExclusive(&srwlock_base);
+    pAcquireSRWLockExclusive(&srwlock_base);
+    if (InterlockedIncrement(&srwlock_seq) != 4)
+        InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
+
+    /* seq 5 */
+    pAcquireSRWLockShared(&srwlock_base);
+    if (srwlock_seq != 5)
+        InterlockedIncrement(&srwlock_base_errors.samethread_excl_shared);
+    pReleaseSRWLockShared(&srwlock_base);
+    pAcquireSRWLockShared(&srwlock_base);
+    if (InterlockedIncrement(&srwlock_seq) != 6)
+        InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
+
+    /* seq 7 */
+    pAcquireSRWLockExclusive(&srwlock_base);
+    if (srwlock_seq != 7)
+        InterlockedIncrement(&srwlock_base_errors.samethread_shared_excl);
+    pReleaseSRWLockExclusive(&srwlock_base);
+    pAcquireSRWLockShared(&srwlock_base);
+    pAcquireSRWLockShared(&srwlock_base);
+    pReleaseSRWLockShared(&srwlock_base);
+    pReleaseSRWLockShared(&srwlock_base);
+    if (InterlockedIncrement(&srwlock_seq) != 8)
+        InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
+
+    /* seq 9, 10 */
+    while (srwlock_seq < 9) Sleep(1);
+    pAcquireSRWLockExclusive(&srwlock_base);
+    if (srwlock_seq != 10)
+        InterlockedIncrement(&srwlock_base_errors.multithread_excl_excl);
+    pReleaseSRWLockExclusive(&srwlock_base);
+    if (InterlockedIncrement(&srwlock_seq) != 11)
+        InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
+
+    /* seq 12 */
+    while (srwlock_seq < 12) Sleep(1);
+    pAcquireSRWLockShared(&srwlock_base);
+    pReleaseSRWLockShared(&srwlock_base);
+    if (InterlockedIncrement(&srwlock_seq) != 13)
+        InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
+
+    /* seq 14 */
+    while (srwlock_seq < 14) Sleep(1);
+    if (InterlockedIncrement(&srwlock_seq) != 15)
+        InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
+
+    /* seq 17 */
+    pAcquireSRWLockExclusive(&srwlock_base);
+    if (srwlock_seq != 17)
+        InterlockedIncrement(&srwlock_base_errors.excl_not_preferred);
+    if (InterlockedIncrement(&srwlock_seq) != 18)
+        InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
+    pReleaseSRWLockExclusive(&srwlock_base);
+
+    return 0;
+}
+
+static DWORD WINAPI srwlock_base_thread3(LPVOID x)
+{
+    /* seq 15 */
+    while (srwlock_seq < 15) Sleep(1);
+    Sleep(50); /* some delay, such that thread2 can try to acquire a second exclusive lock */
+    if (InterlockedIncrement(&srwlock_seq) != 16)
+        InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
+
+    /* seq 18 */
+    pAcquireSRWLockShared(&srwlock_base);
+    if (srwlock_seq != 18)
+        InterlockedIncrement(&srwlock_base_errors.excl_not_preferred);
+    pReleaseSRWLockShared(&srwlock_base);
+    if (InterlockedIncrement(&srwlock_seq) != 19)
+        InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
+
+    return 0;
+}
+
+static void test_srwlock_base(void)
+{
+    HANDLE h1, h2, h3;
+    DWORD dummy;
+
+    if (!pInitializeSRWLock)
+    {
+        /* function is not yet in XP, only in newer Windows */
+        win_skip("no srw lock support.\n");
+        return;
+    }
+
+    pInitializeSRWLock(&srwlock_base);
+    memset(&srwlock_base_errors, 0, sizeof(srwlock_base_errors));
+
+    h1 = CreateThread(NULL, 0, srwlock_base_thread1, NULL, 0, &dummy);
+    h2 = CreateThread(NULL, 0, srwlock_base_thread2, NULL, 0, &dummy);
+    h3 = CreateThread(NULL, 0, srwlock_base_thread3, NULL, 0, &dummy);
+
+    srwlock_seq = 1; /* go */
+    while (srwlock_seq < 19)
+        Sleep(5);
+
+    WaitForSingleObject(h1, 100);
+    WaitForSingleObject(h2, 100);
+    WaitForSingleObject(h3, 100);
+
+    /* the current implementation just consists of stubs and all tests fail */
+    todo_wine
+    {
+    ok(!srwlock_base_errors.wrong_execution_order,
+            "thread commands were executed in the wrong order (occurred %d times).\n",
+            srwlock_base_errors.wrong_execution_order);
+
+    ok(!srwlock_base_errors.samethread_excl_excl,
+            "AcquireSRWLockExclusive didn't block when called multiple times from the same thread (occurred %d times).\n",
+            srwlock_base_errors.samethread_excl_excl);
+
+    ok(!srwlock_base_errors.samethread_excl_shared,
+            "AcquireSRWLockShared didn't block when the same thread holds an exclusive lock (occurred %d times).\n",
+            srwlock_base_errors.samethread_excl_shared);
+
+    ok(!srwlock_base_errors.samethread_shared_excl,
+            "AcquireSRWLockExclusive didn't block when the same thread holds a shared lock (occurred %d times).\n",
+            srwlock_base_errors.samethread_shared_excl);
+
+    ok(!srwlock_base_errors.multithread_excl_excl,
+            "AcquireSRWLockExclusive didn't block when a second thread holds the exclusive lock (occurred %d times).\n",
+            srwlock_base_errors.multithread_excl_excl);
+
+    ok(!srwlock_base_errors.excl_not_preferred,
+            "thread waiting for exclusive access to the SHMLock was not preferred (occurred %d times).\n",
+            srwlock_base_errors.excl_not_preferred);
+    }
+}
 
 START_TEST(sync)
 {
@@ -1685,6 +1939,11 @@ START_TEST(sync)
     pSleepConditionVariableCS = (void *)GetProcAddress(hdll, "SleepConditionVariableCS");
     pWakeAllConditionVariable = (void *)GetProcAddress(hdll, "WakeAllConditionVariable");
     pWakeConditionVariable = (void *)GetProcAddress(hdll, "WakeConditionVariable");
+    pInitializeSRWLock = (void *)GetProcAddress(hdll, "InitializeSRWLock");
+    pAcquireSRWLockExclusive = (void *)GetProcAddress(hdll, "AcquireSRWLockExclusive");
+    pAcquireSRWLockShared = (void *)GetProcAddress(hdll, "AcquireSRWLockShared");
+    pReleaseSRWLockExclusive = (void *)GetProcAddress(hdll, "ReleaseSRWLockExclusive");
+    pReleaseSRWLockShared = (void *)GetProcAddress(hdll, "ReleaseSRWLockShared");
 
     test_signalandwait();
     test_mutex();
@@ -1699,4 +1958,5 @@ START_TEST(sync)
     test_initonce();
     test_condvars_base();
     test_condvars_consumer_producer();
+    test_srwlock_base();
 }
-- 
1.7.9.5



More information about the wine-patches mailing list