1*2b15cb3dSCy Schubert /*
2*2b15cb3dSCy Schubert * timevalops.h -- calculations on 'struct timeval' values
3*2b15cb3dSCy Schubert *
4*2b15cb3dSCy Schubert * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project.
5*2b15cb3dSCy Schubert * The contents of 'html/copyright.html' apply.
6*2b15cb3dSCy Schubert *
7*2b15cb3dSCy Schubert * For a rationale look at 'timespecops.h'; we do the same here, but the
8*2b15cb3dSCy Schubert * normalisation keeps the microseconds in [0 .. 10^6[, of course.
9*2b15cb3dSCy Schubert */
10*2b15cb3dSCy Schubert #ifndef TIMEVALOPS_H
11*2b15cb3dSCy Schubert #define TIMEVALOPS_H
12*2b15cb3dSCy Schubert
13*2b15cb3dSCy Schubert #include <sys/types.h>
14*2b15cb3dSCy Schubert #include <stdio.h>
15*2b15cb3dSCy Schubert
16*2b15cb3dSCy Schubert #include "ntp.h"
17*2b15cb3dSCy Schubert #include "timetoa.h"
18*2b15cb3dSCy Schubert
19*2b15cb3dSCy Schubert
20*2b15cb3dSCy Schubert /* microseconds per second */
21*2b15cb3dSCy Schubert #define MICROSECONDS 1000000
22*2b15cb3dSCy Schubert
23*2b15cb3dSCy Schubert #ifndef HAVE_U_INT64
24*2b15cb3dSCy Schubert # define USE_TSF_USEC_TABLES
25*2b15cb3dSCy Schubert #endif
26*2b15cb3dSCy Schubert
27*2b15cb3dSCy Schubert /*
28*2b15cb3dSCy Schubert * Convert usec to a time stamp fraction.
29*2b15cb3dSCy Schubert */
30*2b15cb3dSCy Schubert #ifdef USE_TSF_USEC_TABLES
31*2b15cb3dSCy Schubert extern const u_int32 ustotslo[];
32*2b15cb3dSCy Schubert extern const u_int32 ustotsmid[];
33*2b15cb3dSCy Schubert extern const u_int32 ustotshi[];
34*2b15cb3dSCy Schubert
35*2b15cb3dSCy Schubert # define TVUTOTSF(tvu, tsf) \
36*2b15cb3dSCy Schubert ((tsf) = ustotslo[(tvu) & 0xff] \
37*2b15cb3dSCy Schubert + ustotsmid[((tvu) >> 8) & 0xff] \
38*2b15cb3dSCy Schubert + ustotshi[((tvu) >> 16) & 0xf])
39*2b15cb3dSCy Schubert #else
40*2b15cb3dSCy Schubert # define TVUTOTSF(tvu, tsf) \
41*2b15cb3dSCy Schubert ((tsf) = (u_int32) \
42*2b15cb3dSCy Schubert ((((u_int64)(tvu) << 32) + MICROSECONDS / 2) / \
43*2b15cb3dSCy Schubert MICROSECONDS))
44*2b15cb3dSCy Schubert #endif
45*2b15cb3dSCy Schubert
46*2b15cb3dSCy Schubert /*
47*2b15cb3dSCy Schubert * Convert a time stamp fraction to microseconds. The time stamp
48*2b15cb3dSCy Schubert * fraction is assumed to be unsigned.
49*2b15cb3dSCy Schubert */
50*2b15cb3dSCy Schubert #ifdef USE_TSF_USEC_TABLES
51*2b15cb3dSCy Schubert extern const u_int32 tstouslo[256];
52*2b15cb3dSCy Schubert extern const u_int32 tstousmid[256];
53*2b15cb3dSCy Schubert extern const u_int32 tstoushi[128];
54*2b15cb3dSCy Schubert
55*2b15cb3dSCy Schubert /*
56*2b15cb3dSCy Schubert * TV_SHIFT is used to turn the table result into a usec value. To
57*2b15cb3dSCy Schubert * round, add in TV_ROUNDBIT before shifting.
58*2b15cb3dSCy Schubert */
59*2b15cb3dSCy Schubert #define TV_SHIFT 3
60*2b15cb3dSCy Schubert #define TV_ROUNDBIT 0x4
61*2b15cb3dSCy Schubert
62*2b15cb3dSCy Schubert # define TSFTOTVU(tsf, tvu) \
63*2b15cb3dSCy Schubert ((tvu) = (tstoushi[((tsf) >> 24) & 0xff] \
64*2b15cb3dSCy Schubert + tstousmid[((tsf) >> 16) & 0xff] \
65*2b15cb3dSCy Schubert + tstouslo[((tsf) >> 9) & 0x7f] \
66*2b15cb3dSCy Schubert + TV_ROUNDBIT) >> TV_SHIFT)
67*2b15cb3dSCy Schubert #else
68*2b15cb3dSCy Schubert # define TSFTOTVU(tsf, tvu) \
69*2b15cb3dSCy Schubert ((tvu) = (int32) \
70*2b15cb3dSCy Schubert (((u_int64)(tsf) * MICROSECONDS + 0x80000000) >> 32))
71*2b15cb3dSCy Schubert #endif
72*2b15cb3dSCy Schubert
73*2b15cb3dSCy Schubert /*
74*2b15cb3dSCy Schubert * Convert a struct timeval to a time stamp.
75*2b15cb3dSCy Schubert */
76*2b15cb3dSCy Schubert #define TVTOTS(tv, ts) \
77*2b15cb3dSCy Schubert do { \
78*2b15cb3dSCy Schubert (ts)->l_ui = (u_long)(tv)->tv_sec; \
79*2b15cb3dSCy Schubert TVUTOTSF((tv)->tv_usec, (ts)->l_uf); \
80*2b15cb3dSCy Schubert } while (FALSE)
81*2b15cb3dSCy Schubert
82*2b15cb3dSCy Schubert #define sTVTOTS(tv, ts) \
83*2b15cb3dSCy Schubert do { \
84*2b15cb3dSCy Schubert int isneg = 0; \
85*2b15cb3dSCy Schubert long usec; \
86*2b15cb3dSCy Schubert (ts)->l_ui = (tv)->tv_sec; \
87*2b15cb3dSCy Schubert usec = (tv)->tv_usec; \
88*2b15cb3dSCy Schubert if (((tv)->tv_sec < 0) || ((tv)->tv_usec < 0)) { \
89*2b15cb3dSCy Schubert usec = -usec; \
90*2b15cb3dSCy Schubert (ts)->l_ui = -(ts)->l_ui; \
91*2b15cb3dSCy Schubert isneg = 1; \
92*2b15cb3dSCy Schubert } \
93*2b15cb3dSCy Schubert TVUTOTSF(usec, (ts)->l_uf); \
94*2b15cb3dSCy Schubert if (isneg) { \
95*2b15cb3dSCy Schubert L_NEG((ts)); \
96*2b15cb3dSCy Schubert } \
97*2b15cb3dSCy Schubert } while (FALSE)
98*2b15cb3dSCy Schubert
99*2b15cb3dSCy Schubert /*
100*2b15cb3dSCy Schubert * Convert a time stamp to a struct timeval. The time stamp
101*2b15cb3dSCy Schubert * has to be positive.
102*2b15cb3dSCy Schubert */
103*2b15cb3dSCy Schubert #define TSTOTV(ts, tv) \
104*2b15cb3dSCy Schubert do { \
105*2b15cb3dSCy Schubert (tv)->tv_sec = (ts)->l_ui; \
106*2b15cb3dSCy Schubert TSFTOTVU((ts)->l_uf, (tv)->tv_usec); \
107*2b15cb3dSCy Schubert if ((tv)->tv_usec == 1000000) { \
108*2b15cb3dSCy Schubert (tv)->tv_sec++; \
109*2b15cb3dSCy Schubert (tv)->tv_usec = 0; \
110*2b15cb3dSCy Schubert } \
111*2b15cb3dSCy Schubert } while (FALSE)
112*2b15cb3dSCy Schubert
113*2b15cb3dSCy Schubert
114*2b15cb3dSCy Schubert /*
115*2b15cb3dSCy Schubert * predicate: returns TRUE if the microseconds are in nominal range
116*2b15cb3dSCy Schubert * use like: int timeval_isnormal(const struct timeval *x)
117*2b15cb3dSCy Schubert */
118*2b15cb3dSCy Schubert #define timeval_isnormal(x) \
119*2b15cb3dSCy Schubert ((x)->tv_usec >= 0 && (x)->tv_usec < MICROSECONDS)
120*2b15cb3dSCy Schubert
121*2b15cb3dSCy Schubert /*
122*2b15cb3dSCy Schubert * Convert milliseconds to a time stamp fraction. Unused except for
123*2b15cb3dSCy Schubert * refclock_leitch.c, so accompanying lookup tables were removed in
124*2b15cb3dSCy Schubert * favor of reusing the microseconds conversion tables.
125*2b15cb3dSCy Schubert */
126*2b15cb3dSCy Schubert #define MSUTOTSF(msu, tsf) TVUTOTSF((msu) * 1000, tsf)
127*2b15cb3dSCy Schubert
128*2b15cb3dSCy Schubert /*
129*2b15cb3dSCy Schubert * predicate: returns TRUE if the microseconds are out-of-bounds
130*2b15cb3dSCy Schubert * use like: int timeval_isdenormal(const struct timeval *x)
131*2b15cb3dSCy Schubert */
132*2b15cb3dSCy Schubert #define timeval_isdenormal(x) (!timeval_isnormal(x))
133*2b15cb3dSCy Schubert
134*2b15cb3dSCy Schubert /* make sure microseconds are in nominal range */
135*2b15cb3dSCy Schubert static inline struct timeval
normalize_tval(struct timeval x)136*2b15cb3dSCy Schubert normalize_tval(
137*2b15cb3dSCy Schubert struct timeval x
138*2b15cb3dSCy Schubert )
139*2b15cb3dSCy Schubert {
140*2b15cb3dSCy Schubert long z;
141*2b15cb3dSCy Schubert
142*2b15cb3dSCy Schubert /*
143*2b15cb3dSCy Schubert * If the fraction becomes excessive denormal, we use division
144*2b15cb3dSCy Schubert * to do first partial normalisation. The normalisation loops
145*2b15cb3dSCy Schubert * following will do the remaining cleanup. Since the size of
146*2b15cb3dSCy Schubert * tv_usec has a peculiar definition by the standard the range
147*2b15cb3dSCy Schubert * check is coded manually. And labs() is intentionally not used
148*2b15cb3dSCy Schubert * here: it has implementation-defined behaviour when applied
149*2b15cb3dSCy Schubert * to LONG_MIN.
150*2b15cb3dSCy Schubert */
151*2b15cb3dSCy Schubert if (x.tv_usec < -3l * MICROSECONDS ||
152*2b15cb3dSCy Schubert x.tv_usec > 3l * MICROSECONDS ) {
153*2b15cb3dSCy Schubert z = x.tv_usec / MICROSECONDS;
154*2b15cb3dSCy Schubert x.tv_usec -= z * MICROSECONDS;
155*2b15cb3dSCy Schubert x.tv_sec += z;
156*2b15cb3dSCy Schubert }
157*2b15cb3dSCy Schubert
158*2b15cb3dSCy Schubert /*
159*2b15cb3dSCy Schubert * Do any remaining normalisation steps in loops. This takes 3
160*2b15cb3dSCy Schubert * steps max, and should outperform a division even if the
161*2b15cb3dSCy Schubert * mul-by-inverse trick is employed. (It also does the floor
162*2b15cb3dSCy Schubert * division adjustment if the above division was executed.)
163*2b15cb3dSCy Schubert */
164*2b15cb3dSCy Schubert if (x.tv_usec < 0)
165*2b15cb3dSCy Schubert do {
166*2b15cb3dSCy Schubert x.tv_usec += MICROSECONDS;
167*2b15cb3dSCy Schubert x.tv_sec--;
168*2b15cb3dSCy Schubert } while (x.tv_usec < 0);
169*2b15cb3dSCy Schubert else if (x.tv_usec >= MICROSECONDS)
170*2b15cb3dSCy Schubert do {
171*2b15cb3dSCy Schubert x.tv_usec -= MICROSECONDS;
172*2b15cb3dSCy Schubert x.tv_sec++;
173*2b15cb3dSCy Schubert } while (x.tv_usec >= MICROSECONDS);
174*2b15cb3dSCy Schubert
175*2b15cb3dSCy Schubert return x;
176*2b15cb3dSCy Schubert }
177*2b15cb3dSCy Schubert
178*2b15cb3dSCy Schubert /* x = a + b */
179*2b15cb3dSCy Schubert static inline struct timeval
add_tval(struct timeval a,struct timeval b)180*2b15cb3dSCy Schubert add_tval(
181*2b15cb3dSCy Schubert struct timeval a,
182*2b15cb3dSCy Schubert struct timeval b
183*2b15cb3dSCy Schubert )
184*2b15cb3dSCy Schubert {
185*2b15cb3dSCy Schubert struct timeval x;
186*2b15cb3dSCy Schubert
187*2b15cb3dSCy Schubert x = a;
188*2b15cb3dSCy Schubert x.tv_sec += b.tv_sec;
189*2b15cb3dSCy Schubert x.tv_usec += b.tv_usec;
190*2b15cb3dSCy Schubert
191*2b15cb3dSCy Schubert return normalize_tval(x);
192*2b15cb3dSCy Schubert }
193*2b15cb3dSCy Schubert
194*2b15cb3dSCy Schubert /* x = a + b, b is fraction only */
195*2b15cb3dSCy Schubert static inline struct timeval
add_tval_us(struct timeval a,long b)196*2b15cb3dSCy Schubert add_tval_us(
197*2b15cb3dSCy Schubert struct timeval a,
198*2b15cb3dSCy Schubert long b
199*2b15cb3dSCy Schubert )
200*2b15cb3dSCy Schubert {
201*2b15cb3dSCy Schubert struct timeval x;
202*2b15cb3dSCy Schubert
203*2b15cb3dSCy Schubert x = a;
204*2b15cb3dSCy Schubert x.tv_usec += b;
205*2b15cb3dSCy Schubert
206*2b15cb3dSCy Schubert return normalize_tval(x);
207*2b15cb3dSCy Schubert }
208*2b15cb3dSCy Schubert
209*2b15cb3dSCy Schubert /* x = a - b */
210*2b15cb3dSCy Schubert static inline struct timeval
sub_tval(struct timeval a,struct timeval b)211*2b15cb3dSCy Schubert sub_tval(
212*2b15cb3dSCy Schubert struct timeval a,
213*2b15cb3dSCy Schubert struct timeval b
214*2b15cb3dSCy Schubert )
215*2b15cb3dSCy Schubert {
216*2b15cb3dSCy Schubert struct timeval x;
217*2b15cb3dSCy Schubert
218*2b15cb3dSCy Schubert x = a;
219*2b15cb3dSCy Schubert x.tv_sec -= b.tv_sec;
220*2b15cb3dSCy Schubert x.tv_usec -= b.tv_usec;
221*2b15cb3dSCy Schubert
222*2b15cb3dSCy Schubert return normalize_tval(x);
223*2b15cb3dSCy Schubert }
224*2b15cb3dSCy Schubert
225*2b15cb3dSCy Schubert /* x = a - b, b is fraction only */
226*2b15cb3dSCy Schubert static inline struct timeval
sub_tval_us(struct timeval a,long b)227*2b15cb3dSCy Schubert sub_tval_us(
228*2b15cb3dSCy Schubert struct timeval a,
229*2b15cb3dSCy Schubert long b
230*2b15cb3dSCy Schubert )
231*2b15cb3dSCy Schubert {
232*2b15cb3dSCy Schubert struct timeval x;
233*2b15cb3dSCy Schubert
234*2b15cb3dSCy Schubert x = a;
235*2b15cb3dSCy Schubert x.tv_usec -= b;
236*2b15cb3dSCy Schubert
237*2b15cb3dSCy Schubert return normalize_tval(x);
238*2b15cb3dSCy Schubert }
239*2b15cb3dSCy Schubert
240*2b15cb3dSCy Schubert /* x = -a */
241*2b15cb3dSCy Schubert static inline struct timeval
neg_tval(struct timeval a)242*2b15cb3dSCy Schubert neg_tval(
243*2b15cb3dSCy Schubert struct timeval a
244*2b15cb3dSCy Schubert )
245*2b15cb3dSCy Schubert {
246*2b15cb3dSCy Schubert struct timeval x;
247*2b15cb3dSCy Schubert
248*2b15cb3dSCy Schubert x.tv_sec = -a.tv_sec;
249*2b15cb3dSCy Schubert x.tv_usec = -a.tv_usec;
250*2b15cb3dSCy Schubert
251*2b15cb3dSCy Schubert return normalize_tval(x);
252*2b15cb3dSCy Schubert }
253*2b15cb3dSCy Schubert
254*2b15cb3dSCy Schubert /* x = abs(a) */
255*2b15cb3dSCy Schubert static inline struct timeval
abs_tval(struct timeval a)256*2b15cb3dSCy Schubert abs_tval(
257*2b15cb3dSCy Schubert struct timeval a
258*2b15cb3dSCy Schubert )
259*2b15cb3dSCy Schubert {
260*2b15cb3dSCy Schubert struct timeval c;
261*2b15cb3dSCy Schubert
262*2b15cb3dSCy Schubert c = normalize_tval(a);
263*2b15cb3dSCy Schubert if (c.tv_sec < 0) {
264*2b15cb3dSCy Schubert if (c.tv_usec != 0) {
265*2b15cb3dSCy Schubert c.tv_sec = -c.tv_sec - 1;
266*2b15cb3dSCy Schubert c.tv_usec = MICROSECONDS - c.tv_usec;
267*2b15cb3dSCy Schubert } else {
268*2b15cb3dSCy Schubert c.tv_sec = -c.tv_sec;
269*2b15cb3dSCy Schubert }
270*2b15cb3dSCy Schubert }
271*2b15cb3dSCy Schubert
272*2b15cb3dSCy Schubert return c;
273*2b15cb3dSCy Schubert }
274*2b15cb3dSCy Schubert
275*2b15cb3dSCy Schubert /*
276*2b15cb3dSCy Schubert * compare previously-normalised a and b
277*2b15cb3dSCy Schubert * return 1 / 0 / -1 if a < / == / > b
278*2b15cb3dSCy Schubert */
279*2b15cb3dSCy Schubert static inline int
cmp_tval(struct timeval a,struct timeval b)280*2b15cb3dSCy Schubert cmp_tval(
281*2b15cb3dSCy Schubert struct timeval a,
282*2b15cb3dSCy Schubert struct timeval b
283*2b15cb3dSCy Schubert )
284*2b15cb3dSCy Schubert {
285*2b15cb3dSCy Schubert int r;
286*2b15cb3dSCy Schubert
287*2b15cb3dSCy Schubert r = (a.tv_sec > b.tv_sec) - (a.tv_sec < b.tv_sec);
288*2b15cb3dSCy Schubert if (0 == r)
289*2b15cb3dSCy Schubert r = (a.tv_usec > b.tv_usec) -
290*2b15cb3dSCy Schubert (a.tv_usec < b.tv_usec);
291*2b15cb3dSCy Schubert
292*2b15cb3dSCy Schubert return r;
293*2b15cb3dSCy Schubert }
294*2b15cb3dSCy Schubert
295*2b15cb3dSCy Schubert /*
296*2b15cb3dSCy Schubert * compare possibly-denormal a and b
297*2b15cb3dSCy Schubert * return 1 / 0 / -1 if a < / == / > b
298*2b15cb3dSCy Schubert */
299*2b15cb3dSCy Schubert static inline int
cmp_tval_denorm(struct timeval a,struct timeval b)300*2b15cb3dSCy Schubert cmp_tval_denorm(
301*2b15cb3dSCy Schubert struct timeval a,
302*2b15cb3dSCy Schubert struct timeval b
303*2b15cb3dSCy Schubert )
304*2b15cb3dSCy Schubert {
305*2b15cb3dSCy Schubert return cmp_tval(normalize_tval(a), normalize_tval(b));
306*2b15cb3dSCy Schubert }
307*2b15cb3dSCy Schubert
308*2b15cb3dSCy Schubert /*
309*2b15cb3dSCy Schubert * test previously-normalised a
310*2b15cb3dSCy Schubert * return 1 / 0 / -1 if a < / == / > 0
311*2b15cb3dSCy Schubert */
312*2b15cb3dSCy Schubert static inline int
test_tval(struct timeval a)313*2b15cb3dSCy Schubert test_tval(
314*2b15cb3dSCy Schubert struct timeval a
315*2b15cb3dSCy Schubert )
316*2b15cb3dSCy Schubert {
317*2b15cb3dSCy Schubert int r;
318*2b15cb3dSCy Schubert
319*2b15cb3dSCy Schubert r = (a.tv_sec > 0) - (a.tv_sec < 0);
320*2b15cb3dSCy Schubert if (r == 0)
321*2b15cb3dSCy Schubert r = (a.tv_usec > 0);
322*2b15cb3dSCy Schubert
323*2b15cb3dSCy Schubert return r;
324*2b15cb3dSCy Schubert }
325*2b15cb3dSCy Schubert
326*2b15cb3dSCy Schubert /*
327*2b15cb3dSCy Schubert * test possibly-denormal a
328*2b15cb3dSCy Schubert * return 1 / 0 / -1 if a < / == / > 0
329*2b15cb3dSCy Schubert */
330*2b15cb3dSCy Schubert static inline int
test_tval_denorm(struct timeval a)331*2b15cb3dSCy Schubert test_tval_denorm(
332*2b15cb3dSCy Schubert struct timeval a
333*2b15cb3dSCy Schubert )
334*2b15cb3dSCy Schubert {
335*2b15cb3dSCy Schubert return test_tval(normalize_tval(a));
336*2b15cb3dSCy Schubert }
337*2b15cb3dSCy Schubert
338*2b15cb3dSCy Schubert /* return LIB buffer ptr to string rep */
339*2b15cb3dSCy Schubert static inline const char *
tvaltoa(struct timeval x)340*2b15cb3dSCy Schubert tvaltoa(
341*2b15cb3dSCy Schubert struct timeval x
342*2b15cb3dSCy Schubert )
343*2b15cb3dSCy Schubert {
344*2b15cb3dSCy Schubert return format_time_fraction(x.tv_sec, x.tv_usec, 6);
345*2b15cb3dSCy Schubert }
346*2b15cb3dSCy Schubert
347*2b15cb3dSCy Schubert /* convert from timeval duration to l_fp duration */
348*2b15cb3dSCy Schubert static inline l_fp
tval_intv_to_lfp(struct timeval x)349*2b15cb3dSCy Schubert tval_intv_to_lfp(
350*2b15cb3dSCy Schubert struct timeval x
351*2b15cb3dSCy Schubert )
352*2b15cb3dSCy Schubert {
353*2b15cb3dSCy Schubert struct timeval v;
354*2b15cb3dSCy Schubert l_fp y;
355*2b15cb3dSCy Schubert
356*2b15cb3dSCy Schubert v = normalize_tval(x);
357*2b15cb3dSCy Schubert TVUTOTSF(v.tv_usec, y.l_uf);
358*2b15cb3dSCy Schubert y.l_i = (int32)v.tv_sec;
359*2b15cb3dSCy Schubert
360*2b15cb3dSCy Schubert return y;
361*2b15cb3dSCy Schubert }
362*2b15cb3dSCy Schubert
363*2b15cb3dSCy Schubert /* x must be UN*X epoch, output *y will be in NTP epoch */
364*2b15cb3dSCy Schubert static inline l_fp
tval_stamp_to_lfp(struct timeval x)365*2b15cb3dSCy Schubert tval_stamp_to_lfp(
366*2b15cb3dSCy Schubert struct timeval x
367*2b15cb3dSCy Schubert )
368*2b15cb3dSCy Schubert {
369*2b15cb3dSCy Schubert l_fp y;
370*2b15cb3dSCy Schubert
371*2b15cb3dSCy Schubert y = tval_intv_to_lfp(x);
372*2b15cb3dSCy Schubert y.l_ui += JAN_1970;
373*2b15cb3dSCy Schubert
374*2b15cb3dSCy Schubert return y;
375*2b15cb3dSCy Schubert }
376*2b15cb3dSCy Schubert
377*2b15cb3dSCy Schubert /* convert to l_fp type, relative signed/unsigned and absolute */
378*2b15cb3dSCy Schubert static inline struct timeval
lfp_intv_to_tval(l_fp x)379*2b15cb3dSCy Schubert lfp_intv_to_tval(
380*2b15cb3dSCy Schubert l_fp x
381*2b15cb3dSCy Schubert )
382*2b15cb3dSCy Schubert {
383*2b15cb3dSCy Schubert struct timeval out;
384*2b15cb3dSCy Schubert l_fp absx;
385*2b15cb3dSCy Schubert int neg;
386*2b15cb3dSCy Schubert
387*2b15cb3dSCy Schubert neg = L_ISNEG(&x);
388*2b15cb3dSCy Schubert absx = x;
389*2b15cb3dSCy Schubert if (neg) {
390*2b15cb3dSCy Schubert L_NEG(&absx);
391*2b15cb3dSCy Schubert }
392*2b15cb3dSCy Schubert TSFTOTVU(absx.l_uf, out.tv_usec);
393*2b15cb3dSCy Schubert out.tv_sec = absx.l_i;
394*2b15cb3dSCy Schubert if (neg) {
395*2b15cb3dSCy Schubert out.tv_sec = -out.tv_sec;
396*2b15cb3dSCy Schubert out.tv_usec = -out.tv_usec;
397*2b15cb3dSCy Schubert out = normalize_tval(out);
398*2b15cb3dSCy Schubert }
399*2b15cb3dSCy Schubert
400*2b15cb3dSCy Schubert return out;
401*2b15cb3dSCy Schubert }
402*2b15cb3dSCy Schubert
403*2b15cb3dSCy Schubert static inline struct timeval
lfp_uintv_to_tval(l_fp x)404*2b15cb3dSCy Schubert lfp_uintv_to_tval(
405*2b15cb3dSCy Schubert l_fp x
406*2b15cb3dSCy Schubert )
407*2b15cb3dSCy Schubert {
408*2b15cb3dSCy Schubert struct timeval out;
409*2b15cb3dSCy Schubert
410*2b15cb3dSCy Schubert TSFTOTVU(x.l_uf, out.tv_usec);
411*2b15cb3dSCy Schubert out.tv_sec = x.l_ui;
412*2b15cb3dSCy Schubert
413*2b15cb3dSCy Schubert return out;
414*2b15cb3dSCy Schubert }
415*2b15cb3dSCy Schubert
416*2b15cb3dSCy Schubert /*
417*2b15cb3dSCy Schubert * absolute (timestamp) conversion. Input is time in NTP epoch, output
418*2b15cb3dSCy Schubert * is in UN*X epoch. The NTP time stamp will be expanded around the
419*2b15cb3dSCy Schubert * pivot time *p or the current time, if p is NULL.
420*2b15cb3dSCy Schubert */
421*2b15cb3dSCy Schubert static inline struct timeval
lfp_stamp_to_tval(l_fp x,const time_t * p)422*2b15cb3dSCy Schubert lfp_stamp_to_tval(
423*2b15cb3dSCy Schubert l_fp x,
424*2b15cb3dSCy Schubert const time_t * p
425*2b15cb3dSCy Schubert )
426*2b15cb3dSCy Schubert {
427*2b15cb3dSCy Schubert struct timeval out;
428*2b15cb3dSCy Schubert vint64 sec;
429*2b15cb3dSCy Schubert
430*2b15cb3dSCy Schubert sec = ntpcal_ntp_to_time(x.l_ui, p);
431*2b15cb3dSCy Schubert TSFTOTVU(x.l_uf, out.tv_usec);
432*2b15cb3dSCy Schubert
433*2b15cb3dSCy Schubert /* copying a vint64 to a time_t needs some care... */
434*2b15cb3dSCy Schubert #if SIZEOF_TIME_T <= 4
435*2b15cb3dSCy Schubert out.tv_sec = (time_t)sec.d_s.lo;
436*2b15cb3dSCy Schubert #elif defined(HAVE_INT64)
437*2b15cb3dSCy Schubert out.tv_sec = (time_t)sec.q_s;
438*2b15cb3dSCy Schubert #else
439*2b15cb3dSCy Schubert out.tv_sec = ((time_t)sec.d_s.hi << 32) | sec.d_s.lo;
440*2b15cb3dSCy Schubert #endif
441*2b15cb3dSCy Schubert out = normalize_tval(out);
442*2b15cb3dSCy Schubert
443*2b15cb3dSCy Schubert return out;
444*2b15cb3dSCy Schubert }
445*2b15cb3dSCy Schubert
446*2b15cb3dSCy Schubert #endif /* TIMEVALOPS_H */
447