wine-staging/patches/ntdll-NtAlertThreadByThreadId/0009-ntdll-Reimplement-the-critical-section-fast-path-on-.patch
2021-06-17 10:06:41 +10:00

250 lines
8.9 KiB
Diff

From acfa81780932de0b511e0454056ad82d1fcccc98 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Mon, 31 Aug 2020 23:38:09 -0500
Subject: [PATCH] ntdll: Reimplement the critical section fast path on top of
Win32 futexes.
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
---
dlls/ntdll/sync.c | 35 +++++++----
dlls/ntdll/unix/loader.c | 3 -
dlls/ntdll/unix/sync.c | 109 ---------------------------------
dlls/ntdll/unix/unix_private.h | 3 -
dlls/ntdll/unixlib.h | 3 -
5 files changed, 23 insertions(+), 130 deletions(-)
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index c73fb09da47..6edf104c5e9 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -738,19 +738,26 @@ static inline HANDLE get_semaphore( RTL_CRITICAL_SECTION *crit )
static inline NTSTATUS wait_semaphore( RTL_CRITICAL_SECTION *crit, int timeout )
{
- NTSTATUS ret;
+ LARGE_INTEGER time = {.QuadPart = timeout * (LONGLONG)-10000000};
/* debug info is cleared by MakeCriticalSectionGlobal */
- if (!crit_section_has_debuginfo( crit ) ||
- ((ret = unix_funcs->fast_RtlpWaitForCriticalSection( crit, timeout )) == STATUS_NOT_IMPLEMENTED))
+ if (!crit_section_has_debuginfo( crit ))
{
HANDLE sem = get_semaphore( crit );
- LARGE_INTEGER time;
-
- time.QuadPart = timeout * (LONGLONG)-10000000;
- ret = NtWaitForSingleObject( sem, FALSE, &time );
+ return NtWaitForSingleObject( sem, FALSE, &time );
+ }
+ else
+ {
+ int *lock = (int *)&crit->LockSemaphore;
+ while (!InterlockedCompareExchange( lock, 0, 1 ))
+ {
+ static const int zero;
+ /* this may wait longer than specified in case of multiple wake-ups */
+ if (RtlWaitOnAddress( lock, &zero, sizeof(int), &time ) == STATUS_TIMEOUT)
+ return STATUS_TIMEOUT;
+ }
+ return STATUS_WAIT_0;
}
- return ret;
}
/******************************************************************************
@@ -840,8 +847,6 @@ NTSTATUS WINAPI RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit )
RtlFreeHeap( GetProcessHeap(), 0, crit->DebugInfo );
crit->DebugInfo = NULL;
}
- if (unix_funcs->fast_RtlDeleteCriticalSection( crit ) == STATUS_NOT_IMPLEMENTED)
- NtClose( crit->LockSemaphore );
}
else NtClose( crit->LockSemaphore );
crit->LockSemaphore = 0;
@@ -917,12 +922,18 @@ NTSTATUS WINAPI RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit )
NTSTATUS ret;
/* debug info is cleared by MakeCriticalSectionGlobal */
- if (!crit_section_has_debuginfo( crit ) ||
- ((ret = unix_funcs->fast_RtlpUnWaitCriticalSection( crit )) == STATUS_NOT_IMPLEMENTED))
+ if (!crit_section_has_debuginfo( crit ))
{
HANDLE sem = get_semaphore( crit );
ret = NtReleaseSemaphore( sem, 1, NULL );
}
+ else
+ {
+ int *lock = (int *)&crit->LockSemaphore;
+ InterlockedExchange( lock, 1 );
+ RtlWakeAddressSingle( lock );
+ ret = STATUS_SUCCESS;
+ }
if (ret) RtlRaiseStatus( ret );
return ret;
}
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c
index b51d726c5e4..063f48148d7 100644
--- a/dlls/ntdll/unix/loader.c
+++ b/dlls/ntdll/unix/loader.c
@@ -1822,9 +1822,6 @@ static struct unix_funcs unix_funcs =
#endif
DbgUiIssueRemoteBreakin,
RtlGetSystemTimePrecise,
- fast_RtlpWaitForCriticalSection,
- fast_RtlpUnWaitCriticalSection,
- fast_RtlDeleteCriticalSection,
fast_RtlTryAcquireSRWLockExclusive,
fast_RtlAcquireSRWLockExclusive,
fast_RtlTryAcquireSRWLockShared,
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index 5e49593fa4a..84f7c937be3 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -2553,115 +2553,6 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG
#endif
-#ifdef __linux__
-
-NTSTATUS CDECL fast_RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit, int timeout )
-{
- int val;
- struct timespec timespec;
-
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
-
- timespec.tv_sec = timeout;
- timespec.tv_nsec = 0;
- while ((val = InterlockedCompareExchange( (int *)&crit->LockSemaphore, 0, 1 )) != 1)
- {
- /* note: this may wait longer than specified in case of signals or */
- /* multiple wake-ups, but that shouldn't be a problem */
- if (futex_wait( (int *)&crit->LockSemaphore, val, &timespec ) == -1 && errno == ETIMEDOUT)
- return STATUS_TIMEOUT;
- }
- return STATUS_WAIT_0;
-}
-
-NTSTATUS CDECL fast_RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit )
-{
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
-
- *(int *)&crit->LockSemaphore = 1;
- futex_wake( (int *)&crit->LockSemaphore, 1 );
- return STATUS_SUCCESS;
-}
-
-NTSTATUS CDECL fast_RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit )
-{
- if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
- return STATUS_SUCCESS;
-}
-
-#elif defined(__APPLE__)
-
-static inline semaphore_t get_mach_semaphore( RTL_CRITICAL_SECTION *crit )
-{
- semaphore_t ret = *(int *)&crit->LockSemaphore;
- if (!ret)
- {
- semaphore_t sem;
- if (semaphore_create( mach_task_self(), &sem, SYNC_POLICY_FIFO, 0 )) return 0;
- if (!(ret = InterlockedCompareExchange( (int *)&crit->LockSemaphore, sem, 0 )))
- ret = sem;
- else
- semaphore_destroy( mach_task_self(), sem ); /* somebody beat us to it */
- }
- return ret;
-}
-
-NTSTATUS CDECL fast_RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit, int timeout )
-{
- mach_timespec_t timespec;
- semaphore_t sem = get_mach_semaphore( crit );
-
- timespec.tv_sec = timeout;
- timespec.tv_nsec = 0;
- for (;;)
- {
- switch( semaphore_timedwait( sem, timespec ))
- {
- case KERN_SUCCESS:
- return STATUS_WAIT_0;
- case KERN_ABORTED:
- continue; /* got a signal, restart */
- case KERN_OPERATION_TIMED_OUT:
- return STATUS_TIMEOUT;
- default:
- return STATUS_INVALID_HANDLE;
- }
- }
-}
-
-NTSTATUS CDECL fast_RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit )
-{
- semaphore_t sem = get_mach_semaphore( crit );
- semaphore_signal( sem );
- return STATUS_SUCCESS;
-}
-
-NTSTATUS CDECL fast_RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit )
-{
- semaphore_destroy( mach_task_self(), *(int *)&crit->LockSemaphore );
- return STATUS_SUCCESS;
-}
-
-#else /* __APPLE__ */
-
-NTSTATUS CDECL fast_RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit, int timeout )
-{
- return STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS CDECL fast_RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit )
-{
- return STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS CDECL fast_RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit )
-{
- return STATUS_NOT_IMPLEMENTED;
-}
-
-#endif
-
-
#ifdef __linux__
/* Futex-based SRW lock implementation:
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
index 9b27dc7ee7d..7460387c4bb 100644
--- a/dlls/ntdll/unix/unix_private.h
+++ b/dlls/ntdll/unix/unix_private.h
@@ -95,9 +95,6 @@ extern NTSTATUS (WINAPI *pKiUserExceptionDispatcher)(EXCEPTION_RECORD*,CONTEXT*)
extern void (WINAPI *pLdrInitializeThunk)(CONTEXT*,void**,ULONG_PTR,ULONG_PTR) DECLSPEC_HIDDEN;
extern void (WINAPI *pRtlUserThreadStart)( PRTL_THREAD_START_ROUTINE entry, void *arg ) DECLSPEC_HIDDEN;
extern void (WINAPI *p__wine_ctrl_routine)(void *) DECLSPEC_HIDDEN;
-extern NTSTATUS CDECL fast_RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit, int timeout ) DECLSPEC_HIDDEN;
-extern NTSTATUS CDECL fast_RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit ) DECLSPEC_HIDDEN;
-extern NTSTATUS CDECL fast_RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit ) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL fast_RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL fast_RtlAcquireSRWLockExclusive( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL fast_RtlTryAcquireSRWLockShared( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h
index 10b0f57fbed..37a0e2da83c 100644
--- a/dlls/ntdll/unixlib.h
+++ b/dlls/ntdll/unixlib.h
@@ -40,9 +40,6 @@ struct unix_funcs
LONGLONG (WINAPI *RtlGetSystemTimePrecise)(void);
/* fast locks */
- NTSTATUS (CDECL *fast_RtlpWaitForCriticalSection)( RTL_CRITICAL_SECTION *crit, int timeout );
- NTSTATUS (CDECL *fast_RtlpUnWaitCriticalSection)( RTL_CRITICAL_SECTION *crit );
- NTSTATUS (CDECL *fast_RtlDeleteCriticalSection)( RTL_CRITICAL_SECTION *crit );
NTSTATUS (CDECL *fast_RtlTryAcquireSRWLockExclusive)( RTL_SRWLOCK *lock );
NTSTATUS (CDECL *fast_RtlAcquireSRWLockExclusive)( RTL_SRWLOCK *lock );
NTSTATUS (CDECL *fast_RtlTryAcquireSRWLockShared)( RTL_SRWLOCK *lock );
--
2.30.2