1b8e80941Smrg/**************************************************************************
2b8e80941Smrg *
3b8e80941Smrg * Copyright 2008-2010 VMware, Inc.
4b8e80941Smrg * All Rights Reserved.
5b8e80941Smrg *
6b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7b8e80941Smrg * copy of this software and associated documentation files (the
8b8e80941Smrg * "Software"), to deal in the Software without restriction, including
9b8e80941Smrg * without limitation the rights to use, copy, modify, merge, publish,
10b8e80941Smrg * distribute, sub license, and/or sell copies of the Software, and to
11b8e80941Smrg * permit persons to whom the Software is furnished to do so, subject to
12b8e80941Smrg * the following conditions:
13b8e80941Smrg *
14b8e80941Smrg * The above copyright notice and this permission notice (including the
15b8e80941Smrg * next paragraph) shall be included in all copies or substantial portions
16b8e80941Smrg * of the Software.
17b8e80941Smrg *
18b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19b8e80941Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20b8e80941Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21b8e80941Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22b8e80941Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23b8e80941Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24b8e80941Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25b8e80941Smrg *
26b8e80941Smrg **************************************************************************/
27b8e80941Smrg
28b8e80941Smrg/**
29b8e80941Smrg * @file
30b8e80941Smrg * OS independent time-manipulation functions.
31b8e80941Smrg *
32b8e80941Smrg * @author Jose Fonseca <jfonseca@vmware.com>
33b8e80941Smrg */
34b8e80941Smrg
35b8e80941Smrg#include "os_time.h"
36b8e80941Smrg
37b8e80941Smrg/* TODO: fix this dependency */
38b8e80941Smrg#include "gallium/include/pipe/p_config.h"
39b8e80941Smrg
40b8e80941Smrg#include "util/u_atomic.h"
41b8e80941Smrg
42b8e80941Smrg#if defined(PIPE_OS_UNIX)
43b8e80941Smrg#  include <unistd.h> /* usleep */
44b8e80941Smrg#  include <time.h> /* timeval */
45b8e80941Smrg#  include <sys/time.h> /* timeval */
46b8e80941Smrg#  include <sched.h> /* sched_yield */
47b8e80941Smrg#  include <errno.h>
48b8e80941Smrg#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
49b8e80941Smrg#  include <windows.h>
50b8e80941Smrg#else
51b8e80941Smrg#  error Unsupported OS
52b8e80941Smrg#endif
53b8e80941Smrg
54b8e80941Smrg
55b8e80941Smrgint64_t
56b8e80941Smrgos_time_get_nano(void)
57b8e80941Smrg{
58b8e80941Smrg#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD)
59b8e80941Smrg
60b8e80941Smrg   struct timespec tv;
61b8e80941Smrg   clock_gettime(CLOCK_MONOTONIC, &tv);
62b8e80941Smrg   return tv.tv_nsec + tv.tv_sec*INT64_C(1000000000);
63b8e80941Smrg
64b8e80941Smrg#elif defined(PIPE_OS_UNIX)
65b8e80941Smrg
66b8e80941Smrg   struct timeval tv;
67b8e80941Smrg   gettimeofday(&tv, NULL);
68b8e80941Smrg   return tv.tv_usec*INT64_C(1000) + tv.tv_sec*INT64_C(1000000000);
69b8e80941Smrg
70b8e80941Smrg#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
71b8e80941Smrg
72b8e80941Smrg   static LARGE_INTEGER frequency;
73b8e80941Smrg   LARGE_INTEGER counter;
74b8e80941Smrg   int64_t secs, nanosecs;
75b8e80941Smrg   if(!frequency.QuadPart)
76b8e80941Smrg      QueryPerformanceFrequency(&frequency);
77b8e80941Smrg   QueryPerformanceCounter(&counter);
78b8e80941Smrg   /* Compute seconds and nanoseconds parts separately to
79b8e80941Smrg    * reduce severity of precision loss.
80b8e80941Smrg    */
81b8e80941Smrg   secs = counter.QuadPart / frequency.QuadPart;
82b8e80941Smrg   nanosecs = (counter.QuadPart % frequency.QuadPart) * INT64_C(1000000000)
83b8e80941Smrg      / frequency.QuadPart;
84b8e80941Smrg   return secs*INT64_C(1000000000) + nanosecs;
85b8e80941Smrg
86b8e80941Smrg#else
87b8e80941Smrg
88b8e80941Smrg#error Unsupported OS
89b8e80941Smrg
90b8e80941Smrg#endif
91b8e80941Smrg}
92b8e80941Smrg
93b8e80941Smrg
94b8e80941Smrg
95b8e80941Smrgvoid
96b8e80941Smrgos_time_sleep(int64_t usecs)
97b8e80941Smrg{
98b8e80941Smrg#if defined(PIPE_OS_LINUX)
99b8e80941Smrg   struct timespec time;
100b8e80941Smrg   time.tv_sec = usecs / 1000000;
101b8e80941Smrg   time.tv_nsec = (usecs % 1000000) * 1000;
102b8e80941Smrg   while (clock_nanosleep(CLOCK_MONOTONIC, 0, &time, &time) == EINTR);
103b8e80941Smrg
104b8e80941Smrg#elif defined(PIPE_OS_UNIX)
105b8e80941Smrg   usleep(usecs);
106b8e80941Smrg
107b8e80941Smrg#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
108b8e80941Smrg   DWORD dwMilliseconds = (DWORD) ((usecs + 999) / 1000);
109b8e80941Smrg   /* Avoid Sleep(O) as that would cause to sleep for an undetermined duration */
110b8e80941Smrg   if (dwMilliseconds) {
111b8e80941Smrg      Sleep(dwMilliseconds);
112b8e80941Smrg   }
113b8e80941Smrg#else
114b8e80941Smrg#  error Unsupported OS
115b8e80941Smrg#endif
116b8e80941Smrg}
117b8e80941Smrg
118b8e80941Smrg
119b8e80941Smrg
120b8e80941Smrgint64_t
121b8e80941Smrgos_time_get_absolute_timeout(uint64_t timeout)
122b8e80941Smrg{
123b8e80941Smrg   int64_t time, abs_timeout;
124b8e80941Smrg
125b8e80941Smrg   /* Also check for the type upper bound. */
126b8e80941Smrg   if (timeout == OS_TIMEOUT_INFINITE || timeout > INT64_MAX)
127b8e80941Smrg      return OS_TIMEOUT_INFINITE;
128b8e80941Smrg
129b8e80941Smrg   time = os_time_get_nano();
130b8e80941Smrg   abs_timeout = time + (int64_t)timeout;
131b8e80941Smrg
132b8e80941Smrg   /* Check for overflow. */
133b8e80941Smrg   if (abs_timeout < time)
134b8e80941Smrg      return OS_TIMEOUT_INFINITE;
135b8e80941Smrg
136b8e80941Smrg   return abs_timeout;
137b8e80941Smrg}
138b8e80941Smrg
139b8e80941Smrg
140b8e80941Smrgbool
141b8e80941Smrgos_wait_until_zero(volatile int *var, uint64_t timeout)
142b8e80941Smrg{
143b8e80941Smrg   if (!p_atomic_read(var))
144b8e80941Smrg      return true;
145b8e80941Smrg
146b8e80941Smrg   if (!timeout)
147b8e80941Smrg      return false;
148b8e80941Smrg
149b8e80941Smrg   if (timeout == OS_TIMEOUT_INFINITE) {
150b8e80941Smrg      while (p_atomic_read(var)) {
151b8e80941Smrg#if defined(PIPE_OS_UNIX)
152b8e80941Smrg         sched_yield();
153b8e80941Smrg#endif
154b8e80941Smrg      }
155b8e80941Smrg      return true;
156b8e80941Smrg   }
157b8e80941Smrg   else {
158b8e80941Smrg      int64_t start_time = os_time_get_nano();
159b8e80941Smrg      int64_t end_time = start_time + timeout;
160b8e80941Smrg
161b8e80941Smrg      while (p_atomic_read(var)) {
162b8e80941Smrg         if (os_time_timeout(start_time, end_time, os_time_get_nano()))
163b8e80941Smrg            return false;
164b8e80941Smrg
165b8e80941Smrg#if defined(PIPE_OS_UNIX)
166b8e80941Smrg         sched_yield();
167b8e80941Smrg#endif
168b8e80941Smrg      }
169b8e80941Smrg      return true;
170b8e80941Smrg   }
171b8e80941Smrg}
172b8e80941Smrg
173b8e80941Smrg
174b8e80941Smrgbool
175b8e80941Smrgos_wait_until_zero_abs_timeout(volatile int *var, int64_t timeout)
176b8e80941Smrg{
177b8e80941Smrg   if (!p_atomic_read(var))
178b8e80941Smrg      return true;
179b8e80941Smrg
180b8e80941Smrg   if (timeout == OS_TIMEOUT_INFINITE)
181b8e80941Smrg      return os_wait_until_zero(var, OS_TIMEOUT_INFINITE);
182b8e80941Smrg
183b8e80941Smrg   while (p_atomic_read(var)) {
184b8e80941Smrg      if (os_time_get_nano() >= timeout)
185b8e80941Smrg         return false;
186b8e80941Smrg
187b8e80941Smrg#if defined(PIPE_OS_UNIX)
188b8e80941Smrg      sched_yield();
189b8e80941Smrg#endif
190b8e80941Smrg   }
191b8e80941Smrg   return true;
192b8e80941Smrg}
193