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 11void 12nstime_init(nstime_t *time, uint64_t ns) { 13 time->ns = ns; 14} 15 16void 17nstime_init2(nstime_t *time, uint64_t sec, uint64_t nsec) { 18 time->ns = sec * BILLION + nsec; 19} 20 21uint64_t 22nstime_ns(const nstime_t *time) { 23 return time->ns; 24} 25 26uint64_t 27nstime_msec(const nstime_t *time) { 28 return time->ns / MILLION; 29} 30 31uint64_t 32nstime_sec(const nstime_t *time) { 33 return time->ns / BILLION; 34} 35 36uint64_t 37nstime_nsec(const nstime_t *time) { 38 return time->ns % BILLION; 39} 40 41void 42nstime_copy(nstime_t *time, const nstime_t *source) { 43 *time = *source; 44} 45 46int 47nstime_compare(const nstime_t *a, const nstime_t *b) { 48 return (a->ns > b->ns) - (a->ns < b->ns); 49} 50 51void 52nstime_add(nstime_t *time, const nstime_t *addend) { 53 assert(UINT64_MAX - time->ns >= addend->ns); 54 55 time->ns += addend->ns; 56} 57 58void 59nstime_iadd(nstime_t *time, uint64_t addend) { 60 assert(UINT64_MAX - time->ns >= addend); 61 62 time->ns += addend; 63} 64 65void 66nstime_subtract(nstime_t *time, const nstime_t *subtrahend) { 67 assert(nstime_compare(time, subtrahend) >= 0); 68 69 time->ns -= subtrahend->ns; 70} 71 72void 73nstime_isubtract(nstime_t *time, uint64_t subtrahend) { 74 assert(time->ns >= subtrahend); 75 76 time->ns -= subtrahend; 77} 78 79void 80nstime_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 87void 88nstime_idivide(nstime_t *time, uint64_t divisor) { 89 assert(divisor != 0); 90 91 time->ns /= divisor; 92} 93 94uint64_t 95nstime_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 103static void 104nstime_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 115static void 116nstime_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 124static void 125nstime_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 133static void 134nstime_get(nstime_t *time) { 135 nstime_init(time, mach_absolute_time()); 136} 137#else 138# define NSTIME_MONOTONIC false 139static void 140nstime_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 148static bool 149nstime_monotonic_impl(void) { 150 return NSTIME_MONOTONIC; 151#undef NSTIME_MONOTONIC 152} 153nstime_monotonic_t *JET_MUTABLE nstime_monotonic = nstime_monotonic_impl; 154 155static bool 156nstime_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} 170nstime_update_t *JET_MUTABLE nstime_update = nstime_update_impl; 171