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