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