mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
Added ntdll-futex-condition-var patchset
This commit is contained in:
parent
2e982e862f
commit
925645e710
@ -0,0 +1,213 @@
|
||||
From e50ac69d04c81813a52ac8959db34c4c40f047cb Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Tue, 24 Jul 2018 11:26:39 -0600
|
||||
Subject: [PATCH] ntdll: Add a futex-based condition variable implementation.
|
||||
|
||||
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
|
||||
---
|
||||
dlls/ntdll/sync.c | 143 +++++++++++++++++++++++++++++++++++++++++++++++++-----
|
||||
1 file changed, 132 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
|
||||
index 8e406ce..4752543 100644
|
||||
--- a/dlls/ntdll/sync.c
|
||||
+++ b/dlls/ntdll/sync.c
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
+#include <limits.h>
|
||||
#include <signal.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
# include <sys/time.h>
|
||||
@@ -36,6 +37,9 @@
|
||||
#ifdef HAVE_SYS_POLL_H
|
||||
# include <sys/poll.h>
|
||||
#endif
|
||||
+#ifdef HAVE_SYS_SYSCALL_H
|
||||
+# include <sys/syscall.h>
|
||||
+#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
@@ -61,6 +65,102 @@ WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
|
||||
|
||||
HANDLE keyed_event = NULL;
|
||||
|
||||
+#define TICKSPERSEC 10000000
|
||||
+
|
||||
+#ifdef __linux__
|
||||
+
|
||||
+static int wait_op = 128; /*FUTEX_WAIT|FUTEX_PRIVATE_FLAG*/
|
||||
+static int wake_op = 129; /*FUTEX_WAKE|FUTEX_PRIVATE_FLAG*/
|
||||
+
|
||||
+static inline int futex_wait( int *addr, int val, struct timespec *timeout )
|
||||
+{
|
||||
+ return syscall( __NR_futex, addr, wait_op, val, timeout, 0, 0 );
|
||||
+}
|
||||
+
|
||||
+static inline int futex_wake( int *addr, int val )
|
||||
+{
|
||||
+ return syscall( __NR_futex, addr, wake_op, val, NULL, 0, 0 );
|
||||
+}
|
||||
+
|
||||
+static inline int use_futexes(void)
|
||||
+{
|
||||
+ static int supported = -1;
|
||||
+
|
||||
+ if (supported == -1)
|
||||
+ {
|
||||
+ futex_wait( &supported, 10, NULL );
|
||||
+ if (errno == ENOSYS)
|
||||
+ {
|
||||
+ wait_op = 0; /*FUTEX_WAIT*/
|
||||
+ wake_op = 1; /*FUTEX_WAKE*/
|
||||
+ futex_wait( &supported, 10, NULL );
|
||||
+ }
|
||||
+ supported = (errno != ENOSYS);
|
||||
+ }
|
||||
+ return supported;
|
||||
+}
|
||||
+
|
||||
+static inline NTSTATUS fast_wait( RTL_CONDITION_VARIABLE *variable, const LARGE_INTEGER *timeout)
|
||||
+{
|
||||
+ int val, ret;
|
||||
+
|
||||
+ if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
|
||||
+
|
||||
+ if (timeout && timeout->QuadPart != TIMEOUT_INFINITE)
|
||||
+ {
|
||||
+ struct timespec timespec;
|
||||
+ LONGLONG duration;
|
||||
+
|
||||
+ if (timeout->QuadPart > 0)
|
||||
+ {
|
||||
+ LARGE_INTEGER now;
|
||||
+ NtQuerySystemTime( &now );
|
||||
+ duration = timeout->QuadPart - now.QuadPart;
|
||||
+ }
|
||||
+ else
|
||||
+ duration = -timeout->QuadPart;
|
||||
+
|
||||
+ timespec.tv_sec = duration / TICKSPERSEC;
|
||||
+ timespec.tv_nsec = (duration % TICKSPERSEC) * 100;
|
||||
+ do
|
||||
+ val = *((int *)&variable->Ptr);
|
||||
+ while (val && (ret = futex_wait( (int *)&variable->Ptr, val, ×pec )) == -1
|
||||
+ && errno == EAGAIN);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ do
|
||||
+ val = *((int *)&variable->Ptr);
|
||||
+ while (val && (ret = futex_wait( (int *)&variable->Ptr, val, NULL )) == -1
|
||||
+ && errno == EAGAIN);
|
||||
+ }
|
||||
+
|
||||
+ if (ret == -1 && errno == ETIMEDOUT) return STATUS_TIMEOUT;
|
||||
+ else if (ret == -1) FIXME("got errno %d %s\n", errno, strerror(errno));
|
||||
+
|
||||
+ return STATUS_WAIT_0;
|
||||
+}
|
||||
+
|
||||
+static inline NTSTATUS fast_wake( RTL_CONDITION_VARIABLE *variable, int val )
|
||||
+{
|
||||
+ if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
|
||||
+
|
||||
+ futex_wake( (int *)&variable->Ptr, val );
|
||||
+ return STATUS_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+#else
|
||||
+static inline NTSTATUS fast_wait( RTL_CRITICAL_SECTION *crit, int timeout )
|
||||
+{
|
||||
+ return STATUS_NOT_IMPLEMENTED;
|
||||
+}
|
||||
+
|
||||
+static inline NTSTATUS fast_wake( RTL_CRITICAL_SECTION *crit )
|
||||
+{
|
||||
+ return STATUS_NOT_IMPLEMENTED;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
static inline int interlocked_dec_if_nonzero( int *dest )
|
||||
{
|
||||
int val, tmp;
|
||||
@@ -1814,7 +1914,11 @@ void WINAPI RtlInitializeConditionVariable( RTL_CONDITION_VARIABLE *variable )
|
||||
void WINAPI RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable )
|
||||
{
|
||||
if (interlocked_dec_if_nonzero( (int *)&variable->Ptr ))
|
||||
- NtReleaseKeyedEvent( keyed_event, &variable->Ptr, FALSE, NULL );
|
||||
+ {
|
||||
+ NTSTATUS ret;
|
||||
+ if ((ret = fast_wake( variable, 1 )) == STATUS_NOT_IMPLEMENTED)
|
||||
+ NtReleaseKeyedEvent( keyed_event, &variable->Ptr, FALSE, NULL );
|
||||
+ }
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@@ -1825,8 +1929,15 @@ void WINAPI RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable )
|
||||
void WINAPI RtlWakeAllConditionVariable( RTL_CONDITION_VARIABLE *variable )
|
||||
{
|
||||
int val = interlocked_xchg( (int *)&variable->Ptr, 0 );
|
||||
- while (val-- > 0)
|
||||
- NtReleaseKeyedEvent( keyed_event, &variable->Ptr, FALSE, NULL );
|
||||
+ if (val)
|
||||
+ {
|
||||
+ NTSTATUS ret;
|
||||
+ if ((ret = fast_wake( variable, INT_MAX )) == STATUS_NOT_IMPLEMENTED)
|
||||
+ {
|
||||
+ while (val-- > 0)
|
||||
+ NtReleaseKeyedEvent( keyed_event, &variable->Ptr, FALSE, NULL );
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@@ -1851,12 +1962,17 @@ NTSTATUS WINAPI RtlSleepConditionVariableCS( RTL_CONDITION_VARIABLE *variable, R
|
||||
interlocked_xchg_add( (int *)&variable->Ptr, 1 );
|
||||
RtlLeaveCriticalSection( crit );
|
||||
|
||||
- status = NtWaitForKeyedEvent( keyed_event, &variable->Ptr, FALSE, timeout );
|
||||
- if (status != STATUS_SUCCESS)
|
||||
+ if ((status = fast_wait( variable, timeout )) == STATUS_NOT_IMPLEMENTED)
|
||||
{
|
||||
- if (!interlocked_dec_if_nonzero( (int *)&variable->Ptr ))
|
||||
- status = NtWaitForKeyedEvent( keyed_event, &variable->Ptr, FALSE, NULL );
|
||||
+ status = NtWaitForKeyedEvent( keyed_event, &variable->Ptr, FALSE, timeout );
|
||||
+ if (status != STATUS_SUCCESS)
|
||||
+ {
|
||||
+ if (!interlocked_dec_if_nonzero( (int *)&variable->Ptr ))
|
||||
+ status = NtWaitForKeyedEvent( keyed_event, &variable->Ptr, FALSE, NULL );
|
||||
+ }
|
||||
}
|
||||
+ else if (status != STATUS_SUCCESS)
|
||||
+ interlocked_dec_if_nonzero( (int *)&variable->Ptr );
|
||||
|
||||
RtlEnterCriticalSection( crit );
|
||||
return status;
|
||||
@@ -1892,12 +2008,17 @@ NTSTATUS WINAPI RtlSleepConditionVariableSRW( RTL_CONDITION_VARIABLE *variable,
|
||||
else
|
||||
RtlReleaseSRWLockExclusive( lock );
|
||||
|
||||
- status = NtWaitForKeyedEvent( keyed_event, &variable->Ptr, FALSE, timeout );
|
||||
- if (status != STATUS_SUCCESS)
|
||||
+ if ((status = fast_wait( variable, timeout )) == STATUS_NOT_IMPLEMENTED)
|
||||
{
|
||||
- if (!interlocked_dec_if_nonzero( (int *)&variable->Ptr ))
|
||||
- status = NtWaitForKeyedEvent( keyed_event, &variable->Ptr, FALSE, NULL );
|
||||
+ status = NtWaitForKeyedEvent( keyed_event, &variable->Ptr, FALSE, timeout );
|
||||
+ if (status != STATUS_SUCCESS)
|
||||
+ {
|
||||
+ if (!interlocked_dec_if_nonzero( (int *)&variable->Ptr ))
|
||||
+ status = NtWaitForKeyedEvent( keyed_event, &variable->Ptr, FALSE, NULL );
|
||||
+ }
|
||||
}
|
||||
+ else if (status != STATUS_SUCCESS)
|
||||
+ interlocked_dec_if_nonzero( (int *)&variable->Ptr );
|
||||
|
||||
if (flags & RTL_CONDITION_VARIABLE_LOCKMODE_SHARED)
|
||||
RtlAcquireSRWLockShared( lock );
|
||||
--
|
||||
2.7.4
|
||||
|
1
patches/ntdll-futex-condition-var/definition
Normal file
1
patches/ntdll-futex-condition-var/definition
Normal file
@ -0,0 +1 @@
|
||||
Fixes: [45524] Add a futex-based implementation of condition variables
|
@ -247,6 +247,7 @@ patch_enable_all ()
|
||||
enable_ntdll_WRITECOPY="$1"
|
||||
enable_ntdll_Wait_User_APC="$1"
|
||||
enable_ntdll_Zero_mod_name="$1"
|
||||
enable_ntdll_futex_condition_var="$1"
|
||||
enable_ntdll_set_full_cpu_context="$1"
|
||||
enable_ntoskrnl_Stubs="$1"
|
||||
enable_nvapi_Stub_DLL="$1"
|
||||
@ -914,6 +915,9 @@ patch_enable ()
|
||||
ntdll-Zero_mod_name)
|
||||
enable_ntdll_Zero_mod_name="$2"
|
||||
;;
|
||||
ntdll-futex-condition-var)
|
||||
enable_ntdll_futex_condition_var="$2"
|
||||
;;
|
||||
ntdll-set_full_cpu_context)
|
||||
enable_ntdll_set_full_cpu_context="$2"
|
||||
;;
|
||||
@ -5388,6 +5392,21 @@ if test "$enable_ntdll_Zero_mod_name" -eq 1; then
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset ntdll-futex-condition-var
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#45524] Add a futex-based implementation of condition variables
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/ntdll/sync.c
|
||||
# |
|
||||
if test "$enable_ntdll_futex_condition_var" -eq 1; then
|
||||
patch_apply ntdll-futex-condition-var/0001-ntdll-Add-a-futex-based-condition-variable-implement.patch
|
||||
(
|
||||
printf '%s\n' '+ { "Zebediah Figura", "ntdll: Add a futex-based condition variable implementation.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset ntdll-set_full_cpu_context
|
||||
# |
|
||||
# | Modified files:
|
||||
|
Loading…
Reference in New Issue
Block a user