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:
parent
246dedaa09
commit
509ad75adb
|
@ -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( ×pec, timeout );
|
||||
ret = futex_wait( futex, val, ×pec );
|
||||
}
|
||||
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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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( ×pec, timeout );
|
||||
ret = futex_wait( futex, val, ×pec );
|
||||
}
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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[] );
|
||||
|
|
Loading…
Reference in New Issue