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