Added header comment
[transsip.git] / src / xutils.h
blob79cd44242ce4ca55b3110a65d17e8eb416508a2a
1 /*
2 * transsip - the telephony network
3 * By Daniel Borkmann <daniel@transsip.org>
4 * Copyright 2011 Daniel Borkmann.
5 * Subject to the GPL, version 2.
6 */
8 #ifndef XUTILS_H
9 #define XUTILS_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 extern void fsync_or_die(int fd, const char *msg);
21 extern int open_or_die(const char *file, int flags);
22 extern int open_or_die_m(const char *file, int flags, mode_t mode);
23 extern ssize_t read_or_die(int fd, void *buf, size_t count);
24 extern ssize_t read_exact(int fd, void *buf, size_t len, int mayexit);
25 extern ssize_t write_exact(int fd, void *buf, size_t len, int mayexit);
26 extern ssize_t write_or_die(int fd, const void *buf, size_t count);
27 extern ssize_t write_or_whine_pipe(int fd, const void *buf, size_t len,
28 const char *msg);
29 extern ssize_t write_or_whine(int fd, const void *buf, size_t len,
30 const char *msg);
31 extern size_t strlcpy(char *dest, const char *src, size_t size);
32 extern int slprintf(char *dst, size_t size, const char *fmt, ...);
33 extern char **strntoargv(char *str, size_t len, int *argc);
35 #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
36 #define TYPE_MAXIMUM(t) \
37 ((t) (! TYPE_SIGNED(t) \
38 ? (t) -1 \
39 : ~ (~ (t) 0 << (sizeof(t) * CHAR_BIT - 1))))
41 #ifndef TIME_T_MAX
42 # define TIME_T_MAX TYPE_MAXIMUM(time_t)
43 #endif
45 static inline int timespec_subtract(struct timespec *result,
46 struct timespec *after,
47 struct timespec *before)
49 result->tv_nsec = after->tv_nsec - before->tv_nsec;
51 if (result->tv_nsec < 0) {
52 /* Borrow 1sec from 'tv_sec' if subtraction -ve */
53 result->tv_nsec += 1000000000;
54 result->tv_sec = after->tv_sec - before->tv_sec - 1;
56 return 1;
57 } else {
58 result->tv_sec = after->tv_sec - before->tv_sec;
59 return 0;
63 /* By Jim Meyering */
64 static inline void xusleep(const struct timespec *ts_delay)
66 struct timeval tv_delay;
68 tv_delay.tv_sec = ts_delay->tv_sec;
69 tv_delay.tv_usec = (ts_delay->tv_nsec + 999) / 1000;
71 if (tv_delay.tv_usec == 1000000) {
72 time_t t1 = tv_delay.tv_sec + 1;
73 if (t1 < tv_delay.tv_sec)
74 tv_delay.tv_usec = 1000000 - 1; /* Close enough */
75 else {
76 tv_delay.tv_sec = t1;
77 tv_delay.tv_usec = 0;
81 select(0, NULL, NULL, NULL, &tv_delay);
84 static inline void xusleep2(long usecs)
86 struct timespec ts = {
87 .tv_sec = 0,
88 .tv_nsec = usecs * 1000,
91 xusleep(&ts);
94 /* By Paul Eggert, Jim Meyering */
95 static inline int xnanosleep(double seconds)
97 enum {
98 BILLION = 1000000000
101 bool overflow = false;
102 double ns;
103 struct timespec ts_sleep;
105 assert(0 <= seconds);
108 * Separate whole seconds from nanoseconds.
109 * Be careful to detect any overflow.
112 ts_sleep.tv_sec = seconds;
113 ns = BILLION * (seconds - ts_sleep.tv_sec);
114 overflow |= !(ts_sleep.tv_sec <= seconds && 0 <= ns && ns <= BILLION);
115 ts_sleep.tv_nsec = ns;
118 * Round up to the next whole number, if necessary, so that we
119 * always sleep for at least the requested amount of time. Assuming
120 * the default rounding mode, we don't have to worry about the
121 * rounding error when computing 'ns' above, since the error won't
122 * cause 'ns' to drop below an integer boundary.
125 ts_sleep.tv_nsec += (ts_sleep.tv_nsec < ns);
127 /* Normalize the interval length. nanosleep requires this. */
129 if (BILLION <= ts_sleep.tv_nsec) {
130 time_t t = ts_sleep.tv_sec + 1;
132 /* Detect integer overflow. */
133 overflow |= (t < ts_sleep.tv_sec);
135 ts_sleep.tv_sec = t;
136 ts_sleep.tv_nsec -= BILLION;
139 for (;;) {
140 if (overflow) {
141 ts_sleep.tv_sec = TIME_T_MAX;
142 ts_sleep.tv_nsec = BILLION - 1;
146 * Linux-2.6.8.1's nanosleep returns -1, but doesn't set errno
147 * when resumed after being suspended. Earlier versions would
148 * set errno to EINTR. nanosleep from linux-2.6.10, as well as
149 * implementations by (all?) other vendors, doesn't return -1
150 * in that case; either it continues sleeping (if time remains)
151 * or it returns zero (if the wake-up time has passed).
154 errno = 0;
156 if (nanosleep(&ts_sleep, NULL) == 0)
157 break;
158 if (errno != EINTR && errno != 0)
159 return -1;
162 return 0;
165 static inline int set_timeout(struct timeval *timeval, unsigned int msec)
167 if (msec == 0)
168 return -EINVAL;
170 timeval->tv_sec = 0;
171 timeval->tv_usec = 0;
173 if (msec < 1000) {
174 timeval->tv_usec = msec * 1000;
175 return 0;
178 timeval->tv_sec = (long) (msec / 1000);
179 timeval->tv_usec = (long) ((msec - (timeval->tv_sec * 1000)) * 1000);
181 return 0;
184 /* x86 ticks */
185 static inline unsigned long long getticks(void)
187 unsigned int __a,__d;
188 __asm__ __volatile__("rdtsc" : "=a" (__a), "=d" (__d));
189 return ((long long)__a) | (((long long)__d)<<32);
192 #endif /* XUTILS_H */