Added dht files, updated dependencies
[transsip-mirror.git] / src / timespec.h
blobbf366c5e91ecf2a33457ec6c38f39791bcc7ec6d
1 /*
2 * transsip - the telephony network
3 * By Daniel Borkmann <daniel@transsip.org>
4 * Copyright 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,
5 * Swiss federal institute of technology (ETH Zurich)
6 * Subject to the GPL, version 2.
7 */
9 #ifndef TIMESPEC_H
10 #define TIMESPEC_H
12 #include <limits.h>
13 #include <time.h>
14 #include <sys/time.h>
15 #include <sys/types.h>
16 #include <unistd.h>
17 #include <assert.h>
18 #include <errno.h>
19 #include <stdbool.h>
21 #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
22 #define TYPE_MAXIMUM(t) \
23 ((t) (! TYPE_SIGNED(t) \
24 ? (t) -1 \
25 : ~ (~ (t) 0 << (sizeof(t) * CHAR_BIT - 1))))
27 #ifndef TIME_T_MAX
28 # define TIME_T_MAX TYPE_MAXIMUM(time_t)
29 #endif
31 static inline int timespec_subtract(struct timespec *result,
32 struct timespec *after,
33 struct timespec *before)
35 result->tv_nsec = after->tv_nsec - before->tv_nsec;
37 if (result->tv_nsec < 0) {
38 /* Borrow 1sec from 'tv_sec' if subtraction -ve */
39 result->tv_nsec += 1000000000;
40 result->tv_sec = after->tv_sec - before->tv_sec - 1;
42 return 1;
43 } else {
44 result->tv_sec = after->tv_sec - before->tv_sec;
45 return 0;
49 /* By Jim Meyering */
50 static inline void xusleep(const struct timespec *ts_delay)
52 struct timeval tv_delay;
54 tv_delay.tv_sec = ts_delay->tv_sec;
55 tv_delay.tv_usec = (ts_delay->tv_nsec + 999) / 1000;
57 if (tv_delay.tv_usec == 1000000) {
58 time_t t1 = tv_delay.tv_sec + 1;
59 if (t1 < tv_delay.tv_sec)
60 tv_delay.tv_usec = 1000000 - 1; /* Close enough */
61 else {
62 tv_delay.tv_sec = t1;
63 tv_delay.tv_usec = 0;
67 select(0, NULL, NULL, NULL, &tv_delay);
70 static inline void xusleep2(long usecs)
72 struct timespec ts = {
73 .tv_sec = 0,
74 .tv_nsec = usecs * 1000,
77 xusleep(&ts);
80 /* By Paul Eggert, Jim Meyering */
81 static inline int xnanosleep(double seconds)
83 enum {
84 BILLION = 1000000000
87 bool overflow = false;
88 double ns;
89 struct timespec ts_sleep;
91 assert(0 <= seconds);
94 * Separate whole seconds from nanoseconds.
95 * Be careful to detect any overflow.
98 ts_sleep.tv_sec = seconds;
99 ns = BILLION * (seconds - ts_sleep.tv_sec);
100 overflow |= !(ts_sleep.tv_sec <= seconds && 0 <= ns && ns <= BILLION);
101 ts_sleep.tv_nsec = ns;
104 * Round up to the next whole number, if necessary, so that we
105 * always sleep for at least the requested amount of time. Assuming
106 * the default rounding mode, we don't have to worry about the
107 * rounding error when computing 'ns' above, since the error won't
108 * cause 'ns' to drop below an integer boundary.
111 ts_sleep.tv_nsec += (ts_sleep.tv_nsec < ns);
113 /* Normalize the interval length. nanosleep requires this. */
115 if (BILLION <= ts_sleep.tv_nsec) {
116 time_t t = ts_sleep.tv_sec + 1;
118 /* Detect integer overflow. */
119 overflow |= (t < ts_sleep.tv_sec);
121 ts_sleep.tv_sec = t;
122 ts_sleep.tv_nsec -= BILLION;
125 for (;;) {
126 if (overflow) {
127 ts_sleep.tv_sec = TIME_T_MAX;
128 ts_sleep.tv_nsec = BILLION - 1;
132 * Linux-2.6.8.1's nanosleep returns -1, but doesn't set errno
133 * when resumed after being suspended. Earlier versions would
134 * set errno to EINTR. nanosleep from linux-2.6.10, as well as
135 * implementations by (all?) other vendors, doesn't return -1
136 * in that case; either it continues sleeping (if time remains)
137 * or it returns zero (if the wake-up time has passed).
140 errno = 0;
142 if (nanosleep(&ts_sleep, NULL) == 0)
143 break;
144 if (errno != EINTR && errno != 0)
145 return -1;
148 return 0;
151 static inline int set_timeout(struct timeval *timeval, unsigned int msec)
154 if (msec == 0)
155 return -EINVAL;
157 timeval->tv_sec = 0;
158 timeval->tv_usec = 0;
160 if (msec < 1000) {
161 timeval->tv_usec = msec * 1000;
162 return 0;
165 timeval->tv_sec = (long) (msec / 1000);
166 timeval->tv_usec = (long) ((msec - (timeval->tv_sec * 1000)) * 1000);
168 return 0;
171 /* x86 ticks */
172 static inline unsigned long long getticks(void)
174 unsigned int __a,__d;
176 __asm__ __volatile__("rdtsc" : "=a" (__a), "=d" (__d));
177 return ((long long)__a) | (((long long)__d)<<32);
180 #endif /* TIMESPEC_H */