ntdll: Move the futex-based condition variable implementation to the Unix library.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2020-06-09 12:38:37 +02:00
parent 246dedaa09
commit 509ad75adb
5 changed files with 138 additions and 114 deletions

View File

@ -105,16 +105,6 @@ static inline int use_futexes(void)
return supported; 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 ) static void timespec_from_timeout( struct timespec *timespec, const LARGE_INTEGER *timeout )
{ {
LARGE_INTEGER now; LARGE_INTEGER now;
@ -1437,105 +1427,6 @@ BOOLEAN WINAPI RtlTryAcquireSRWLockShared( RTL_SRWLOCK *lock )
return TRUE; return TRUE;
} }
#ifdef __linux__
static NTSTATUS fast_wait_cv( int *futex, int val, const LARGE_INTEGER *timeout )
{
struct timespec timespec;
int ret;
if (timeout && timeout->QuadPart != TIMEOUT_INFINITE)
{
timespec_from_timeout( &timespec, timeout );
ret = futex_wait( futex, val, &timespec );
}
else
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;
if (!(futex = get_futex( &variable->Ptr )))
return STATUS_NOT_IMPLEMENTED;
InterlockedIncrement( futex );
futex_wake( futex, count );
return STATUS_SUCCESS;
}
#else
static NTSTATUS fast_sleep_srw_cv( RTL_CONDITION_VARIABLE *variable,
RTL_SRWLOCK *lock, const LARGE_INTEGER *timeout, ULONG flags )
{
return STATUS_NOT_IMPLEMENTED;
}
static NTSTATUS fast_sleep_cs_cv( RTL_CONDITION_VARIABLE *variable,
RTL_CRITICAL_SECTION *cs, const LARGE_INTEGER *timeout )
{
return STATUS_NOT_IMPLEMENTED;
}
static NTSTATUS fast_wake_cv( RTL_CONDITION_VARIABLE *variable, int count )
{
return STATUS_NOT_IMPLEMENTED;
}
#endif
/*********************************************************************** /***********************************************************************
* RtlInitializeConditionVariable (NTDLL.@) * RtlInitializeConditionVariable (NTDLL.@)
* *
@ -1569,7 +1460,7 @@ void WINAPI RtlInitializeConditionVariable( RTL_CONDITION_VARIABLE *variable )
*/ */
void WINAPI RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable ) void WINAPI RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable )
{ {
if (fast_wake_cv( variable, 1 ) == STATUS_NOT_IMPLEMENTED) if (unix_funcs->fast_RtlWakeConditionVariable( variable, 1 ) == STATUS_NOT_IMPLEMENTED)
{ {
InterlockedIncrement( (int *)&variable->Ptr ); InterlockedIncrement( (int *)&variable->Ptr );
RtlWakeAddressSingle( variable ); RtlWakeAddressSingle( variable );
@ -1583,7 +1474,7 @@ void WINAPI RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable )
*/ */
void WINAPI RtlWakeAllConditionVariable( RTL_CONDITION_VARIABLE *variable ) void WINAPI RtlWakeAllConditionVariable( RTL_CONDITION_VARIABLE *variable )
{ {
if (fast_wake_cv( variable, INT_MAX ) == STATUS_NOT_IMPLEMENTED) if (unix_funcs->fast_RtlWakeConditionVariable( variable, INT_MAX ) == STATUS_NOT_IMPLEMENTED)
{ {
InterlockedIncrement( (int *)&variable->Ptr ); InterlockedIncrement( (int *)&variable->Ptr );
RtlWakeAddressAll( variable ); RtlWakeAddressAll( variable );
@ -1611,7 +1502,8 @@ NTSTATUS WINAPI RtlSleepConditionVariableCS( RTL_CONDITION_VARIABLE *variable, R
NTSTATUS status; NTSTATUS status;
int val; int val;
if ((status = fast_sleep_cs_cv( variable, crit, timeout )) != STATUS_NOT_IMPLEMENTED) if ((status = unix_funcs->fast_RtlSleepConditionVariableCS( variable, crit,
timeout )) != STATUS_NOT_IMPLEMENTED)
return status; return status;
val = *(int *)&variable->Ptr; val = *(int *)&variable->Ptr;
@ -1646,7 +1538,8 @@ NTSTATUS WINAPI RtlSleepConditionVariableSRW( RTL_CONDITION_VARIABLE *variable,
NTSTATUS status; NTSTATUS status;
int val; int val;
if ((status = fast_sleep_srw_cv( variable, lock, timeout, flags )) != STATUS_NOT_IMPLEMENTED) if ((status = unix_funcs->fast_RtlSleepConditionVariableSRW( variable, lock, timeout,
flags )) != STATUS_NOT_IMPLEMENTED)
return status; return status;
val = *(int *)&variable->Ptr; val = *(int *)&variable->Ptr;

View File

@ -1052,6 +1052,9 @@ static struct unix_funcs unix_funcs =
fast_RtlAcquireSRWLockShared, fast_RtlAcquireSRWLockShared,
fast_RtlReleaseSRWLockExclusive, fast_RtlReleaseSRWLockExclusive,
fast_RtlReleaseSRWLockShared, fast_RtlReleaseSRWLockShared,
fast_RtlSleepConditionVariableSRW,
fast_RtlSleepConditionVariableCS,
fast_RtlWakeConditionVariable,
get_main_args, get_main_args,
get_paths, get_paths,
get_dll_path, get_dll_path,

View File

@ -67,6 +67,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(sync); WINE_DEFAULT_DEBUG_CHANNEL(sync);
#define TICKSPERSEC 10000000
HANDLE keyed_event = 0; HANDLE keyed_event = 0;
@ -126,6 +127,23 @@ static int *get_futex(void **ptr)
return NULL; return NULL;
} }
static void timespec_from_timeout( struct timespec *timespec, const LARGE_INTEGER *timeout )
{
LARGE_INTEGER now;
timeout_t diff;
if (timeout->QuadPart > 0)
{
NtQuerySystemTime( &now );
diff = timeout->QuadPart - now.QuadPart;
}
else
diff = -timeout->QuadPart;
timespec->tv_sec = diff / TICKSPERSEC;
timespec->tv_nsec = (diff % TICKSPERSEC) * 100;
}
#endif #endif
@ -1260,6 +1278,86 @@ NTSTATUS CDECL fast_RtlReleaseSRWLockShared( RTL_SRWLOCK *lock )
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
static NTSTATUS wait_cv( int *futex, int val, const LARGE_INTEGER *timeout )
{
struct timespec timespec;
int ret;
if (timeout && timeout->QuadPart != TIMEOUT_INFINITE)
{
timespec_from_timeout( &timespec, timeout );
ret = futex_wait( futex, val, &timespec );
}
else
ret = futex_wait( futex, val, NULL );
if (ret == -1 && errno == ETIMEDOUT)
return STATUS_TIMEOUT;
return STATUS_WAIT_0;
}
NTSTATUS CDECL fast_RtlSleepConditionVariableCS( 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 = wait_cv( futex, val, timeout );
RtlEnterCriticalSection( cs );
return status;
}
NTSTATUS CDECL fast_RtlSleepConditionVariableSRW( 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 )) || !get_futex( &lock->Ptr ))
return STATUS_NOT_IMPLEMENTED;
val = *futex;
if (flags & RTL_CONDITION_VARIABLE_LOCKMODE_SHARED)
fast_RtlReleaseSRWLockShared( lock );
else
fast_RtlReleaseSRWLockExclusive( lock );
status = wait_cv( futex, val, timeout );
if (flags & RTL_CONDITION_VARIABLE_LOCKMODE_SHARED)
fast_RtlAcquireSRWLockShared( lock );
else
fast_RtlAcquireSRWLockExclusive( lock );
return status;
}
NTSTATUS CDECL fast_RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable, int count )
{
int *futex;
if (!use_futexes()) return STATUS_NOT_IMPLEMENTED;
if (!(futex = get_futex( &variable->Ptr )))
return STATUS_NOT_IMPLEMENTED;
InterlockedIncrement( futex );
futex_wake( futex, count );
return STATUS_SUCCESS;
}
#else #else
NTSTATUS CDECL fast_RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock ) NTSTATUS CDECL fast_RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
@ -1292,4 +1390,21 @@ NTSTATUS CDECL fast_RtlReleaseSRWLockShared( RTL_SRWLOCK *lock )
return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED;
} }
NTSTATUS CDECL fast_RtlSleepConditionVariableSRW( RTL_CONDITION_VARIABLE *variable, RTL_SRWLOCK *lock,
const LARGE_INTEGER *timeout, ULONG flags )
{
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS CDECL fast_RtlSleepConditionVariableCS( RTL_CONDITION_VARIABLE *variable,
RTL_CRITICAL_SECTION *cs, const LARGE_INTEGER *timeout )
{
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS CDECL fast_RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable, int count )
{
return STATUS_NOT_IMPLEMENTED;
}
#endif #endif

View File

@ -63,6 +63,12 @@ extern NTSTATUS CDECL fast_RtlTryAcquireSRWLockShared( RTL_SRWLOCK *lock ) DECLS
extern NTSTATUS CDECL fast_RtlAcquireSRWLockShared( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN; extern NTSTATUS CDECL fast_RtlAcquireSRWLockShared( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL fast_RtlReleaseSRWLockExclusive( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN; extern NTSTATUS CDECL fast_RtlReleaseSRWLockExclusive( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL fast_RtlReleaseSRWLockShared( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN; extern NTSTATUS CDECL fast_RtlReleaseSRWLockShared( RTL_SRWLOCK *lock ) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL fast_RtlSleepConditionVariableSRW( RTL_CONDITION_VARIABLE *variable, RTL_SRWLOCK *lock,
const LARGE_INTEGER *timeout, ULONG flags ) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL fast_RtlSleepConditionVariableCS( RTL_CONDITION_VARIABLE *variable,
RTL_CRITICAL_SECTION *cs,
const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL fast_RtlWakeConditionVariable( RTL_CONDITION_VARIABLE *variable, int count ) DECLSPEC_HIDDEN;
void CDECL mmap_add_reserved_area( void *addr, SIZE_T size ) DECLSPEC_HIDDEN; void CDECL mmap_add_reserved_area( void *addr, SIZE_T size ) DECLSPEC_HIDDEN;
void CDECL mmap_remove_reserved_area( void *addr, SIZE_T size ) DECLSPEC_HIDDEN; void CDECL mmap_remove_reserved_area( void *addr, SIZE_T size ) DECLSPEC_HIDDEN;

View File

@ -28,7 +28,7 @@ struct ldt_copy;
struct msghdr; struct msghdr;
/* increment this when you change the function table */ /* increment this when you change the function table */
#define NTDLL_UNIXLIB_VERSION 35 #define NTDLL_UNIXLIB_VERSION 36
struct unix_funcs struct unix_funcs
{ {
@ -151,6 +151,13 @@ struct unix_funcs
NTSTATUS (CDECL *fast_RtlAcquireSRWLockShared)( RTL_SRWLOCK *lock ); NTSTATUS (CDECL *fast_RtlAcquireSRWLockShared)( RTL_SRWLOCK *lock );
NTSTATUS (CDECL *fast_RtlReleaseSRWLockExclusive)( RTL_SRWLOCK *lock ); NTSTATUS (CDECL *fast_RtlReleaseSRWLockExclusive)( RTL_SRWLOCK *lock );
NTSTATUS (CDECL *fast_RtlReleaseSRWLockShared)( RTL_SRWLOCK *lock ); NTSTATUS (CDECL *fast_RtlReleaseSRWLockShared)( RTL_SRWLOCK *lock );
NTSTATUS (CDECL *fast_RtlSleepConditionVariableSRW)( RTL_CONDITION_VARIABLE *variable,
RTL_SRWLOCK *lock,
const LARGE_INTEGER *timeout, ULONG flags );
NTSTATUS (CDECL *fast_RtlSleepConditionVariableCS)( RTL_CONDITION_VARIABLE *variable,
RTL_CRITICAL_SECTION *cs,
const LARGE_INTEGER *timeout );
NTSTATUS (CDECL *fast_RtlWakeConditionVariable)( RTL_CONDITION_VARIABLE *variable, int count );
/* environment functions */ /* environment functions */
void (CDECL *get_main_args)( int *argc, char **argv[], char **envp[] ); void (CDECL *get_main_args)( int *argc, char **argv[], char **envp[] );