Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48389 Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/kernel32/tests/sync.c | 76 ++++++++++++++++----------- dlls/ntdll/sync.c | 105 ++++++++++++++++++++++++++++++------- 2 files changed, 132 insertions(+), 49 deletions(-)
diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c index 40cad1c4c5..477a35287d 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c @@ -1718,10 +1718,18 @@ static void test_condvars_consumer_producer(void)
/* Sample test for some sequence of events happening, sequenced using "condvar_seq" */ static DWORD condvar_seq = 0; -static CONDITION_VARIABLE condvar_base = CONDITION_VARIABLE_INIT; +static CONDITION_VARIABLE aligned_cv; static CRITICAL_SECTION condvar_crit; static SRWLOCK condvar_srwlock;
+#include "pshpack1.h" +static struct +{ + char c; + CONDITION_VARIABLE cv; +} unaligned_cv; +#include "poppack.h" + /* Sequence of wake/sleep to check boundary conditions: * 0: init * 1: producer emits a WakeConditionVariable without consumer waiting. @@ -1741,28 +1749,31 @@ static SRWLOCK condvar_srwlock; * 12: producer (shared) wakes up consumer (shared) * 13: end */ -static DWORD WINAPI condvar_base_producer(LPVOID x) { +static DWORD WINAPI condvar_base_producer(void *arg) +{ + CONDITION_VARIABLE *cv = arg; + while (condvar_seq < 1) Sleep(1);
- pWakeConditionVariable (&condvar_base); + pWakeConditionVariable(cv); condvar_seq = 2;
while (condvar_seq < 3) Sleep(1); - pWakeAllConditionVariable (&condvar_base); + pWakeAllConditionVariable(cv); condvar_seq = 4;
while (condvar_seq < 5) Sleep(1); EnterCriticalSection (&condvar_crit); - pWakeConditionVariable (&condvar_base); + pWakeConditionVariable(cv); LeaveCriticalSection (&condvar_crit); while (condvar_seq < 6) Sleep(1); EnterCriticalSection (&condvar_crit); - pWakeAllConditionVariable (&condvar_base); + pWakeAllConditionVariable(cv); LeaveCriticalSection (&condvar_crit);
while (condvar_seq < 8) Sleep(1); EnterCriticalSection (&condvar_crit); - pWakeConditionVariable (&condvar_base); + pWakeConditionVariable(cv); Sleep(50); LeaveCriticalSection (&condvar_crit);
@@ -1772,36 +1783,38 @@ static DWORD WINAPI condvar_base_producer(LPVOID x) {
while (condvar_seq < 9) Sleep(1); pAcquireSRWLockExclusive(&condvar_srwlock); - pWakeConditionVariable(&condvar_base); + pWakeConditionVariable(cv); pReleaseSRWLockExclusive(&condvar_srwlock);
while (condvar_seq < 10) Sleep(1); pAcquireSRWLockExclusive(&condvar_srwlock); - pWakeConditionVariable(&condvar_base); + pWakeConditionVariable(cv); pReleaseSRWLockExclusive(&condvar_srwlock);
while (condvar_seq < 11) Sleep(1); pAcquireSRWLockShared(&condvar_srwlock); - pWakeConditionVariable(&condvar_base); + pWakeConditionVariable(cv); pReleaseSRWLockShared(&condvar_srwlock);
while (condvar_seq < 12) Sleep(1); Sleep(50); /* ensure that consumer waits for cond variable */ pAcquireSRWLockShared(&condvar_srwlock); - pWakeConditionVariable(&condvar_base); + pWakeConditionVariable(cv); pReleaseSRWLockShared(&condvar_srwlock);
return 0; }
-static DWORD WINAPI condvar_base_consumer(LPVOID x) { +static DWORD WINAPI condvar_base_consumer(void *arg) +{ + CONDITION_VARIABLE *cv = arg; BOOL ret;
while (condvar_seq < 2) Sleep(1);
/* wake was emitted, but we were not sleeping */ EnterCriticalSection (&condvar_crit); - ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10); + ret = pSleepConditionVariableCS(cv, &condvar_crit, 10); LeaveCriticalSection (&condvar_crit); ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n"); ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError()); @@ -1811,33 +1824,33 @@ static DWORD WINAPI condvar_base_consumer(LPVOID x) {
/* wake all was emitted, but we were not sleeping */ EnterCriticalSection (&condvar_crit); - ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10); + ret = pSleepConditionVariableCS(cv, &condvar_crit, 10); LeaveCriticalSection (&condvar_crit); ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n"); ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
EnterCriticalSection (&condvar_crit); condvar_seq = 5; - ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 200); + ret = pSleepConditionVariableCS(cv, &condvar_crit, 200); LeaveCriticalSection (&condvar_crit); ok (ret, "SleepConditionVariableCS should return TRUE on good wake\n");
EnterCriticalSection (&condvar_crit); condvar_seq = 6; - ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 200); + ret = pSleepConditionVariableCS(cv, &condvar_crit, 200); LeaveCriticalSection (&condvar_crit); ok (ret, "SleepConditionVariableCS should return TRUE on good wakeall\n"); condvar_seq = 7;
EnterCriticalSection (&condvar_crit); - ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10); + ret = pSleepConditionVariableCS(cv, &condvar_crit, 10); LeaveCriticalSection (&condvar_crit); ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n"); ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
EnterCriticalSection (&condvar_crit); condvar_seq = 8; - ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 20); + ret = pSleepConditionVariableCS(cv, &condvar_crit, 20); LeaveCriticalSection (&condvar_crit); ok (ret, "SleepConditionVariableCS should still return TRUE on crit unlock delay\n");
@@ -1851,25 +1864,25 @@ static DWORD WINAPI condvar_base_consumer(LPVOID x) {
pAcquireSRWLockExclusive(&condvar_srwlock); condvar_seq = 9; - ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 200, 0); + ret = pSleepConditionVariableSRW(cv, &condvar_srwlock, 200, 0); pReleaseSRWLockExclusive(&condvar_srwlock); ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n");
pAcquireSRWLockShared(&condvar_srwlock); condvar_seq = 10; - ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 200, CONDITION_VARIABLE_LOCKMODE_SHARED); + ret = pSleepConditionVariableSRW(cv, &condvar_srwlock, 200, CONDITION_VARIABLE_LOCKMODE_SHARED); pReleaseSRWLockShared(&condvar_srwlock); ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n");
pAcquireSRWLockExclusive(&condvar_srwlock); condvar_seq = 11; - ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 200, 0); + ret = pSleepConditionVariableSRW(cv, &condvar_srwlock, 200, 0); pReleaseSRWLockExclusive(&condvar_srwlock); ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n");
pAcquireSRWLockShared(&condvar_srwlock); condvar_seq = 12; - ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 200, CONDITION_VARIABLE_LOCKMODE_SHARED); + ret = pSleepConditionVariableSRW(cv, &condvar_srwlock, 200, CONDITION_VARIABLE_LOCKMODE_SHARED); pReleaseSRWLockShared(&condvar_srwlock); ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n");
@@ -1877,12 +1890,12 @@ static DWORD WINAPI condvar_base_consumer(LPVOID x) { return 0; }
-static void test_condvars_base(void) { +static void test_condvars_base(RTL_CONDITION_VARIABLE *cv) +{ HANDLE hp, hc; DWORD dummy; BOOL ret;
- if (!pInitializeConditionVariable) { /* function is not yet in XP, only in newer Windows */ win_skip("no condition variable support.\n"); @@ -1895,7 +1908,7 @@ static void test_condvars_base(void) { pInitializeSRWLock(&condvar_srwlock);
EnterCriticalSection (&condvar_crit); - ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10); + ret = pSleepConditionVariableCS(cv, &condvar_crit, 10); LeaveCriticalSection (&condvar_crit);
ok (!ret, "SleepConditionVariableCS should return FALSE on untriggered condvar\n"); @@ -1904,23 +1917,23 @@ static void test_condvars_base(void) { if (pInitializeSRWLock) { pAcquireSRWLockExclusive(&condvar_srwlock); - ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 10, 0); + ret = pSleepConditionVariableSRW(cv, &condvar_srwlock, 10, 0); pReleaseSRWLockExclusive(&condvar_srwlock);
ok(!ret, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n"); ok(GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
pAcquireSRWLockShared(&condvar_srwlock); - ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 10, CONDITION_VARIABLE_LOCKMODE_SHARED); + ret = pSleepConditionVariableSRW(cv, &condvar_srwlock, 10, CONDITION_VARIABLE_LOCKMODE_SHARED); pReleaseSRWLockShared(&condvar_srwlock);
ok(!ret, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n"); ok(GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError()); }
- - hp = CreateThread(NULL, 0, condvar_base_producer, NULL, 0, &dummy); - hc = CreateThread(NULL, 0, condvar_base_consumer, NULL, 0, &dummy); + condvar_seq = 0; + hp = CreateThread(NULL, 0, condvar_base_producer, cv, 0, &dummy); + hc = CreateThread(NULL, 0, condvar_base_consumer, cv, 0, &dummy);
condvar_seq = 1; /* go */
@@ -2728,7 +2741,8 @@ START_TEST(sync) test_WaitForSingleObject(); test_WaitForMultipleObjects(); test_initonce(); - test_condvars_base(); + test_condvars_base(&aligned_cv); + test_condvars_base(&unaligned_cv.cv); test_condvars_consumer_producer(); test_srwlock_base(); test_srwlock_example(); diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c index 0dc6fc3390..302b4cc7e0 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -115,6 +115,16 @@ static inline int use_futexes(void) return supported; }
+static int *get_futex(void **ptr) +{ + if (sizeof(void *) == 8) + return (int *)((((ULONG_PTR)ptr) + 3) & ~3); + else if (!(((ULONG_PTR)ptr) & 3)) + return (int *)ptr; + else + return NULL; +} + static void timespec_from_timeout( struct timespec *timespec, const LARGE_INTEGER *timeout ) { LARGE_INTEGER now; @@ -2179,32 +2189,83 @@ BOOLEAN WINAPI RtlTryAcquireSRWLockShared( RTL_SRWLOCK *lock ) }
#ifdef __linux__ -static NTSTATUS fast_wait_cv( RTL_CONDITION_VARIABLE *variable, int val, const LARGE_INTEGER *timeout ) +static NTSTATUS fast_wait_cv( int *futex, int val, const LARGE_INTEGER *timeout ) { struct timespec timespec; int ret;
- if (!use_futexes()) - return STATUS_NOT_IMPLEMENTED; - if (timeout && timeout->QuadPart != TIMEOUT_INFINITE) { timespec_from_timeout( ×pec, timeout ); - ret = futex_wait( (int *)&variable->Ptr, val, ×pec ); + ret = futex_wait( futex, val, ×pec ); } else - ret = futex_wait( (int *)&variable->Ptr, val, NULL ); + ret = futex_wait( futex, val, NULL );
if (ret == -1 && errno == ETIMEDOUT) return STATUS_TIMEOUT; return STATUS_WAIT_0; }
+static NTSTATUS fast_sleep_cs_cv( RTL_CONDITION_VARIABLE *variable, + RTL_CRITICAL_SECTION *cs, const LARGE_INTEGER *timeout ) +{ + NTSTATUS status; + int val, *futex; + + if (!use_futexes()) + return STATUS_NOT_IMPLEMENTED; + + if (!(futex = get_futex( &variable->Ptr ))) + return STATUS_NOT_IMPLEMENTED; + + val = *futex; + + RtlLeaveCriticalSection( cs ); + status = fast_wait_cv( futex, val, timeout ); + RtlEnterCriticalSection( cs ); + return status; +} + +static NTSTATUS fast_sleep_srw_cv( RTL_CONDITION_VARIABLE *variable, + RTL_SRWLOCK *lock, const LARGE_INTEGER *timeout, ULONG flags ) +{ + NTSTATUS status; + int val, *futex; + + if (!use_futexes()) + return STATUS_NOT_IMPLEMENTED; + + if (!(futex = get_futex( &variable->Ptr ))) + return STATUS_NOT_IMPLEMENTED; + + val = *futex; + + if (flags & RTL_CONDITION_VARIABLE_LOCKMODE_SHARED) + RtlReleaseSRWLockShared( lock ); + else + RtlReleaseSRWLockExclusive( lock ); + + status = fast_wait_cv( futex, val, timeout ); + + if (flags & RTL_CONDITION_VARIABLE_LOCKMODE_SHARED) + RtlAcquireSRWLockShared( lock ); + else + RtlAcquireSRWLockExclusive( lock ); + return status; +} + static NTSTATUS fast_wake_cv( RTL_CONDITION_VARIABLE *variable, int count ) { + int *futex; + if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
- futex_wake( (int *)&variable->Ptr, count ); + if (!(futex = get_futex( &variable->Ptr ))) + return STATUS_NOT_IMPLEMENTED; + + interlocked_xchg_add( futex, 1 ); + futex_wake( futex, count ); return STATUS_SUCCESS; } #else @@ -2252,9 +2313,11 @@ void WINAPI RtlInitializeConditionVariable( RTL_CONDITION_VARIABLE *variable ) */ void WINAPI RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable ) { - interlocked_xchg_add( (int *)&variable->Ptr, 1 ); if (fast_wake_cv( variable, 1 ) == STATUS_NOT_IMPLEMENTED) + { + interlocked_xchg_add( (int *)&variable->Ptr, 1 ); RtlWakeAddressSingle( variable ); + } }
/*********************************************************************** @@ -2264,9 +2327,11 @@ void WINAPI RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable ) */ void WINAPI RtlWakeAllConditionVariable( RTL_CONDITION_VARIABLE *variable ) { - interlocked_xchg_add( (int *)&variable->Ptr, 1 ); if (fast_wake_cv( variable, INT_MAX ) == STATUS_NOT_IMPLEMENTED) + { + interlocked_xchg_add( (int *)&variable->Ptr, 1 ); RtlWakeAddressAll( variable ); + } }
/*********************************************************************** @@ -2288,15 +2353,15 @@ NTSTATUS WINAPI RtlSleepConditionVariableCS( RTL_CONDITION_VARIABLE *variable, R const LARGE_INTEGER *timeout ) { NTSTATUS status; - int val = *(int *)&variable->Ptr; - - RtlLeaveCriticalSection( crit ); + int val;
- if ((status = fast_wait_cv( variable, val, timeout )) == STATUS_NOT_IMPLEMENTED) - status = RtlWaitOnAddress( &variable->Ptr, &val, sizeof(int), timeout ); + if ((status = fast_sleep_cs_cv( variable, crit, timeout )) != STATUS_NOT_IMPLEMENTED) + return status;
+ val = *(int *)&variable->Ptr; + RtlLeaveCriticalSection( crit ); + status = RtlWaitOnAddress( &variable->Ptr, &val, sizeof(int), timeout ); RtlEnterCriticalSection( crit ); - return status; }
@@ -2323,15 +2388,19 @@ NTSTATUS WINAPI RtlSleepConditionVariableSRW( RTL_CONDITION_VARIABLE *variable, const LARGE_INTEGER *timeout, ULONG flags ) { NTSTATUS status; - int val = *(int *)&variable->Ptr; + int val; + + if ((status = fast_sleep_srw_cv( variable, lock, timeout, flags )) != STATUS_NOT_IMPLEMENTED) + return status; + + val = *(int *)&variable->Ptr;
if (flags & RTL_CONDITION_VARIABLE_LOCKMODE_SHARED) RtlReleaseSRWLockShared( lock ); else RtlReleaseSRWLockExclusive( lock );
- if ((status = fast_wait_cv( variable, val, timeout )) == STATUS_NOT_IMPLEMENTED) - status = RtlWaitOnAddress( &variable->Ptr, &val, sizeof(int), timeout ); + status = RtlWaitOnAddress( &variable->Ptr, &val, sizeof(int), timeout );
if (flags & RTL_CONDITION_VARIABLE_LOCKMODE_SHARED) RtlAcquireSRWLockShared( lock );
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/kernel32/tests/sync.c | 174 ++++++++++++++++++++----------------- dlls/ntdll/sync.c | 74 ++++++++++------ 2 files changed, 141 insertions(+), 107 deletions(-)
diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c index 477a35287d..dfd98cf102 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c @@ -1944,7 +1944,7 @@ static void test_condvars_base(RTL_CONDITION_VARIABLE *cv) }
static LONG srwlock_seq = 0; -static SRWLOCK srwlock_base; +static SRWLOCK aligned_srwlock; static struct { LONG wrong_execution_order; @@ -1957,6 +1957,14 @@ static struct LONG trylock_shared; } srwlock_base_errors;
+#include "pshpack1.h" +struct +{ + char c; + SRWLOCK lock; +} unaligned_srwlock; +#include "poppack.h" + /* Sequence of acquire/release to check boundary conditions: * 0: init * @@ -2028,49 +2036,51 @@ static struct * 31: end */
-static DWORD WINAPI srwlock_base_thread1(LPVOID x) +static DWORD WINAPI srwlock_base_thread1(void *arg) { + SRWLOCK *lock = arg; + /* 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); + pReleaseSRWLockExclusive(lock);
/* 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); + pReleaseSRWLockExclusive(lock);
/* 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); + pReleaseSRWLockShared(lock);
/* seq 8 */ while (srwlock_seq < 8) Sleep(1); - pAcquireSRWLockExclusive(&srwlock_base); + pAcquireSRWLockExclusive(lock); 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); + pReleaseSRWLockExclusive(lock);
/* seq 11 */ while (srwlock_seq < 11) Sleep(1); - pAcquireSRWLockShared(&srwlock_base); + pAcquireSRWLockShared(lock); 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); + pReleaseSRWLockShared(lock); + pAcquireSRWLockShared(lock); if (InterlockedIncrement(&srwlock_seq) != 14) InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
@@ -2079,7 +2089,7 @@ static DWORD WINAPI srwlock_base_thread1(LPVOID x) 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); + pReleaseSRWLockShared(lock);
/* skip over remaining tests if TryAcquireSRWLock* is not available */ if (!pTryAcquireSRWLockExclusive) @@ -2087,125 +2097,127 @@ static DWORD WINAPI srwlock_base_thread1(LPVOID x)
/* seq 19 */ while (srwlock_seq < 19) Sleep(1); - if (pTryAcquireSRWLockExclusive(&srwlock_base)) + if (pTryAcquireSRWLockExclusive(lock)) { - if (pTryAcquireSRWLockShared(&srwlock_base)) + if (pTryAcquireSRWLockShared(lock)) InterlockedIncrement(&srwlock_base_errors.trylock_shared); - if (pTryAcquireSRWLockExclusive(&srwlock_base)) + if (pTryAcquireSRWLockExclusive(lock)) InterlockedIncrement(&srwlock_base_errors.trylock_excl); - pReleaseSRWLockExclusive(&srwlock_base); + pReleaseSRWLockExclusive(lock); } else InterlockedIncrement(&srwlock_base_errors.trylock_excl);
- if (pTryAcquireSRWLockShared(&srwlock_base)) + if (pTryAcquireSRWLockShared(lock)) { - if (pTryAcquireSRWLockShared(&srwlock_base)) - pReleaseSRWLockShared(&srwlock_base); + if (pTryAcquireSRWLockShared(lock)) + pReleaseSRWLockShared(lock); else InterlockedIncrement(&srwlock_base_errors.trylock_shared); - if (pTryAcquireSRWLockExclusive(&srwlock_base)) + if (pTryAcquireSRWLockExclusive(lock)) InterlockedIncrement(&srwlock_base_errors.trylock_excl); - pReleaseSRWLockShared(&srwlock_base); + pReleaseSRWLockShared(lock); } else InterlockedIncrement(&srwlock_base_errors.trylock_shared);
- pAcquireSRWLockExclusive(&srwlock_base); + pAcquireSRWLockExclusive(lock); if (InterlockedIncrement(&srwlock_seq) != 20) InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
/* seq 21 */ while (srwlock_seq < 21) Sleep(1); - pReleaseSRWLockExclusive(&srwlock_base); - pAcquireSRWLockShared(&srwlock_base); + pReleaseSRWLockExclusive(lock); + pAcquireSRWLockShared(lock); if (InterlockedIncrement(&srwlock_seq) != 22) InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
/* seq 23 */ while (srwlock_seq < 23) Sleep(1); - pReleaseSRWLockShared(&srwlock_base); - pAcquireSRWLockShared(&srwlock_base); + pReleaseSRWLockShared(lock); + pAcquireSRWLockShared(lock); if (InterlockedIncrement(&srwlock_seq) != 24) InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
/* seq 25 */ - pAcquireSRWLockExclusive(&srwlock_base); + pAcquireSRWLockExclusive(lock); if (srwlock_seq != 25) InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); - pReleaseSRWLockExclusive(&srwlock_base); + pReleaseSRWLockExclusive(lock);
- pAcquireSRWLockShared(&srwlock_base); - pAcquireSRWLockShared(&srwlock_base); + pAcquireSRWLockShared(lock); + pAcquireSRWLockShared(lock); if (InterlockedIncrement(&srwlock_seq) != 26) InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
/* seq 27 */ while (srwlock_seq < 27) Sleep(1); - pReleaseSRWLockShared(&srwlock_base); + pReleaseSRWLockShared(lock); if (InterlockedIncrement(&srwlock_seq) != 28) InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
/* seq 29 */ while (srwlock_seq < 29) Sleep(1); - pReleaseSRWLockShared(&srwlock_base); + pReleaseSRWLockShared(lock); if (InterlockedIncrement(&srwlock_seq) != 30) InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
return 0; }
-static DWORD WINAPI srwlock_base_thread2(LPVOID x) +static DWORD WINAPI srwlock_base_thread2(void *arg) { + SRWLOCK *lock = arg; + /* seq 1 */ while (srwlock_seq < 1) Sleep(1); - pAcquireSRWLockExclusive(&srwlock_base); + pAcquireSRWLockExclusive(lock); if (InterlockedIncrement(&srwlock_seq) != 2) InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
/* seq 3 */ - pAcquireSRWLockExclusive(&srwlock_base); + pAcquireSRWLockExclusive(lock); if (srwlock_seq != 3) InterlockedIncrement(&srwlock_base_errors.samethread_excl_excl); - pReleaseSRWLockExclusive(&srwlock_base); - pAcquireSRWLockExclusive(&srwlock_base); + pReleaseSRWLockExclusive(lock); + pAcquireSRWLockExclusive(lock); if (InterlockedIncrement(&srwlock_seq) != 4) InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
/* seq 5 */ - pAcquireSRWLockShared(&srwlock_base); + pAcquireSRWLockShared(lock); if (srwlock_seq != 5) InterlockedIncrement(&srwlock_base_errors.samethread_excl_shared); - pReleaseSRWLockShared(&srwlock_base); - pAcquireSRWLockShared(&srwlock_base); + pReleaseSRWLockShared(lock); + pAcquireSRWLockShared(lock); if (InterlockedIncrement(&srwlock_seq) != 6) InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
/* seq 7 */ - pAcquireSRWLockExclusive(&srwlock_base); + pAcquireSRWLockExclusive(lock); 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); + pReleaseSRWLockExclusive(lock); + pAcquireSRWLockShared(lock); + pAcquireSRWLockShared(lock); + pReleaseSRWLockShared(lock); + pReleaseSRWLockShared(lock); if (InterlockedIncrement(&srwlock_seq) != 8) InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
/* seq 9, 10 */ while (srwlock_seq < 9) Sleep(1); - pAcquireSRWLockExclusive(&srwlock_base); + pAcquireSRWLockExclusive(lock); if (srwlock_seq != 10) InterlockedIncrement(&srwlock_base_errors.multithread_excl_excl); - pReleaseSRWLockExclusive(&srwlock_base); + pReleaseSRWLockExclusive(lock); 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); + pAcquireSRWLockShared(lock); + pReleaseSRWLockShared(lock); if (InterlockedIncrement(&srwlock_seq) != 13) InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
@@ -2215,12 +2227,12 @@ static DWORD WINAPI srwlock_base_thread2(LPVOID x) InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
/* seq 17 */ - pAcquireSRWLockExclusive(&srwlock_base); + pAcquireSRWLockExclusive(lock); 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); + pReleaseSRWLockExclusive(lock);
/* skip over remaining tests if TryAcquireSRWLock* is not available */ if (!pTryAcquireSRWLockExclusive) @@ -2228,20 +2240,20 @@ static DWORD WINAPI srwlock_base_thread2(LPVOID x)
/* seq 20 */ while (srwlock_seq < 20) Sleep(1); - if (pTryAcquireSRWLockShared(&srwlock_base)) + if (pTryAcquireSRWLockShared(lock)) InterlockedIncrement(&srwlock_base_errors.trylock_shared); - if (pTryAcquireSRWLockExclusive(&srwlock_base)) + if (pTryAcquireSRWLockExclusive(lock)) InterlockedIncrement(&srwlock_base_errors.trylock_excl); if (InterlockedIncrement(&srwlock_seq) != 21) InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
/* seq 22 */ while (srwlock_seq < 22) Sleep(1); - if (pTryAcquireSRWLockShared(&srwlock_base)) - pReleaseSRWLockShared(&srwlock_base); + if (pTryAcquireSRWLockShared(lock)) + pReleaseSRWLockShared(lock); else InterlockedIncrement(&srwlock_base_errors.trylock_shared); - if (pTryAcquireSRWLockExclusive(&srwlock_base)) + if (pTryAcquireSRWLockExclusive(lock)) InterlockedIncrement(&srwlock_base_errors.trylock_excl); if (InterlockedIncrement(&srwlock_seq) != 23) InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); @@ -2249,47 +2261,47 @@ static DWORD WINAPI srwlock_base_thread2(LPVOID x) /* seq 24 */ while (srwlock_seq < 24) Sleep(1); Sleep(50); /* ensure that exclusive access request is queued */ - if (pTryAcquireSRWLockShared(&srwlock_base)) + if (pTryAcquireSRWLockShared(lock)) { - pReleaseSRWLockShared(&srwlock_base); + pReleaseSRWLockShared(lock); InterlockedIncrement(&srwlock_base_errors.excl_not_preferred); } - if (pTryAcquireSRWLockExclusive(&srwlock_base)) + if (pTryAcquireSRWLockExclusive(lock)) InterlockedIncrement(&srwlock_base_errors.trylock_excl); if (InterlockedIncrement(&srwlock_seq) != 25) InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); - pReleaseSRWLockShared(&srwlock_base); + pReleaseSRWLockShared(lock);
/* seq 26 */ while (srwlock_seq < 26) Sleep(1); - if (pTryAcquireSRWLockShared(&srwlock_base)) - pReleaseSRWLockShared(&srwlock_base); + if (pTryAcquireSRWLockShared(lock)) + pReleaseSRWLockShared(lock); else InterlockedIncrement(&srwlock_base_errors.trylock_shared); - if (pTryAcquireSRWLockExclusive(&srwlock_base)) + if (pTryAcquireSRWLockExclusive(lock)) InterlockedIncrement(&srwlock_base_errors.trylock_excl); if (InterlockedIncrement(&srwlock_seq) != 27) InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
/* seq 28 */ while (srwlock_seq < 28) Sleep(1); - if (pTryAcquireSRWLockShared(&srwlock_base)) - pReleaseSRWLockShared(&srwlock_base); + if (pTryAcquireSRWLockShared(lock)) + pReleaseSRWLockShared(lock); else InterlockedIncrement(&srwlock_base_errors.trylock_shared); - if (pTryAcquireSRWLockExclusive(&srwlock_base)) + if (pTryAcquireSRWLockExclusive(lock)) InterlockedIncrement(&srwlock_base_errors.trylock_excl); if (InterlockedIncrement(&srwlock_seq) != 29) InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
/* seq 30 */ while (srwlock_seq < 30) Sleep(1); - if (pTryAcquireSRWLockShared(&srwlock_base)) - pReleaseSRWLockShared(&srwlock_base); + if (pTryAcquireSRWLockShared(lock)) + pReleaseSRWLockShared(lock); else InterlockedIncrement(&srwlock_base_errors.trylock_shared); - if (pTryAcquireSRWLockExclusive(&srwlock_base)) - pReleaseSRWLockExclusive(&srwlock_base); + if (pTryAcquireSRWLockExclusive(lock)) + pReleaseSRWLockExclusive(lock); else InterlockedIncrement(&srwlock_base_errors.trylock_excl); if (InterlockedIncrement(&srwlock_seq) != 31) @@ -2298,8 +2310,10 @@ static DWORD WINAPI srwlock_base_thread2(LPVOID x) return 0; }
-static DWORD WINAPI srwlock_base_thread3(LPVOID x) +static DWORD WINAPI srwlock_base_thread3(void *arg) { + SRWLOCK *lock = arg; + /* seq 15 */ while (srwlock_seq < 15) Sleep(1); Sleep(50); /* some delay, so that thread2 can try to acquire a second exclusive lock */ @@ -2307,10 +2321,10 @@ static DWORD WINAPI srwlock_base_thread3(LPVOID x) InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
/* seq 18 */ - pAcquireSRWLockShared(&srwlock_base); + pAcquireSRWLockShared(lock); if (srwlock_seq != 18) InterlockedIncrement(&srwlock_base_errors.excl_not_preferred); - pReleaseSRWLockShared(&srwlock_base); + pReleaseSRWLockShared(lock); if (InterlockedIncrement(&srwlock_seq) != 19) InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
@@ -2326,7 +2340,7 @@ static DWORD WINAPI srwlock_base_thread3(LPVOID x) return 0; }
-static void test_srwlock_base(void) +static void test_srwlock_base(SRWLOCK *lock) { HANDLE h1, h2, h3; DWORD dummy; @@ -2338,12 +2352,13 @@ static void test_srwlock_base(void) return; }
- pInitializeSRWLock(&srwlock_base); + pInitializeSRWLock(lock); memset(&srwlock_base_errors, 0, sizeof(srwlock_base_errors)); + srwlock_seq = 0;
- 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); + h1 = CreateThread(NULL, 0, srwlock_base_thread1, lock, 0, &dummy); + h2 = CreateThread(NULL, 0, srwlock_base_thread2, lock, 0, &dummy); + h3 = CreateThread(NULL, 0, srwlock_base_thread3, lock, 0, &dummy);
srwlock_seq = 1; /* go */ while (srwlock_seq < 31) @@ -2744,7 +2759,8 @@ START_TEST(sync) test_condvars_base(&aligned_cv); test_condvars_base(&unaligned_cv.cv); test_condvars_consumer_producer(); - test_srwlock_base(); + test_srwlock_base(&aligned_srwlock); + test_srwlock_base(&unaligned_srwlock.lock); test_srwlock_example(); test_alertable_wait(); test_apc_deadlock(); diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c index 302b4cc7e0..1bc002608a 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -1698,14 +1698,17 @@ DWORD WINAPI RtlRunOnceExecuteOnce( RTL_RUN_ONCE *once, PRTL_RUN_ONCE_INIT_FN fu
static NTSTATUS fast_try_acquire_srw_exclusive( RTL_SRWLOCK *lock ) { - int old, new; + int old, new, *futex; NTSTATUS ret;
if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
+ if (!(futex = get_futex( &lock->Ptr ))) + return STATUS_NOT_IMPLEMENTED; + do { - old = *(int *)lock; + old = *futex;
if (!(old & SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT) && !(old & SRWLOCK_FUTEX_SHARED_OWNERS_MASK)) @@ -1719,31 +1722,34 @@ static NTSTATUS fast_try_acquire_srw_exclusive( RTL_SRWLOCK *lock ) new = old; ret = STATUS_TIMEOUT; } - } while (interlocked_cmpxchg( (int *)lock, new, old ) != old); + } while (interlocked_cmpxchg( futex, new, old ) != old);
return ret; }
static NTSTATUS fast_acquire_srw_exclusive( RTL_SRWLOCK *lock ) { - int old, new; + int old, new, *futex; BOOLEAN wait;
if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
+ if (!(futex = get_futex( &lock->Ptr ))) + return STATUS_NOT_IMPLEMENTED; + /* Atomically increment the exclusive waiter count. */ do { - old = *(int *)lock; + old = *futex; new = old + SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_INC; assert(new & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK); - } while (interlocked_cmpxchg( (int *)lock, new, old ) != old); + } while (interlocked_cmpxchg( futex, new, old ) != old);
for (;;) { do { - old = *(int *)lock; + old = *futex;
if (!(old & SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT) && !(old & SRWLOCK_FUTEX_SHARED_OWNERS_MASK)) @@ -1759,12 +1765,12 @@ static NTSTATUS fast_acquire_srw_exclusive( RTL_SRWLOCK *lock ) new = old; wait = TRUE; } - } while (interlocked_cmpxchg( (int *)lock, new, old ) != old); + } while (interlocked_cmpxchg( futex, new, old ) != old);
if (!wait) return STATUS_SUCCESS;
- futex_wait_bitset( (int *)lock, new, NULL, SRWLOCK_FUTEX_BITSET_EXCLUSIVE ); + futex_wait_bitset( futex, new, NULL, SRWLOCK_FUTEX_BITSET_EXCLUSIVE ); }
return STATUS_SUCCESS; @@ -1772,14 +1778,17 @@ static NTSTATUS fast_acquire_srw_exclusive( RTL_SRWLOCK *lock )
static NTSTATUS fast_try_acquire_srw_shared( RTL_SRWLOCK *lock ) { - int new, old; + int new, old, *futex; NTSTATUS ret;
if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
+ if (!(futex = get_futex( &lock->Ptr ))) + return STATUS_NOT_IMPLEMENTED; + do { - old = *(int *)lock; + old = *futex;
if (!(old & SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT) && !(old & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK)) @@ -1795,23 +1804,26 @@ static NTSTATUS fast_try_acquire_srw_shared( RTL_SRWLOCK *lock ) new = old; ret = STATUS_TIMEOUT; } - } while (interlocked_cmpxchg( (int *)lock, new, old ) != old); + } while (interlocked_cmpxchg( futex, new, old ) != old);
return ret; }
static NTSTATUS fast_acquire_srw_shared( RTL_SRWLOCK *lock ) { - int old, new; + int old, new, *futex; BOOLEAN wait;
if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
+ if (!(futex = get_futex( &lock->Ptr ))) + return STATUS_NOT_IMPLEMENTED; + for (;;) { do { - old = *(int *)lock; + old = *futex;
if (!(old & SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT) && !(old & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK)) @@ -1827,12 +1839,12 @@ static NTSTATUS fast_acquire_srw_shared( RTL_SRWLOCK *lock ) new = old | SRWLOCK_FUTEX_SHARED_WAITERS_BIT; wait = TRUE; } - } while (interlocked_cmpxchg( (int *)lock, new, old ) != old); + } while (interlocked_cmpxchg( futex, new, old ) != old);
if (!wait) return STATUS_SUCCESS;
- futex_wait_bitset( (int *)lock, new, NULL, SRWLOCK_FUTEX_BITSET_SHARED ); + futex_wait_bitset( futex, new, NULL, SRWLOCK_FUTEX_BITSET_SHARED ); }
return STATUS_SUCCESS; @@ -1840,17 +1852,20 @@ static NTSTATUS fast_acquire_srw_shared( RTL_SRWLOCK *lock )
static NTSTATUS fast_release_srw_exclusive( RTL_SRWLOCK *lock ) { - int old, new; + int old, new, *futex;
if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
+ if (!(futex = get_futex( &lock->Ptr ))) + return STATUS_NOT_IMPLEMENTED; + do { - old = *(int *)lock; + old = *futex;
if (!(old & SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT)) { - ERR("Lock %p is not owned exclusive! (%#x)\n", lock, *(int *)lock); + ERR("Lock %p is not owned exclusive! (%#x)\n", lock, *futex); return STATUS_RESOURCE_NOT_OWNED; }
@@ -1858,43 +1873,46 @@ static NTSTATUS fast_release_srw_exclusive( RTL_SRWLOCK *lock )
if (!(new & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK)) new &= ~SRWLOCK_FUTEX_SHARED_WAITERS_BIT; - } while (interlocked_cmpxchg( (int *)lock, new, old ) != old); + } while (interlocked_cmpxchg( futex, new, old ) != old);
if (new & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK) - futex_wake_bitset( (int *)lock, 1, SRWLOCK_FUTEX_BITSET_EXCLUSIVE ); + futex_wake_bitset( futex, 1, SRWLOCK_FUTEX_BITSET_EXCLUSIVE ); else if (old & SRWLOCK_FUTEX_SHARED_WAITERS_BIT) - futex_wake_bitset( (int *)lock, INT_MAX, SRWLOCK_FUTEX_BITSET_SHARED ); + futex_wake_bitset( futex, INT_MAX, SRWLOCK_FUTEX_BITSET_SHARED );
return STATUS_SUCCESS; }
static NTSTATUS fast_release_srw_shared( RTL_SRWLOCK *lock ) { - int old, new; + int old, new, *futex;
if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
+ if (!(futex = get_futex( &lock->Ptr ))) + return STATUS_NOT_IMPLEMENTED; + do { - old = *(int *)lock; + old = *futex;
if (old & SRWLOCK_FUTEX_EXCLUSIVE_LOCK_BIT) { - ERR("Lock %p is owned exclusive! (%#x)\n", lock, *(int *)lock); + ERR("Lock %p is owned exclusive! (%#x)\n", lock, *futex); return STATUS_RESOURCE_NOT_OWNED; } else if (!(old & SRWLOCK_FUTEX_SHARED_OWNERS_MASK)) { - ERR("Lock %p is not owned shared! (%#x)\n", lock, *(int *)lock); + ERR("Lock %p is not owned shared! (%#x)\n", lock, *futex); return STATUS_RESOURCE_NOT_OWNED; }
new = old - SRWLOCK_FUTEX_SHARED_OWNERS_INC; - } while (interlocked_cmpxchg( (int *)lock, new, old ) != old); + } while (interlocked_cmpxchg( futex, new, old ) != old);
/* Optimization: only bother waking if there are actually exclusive waiters. */ if (!(new & SRWLOCK_FUTEX_SHARED_OWNERS_MASK) && (new & SRWLOCK_FUTEX_EXCLUSIVE_WAITERS_MASK)) - futex_wake_bitset( (int *)lock, 1, SRWLOCK_FUTEX_BITSET_EXCLUSIVE ); + futex_wake_bitset( futex, 1, SRWLOCK_FUTEX_BITSET_EXCLUSIVE );
return STATUS_SUCCESS; }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=62679
Your paranoid android.
=== debian10 (32 bit report) ===
kernel32: sync.c:2371: Test failed: thread commands were executed in the wrong order (occurred 9 times). sync.c:2375: Test failed: AcquireSRWLockExclusive didn't block when called multiple times from the same thread (occurred 2 times). sync.c:2379: Test failed: AcquireSRWLockShared didn't block when the same thread holds an exclusive lock (occurred 2 times). sync.c:2383: Test failed: AcquireSRWLockExclusive didn't block when the same thread holds a shared lock (occurred 2 times). sync.c:2387: Test failed: AcquireSRWLockExclusive didn't block when a second thread holds the exclusive lock (occurred 2 times). sync.c:2391: Test failed: thread waiting for exclusive access to the SHMLock was not preferred (occurred 2 times).
=== debian10 (32 bit French report) ===
kernel32: sync.c:2371: Test failed: thread commands were executed in the wrong order (occurred 11 times). sync.c:2375: Test failed: AcquireSRWLockExclusive didn't block when called multiple times from the same thread (occurred 2 times). sync.c:2379: Test failed: AcquireSRWLockShared didn't block when the same thread holds an exclusive lock (occurred 2 times). sync.c:2383: Test failed: AcquireSRWLockExclusive didn't block when the same thread holds a shared lock (occurred 2 times). sync.c:2387: Test failed: AcquireSRWLockExclusive didn't block when a second thread holds the exclusive lock (occurred 2 times). sync.c:2391: Test failed: thread waiting for exclusive access to the SHMLock was not preferred (occurred 3 times).
=== debian10 (32 bit Japanese:Japan report) ===
kernel32: sync.c:2371: Test failed: thread commands were executed in the wrong order (occurred 9 times). sync.c:2375: Test failed: AcquireSRWLockExclusive didn't block when called multiple times from the same thread (occurred 2 times). sync.c:2379: Test failed: AcquireSRWLockShared didn't block when the same thread holds an exclusive lock (occurred 2 times). sync.c:2383: Test failed: AcquireSRWLockExclusive didn't block when the same thread holds a shared lock (occurred 2 times). sync.c:2387: Test failed: AcquireSRWLockExclusive didn't block when a second thread holds the exclusive lock (occurred 2 times). sync.c:2391: Test failed: thread waiting for exclusive access to the SHMLock was not preferred (occurred 2 times).
=== debian10 (32 bit Chinese:China report) ===
kernel32: sync.c:2371: Test failed: thread commands were executed in the wrong order (occurred 11 times). sync.c:2375: Test failed: AcquireSRWLockExclusive didn't block when called multiple times from the same thread (occurred 2 times). sync.c:2379: Test failed: AcquireSRWLockShared didn't block when the same thread holds an exclusive lock (occurred 2 times). sync.c:2383: Test failed: AcquireSRWLockExclusive didn't block when the same thread holds a shared lock (occurred 2 times). sync.c:2387: Test failed: AcquireSRWLockExclusive didn't block when a second thread holds the exclusive lock (occurred 2 times). sync.c:2391: Test failed: thread waiting for exclusive access to the SHMLock was not preferred (occurred 3 times).
=== debian10 (32 bit WoW report) ===
kernel32: sync.c:2371: Test failed: thread commands were executed in the wrong order (occurred 9 times). sync.c:2375: Test failed: AcquireSRWLockExclusive didn't block when called multiple times from the same thread (occurred 2 times). sync.c:2379: Test failed: AcquireSRWLockShared didn't block when the same thread holds an exclusive lock (occurred 2 times). sync.c:2383: Test failed: AcquireSRWLockExclusive didn't block when the same thread holds a shared lock (occurred 2 times). sync.c:2387: Test failed: AcquireSRWLockExclusive didn't block when a second thread holds the exclusive lock (occurred 2 times). sync.c:2391: Test failed: thread waiting for exclusive access to the SHMLock was not preferred (occurred 2 times).
=== debian10 (64 bit WoW report) ===
kernel32: sync.c:2371: Test failed: thread commands were executed in the wrong order (occurred 9 times). sync.c:2375: Test failed: AcquireSRWLockExclusive didn't block when called multiple times from the same thread (occurred 2 times). sync.c:2379: Test failed: AcquireSRWLockShared didn't block when the same thread holds an exclusive lock (occurred 2 times). sync.c:2383: Test failed: AcquireSRWLockExclusive didn't block when the same thread holds a shared lock (occurred 2 times). sync.c:2387: Test failed: AcquireSRWLockExclusive didn't block when a second thread holds the exclusive lock (occurred 2 times). sync.c:2391: Test failed: thread waiting for exclusive access to the SHMLock was not preferred (occurred 2 times).