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 | 117 +++++++++++++++++++++++++++++++------ 2 files changed, 144 insertions(+), 49 deletions(-)
diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c index 6426d7cc6fb..8cdb7f10887 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c @@ -2241,10 +2241,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. @@ -2264,28 +2272,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);
@@ -2295,36 +2306,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()); @@ -2334,33 +2347,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");
@@ -2374,25 +2387,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");
@@ -2400,12 +2413,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"); @@ -2418,7 +2431,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"); @@ -2427,23 +2440,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 */
@@ -3252,7 +3265,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 62a60362768..d7319405889 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; @@ -2227,35 +2237,98 @@ 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 +static NTSTATUS fast_sleep_srw_cv( RTL_CONDITION_VARIABLE *variable, + RTL_SRWLOCK *lock, const LARGE_INTEGER *timeout, ULONG flags ) +{ + return STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS fast_sleep_cs_cv( RTL_CONDITION_VARIABLE *variable, + RTL_CRITICAL_SECTION *cs, const LARGE_INTEGER *timeout ) +{ + return STATUS_NOT_IMPLEMENTED; +} + static NTSTATUS fast_wait_cv( RTL_CONDITION_VARIABLE *variable, int val, const LARGE_INTEGER *timeout ) { return STATUS_NOT_IMPLEMENTED; @@ -2300,9 +2373,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 ); + } }
/*********************************************************************** @@ -2312,9 +2387,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 ); + } }
/*********************************************************************** @@ -2336,15 +2413,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; }
@@ -2371,15 +2448,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/ntdll/sync.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c index d7319405889..a0a37b555e2 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -2026,11 +2026,11 @@ static NTSTATUS fast_release_srw_shared( RTL_SRWLOCK *lock ) #define SRWLOCK_RES_SHARED 0x00000001
#ifdef WORDS_BIGENDIAN -#define srwlock_key_exclusive(lock) (&lock->Ptr) -#define srwlock_key_shared(lock) ((void *)((char *)&lock->Ptr + 2)) +#define srwlock_key_exclusive(lock) ((void *)(((ULONG_PTR)&lock->Ptr + 1) & ~1)) +#define srwlock_key_shared(lock) ((void *)(((ULONG_PTR)&lock->Ptr + 3) & ~1)) #else -#define srwlock_key_exclusive(lock) ((void *)((char *)&lock->Ptr + 2)) -#define srwlock_key_shared(lock) (&lock->Ptr) +#define srwlock_key_exclusive(lock) ((void *)(((ULONG_PTR)&lock->Ptr + 3) & ~1)) +#define srwlock_key_shared(lock) ((void *)(((ULONG_PTR)&lock->Ptr + 1) & ~1)) #endif
static inline void srwlock_check_invalid( unsigned int val )
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=69494
Your paranoid android.
=== debiant (32 bit WoW report) ===
ntdll: threadpool.c:1419: Test failed: expected approximately 600 ticks, got 400
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 8cdb7f10887..bf4e4333edd 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c @@ -2467,7 +2467,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; @@ -2480,6 +2480,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 * @@ -2551,49 +2559,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);
@@ -2602,7 +2612,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) @@ -2610,125 +2620,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);
@@ -2738,12 +2750,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) @@ -2751,20 +2763,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); @@ -2772,47 +2784,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) @@ -2821,8 +2833,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 */ @@ -2830,10 +2844,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);
@@ -2849,7 +2863,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; @@ -2861,12 +2875,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) @@ -3268,7 +3283,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 a0a37b555e2..67dd4e65777 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -1746,14 +1746,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)) @@ -1767,31 +1770,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)) @@ -1807,12 +1813,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; @@ -1820,14 +1826,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)) @@ -1843,23 +1852,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)) @@ -1875,12 +1887,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; @@ -1888,17 +1900,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; }
@@ -1906,43 +1921,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=69495
Your paranoid android.
=== w864 (64 bit report) ===
kernel32: sync.c:1854: Test failed: SleepConditionVariableCS should still return TRUE on crit unlock delay
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=69493
Your paranoid android.
=== w1064v1809 (64 bit report) ===
kernel32: sync.c:1854: Test failed: SleepConditionVariableCS should still return TRUE on crit unlock delay