time: use timespec instead of timeval.
[ccan] / ccan / time / time.c
1 /* Licensed under BSD-MIT - see LICENSE file for details */
2 #include <ccan/time/time.h>
3 #include <stdlib.h>
4 #include <assert.h>
5
6 #if !HAVE_CLOCK_GETTIME && !HAVE_CLOCK_GETTIME_IN_LIBRT
7 #include <sys/time.h>
8
9 struct timespec time_now(void)
10 {
11         struct timeval now;
12         struct timespec ret;
13         gettimeofday(&now, NULL);
14         ret.tv_sec = now.tv_sec;
15         ret.tv_nsec = now.tv_usec * 1000;
16         return ret;
17 }
18 #else
19 #include <time.h>
20 struct timespec time_now(void)
21 {
22         struct timespec ret;
23         clock_gettime(CLOCK_REALTIME, &ret);
24         return ret;
25 }
26 #endif /* HAVE_CLOCK_GETTIME || HAVE_CLOCK_GETTIME_IN_LIBRT */
27
28 bool time_greater(struct timespec a, struct timespec b)
29 {
30         if (a.tv_sec > b.tv_sec)
31                 return true;
32         else if (a.tv_sec < b.tv_sec)
33                  return false;
34
35         return a.tv_nsec > b.tv_nsec;
36 }
37
38 bool time_less(struct timespec a, struct timespec b)
39 {
40         if (a.tv_sec < b.tv_sec)
41                 return true;
42         else if (a.tv_sec > b.tv_sec)
43                  return false;
44
45         return a.tv_nsec < b.tv_nsec;
46 }
47
48 bool time_eq(struct timespec a, struct timespec b)
49 {
50         return a.tv_sec == b.tv_sec && a.tv_nsec == b.tv_nsec;
51 }
52
53 struct timespec time_sub(struct timespec recent, struct timespec old)
54 {
55         struct timespec diff;
56
57         diff.tv_sec = recent.tv_sec - old.tv_sec;
58         if (old.tv_nsec > recent.tv_nsec) {
59                 diff.tv_sec--;
60                 diff.tv_nsec = 1000000000 + recent.tv_nsec - old.tv_nsec;
61         } else
62                 diff.tv_nsec = recent.tv_nsec - old.tv_nsec;
63
64         assert(diff.tv_sec >= 0);
65         return diff;
66 }
67
68 struct timespec time_add(struct timespec a, struct timespec b)
69 {
70         struct timespec sum;
71
72         sum.tv_sec = a.tv_sec + b.tv_sec;
73         sum.tv_nsec = a.tv_nsec + b.tv_nsec;
74         if (sum.tv_nsec >= 1000000000) {
75                 sum.tv_sec++;
76                 sum.tv_nsec -= 1000000000;
77         }
78         return sum;
79 }
80
81 struct timespec time_divide(struct timespec t, unsigned long div)
82 {
83         struct timespec res;
84         uint64_t rem, ns;
85
86         /* Dividing seconds is simple. */
87         res.tv_sec = t.tv_sec / div;
88         rem = t.tv_sec % div;
89
90         /* If we can't fit remainder * 1,000,000,000 in 64 bits? */
91 #if 0 /* ilog is great, but we use fp for multiply anyway. */
92         bits = ilog64(rem);
93         if (bits + 30 >= 64) {
94                 /* Reduce accuracy slightly */
95                 rem >>= (bits - (64 - 30));
96                 div >>= (bits - (64 - 30));
97         }
98 #endif
99         if (rem & ~(((uint64_t)1 << 30) - 1)) {
100                 /* FIXME: fp is cheating! */
101                 double nsec = rem * 1000000000.0 + t.tv_nsec;
102                 res.tv_nsec = nsec / div;
103         } else {
104                 ns = rem * 1000000000 + t.tv_nsec;
105                 res.tv_nsec = ns / div;
106         }
107         return res;
108 }
109
110 struct timespec time_multiply(struct timespec t, unsigned long mult)
111 {
112         struct timespec res;
113
114         /* Are we going to overflow if we multiply nsec? */
115         if (mult & ~((1UL << 30) - 1)) {
116                 /* FIXME: fp is cheating! */
117                 double nsec = (double)t.tv_nsec * mult;
118
119                 res.tv_sec = nsec / 1000000000.0;
120                 res.tv_nsec = nsec - (res.tv_sec * 1000000000.0);
121         } else {
122                 uint64_t nsec = t.tv_nsec * mult;
123
124                 res.tv_nsec = nsec % 1000000000;
125                 res.tv_sec = nsec / 1000000000;
126         }
127         res.tv_sec += t.tv_sec * mult;
128         return res;
129 }
130
131 uint64_t time_to_msec(struct timespec t)
132 {
133         uint64_t msec;
134
135         msec = t.tv_nsec / 1000000 + (uint64_t)t.tv_sec * 1000;
136         return msec;
137 }
138
139 uint64_t time_to_usec(struct timespec t)
140 {
141         uint64_t usec;
142
143         usec = t.tv_nsec / 1000 + (uint64_t)t.tv_sec * 1000000;
144         return usec;
145 }
146
147 uint64_t time_to_nsec(struct timespec t)
148 {
149         uint64_t nsec;
150
151         nsec = t.tv_nsec + (uint64_t)t.tv_sec * 1000000000;
152         return nsec;
153 }
154
155 struct timespec time_from_msec(uint64_t msec)
156 {
157         struct timespec t;
158
159         t.tv_nsec = (msec % 1000) * 1000000;
160         t.tv_sec = msec / 1000;
161         return t;
162 }
163
164 struct timespec time_from_usec(uint64_t usec)
165 {
166         struct timespec t;
167
168         t.tv_nsec = (usec % 1000000) * 1000;
169         t.tv_sec = usec / 1000000;
170         return t;
171 }
172
173 struct timespec time_from_nsec(uint64_t nsec)
174 {
175         struct timespec t;
176
177         t.tv_nsec = nsec % 1000000000;
178         t.tv_sec = nsec / 1000000000;
179         return t;
180 }