win32: Implement rtclock based on QueryPerformanceCounter
[pulseaudio-mirror.git] / src / pulse / timeval.c
blob10ba322f067236fa372f9fbf10021ad688e70a02
1 /***
2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as
9 published by the Free Software Foundation; either version 2.1 of the
10 License, or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 USA.
21 ***/
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include <stddef.h>
28 #include <sys/time.h>
30 #ifdef HAVE_WINDOWS_H
31 #include <windows.h>
32 #endif
34 #include <pulsecore/macro.h>
35 #include <pulsecore/core-util.h>
37 #include "timeval.h"
39 struct timeval *pa_gettimeofday(struct timeval *tv) {
40 pa_assert(tv);
42 #if defined(OS_IS_WIN32)
44 * Copied from implementation by Steven Edwards (LGPL).
45 * Found on wine mailing list.
47 #if defined(_MSC_VER) || defined(__BORLANDC__)
48 #define EPOCHFILETIME (116444736000000000i64)
49 #else
50 #define EPOCHFILETIME (116444736000000000LL)
51 #endif
52 FILETIME ft;
53 LARGE_INTEGER li;
54 int64_t t;
56 GetSystemTimeAsFileTime(&ft);
57 li.LowPart = ft.dwLowDateTime;
58 li.HighPart = ft.dwHighDateTime;
59 t = li.QuadPart; /* In 100-nanosecond intervals */
60 t -= EPOCHFILETIME; /* Offset to the Epoch time */
61 t /= 10; /* In microseconds */
62 tv->tv_sec = (time_t) (t / PA_USEC_PER_SEC);
63 tv->tv_usec = (suseconds_t) (t % PA_USEC_PER_SEC);
64 #elif defined(HAVE_GETTIMEOFDAY)
65 pa_assert_se(gettimeofday(tv, NULL) == 0);
66 #else
67 #error "Platform lacks gettimeofday() or equivalent function."
68 #endif
70 return tv;
73 pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) {
74 pa_usec_t r;
76 pa_assert(a);
77 pa_assert(b);
79 /* Check which whan is the earlier time and swap the two arguments if required. */
80 if (PA_UNLIKELY(pa_timeval_cmp(a, b) < 0)) {
81 const struct timeval *c;
82 c = a;
83 a = b;
84 b = c;
87 /* Calculate the second difference*/
88 r = ((pa_usec_t) a->tv_sec - (pa_usec_t) b->tv_sec) * PA_USEC_PER_SEC;
90 /* Calculate the microsecond difference */
91 if (a->tv_usec > b->tv_usec)
92 r += (pa_usec_t) a->tv_usec - (pa_usec_t) b->tv_usec;
93 else if (a->tv_usec < b->tv_usec)
94 r -= (pa_usec_t) b->tv_usec - (pa_usec_t) a->tv_usec;
96 return r;
99 int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) {
100 pa_assert(a);
101 pa_assert(b);
103 if (a->tv_sec < b->tv_sec)
104 return -1;
106 if (a->tv_sec > b->tv_sec)
107 return 1;
109 if (a->tv_usec < b->tv_usec)
110 return -1;
112 if (a->tv_usec > b->tv_usec)
113 return 1;
115 return 0;
118 pa_usec_t pa_timeval_age(const struct timeval *tv) {
119 struct timeval now;
120 pa_assert(tv);
122 return pa_timeval_diff(pa_gettimeofday(&now), tv);
125 struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v) {
126 time_t secs;
127 pa_assert(tv);
129 secs = (time_t) (v/PA_USEC_PER_SEC);
131 if (PA_UNLIKELY(tv->tv_sec > PA_INT_TYPE_MAX(time_t) - secs))
132 goto overflow;
134 tv->tv_sec += secs;
135 v -= (pa_usec_t) secs * PA_USEC_PER_SEC;
136 tv->tv_usec += (suseconds_t) v;
138 /* Normalize */
139 while ((pa_usec_t) tv->tv_usec >= PA_USEC_PER_SEC) {
141 if (PA_UNLIKELY(tv->tv_sec >= PA_INT_TYPE_MAX(time_t)))
142 goto overflow;
144 tv->tv_sec++;
145 tv->tv_usec -= (suseconds_t) PA_USEC_PER_SEC;
148 return tv;
150 overflow:
151 tv->tv_sec = PA_INT_TYPE_MAX(time_t);
152 tv->tv_usec = (suseconds_t) (PA_USEC_PER_SEC-1);
153 return tv;
156 struct timeval* pa_timeval_sub(struct timeval *tv, pa_usec_t v) {
157 time_t secs;
158 pa_assert(tv);
160 secs = (time_t) (v/PA_USEC_PER_SEC);
162 if (PA_UNLIKELY(tv->tv_sec < secs))
163 goto underflow;
165 tv->tv_sec -= secs;
166 v -= (pa_usec_t) secs * PA_USEC_PER_SEC;
168 if (tv->tv_usec >= (suseconds_t) v)
169 tv->tv_usec -= (suseconds_t) v;
170 else {
172 if (PA_UNLIKELY(tv->tv_sec <= 0))
173 goto underflow;
175 tv->tv_sec --;
176 tv->tv_usec += (suseconds_t) (PA_USEC_PER_SEC - v);
179 return tv;
181 underflow:
182 tv->tv_sec = 0;
183 tv->tv_usec = 0;
184 return tv;
187 struct timeval* pa_timeval_store(struct timeval *tv, pa_usec_t v) {
188 pa_assert(tv);
190 if (PA_UNLIKELY(v == PA_USEC_INVALID)) {
191 tv->tv_sec = PA_INT_TYPE_MAX(time_t);
192 tv->tv_usec = (suseconds_t) (PA_USEC_PER_SEC-1);
194 return tv;
197 tv->tv_sec = (time_t) (v / PA_USEC_PER_SEC);
198 tv->tv_usec = (suseconds_t) (v % PA_USEC_PER_SEC);
200 return tv;
203 pa_usec_t pa_timeval_load(const struct timeval *tv) {
205 if (PA_UNLIKELY(!tv))
206 return PA_USEC_INVALID;
208 return
209 (pa_usec_t) tv->tv_sec * PA_USEC_PER_SEC +
210 (pa_usec_t) tv->tv_usec;