xref: /freebsd/contrib/ntp/include/timevalops.h (revision 2b15cb3d)
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