diff --git a/src/gallium/auxiliary/os/os_time.c b/src/gallium/auxiliary/os/os_time.c index bd09452df16..3d2e4167222 100644 --- a/src/gallium/auxiliary/os/os_time.c +++ b/src/gallium/auxiliary/os/os_time.c @@ -96,6 +96,26 @@ os_time_sleep(int64_t usecs) #endif +int64_t +os_time_get_absolute_timeout(uint64_t timeout) +{ + int64_t time, abs_timeout; + + /* Also check for the type upper bound. */ + if (timeout == PIPE_TIMEOUT_INFINITE || timeout > INT64_MAX) + return PIPE_TIMEOUT_INFINITE; + + time = os_time_get_nano(); + abs_timeout = time + (int64_t)timeout; + + /* Check for overflow. */ + if (abs_timeout < time) + return PIPE_TIMEOUT_INFINITE; + + return abs_timeout; +} + + bool os_wait_until_zero(volatile int *var, uint64_t timeout) { @@ -128,3 +148,24 @@ os_wait_until_zero(volatile int *var, uint64_t timeout) return true; } } + + +bool +os_wait_until_zero_abs_timeout(volatile int *var, int64_t timeout) +{ + if (!p_atomic_read(var)) + return true; + + if (timeout == PIPE_TIMEOUT_INFINITE) + return os_wait_until_zero(var, PIPE_TIMEOUT_INFINITE); + + while (p_atomic_read(var)) { + if (os_time_get_nano() >= timeout) + return false; + +#if defined(PIPE_OS_UNIX) + sched_yield(); +#endif + } + return true; +} diff --git a/src/gallium/auxiliary/os/os_time.h b/src/gallium/auxiliary/os/os_time.h index 2989af10fe2..21979a72ac5 100644 --- a/src/gallium/auxiliary/os/os_time.h +++ b/src/gallium/auxiliary/os/os_time.h @@ -94,6 +94,17 @@ os_time_timeout(int64_t start, } +/** + * Convert a relative timeout in nanoseconds into an absolute timeout, + * in other words, it returns current time + timeout. + * os_time_get_nano() must be monotonic. + * PIPE_TIMEOUT_INFINITE is passed through unchanged. If the calculation + * overflows, PIPE_TIMEOUT_INFINITE is returned. + */ +int64_t +os_time_get_absolute_timeout(uint64_t timeout); + + /** * Wait until the variable at the given memory location is zero. * @@ -105,6 +116,21 @@ os_time_timeout(int64_t start, bool os_wait_until_zero(volatile int *var, uint64_t timeout); + +/** + * Wait until the variable at the given memory location is zero. + * The timeout is the absolute time when the waiting should stop. If it is + * less than or equal to the current time, it only returns the status and + * doesn't wait. PIPE_TIME_INFINITE waits forever. This requires that + * os_time_get_nano is monotonic. + * + * \param var variable + * \param timeout the time in ns when the waiting should stop + * \return true if the variable is zero + */ +bool +os_wait_until_zero_abs_timeout(volatile int *var, int64_t timeout); + #ifdef __cplusplus } #endif