xref: /illumos-gate/usr/src/compat/bhyve/sys/time.h (revision 2699b94c)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2013 Pluribus Networks Inc.
14  * Copyright 2020 Oxide Computer Company
15  */
16 
17 #ifndef _COMPAT_FREEBSD_SYS_TIME_H_
18 #define	_COMPAT_FREEBSD_SYS_TIME_H_
19 
20 #include_next <sys/time.h>
21 
22 #define	tc_precexp	0
23 
24 struct bintime {
25 	ulong_t		sec;		/* seconds */
26 	uint64_t	frac;		/* 64 bit fraction of a second */
27 };
28 
29 #define	BT2FREQ(bt)							\
30 	(((uint64_t)0x8000000000000000 + ((bt)->frac >> 2)) /		\
31 	    ((bt)->frac >> 1))
32 
33 #define	FREQ2BT(freq, bt)						\
34 {									\
35 	(bt)->sec = 0;							\
36 	(bt)->frac = ((uint64_t)0x8000000000000000  / (freq)) << 1;	\
37 }
38 
39 static __inline void
binuptime(struct bintime * bt)40 binuptime(struct bintime *bt)
41 {
42 	hrtime_t	now = gethrtime();
43 
44 	bt->sec = now / 1000000000;
45 	/* 18446744073 = int(2^64 / 1000000000) = 1ns in 64-bit fractions */
46 	bt->frac = (now % 1000000000) * (uint64_t)18446744073LL;
47 }
48 
49 #define	bintime_cmp(a, b, cmp)						\
50 	(((a)->sec == (b)->sec) ?					\
51 	    ((a)->frac cmp (b)->frac) :					\
52 	    ((a)->sec cmp (b)->sec))
53 
54 /*
55  * The bintime_cmp() macro is problematic for a couple reasons:
56  * 1. Bearing a lowercase name suggests it is a function rather than a macro.
57  * 2. Placing the comparison operator as the last argument runs afoul of our
58  *    cstyle rules, unlike cases such as VERIFY3*().
59  *
60  * To remedy these issues in illumos bhyve, we provide a slightly modified
61  * version which addresses both problems.
62  */
63 #define	BINTIME_CMP(a, cmp, b)	bintime_cmp((a), (b), cmp)
64 
65 #define SBT_1S  ((sbintime_t)1 << 32)
66 #define SBT_1M  (SBT_1S * 60)
67 #define SBT_1MS (SBT_1S / 1000)
68 #define SBT_1US (SBT_1S / 1000000)
69 #define SBT_1NS (SBT_1S / 1000000000)
70 #define SBT_MAX 0x7fffffffffffffffLL
71 
72 
73 static __inline void
bintime_add(struct bintime * bt,const struct bintime * bt2)74 bintime_add(struct bintime *bt, const struct bintime *bt2)
75 {
76 	uint64_t u;
77 
78 	u = bt->frac;
79 	bt->frac += bt2->frac;
80 	if (u > bt->frac)
81 		bt->sec++;
82 	bt->sec += bt2->sec;
83 }
84 
85 static __inline void
bintime_sub(struct bintime * bt,const struct bintime * bt2)86 bintime_sub(struct bintime *bt, const struct bintime *bt2)
87 {
88 	uint64_t u;
89 
90 	u = bt->frac;
91 	bt->frac -= bt2->frac;
92 	if (u < bt->frac)
93 		bt->sec--;
94 	bt->sec -= bt2->sec;
95 }
96 
97 static __inline void
bintime_mul(struct bintime * bt,u_int x)98 bintime_mul(struct bintime *bt, u_int x)
99 {
100 	uint64_t p1, p2;
101 
102 	p1 = (bt->frac & 0xffffffffull) * x;
103 	p2 = (bt->frac >> 32) * x + (p1 >> 32);
104 	bt->sec *= x;
105 	bt->sec += (p2 >> 32);
106 	bt->frac = (p2 << 32) | (p1 & 0xffffffffull);
107 }
108 
109 static __inline sbintime_t
bttosbt(const struct bintime bt)110 bttosbt(const struct bintime bt)
111 {
112 	return (((sbintime_t)bt.sec << 32) + (bt.frac >> 32));
113 }
114 
115 static __inline struct bintime
sbttobt(sbintime_t _sbt)116 sbttobt(sbintime_t _sbt)
117 {
118 	struct bintime _bt;
119 
120 	_bt.sec = _sbt >> 32;
121 	_bt.frac = _sbt << 32;
122 	return (_bt);
123 }
124 
125 static __inline sbintime_t
sbinuptime(void)126 sbinuptime(void)
127 {
128 	hrtime_t hrt = gethrtime();
129 	uint64_t sec = hrt / NANOSEC;
130 	uint64_t nsec = hrt % NANOSEC;
131 
132 	return (((sbintime_t)sec << 32) +
133 	    (nsec * (((uint64_t)1 << 63) / 500000000) >> 32));
134 }
135 
136 #endif	/* _COMPAT_FREEBSD_SYS_TIME_H_ */
137