summaryrefslogtreecommitdiff
path: root/usr/src/compat/bhyve/sys/time.h
blob: 48bdcc304ead3d4f73d365210a8cde8243761667 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
 * This file and its contents are supplied under the terms of the
 * Common Development and Distribution License ("CDDL"), version 1.0.
 * You may only use this file in accordance with the terms of version
 * 1.0 of the CDDL.
 *
 * A full copy of the text of the CDDL should have accompanied this
 * source.  A copy of the CDDL is also available via the Internet at
 * http://www.illumos.org/license/CDDL.
 */

/*
 * Copyright 2013 Pluribus Networks Inc.
 * Copyright 2020 Oxide Computer Company
 */

#ifndef _COMPAT_FREEBSD_SYS_TIME_H_
#define	_COMPAT_FREEBSD_SYS_TIME_H_

#include_next <sys/time.h>

#define	tc_precexp	0

struct bintime {
	ulong_t		sec;		/* seconds */
	uint64_t	frac;		/* 64 bit fraction of a second */
};

#define	BT2FREQ(bt)							\
	(((uint64_t)0x8000000000000000 + ((bt)->frac >> 2)) /		\
	    ((bt)->frac >> 1))

#define	FREQ2BT(freq, bt)						\
{									\
	(bt)->sec = 0;							\
	(bt)->frac = ((uint64_t)0x8000000000000000  / (freq)) << 1;	\
}

static __inline void
binuptime(struct bintime *bt)
{
	hrtime_t	now = gethrtime();

	bt->sec = now / 1000000000;
	/* 18446744073 = int(2^64 / 1000000000) = 1ns in 64-bit fractions */
	bt->frac = (now % 1000000000) * (uint64_t)18446744073LL;
}

#define	bintime_cmp(a, b, cmp)						\
	(((a)->sec == (b)->sec) ?					\
	    ((a)->frac cmp (b)->frac) :					\
	    ((a)->sec cmp (b)->sec))

/*
 * The bintime_cmp() macro is problematic for a couple reasons:
 * 1. Bearing a lowercase name suggests it is a function rather than a macro.
 * 2. Placing the comparison operator as the last argument runs afoul of our
 *    cstyle rules, unlike cases such as VERIFY3*().
 *
 * To remedy these issues in illumos bhyve, we provide a slightly modified
 * version which addresses both problems.
 */
#define	BINTIME_CMP(a, cmp, b)	bintime_cmp((a), (b), cmp)

#define SBT_1S  ((sbintime_t)1 << 32)
#define SBT_1M  (SBT_1S * 60)
#define SBT_1MS (SBT_1S / 1000)
#define SBT_1US (SBT_1S / 1000000)
#define SBT_1NS (SBT_1S / 1000000000)
#define SBT_MAX 0x7fffffffffffffffLL


static __inline void
bintime_add(struct bintime *bt, const struct bintime *bt2)
{
	uint64_t u;

	u = bt->frac;
	bt->frac += bt2->frac;
	if (u > bt->frac)
		bt->sec++;
	bt->sec += bt2->sec;
}

static __inline void
bintime_sub(struct bintime *bt, const struct bintime *bt2)
{
	uint64_t u;

	u = bt->frac;
	bt->frac -= bt2->frac;
	if (u < bt->frac)
		bt->sec--;
	bt->sec -= bt2->sec;
}

static __inline void
bintime_mul(struct bintime *bt, u_int x)
{
	uint64_t p1, p2;

	p1 = (bt->frac & 0xffffffffull) * x;
	p2 = (bt->frac >> 32) * x + (p1 >> 32);
	bt->sec *= x;
	bt->sec += (p2 >> 32);
	bt->frac = (p2 << 32) | (p1 & 0xffffffffull);
}

static __inline sbintime_t
bttosbt(const struct bintime bt)
{
	return (((sbintime_t)bt.sec << 32) + (bt.frac >> 32));
}

static __inline struct bintime
sbttobt(sbintime_t _sbt)
{
	struct bintime _bt;

	_bt.sec = _sbt >> 32;
	_bt.frac = _sbt << 32;
	return (_bt);
}

static __inline sbintime_t
sbinuptime(void)
{
	hrtime_t hrt = gethrtime();
	uint64_t sec = hrt / NANOSEC;
	uint64_t nsec = hrt % NANOSEC;

	return (((sbintime_t)sec << 32) +
	    (nsec * (((uint64_t)1 << 63) / 500000000) >> 32));
}

#endif	/* _COMPAT_FREEBSD_SYS_TIME_H_ */