Skip to content

Commit

Permalink
ntdll: Use a 64-bit absolute timeout in futex2 operations.
Browse files Browse the repository at this point in the history
  • Loading branch information
zfigura authored and aeikum committed Jan 20, 2021
1 parent 661e343 commit f68a504
Showing 1 changed file with 81 additions and 47 deletions.
128 changes: 81 additions & 47 deletions dlls/ntdll/unix/fsync.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,17 @@ static inline void small_pause(void)
#endif
}

static LONGLONG update_timeout( ULONGLONG end )
{
LARGE_INTEGER now;
LONGLONG timeleft;

NtQuerySystemTime( &now );
timeleft = end - now.QuadPart;
if (timeleft < 0) timeleft = 0;
return timeleft;
}

/* futex2 experimental interface */

static long nr_futex2_wait, nr_futex2_waitv, nr_futex2_wake;
Expand All @@ -103,11 +114,43 @@ static inline int futex_wake( int *addr, int count )
return syscall( __NR_futex, addr, 1, count, NULL, 0, 0 );
}

static inline int futex_wait( int *addr, int val, struct timespec *timeout )
struct timespec64
{
long long tv_sec;
long long tv_nsec;
};

static inline int futex_wait( int *addr, int val, const ULONGLONG *end )
{
if (nr_futex2_wait)
return syscall( nr_futex2_wait, addr, val, FUTEX_32 | FUTEX_SHARED_FLAG, timeout );
return syscall( __NR_futex, addr, 0, val, timeout, 0, 0 );
{
if (end)
{
struct timespec64 timespec;
timespec.tv_sec = *end / (ULONGLONG)TICKSPERSEC;
timespec.tv_nsec = (*end % TICKSPERSEC) * 100;
return syscall( nr_futex2_wait, addr, val, FUTEX_32 | FUTEX_SHARED_FLAG, &timespec );
}
else
{
return syscall( nr_futex2_wait, addr, val, FUTEX_32 | FUTEX_SHARED_FLAG, NULL );
}
}
else
{
if (end)
{
LONGLONG timeleft = update_timeout( *end );
struct timespec timespec;
timespec.tv_sec = timeleft / (ULONGLONG)TICKSPERSEC;
timespec.tv_nsec = (timeleft % TICKSPERSEC) * 100;
return syscall( __NR_futex, addr, 0, val, &timespec, 0, 0 );
}
else
{
return syscall( __NR_futex, addr, 0, val, NULL, 0, 0 );
}
}
}

union futex_vector
Expand Down Expand Up @@ -138,12 +181,37 @@ static inline void futex_vector_set( union futex_vector *vector, unsigned int in
}
}

static inline int futex_wait_multiple( union futex_vector *vector,
unsigned int count, const struct timespec *timeout )
static inline int futex_wait_multiple( union futex_vector *vector, unsigned int count, const ULONGLONG *end )
{
if (nr_futex2_waitv)
return syscall( nr_futex2_waitv, &vector->futex2, count, 0, timeout );
return syscall( __NR_futex, &vector->futex, 31, count, timeout, 0, 0 );
{
if (end)
{
struct timespec64 timespec;
timespec.tv_sec = *end / (ULONGLONG)TICKSPERSEC;
timespec.tv_nsec = (*end % TICKSPERSEC) * 100;
return syscall( nr_futex2_waitv, &vector->futex2, count, 0, &timespec );
}
else
{
return syscall( nr_futex2_waitv, &vector->futex2, count, 0, NULL );
}
}
else
{
if (end)
{
LONGLONG timeleft = update_timeout( *end );
struct timespec timespec;
timespec.tv_sec = timeleft / (ULONGLONG)TICKSPERSEC;
timespec.tv_nsec = (timeleft % TICKSPERSEC) * 100;
return syscall( __NR_futex, &vector->futex, 31, count, &timespec, 0, 0 );
}
else
{
return syscall( __NR_futex, &vector->futex, 31, count, NULL, 0, 0 );
}
}
}

int do_fsync(void)
Expand Down Expand Up @@ -182,7 +250,7 @@ int do_fsync(void)
else
{
static const struct timespec zero;
futex_wait_multiple( NULL, 0, &zero );
syscall( __NR_futex, NULL, 31, 0, &zero, 0, 0 );
do_fsync_cached = (errno != ENOSYS);
}
do_fsync_cached = getenv("WINEFSYNC") && atoi(getenv("WINEFSYNC")) && do_fsync_cached;
Expand Down Expand Up @@ -727,18 +795,7 @@ NTSTATUS fsync_query_mutex( HANDLE handle, void *info, ULONG *ret_len )
return STATUS_SUCCESS;
}

static LONGLONG update_timeout( ULONGLONG end )
{
LARGE_INTEGER now;
LONGLONG timeleft;

NtQuerySystemTime( &now );
timeleft = end - now.QuadPart;
if (timeleft < 0) timeleft = 0;
return timeleft;
}

static NTSTATUS do_single_wait( int *addr, int val, ULONGLONG *end, BOOLEAN alertable )
static NTSTATUS do_single_wait( int *addr, int val, const ULONGLONG *end, BOOLEAN alertable )
{
int ret;

Expand All @@ -753,32 +810,14 @@ static NTSTATUS do_single_wait( int *addr, int val, ULONGLONG *end, BOOLEAN aler
futex_vector_set( &futexes, 0, addr, val );
futex_vector_set( &futexes, 1, apc_futex, 0 );

if (end)
{
LONGLONG timeleft = update_timeout( *end );
struct timespec tmo_p;
tmo_p.tv_sec = timeleft / (ULONGLONG)TICKSPERSEC;
tmo_p.tv_nsec = (timeleft % TICKSPERSEC) * 100;
ret = futex_wait_multiple( &futexes, 2, &tmo_p );
}
else
ret = futex_wait_multiple( &futexes, 2, NULL );
ret = futex_wait_multiple( &futexes, 2, end );

if (__atomic_load_n( apc_futex, __ATOMIC_SEQ_CST ))
return STATUS_USER_APC;
}
else
{
if (end)
{
LONGLONG timeleft = update_timeout( *end );
struct timespec tmo_p;
tmo_p.tv_sec = timeleft / (ULONGLONG)TICKSPERSEC;
tmo_p.tv_nsec = (timeleft % TICKSPERSEC) * 100;
ret = futex_wait( addr, val, &tmo_p );
}
else
ret = futex_wait( addr, val, NULL );
ret = futex_wait( addr, val, end );
}

if (!ret)
Expand Down Expand Up @@ -1026,15 +1065,10 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles,
}
else if (timeout)
{
LONGLONG timeleft = update_timeout( end );
struct timespec tmo_p;
tmo_p.tv_sec = timeleft / (ULONGLONG)TICKSPERSEC;
tmo_p.tv_nsec = (timeleft % TICKSPERSEC) * 100;

if (waitcount == 1)
ret = futex_wait( futexes.futex2[0].uaddr, futexes.futex2[0].val, &tmo_p );
ret = futex_wait( futexes.futex2[0].uaddr, futexes.futex2[0].val, &end );
else
ret = futex_wait_multiple( &futexes, waitcount, &tmo_p );
ret = futex_wait_multiple( &futexes, waitcount, &end );
}
else
{
Expand Down

0 comments on commit f68a504

Please sign in to comment.