Branch data Line data Source code
1 : : /***
2 : : This file is part of PulseAudio.
3 : :
4 : : Copyright 2004-2006 Lennart Poettering
5 : : Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6 : :
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.
11 : :
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.
16 : :
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 : : ***/
22 : :
23 : : #ifdef HAVE_CONFIG_H
24 : : #include <config.h>
25 : : #endif
26 : :
27 : : #include <stddef.h>
28 : : #include <sys/time.h>
29 : :
30 : : #ifdef HAVE_WINDOWS_H
31 : : #include <windows.h>
32 : : #endif
33 : :
34 : : #include <pulsecore/macro.h>
35 : : #include <pulsecore/core-util.h>
36 : :
37 : : #include "timeval.h"
38 : :
39 : 0 : struct timeval *pa_gettimeofday(struct timeval *tv) {
40 [ # # ]: 0 : pa_assert(tv);
41 : :
42 : : #if defined(OS_IS_WIN32)
43 : : /*
44 : : * Copied from implementation by Steven Edwards (LGPL).
45 : : * Found on wine mailing list.
46 : : */
47 : : #if defined(_MSC_VER) || defined(__BORLANDC__)
48 : : #define EPOCHFILETIME (116444736000000000i64)
49 : : #else
50 : : #define EPOCHFILETIME (116444736000000000LL)
51 : : #endif
52 : : {
53 : : FILETIME ft;
54 : : LARGE_INTEGER li;
55 : : int64_t t;
56 : :
57 : : GetSystemTimeAsFileTime(&ft);
58 : : li.LowPart = ft.dwLowDateTime;
59 : : li.HighPart = ft.dwHighDateTime;
60 : : t = li.QuadPart; /* In 100-nanosecond intervals */
61 : : t -= EPOCHFILETIME; /* Offset to the Epoch time */
62 : : t /= 10; /* In microseconds */
63 : : tv->tv_sec = (time_t) (t / PA_USEC_PER_SEC);
64 : : tv->tv_usec = (suseconds_t) (t % PA_USEC_PER_SEC);
65 : : }
66 : : #elif defined(HAVE_GETTIMEOFDAY)
67 [ # # ]: 0 : pa_assert_se(gettimeofday(tv, NULL) == 0);
68 : : #else
69 : : #error "Platform lacks gettimeofday() or equivalent function."
70 : : #endif
71 : :
72 : 0 : return tv;
73 : : }
74 : :
75 : 1 : pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) {
76 : : pa_usec_t r;
77 : :
78 [ - + ]: 1 : pa_assert(a);
79 [ - + ]: 1 : pa_assert(b);
80 : :
81 : : /* Check which is the earlier time and swap the two arguments if required. */
82 [ - + ]: 1 : if (PA_UNLIKELY(pa_timeval_cmp(a, b) < 0)) {
83 : : const struct timeval *c;
84 : 0 : c = a;
85 : 0 : a = b;
86 : 0 : b = c;
87 : : }
88 : :
89 : : /* Calculate the second difference*/
90 : 1 : r = ((pa_usec_t) a->tv_sec - (pa_usec_t) b->tv_sec) * PA_USEC_PER_SEC;
91 : :
92 : : /* Calculate the microsecond difference */
93 [ - + ]: 1 : if (a->tv_usec > b->tv_usec)
94 : 0 : r += (pa_usec_t) a->tv_usec - (pa_usec_t) b->tv_usec;
95 [ + - ]: 1 : else if (a->tv_usec < b->tv_usec)
96 : 1 : r -= (pa_usec_t) b->tv_usec - (pa_usec_t) a->tv_usec;
97 : :
98 : 1 : return r;
99 : : }
100 : :
101 : 5 : int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) {
102 [ - + ]: 5 : pa_assert(a);
103 [ - + ]: 5 : pa_assert(b);
104 : :
105 [ + + ]: 5 : if (a->tv_sec < b->tv_sec)
106 : : return -1;
107 : :
108 [ + + ]: 3 : if (a->tv_sec > b->tv_sec)
109 : : return 1;
110 : :
111 [ - + ]: 1 : if (a->tv_usec < b->tv_usec)
112 : : return -1;
113 : :
114 [ # # ]: 0 : if (a->tv_usec > b->tv_usec)
115 : : return 1;
116 : :
117 : 5 : return 0;
118 : : }
119 : :
120 : 0 : pa_usec_t pa_timeval_age(const struct timeval *tv) {
121 : : struct timeval now;
122 [ # # ]: 0 : pa_assert(tv);
123 : :
124 : 0 : return pa_timeval_diff(pa_gettimeofday(&now), tv);
125 : : }
126 : :
127 : 2 : struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v) {
128 : : time_t secs;
129 [ - + ]: 2 : pa_assert(tv);
130 : :
131 : 2 : secs = (time_t) (v/PA_USEC_PER_SEC);
132 : :
133 [ + - ]: 2 : if (PA_UNLIKELY(tv->tv_sec > PA_INT_TYPE_MAX(time_t) - secs))
134 : : goto overflow;
135 : :
136 : 2 : tv->tv_sec += secs;
137 : 2 : v -= (pa_usec_t) secs * PA_USEC_PER_SEC;
138 : 2 : tv->tv_usec += (suseconds_t) v;
139 : :
140 : : /* Normalize */
141 [ - + ]: 2 : while ((pa_usec_t) tv->tv_usec >= PA_USEC_PER_SEC) {
142 : :
143 [ # # ]: 0 : if (PA_UNLIKELY(tv->tv_sec >= PA_INT_TYPE_MAX(time_t)))
144 : : goto overflow;
145 : :
146 : 0 : tv->tv_sec++;
147 : 0 : tv->tv_usec -= (suseconds_t) PA_USEC_PER_SEC;
148 : : }
149 : :
150 : : return tv;
151 : :
152 : : overflow:
153 : 0 : tv->tv_sec = PA_INT_TYPE_MAX(time_t);
154 : 0 : tv->tv_usec = (suseconds_t) (PA_USEC_PER_SEC-1);
155 : 2 : return tv;
156 : : }
157 : :
158 : 0 : struct timeval* pa_timeval_sub(struct timeval *tv, pa_usec_t v) {
159 : : time_t secs;
160 [ # # ]: 0 : pa_assert(tv);
161 : :
162 : 0 : secs = (time_t) (v/PA_USEC_PER_SEC);
163 : :
164 [ # # ]: 0 : if (PA_UNLIKELY(tv->tv_sec < secs))
165 : : goto underflow;
166 : :
167 : 0 : tv->tv_sec -= secs;
168 : 0 : v -= (pa_usec_t) secs * PA_USEC_PER_SEC;
169 : :
170 [ # # ]: 0 : if (tv->tv_usec >= (suseconds_t) v)
171 : 0 : tv->tv_usec -= (suseconds_t) v;
172 : : else {
173 : :
174 [ # # ]: 0 : if (PA_UNLIKELY(tv->tv_sec <= 0))
175 : : goto underflow;
176 : :
177 : 0 : tv->tv_sec --;
178 : 0 : tv->tv_usec += (suseconds_t) (PA_USEC_PER_SEC - v);
179 : : }
180 : :
181 : : return tv;
182 : :
183 : : underflow:
184 : 0 : tv->tv_sec = 0;
185 : 0 : tv->tv_usec = 0;
186 : 0 : return tv;
187 : : }
188 : :
189 : 5 : struct timeval* pa_timeval_store(struct timeval *tv, pa_usec_t v) {
190 [ - + ]: 5 : pa_assert(tv);
191 : :
192 [ - + ]: 5 : if (PA_UNLIKELY(v == PA_USEC_INVALID)) {
193 : 0 : tv->tv_sec = PA_INT_TYPE_MAX(time_t);
194 : 0 : tv->tv_usec = (suseconds_t) (PA_USEC_PER_SEC-1);
195 : :
196 : 0 : return tv;
197 : : }
198 : :
199 : 5 : tv->tv_sec = (time_t) (v / PA_USEC_PER_SEC);
200 : 5 : tv->tv_usec = (suseconds_t) (v % PA_USEC_PER_SEC);
201 : :
202 : 5 : return tv;
203 : : }
204 : :
205 : 9 : pa_usec_t pa_timeval_load(const struct timeval *tv) {
206 : :
207 [ + - ]: 9 : if (PA_UNLIKELY(!tv))
208 : : return PA_USEC_INVALID;
209 : :
210 : 9 : return
211 : 9 : (pa_usec_t) tv->tv_sec * PA_USEC_PER_SEC +
212 : 9 : (pa_usec_t) tv->tv_usec;
213 : : }
|