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