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;
}
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 )
{
LARGE_INTEGER now;
@ -1437,105 +1427,6 @@ BOOLEAN WINAPI RtlTryAcquireSRWLockShared( RTL_SRWLOCK *lock )
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.@)
*
@ -1569,7 +1460,7 @@ void WINAPI RtlInitializeConditionVariable( 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 );
RtlWakeAddressSingle( variable );
@ -1583,7 +1474,7 @@ void WINAPI RtlWakeConditionVariable( 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 );
RtlWakeAddressAll( variable );
@ -1611,7 +1502,8 @@ NTSTATUS WINAPI RtlSleepConditionVariableCS( RTL_CONDITION_VARIABLE *variable, R
NTSTATUS status;
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;
val = *(int *)&variable->Ptr;
@ -1646,7 +1538,8 @@ NTSTATUS WINAPI RtlSleepConditionVariableSRW( RTL_CONDITION_VARIABLE *variable,
NTSTATUS status;
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;
val = *(int *)&variable->Ptr;

View File

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

View File

@ -67,6 +67,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(sync);
#define TICKSPERSEC 10000000
HANDLE keyed_event = 0;
@ -126,6 +127,23 @@ static int *get_futex(void **ptr)
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
@ -1260,6 +1278,86 @@ NTSTATUS CDECL fast_RtlReleaseSRWLockShared( RTL_SRWLOCK *lock )
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
NTSTATUS CDECL fast_RtlTryAcquireSRWLockExclusive( RTL_SRWLOCK *lock )
@ -1292,4 +1390,21 @@ NTSTATUS CDECL fast_RtlReleaseSRWLockShared( RTL_SRWLOCK *lock )
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

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_RtlReleaseSRWLockExclusive( 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_remove_reserved_area( void *addr, SIZE_T size ) DECLSPEC_HIDDEN;

View File

@ -28,7 +28,7 @@ struct ldt_copy;
struct msghdr;
/* increment this when you change the function table */
#define NTDLL_UNIXLIB_VERSION 35
#define NTDLL_UNIXLIB_VERSION 36
struct unix_funcs
{
@ -151,6 +151,13 @@ struct unix_funcs
NTSTATUS (CDECL *fast_RtlAcquireSRWLockShared)( RTL_SRWLOCK *lock );
NTSTATUS (CDECL *fast_RtlReleaseSRWLockExclusive)( 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 */
void (CDECL *get_main_args)( int *argc, char **argv[], char **envp[] );