tgsi: break gigantic tgsi_scan_shader() function into pieces
[mesa.git] / src / gallium / auxiliary / os / os_time.c
index 84907215fe6ced1fd642d39cffeb3c80cd3ed373..3d2e4167222a5c31d978d31047fbaf4e51a2b164 100644 (file)
  */
 
 
-#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
@@ -55,74 +50,122 @@ extern VOID KeQuerySystemTime(PLARGE_INTEGER);
 
 
 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;
+}