Added support for UDP in flowtop
[netsniff-ng.git] / src / timespec.h
blob2b57758f56434ad1cb37dbe5e5595c3089ac159a
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2009, 2010 Daniel Borkmann.
5 * Subject to the GPL, version 2.
6 */
8 #ifndef TIMESPEC_H
9 #define TIMESPEC_H
11 #include <limits.h>
12 #include <time.h>
13 #include <sys/time.h>
14 #include <sys/types.h>
15 #include <unistd.h>
16 #include <assert.h>
17 #include <errno.h>
18 #include <stdbool.h>
20 #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
21 #define TYPE_MAXIMUM(t) \
22 ((t) (! TYPE_SIGNED(t) \
23 ? (t) -1 \
24 : ~ (~ (t) 0 << (sizeof(t) * CHAR_BIT - 1))))
26 #ifndef TIME_T_MAX
27 # define TIME_T_MAX TYPE_MAXIMUM(time_t)
28 #endif
30 static inline int timespec_subtract(struct timespec *result,
31 struct timespec *after,
32 struct timespec *before)
34 result->tv_nsec = after->tv_nsec - before->tv_nsec;
36 if (result->tv_nsec < 0) {
37 /* Borrow 1sec from 'tv_sec' if subtraction -ve */
38 result->tv_nsec += 1000000000;
39 result->tv_sec = after->tv_sec - before->tv_sec - 1;
41 return 1;
42 } else {
43 result->tv_sec = after->tv_sec - before->tv_sec;
44 return 0;
48 /* By Jim Meyering */
49 static inline void xusleep(const struct timespec *ts_delay)
51 struct timeval tv_delay;
53 tv_delay.tv_sec = ts_delay->tv_sec;
54 tv_delay.tv_usec = (ts_delay->tv_nsec + 999) / 1000;
56 if (tv_delay.tv_usec == 1000000) {
57 time_t t1 = tv_delay.tv_sec + 1;
58 if (t1 < tv_delay.tv_sec)
59 tv_delay.tv_usec = 1000000 - 1; /* Close enough */
60 else {
61 tv_delay.tv_sec = t1;
62 tv_delay.tv_usec = 0;
66 select(0, NULL, NULL, NULL, &tv_delay);
69 static inline void xusleep2(long usecs)
71 struct timespec ts = {
72 .tv_sec = 0,
73 .tv_nsec = usecs * 1000,
76 xusleep(&ts);
79 /* By Paul Eggert, Jim Meyering */
80 static inline int xnanosleep(double seconds)
82 enum {
83 BILLION = 1000000000
86 bool overflow = false;
87 double ns;
88 struct timespec ts_sleep;
90 assert(0 <= seconds);
93 * Separate whole seconds from nanoseconds.
94 * Be careful to detect any overflow.
97 ts_sleep.tv_sec = seconds;
98 ns = BILLION * (seconds - ts_sleep.tv_sec);
99 overflow |= !(ts_sleep.tv_sec <= seconds && 0 <= ns && ns <= BILLION);
100 ts_sleep.tv_nsec = ns;
103 * Round up to the next whole number, if necessary, so that we
104 * always sleep for at least the requested amount of time. Assuming
105 * the default rounding mode, we don't have to worry about the
106 * rounding error when computing 'ns' above, since the error won't
107 * cause 'ns' to drop below an integer boundary.
110 ts_sleep.tv_nsec += (ts_sleep.tv_nsec < ns);
112 /* Normalize the interval length. nanosleep requires this. */
114 if (BILLION <= ts_sleep.tv_nsec) {
115 time_t t = ts_sleep.tv_sec + 1;
117 /* Detect integer overflow. */
118 if (ts_sleep.tv_sec >= TIME_T_MAX)
119 overflow |= 1;
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 */