*/
-#include "pipe/p_config.h"
+#include "pipe/p_defines.h"
+#include "util/u_atomic.h"
-#if !defined(PIPE_OS_EMBEDDED)
-
-#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) || defined(PIPE_OS_CYGWIN)
+#if defined(PIPE_OS_UNIX)
+# include <time.h> /* timeval */
# include <sys/time.h> /* timeval */
-#elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
-# include <windows.h>
-# include <winddi.h>
-#elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
-# include <windows.h>
-extern VOID KeQuerySystemTime(PLARGE_INTEGER);
-#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_SUBSYSTEM_WINDOWS_CE)
+# include <sched.h> /* sched_yield */
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
# include <windows.h>
#else
# error Unsupported OS
int64_t
-os_time_get(void)
+os_time_get_nano(void)
{
-#if defined(PIPE_OS_UNIX)
+#if defined(PIPE_OS_LINUX)
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return tv.tv_usec + tv.tv_sec*1000000LL;
+ struct timespec tv;
+ clock_gettime(CLOCK_MONOTONIC, &tv);
+ return tv.tv_nsec + tv.tv_sec*INT64_C(1000000000);
-#elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
+#elif defined(PIPE_OS_UNIX)
- static LONGLONG frequency;
- LONGLONG counter;
- if(!frequency)
- EngQueryPerformanceFrequency(&frequency);
- EngQueryPerformanceCounter(&counter);
- return counter*INT64_C(1000000)/frequency;
+ 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) || defined(PIPE_SUBSYSTEM_WINDOWS_CE)
+#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
static LARGE_INTEGER frequency;
LARGE_INTEGER counter;
if(!frequency.QuadPart)
QueryPerformanceFrequency(&frequency);
QueryPerformanceCounter(&counter);
- return counter.QuadPart*INT64_C(1000000)/frequency.QuadPart;
+ return counter.QuadPart*INT64_C(1000000000)/frequency.QuadPart;
-#elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
+#else
- /* Updated every 10 miliseconds, measured in units of 100 nanoseconds.
- * http://msdn.microsoft.com/en-us/library/ms801642.aspx */
- LARGE_INTEGER counter;
- KeQuerySystemTime(&counter);
- return counter.QuadPart/10;
+#error Unsupported OS
#endif
}
-#if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
+#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
void
os_time_sleep(int64_t usecs)
{
- static LONGLONG frequency;
- LONGLONG start, curr, end;
-
- EngQueryPerformanceCounter(&start);
-
- if(!frequency)
- EngQueryPerformanceFrequency(&frequency);
-
- end = start + (usecs * frequency + 999999LL)/1000000LL;
-
- do {
- EngQueryPerformanceCounter(&curr);
- } while(start <= curr && curr < end ||
- end < start && (curr < end || start <= curr));
+ DWORD dwMilliseconds = (DWORD) ((usecs + 999) / 1000);
+ /* Avoid Sleep(O) as that would cause to sleep for an undetermined duration */
+ if (dwMilliseconds) {
+ Sleep(dwMilliseconds);
+ }
}
-#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
+#endif
-void
-os_time_sleep(int64_t usecs)
+
+int64_t
+os_time_get_absolute_timeout(uint64_t timeout)
{
- Sleep((usecs + 999) / 1000);
+ 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)
+{
+ if (!p_atomic_read(var))
+ return true;
+
+ if (!timeout)
+ return false;
+
+ if (timeout == PIPE_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 == 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;
-#endif /* !PIPE_OS_EMBEDDED */
+#if defined(PIPE_OS_UNIX)
+ sched_yield();
+#endif
+ }
+ return true;
+}