1 /* Licensed under BSD-MIT - see LICENSE file for details */
2 #include <ccan/time/time.h>
7 #include <ccan/str/str.h>
8 #define TIME_CHECK(t) time_check((t), __FILE__ ":" stringify(__LINE__))
10 #define TIME_CHECK(t) (t)
13 #if !HAVE_CLOCK_GETTIME && !HAVE_CLOCK_GETTIME_IN_LIBRT
16 struct timespec time_now(void)
20 gettimeofday(&now, NULL);
21 ret.tv_sec = now.tv_sec;
22 ret.tv_nsec = now.tv_usec * 1000;
23 return TIME_CHECK(ret);
27 struct timespec time_now(void)
30 clock_gettime(CLOCK_REALTIME, &ret);
31 return TIME_CHECK(ret);
33 #endif /* HAVE_CLOCK_GETTIME || HAVE_CLOCK_GETTIME_IN_LIBRT */
35 bool time_greater(struct timespec a, struct timespec b)
37 if (TIME_CHECK(a).tv_sec > TIME_CHECK(b).tv_sec)
39 else if (a.tv_sec < b.tv_sec)
42 return a.tv_nsec > b.tv_nsec;
45 bool time_less(struct timespec a, struct timespec b)
47 if (TIME_CHECK(a).tv_sec < TIME_CHECK(b).tv_sec)
49 else if (a.tv_sec > b.tv_sec)
52 return a.tv_nsec < b.tv_nsec;
55 bool time_eq(struct timespec a, struct timespec b)
57 return TIME_CHECK(a).tv_sec == TIME_CHECK(b).tv_sec && a.tv_nsec == b.tv_nsec;
60 struct timespec time_sub(struct timespec recent, struct timespec old)
64 diff.tv_sec = TIME_CHECK(recent).tv_sec - TIME_CHECK(old).tv_sec;
65 if (old.tv_nsec > recent.tv_nsec) {
67 diff.tv_nsec = 1000000000 + recent.tv_nsec - old.tv_nsec;
69 diff.tv_nsec = recent.tv_nsec - old.tv_nsec;
71 return TIME_CHECK(diff);
74 struct timespec time_add(struct timespec a, struct timespec b)
78 sum.tv_sec = TIME_CHECK(a).tv_sec + TIME_CHECK(b).tv_sec;
79 sum.tv_nsec = a.tv_nsec + b.tv_nsec;
80 if (sum.tv_nsec >= 1000000000) {
82 sum.tv_nsec -= 1000000000;
84 return TIME_CHECK(sum);
87 struct timespec time_divide(struct timespec t, unsigned long div)
92 /* Dividing seconds is simple. */
93 res.tv_sec = TIME_CHECK(t).tv_sec / div;
96 /* If we can't fit remainder * 1,000,000,000 in 64 bits? */
97 #if 0 /* ilog is great, but we use fp for multiply anyway. */
99 if (bits + 30 >= 64) {
100 /* Reduce accuracy slightly */
101 rem >>= (bits - (64 - 30));
102 div >>= (bits - (64 - 30));
105 if (rem & ~(((uint64_t)1 << 30) - 1)) {
106 /* FIXME: fp is cheating! */
107 double nsec = rem * 1000000000.0 + t.tv_nsec;
108 res.tv_nsec = nsec / div;
110 ns = rem * 1000000000 + t.tv_nsec;
111 res.tv_nsec = ns / div;
113 return TIME_CHECK(res);
116 struct timespec time_multiply(struct timespec t, unsigned long mult)
120 /* Are we going to overflow if we multiply nsec? */
121 if (mult & ~((1UL << 30) - 1)) {
122 /* FIXME: fp is cheating! */
123 double nsec = (double)t.tv_nsec * mult;
125 res.tv_sec = nsec / 1000000000.0;
126 res.tv_nsec = nsec - (res.tv_sec * 1000000000.0);
128 uint64_t nsec = t.tv_nsec * mult;
130 res.tv_nsec = nsec % 1000000000;
131 res.tv_sec = nsec / 1000000000;
133 res.tv_sec += TIME_CHECK(t).tv_sec * mult;
134 return TIME_CHECK(res);
137 uint64_t time_to_msec(struct timespec t)
141 msec = TIME_CHECK(t).tv_nsec / 1000000 + (uint64_t)t.tv_sec * 1000;
145 uint64_t time_to_usec(struct timespec t)
149 usec = TIME_CHECK(t).tv_nsec / 1000 + (uint64_t)t.tv_sec * 1000000;
153 uint64_t time_to_nsec(struct timespec t)
157 nsec = TIME_CHECK(t).tv_nsec + (uint64_t)t.tv_sec * 1000000000;
161 struct timespec time_from_msec(uint64_t msec)
165 t.tv_nsec = (msec % 1000) * 1000000;
166 t.tv_sec = msec / 1000;
167 return TIME_CHECK(t);
170 struct timespec time_from_usec(uint64_t usec)
174 t.tv_nsec = (usec % 1000000) * 1000;
175 t.tv_sec = usec / 1000000;
176 return TIME_CHECK(t);
179 struct timespec time_from_nsec(uint64_t nsec)
183 t.tv_nsec = nsec % 1000000000;
184 t.tv_sec = nsec / 1000000000;
185 return TIME_CHECK(t);
188 struct timespec time_check(struct timespec t, const char *abortstr)
190 if (t.tv_sec < 0 || t.tv_nsec >= 1000000000) {
192 fprintf(stderr, "%s: malformed time %li.%09li\n",
194 (long)t.tv_sec, (long)t.tv_nsec);
197 struct timespec old = t;
199 if (t.tv_nsec >= 1000000000) {
200 t.tv_sec += t.tv_nsec / 1000000000;
201 t.tv_nsec %= 1000000000;
206 fprintf(stderr, "WARNING: malformed time"
207 " %li seconds %li ns converted to %li.%09li.\n",
208 (long)old.tv_sec, (long)old.tv_nsec,
209 (long)t.tv_sec, (long)t.tv_nsec);