ntdll: Reimplement the critical section fast path on top of Win32 futexes.
Signed-off-by: Zebediah Figura <zfigura@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
6bdb914a25
commit
c577ce2671
|
@ -172,19 +172,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;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -274,8 +281,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;
|
||||
|
@ -351,12 +356,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;
|
||||
}
|
||||
|
|
|
@ -2145,9 +2145,6 @@ static struct unix_funcs unix_funcs =
|
|||
NtCurrentTeb,
|
||||
#endif
|
||||
RtlGetSystemTimePrecise,
|
||||
fast_RtlpWaitForCriticalSection,
|
||||
fast_RtlpUnWaitCriticalSection,
|
||||
fast_RtlDeleteCriticalSection,
|
||||
fast_RtlTryAcquireSRWLockExclusive,
|
||||
fast_RtlAcquireSRWLockExclusive,
|
||||
fast_RtlTryAcquireSRWLockShared,
|
||||
|
|
|
@ -2550,115 +2550,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, ×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:
|
||||
|
|
|
@ -100,10 +100,6 @@ extern void (WINAPI *pLdrInitializeThunk)(CONTEXT*,void**,ULONG_PTR,ULONG_PT
|
|||
extern void (WINAPI *pRtlUserThreadStart)( PRTL_THREAD_START_ROUTINE entry, void *arg ) DECLSPEC_HIDDEN;
|
||||
extern void (WINAPI *p__wine_ctrl_routine)(void *) DECLSPEC_HIDDEN;
|
||||
extern SYSTEM_DLL_INIT_BLOCK *pLdrSystemDllInitBlock 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;
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
struct _DISPATCHER_CONTEXT;
|
||||
|
||||
/* increment this when you change the function table */
|
||||
#define NTDLL_UNIXLIB_VERSION 129
|
||||
#define NTDLL_UNIXLIB_VERSION 130
|
||||
|
||||
struct unix_funcs
|
||||
{
|
||||
|
@ -39,9 +39,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 );
|
||||
|
|
Loading…
Reference in New Issue