Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
December 2019
- 73 participants
- 1394 messages
[PATCH] kernel32: Exclude IsBadStringPtrA() from relay traces.
by Zebediah Figura
It messes up 16-bit relay traces due to krnl386's use of debugstr_a().
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/kernel32/kernel32.spec | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index a87747bf61..c115fd3d75 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -971,7 +971,7 @@
@ stdcall IsBadHugeReadPtr(ptr long)
@ stdcall IsBadHugeWritePtr(ptr long)
@ stdcall IsBadReadPtr(ptr long)
-@ stdcall IsBadStringPtrA(ptr long)
+@ stdcall -norelay IsBadStringPtrA(ptr long)
@ stdcall IsBadStringPtrW(ptr long)
@ stdcall IsBadWritePtr(ptr long)
# @ stub IsCalendarLeapDay
--
2.24.1
Dec. 30, 2019
[PATCH v2 3/3] ntdll: Handle unaligned SRW locks when using futexes.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)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 efe9af8137..c76a854797 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;
}
--
2.24.1
Dec. 30, 2019
[PATCH v2 2/3] ntdll: Handle unaligned SRW locks when using keyed events.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)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 302b4cc7e0..efe9af8137 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -1978,11 +1978,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 )
--
2.24.1
Dec. 30, 2019
[PATCH v2 1/3] ntdll: Handle unaligned condition variables when using futexes.
by Zebediah Figura
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48389
Signed-off-by: Zebediah Figura <z.figura12(a)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 );
--
2.24.1
Dec. 30, 2019
Re: win32 on macOS
by Ken Thomases
On Dec 30, 2019, at 4:02 PM, Martin Storsjö <martin(a)martin.st> wrote:
>
> On Mon, 30 Dec 2019, Ken Thomases wrote:
>
>> Hi Fabian,
>>
>> On Dec 20, 2019, at 6:37 AM, Fabian Maurer <dark.shadow4(a)web.de> wrote:
>>>
>>> do you plan to continue to work on the custom compiler or do you want to work
>>> into a different direction using unpatched clang?
>>
>> For the near- and mid-term, we're probably going to continue using the custom compiler.
>
> Out of curiosity - are you planning on trying to upstream some of these modifications into upstream llvm/clang?
We plan to try, yes. It's not clear if they would be accepted, especially if the sole current use-case (Wine) is not going to accept depending on them.
-Ken
Dec. 30, 2019
Re: win32 on macOS
by Martin Storsjö
On Mon, 30 Dec 2019, Ken Thomases wrote:
> Hi Fabian,
>
> On Dec 20, 2019, at 6:37 AM, Fabian Maurer <dark.shadow4(a)web.de> wrote:
>>
>> do you plan to continue to work on the custom compiler or do you want to work
>> into a different direction using unpatched clang?
>
> For the near- and mid-term, we're probably going to continue using the
> custom compiler.
Out of curiosity - are you planning on trying to upstream some of these
modifications into upstream llvm/clang?
// Martin
Dec. 30, 2019
Re: win32 on macOS
by Ken Thomases
Hi Fabian,
On Dec 20, 2019, at 6:37 AM, Fabian Maurer <dark.shadow4(a)web.de> wrote:
>
> do you plan to continue to work on the custom compiler or do you want to work
> into a different direction using unpatched clang?
For the near- and mid-term, we're probably going to continue using the custom compiler.
Alexandre doesn't want an approach that requires the custom compiler in upstream Wine, so we'll presumably eventually need another approach. I think he basically wants to reduce the non-PE surface area far enough that it becomes feasible to manually write thunks at the PE/host interface.
I hope that answers your question.
-Ken
Dec. 30, 2019
Re: [PATCH 2/2] ntdll: Handle unaligned SRW locks when using futexes.
by Marvin
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).
Dec. 30, 2019
[PATCH 2/2] ntdll: Handle unaligned SRW locks when using futexes.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)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;
}
--
2.24.1
Dec. 30, 2019
[PATCH 1/2] ntdll: Handle unaligned condition variables when using futexes.
by Zebediah Figura
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48389
Signed-off-by: Zebediah Figura <z.figura12(a)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 );
--
2.24.1
Dec. 30, 2019