diff options
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/Makefile.sources | 2 | ||||
-rw-r--r-- | src/util/meson.build | 2 | ||||
-rw-r--r-- | src/util/os_time.c | 191 | ||||
-rw-r--r-- | src/util/os_time.h | 130 |
4 files changed, 325 insertions, 0 deletions
diff --git a/src/util/Makefile.sources b/src/util/Makefile.sources index f8096feb232..104ecae8ed3 100644 --- a/src/util/Makefile.sources +++ b/src/util/Makefile.sources @@ -22,6 +22,8 @@ MESA_UTIL_FILES := \ macros.h \ mesa-sha1.c \ mesa-sha1.h \ + os_time.c \ + os_time.h \ sha1/sha1.c \ sha1/sha1.h \ ralloc.c \ diff --git a/src/util/meson.build b/src/util/meson.build index a9ab5bf545c..ac86c9e111e 100644 --- a/src/util/meson.build +++ b/src/util/meson.build @@ -46,6 +46,8 @@ files_mesa_util = files( 'macros.h', 'mesa-sha1.c', 'mesa-sha1.h', + 'os_time.c', + 'os_time.h', 'sha1/sha1.c', 'sha1/sha1.h', 'ralloc.c', diff --git a/src/util/os_time.c b/src/util/os_time.c new file mode 100644 index 00000000000..8d8291ff173 --- /dev/null +++ b/src/util/os_time.c @@ -0,0 +1,191 @@ +/************************************************************************** + * + * Copyright 2008-2010 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * @file + * OS independent time-manipulation functions. + * + * @author Jose Fonseca <[email protected]> + */ + +#include "os_time.h" + +/* TODO: fix this dependency */ +#include "gallium/include/pipe/p_config.h" + +#include "util/u_atomic.h" + +#if defined(PIPE_OS_UNIX) +# include <time.h> /* timeval */ +# include <sys/time.h> /* timeval */ +# include <sched.h> /* sched_yield */ +# include <errno.h> +#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) +# include <windows.h> +#else +# error Unsupported OS +#endif + + +int64_t +os_time_get_nano(void) +{ +#if defined(PIPE_OS_LINUX) + + struct timespec tv; + clock_gettime(CLOCK_MONOTONIC, &tv); + return tv.tv_nsec + tv.tv_sec*INT64_C(1000000000); + +#elif defined(PIPE_OS_UNIX) + + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_usec*INT64_C(1000) + tv.tv_sec*INT64_C(1000000000); + +#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) + + static LARGE_INTEGER frequency; + LARGE_INTEGER counter; + int64_t secs, nanosecs; + if(!frequency.QuadPart) + QueryPerformanceFrequency(&frequency); + QueryPerformanceCounter(&counter); + /* Compute seconds and nanoseconds parts separately to + * reduce severity of precision loss. + */ + secs = counter.QuadPart / frequency.QuadPart; + nanosecs = (counter.QuadPart % frequency.QuadPart) * INT64_C(1000000000) + / frequency.QuadPart; + return secs*INT64_C(1000000000) + nanosecs; + +#else + +#error Unsupported OS + +#endif +} + + + +void +os_time_sleep(int64_t usecs) +{ +#if defined(PIPE_OS_LINUX) + struct timespec time; + time.tv_sec = usecs / 1000000; + time.tv_nsec = (usecs % 1000000) * 1000; + while (clock_nanosleep(CLOCK_MONOTONIC, 0, &time, &time) == EINTR); + +#elif defined(PIPE_OS_UNIX) + usleep(usecs); + +#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) + DWORD dwMilliseconds = (DWORD) ((usecs + 999) / 1000); + /* Avoid Sleep(O) as that would cause to sleep for an undetermined duration */ + if (dwMilliseconds) { + Sleep(dwMilliseconds); + } +#else +# error Unsupported OS +#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 == OS_TIMEOUT_INFINITE || timeout > INT64_MAX) + return OS_TIMEOUT_INFINITE; + + time = os_time_get_nano(); + abs_timeout = time + (int64_t)timeout; + + /* Check for overflow. */ + if (abs_timeout < time) + return OS_TIMEOUT_INFINITE; + + return abs_timeout; +} + + +bool +os_wait_until_zero(volatile int *var, uint64_t timeout) +{ + if (!p_atomic_read(var)) + return true; + + if (!timeout) + return false; + + if (timeout == OS_TIMEOUT_INFINITE) { + while (p_atomic_read(var)) { +#if defined(PIPE_OS_UNIX) + sched_yield(); +#endif + } + return true; + } + else { + int64_t start_time = os_time_get_nano(); + int64_t end_time = start_time + timeout; + + while (p_atomic_read(var)) { + if (os_time_timeout(start_time, end_time, os_time_get_nano())) + return false; + +#if defined(PIPE_OS_UNIX) + sched_yield(); +#endif + } + return true; + } +} + + +bool +os_wait_until_zero_abs_timeout(volatile int *var, int64_t timeout) +{ + if (!p_atomic_read(var)) + return true; + + if (timeout == OS_TIMEOUT_INFINITE) + return os_wait_until_zero(var, OS_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/util/os_time.h b/src/util/os_time.h new file mode 100644 index 00000000000..049ab118db2 --- /dev/null +++ b/src/util/os_time.h @@ -0,0 +1,130 @@ +/************************************************************************** + * + * Copyright 2008-2010 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * @file + * OS independent time-manipulation functions. + * + * @author Jose Fonseca <[email protected]> + */ + +#ifndef _OS_TIME_H_ +#define _OS_TIME_H_ + +#include <stdbool.h> +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* must be equal to PIPE_TIMEOUT_INFINITE */ +#define OS_TIMEOUT_INFINITE 0xffffffffffffffffull + +/* + * Get the current time in nanoseconds from an unknown base. + */ +int64_t +os_time_get_nano(void); + + +/* + * Get the current time in microseconds from an unknown base. + */ +static inline int64_t +os_time_get(void) +{ + return os_time_get_nano() / 1000; +} + + +/* + * Sleep. + */ +void +os_time_sleep(int64_t usecs); + + +/* + * Helper function for detecting time outs, taking in account overflow. + * + * Returns true if the current time has elapsed beyond the specified interval. + */ +static inline bool +os_time_timeout(int64_t start, + int64_t end, + int64_t curr) +{ + if (start <= end) + return !(start <= curr && curr < end); + else + return !((start <= curr) || (curr < end)); +} + + +/** + * 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. + * OS_TIMEOUT_INFINITE is passed through unchanged. If the calculation + * overflows, OS_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. + * + * \param var variable + * \param timeout timeout in ns, can be anything from 0 (no wait) to + * OS_TIMEOUT_INFINITE (wait forever) + * \return true if the variable is zero + */ +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. OS_TIMEOUT_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 + +#endif /* _OS_TIME_H_ */ |