1#include "jemalloc/internal/jemalloc_internal.h"
2
3#define	BILLION	UINT64_C(1000000000)
4
5void
6nstime_init(nstime_t *time, uint64_t ns)
7{
8	time->ns = ns;
9}
10
11void
12nstime_init2(nstime_t *time, uint64_t sec, uint64_t nsec)
13{
14	time->ns = sec * BILLION + nsec;
15}
16
17uint64_t
18nstime_ns(const nstime_t *time)
19{
20	return (time->ns);
21}
22
23uint64_t
24nstime_sec(const nstime_t *time)
25{
26	return (time->ns / BILLION);
27}
28
29uint64_t
30nstime_nsec(const nstime_t *time)
31{
32	return (time->ns % BILLION);
33}
34
35void
36nstime_copy(nstime_t *time, const nstime_t *source)
37{
38	*time = *source;
39}
40
41int
42nstime_compare(const nstime_t *a, const nstime_t *b)
43{
44	return ((a->ns > b->ns) - (a->ns < b->ns));
45}
46
47void
48nstime_add(nstime_t *time, const nstime_t *addend)
49{
50	assert(UINT64_MAX - time->ns >= addend->ns);
51
52	time->ns += addend->ns;
53}
54
55void
56nstime_subtract(nstime_t *time, const nstime_t *subtrahend)
57{
58	assert(nstime_compare(time, subtrahend) >= 0);
59
60	time->ns -= subtrahend->ns;
61}
62
63void
64nstime_imultiply(nstime_t *time, uint64_t multiplier)
65{
66	assert((((time->ns | multiplier) & (UINT64_MAX << (sizeof(uint64_t) <<
67	    2))) == 0) || ((time->ns * multiplier) / multiplier == time->ns));
68
69	time->ns *= multiplier;
70}
71
72void
73nstime_idivide(nstime_t *time, uint64_t divisor)
74{
75	assert(divisor != 0);
76
77	time->ns /= divisor;
78}
79
80uint64_t
81nstime_divide(const nstime_t *time, const nstime_t *divisor)
82{
83	assert(divisor->ns != 0);
84
85	return (time->ns / divisor->ns);
86}
87
88#ifdef _WIN32
89#  define NSTIME_MONOTONIC true
90static void
91nstime_get(nstime_t *time)
92{
93	FILETIME ft;
94	uint64_t ticks_100ns;
95
96	GetSystemTimeAsFileTime(&ft);
97	ticks_100ns = (((uint64_t)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
98
99	nstime_init(time, ticks_100ns * 100);
100}
101#elif JEMALLOC_HAVE_CLOCK_MONOTONIC_COARSE
102#  define NSTIME_MONOTONIC true
103static void
104nstime_get(nstime_t *time)
105{
106	struct timespec ts;
107
108	clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
109	nstime_init2(time, ts.tv_sec, ts.tv_nsec);
110}
111#elif JEMALLOC_HAVE_CLOCK_MONOTONIC
112#  define NSTIME_MONOTONIC true
113static void
114nstime_get(nstime_t *time)
115{
116	struct timespec ts;
117
118	clock_gettime(CLOCK_MONOTONIC, &ts);
119	nstime_init2(time, ts.tv_sec, ts.tv_nsec);
120}
121#elif JEMALLOC_HAVE_MACH_ABSOLUTE_TIME
122#  define NSTIME_MONOTONIC true
123static void
124nstime_get(nstime_t *time)
125{
126	nstime_init(time, mach_absolute_time());
127}
128#else
129#  define NSTIME_MONOTONIC false
130static void
131nstime_get(nstime_t *time)
132{
133	struct timeval tv;
134
135	gettimeofday(&tv, NULL);
136	nstime_init2(time, tv.tv_sec, tv.tv_usec * 1000);
137}
138#endif
139
140#ifdef JEMALLOC_JET
141#undef nstime_monotonic
142#define	nstime_monotonic JEMALLOC_N(n_nstime_monotonic)
143#endif
144bool
145nstime_monotonic(void)
146{
147	return (NSTIME_MONOTONIC);
148#undef NSTIME_MONOTONIC
149}
150#ifdef JEMALLOC_JET
151#undef nstime_monotonic
152#define	nstime_monotonic JEMALLOC_N(nstime_monotonic)
153nstime_monotonic_t *nstime_monotonic = JEMALLOC_N(n_nstime_monotonic);
154#endif
155
156#ifdef JEMALLOC_JET
157#undef nstime_update
158#define	nstime_update JEMALLOC_N(n_nstime_update)
159#endif
160bool
161nstime_update(nstime_t *time)
162{
163	nstime_t old_time;
164
165	nstime_copy(&old_time, time);
166	nstime_get(time);
167
168	/* Handle non-monotonic clocks. */
169	if (unlikely(nstime_compare(&old_time, time) > 0)) {
170		nstime_copy(time, &old_time);
171		return (true);
172	}
173
174	return (false);
175}
176#ifdef JEMALLOC_JET
177#undef nstime_update
178#define	nstime_update JEMALLOC_N(nstime_update)
179nstime_update_t *nstime_update = JEMALLOC_N(n_nstime_update);
180#endif
181