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.
15 #include <sys/types.h>
21 #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
22 #define TYPE_MAXIMUM(t) \
23 ((t) (! TYPE_SIGNED(t) \
25 : ~ (~ (t) 0 << (sizeof(t) * CHAR_BIT - 1))))
28 # define TIME_T_MAX TYPE_MAXIMUM(time_t)
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;
44 result
->tv_sec
= after
->tv_sec
- before
->tv_sec
;
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 */
67 select(0, NULL
, NULL
, NULL
, &tv_delay
);
70 static inline void xusleep2(long usecs
)
72 struct timespec ts
= {
74 .tv_nsec
= usecs
* 1000,
80 /* By Paul Eggert, Jim Meyering */
81 static inline int xnanosleep(double seconds
)
87 bool overflow
= false;
89 struct timespec ts_sleep
;
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
);
122 ts_sleep
.tv_nsec
-= BILLION
;
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).
142 if (nanosleep(&ts_sleep
, NULL
) == 0)
144 if (errno
!= EINTR
&& errno
!= 0)
151 static inline int set_timeout(struct timeval
*timeval
, unsigned int msec
)
158 timeval
->tv_usec
= 0;
161 timeval
->tv_usec
= msec
* 1000;
165 timeval
->tv_sec
= (long) (msec
/ 1000);
166 timeval
->tv_usec
= (long) ((msec
- (timeval
->tv_sec
* 1000)) * 1000);
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 */