From aae4ecb64fea01acde1b44c95f063acd29f74a7e Mon Sep 17 00:00:00 2001 From: Zebediah Figura 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 --- 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 | 5 +- 5 files changed, 24 insertions(+), 131 deletions(-) diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c index 09975ac3d45..97a5ce7fffa 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -765,19 +765,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; } /****************************************************************************** @@ -867,8 +874,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; @@ -944,12 +949,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 aff4594ab46..38a18d9c949 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -1691,9 +1691,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 41005425a90..6b97028fb68 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -2409,115 +2409,6 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG } -#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, ×pec ) == -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 d056b1500c9..4033d8fee76 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -98,9 +98,6 @@ extern void (WINAPI *pKiUserApcDispatcher)(CONTEXT*,ULONG_PTR,ULONG_PTR,ULON extern NTSTATUS (WINAPI *pKiUserExceptionDispatcher)(EXCEPTION_RECORD*,CONTEXT*) DECLSPEC_HIDDEN; 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 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 e84b6052378..f9c024d2e78 100644 --- a/dlls/ntdll/unixlib.h +++ b/dlls/ntdll/unixlib.h @@ -26,7 +26,7 @@ struct _DISPATCHER_CONTEXT; /* increment this when you change the function table */ -#define NTDLL_UNIXLIB_VERSION 116 +#define NTDLL_UNIXLIB_VERSION 117 struct unix_funcs { @@ -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.20.1