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