1 | /* |
2 | * librdkafka - Apache Kafka C library |
3 | * |
4 | * Copyright (c) 2012-2015 Magnus Edenhill |
5 | * All rights reserved. |
6 | * |
7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions are met: |
9 | * |
10 | * 1. Redistributions of source code must retain the above copyright notice, |
11 | * this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright notice, |
13 | * this list of conditions and the following disclaimer in the documentation |
14 | * and/or other materials provided with the distribution. |
15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
26 | * POSSIBILITY OF SUCH DAMAGE. |
27 | */ |
28 | |
29 | /** |
30 | * POSIX system support |
31 | */ |
32 | #ifndef _RDPOSIX_H_ |
33 | #define _RDPOSIX_H_ |
34 | |
35 | #include <unistd.h> |
36 | #include <stdio.h> |
37 | #include <sys/time.h> |
38 | #include <inttypes.h> |
39 | #include <fcntl.h> |
40 | #include <errno.h> |
41 | #include <string.h> |
42 | |
43 | /** |
44 | * Types |
45 | */ |
46 | |
47 | |
48 | /** |
49 | * Annotations, attributes, optimizers |
50 | */ |
51 | #ifndef likely |
52 | #define likely(x) __builtin_expect((x),1) |
53 | #endif |
54 | #ifndef unlikely |
55 | #define unlikely(x) __builtin_expect((x),0) |
56 | #endif |
57 | |
58 | #define RD_UNUSED __attribute__((unused)) |
59 | #define RD_INLINE inline |
60 | #define RD_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) |
61 | #define RD_NORETURN __attribute__((noreturn)) |
62 | #define RD_IS_CONSTANT(p) __builtin_constant_p((p)) |
63 | #define RD_TLS __thread |
64 | |
65 | /** |
66 | * Allocation |
67 | */ |
68 | #if !defined(__FreeBSD__) |
69 | /* alloca(3) is in stdlib on FreeBSD */ |
70 | #include <alloca.h> |
71 | #endif |
72 | |
73 | #define rd_alloca(N) alloca(N) |
74 | |
75 | |
76 | /** |
77 | * Strings, formatting, printf, .. |
78 | */ |
79 | |
80 | /* size_t and ssize_t format strings */ |
81 | #define PRIusz "zu" |
82 | #define PRIdsz "zd" |
83 | |
84 | #define RD_FORMAT(...) __attribute__((format (__VA_ARGS__))) |
85 | #define rd_snprintf(...) snprintf(__VA_ARGS__) |
86 | #define rd_vsnprintf(...) vsnprintf(__VA_ARGS__) |
87 | |
88 | #define rd_strcasecmp(A,B) strcasecmp(A,B) |
89 | #define rd_strncasecmp(A,B,N) strncasecmp(A,B,N) |
90 | |
91 | /** |
92 | * Errors |
93 | */ |
94 | |
95 | |
96 | #define rd_set_errno(err) (errno = (err)) |
97 | |
98 | #if HAVE_STRERROR_R |
99 | static RD_INLINE RD_UNUSED const char *rd_strerror(int err) { |
100 | static RD_TLS char ret[128]; |
101 | |
102 | #if defined(__GLIBC__) && defined(_GNU_SOURCE) |
103 | return strerror_r(err, ret, sizeof(ret)); |
104 | #else /* XSI version */ |
105 | int r; |
106 | /* The r assignment is to catch the case where |
107 | * _GNU_SOURCE is not defined but the GNU version is |
108 | * picked up anyway. */ |
109 | r = strerror_r(err, ret, sizeof(ret)); |
110 | if (unlikely(r)) |
111 | rd_snprintf(ret, sizeof(ret), |
112 | "strerror_r(%d) failed (ret %d)" , err, r); |
113 | return ret; |
114 | #endif |
115 | } |
116 | #else |
117 | #define rd_strerror(err) strerror(err) |
118 | #endif |
119 | |
120 | |
121 | /** |
122 | * Atomics |
123 | */ |
124 | #include "rdatomic.h" |
125 | |
126 | /** |
127 | * Misc |
128 | */ |
129 | |
130 | /** |
131 | * Microsecond sleep. |
132 | * Will retry on signal interrupt unless *terminate is true. |
133 | */ |
134 | static RD_INLINE RD_UNUSED |
135 | void rd_usleep (int usec, rd_atomic32_t *terminate) { |
136 | struct timespec req = {usec / 1000000, (long)(usec % 1000000) * 1000}; |
137 | |
138 | /* Retry until complete (issue #272), unless terminating. */ |
139 | while (nanosleep(&req, &req) == -1 && |
140 | (errno == EINTR && (!terminate || !rd_atomic32_get(terminate)))) |
141 | ; |
142 | } |
143 | |
144 | |
145 | |
146 | |
147 | #define rd_gettimeofday(tv,tz) gettimeofday(tv,tz) |
148 | |
149 | |
150 | #define rd_assert(EXPR) assert(EXPR) |
151 | |
152 | /** |
153 | * Empty struct initializer |
154 | */ |
155 | #define RD_ZERO_INIT {} |
156 | |
157 | /** |
158 | * Sockets, IO |
159 | */ |
160 | |
161 | /** |
162 | * @brief Set socket to non-blocking |
163 | * @returns 0 on success or errno on failure. |
164 | */ |
165 | static RD_UNUSED int rd_fd_set_nonblocking (int fd) { |
166 | int fl = fcntl(fd, F_GETFL, 0); |
167 | if (fl == -1 || |
168 | fcntl(fd, F_SETFL, fl | O_NONBLOCK) == -1) |
169 | return errno; |
170 | return 0; |
171 | } |
172 | |
173 | /** |
174 | * @brief Create non-blocking pipe |
175 | * @returns 0 on success or errno on failure |
176 | */ |
177 | static RD_UNUSED int rd_pipe_nonblocking (int *fds) { |
178 | if (pipe(fds) == -1 || |
179 | rd_fd_set_nonblocking(fds[0]) == -1 || |
180 | rd_fd_set_nonblocking(fds[1])) |
181 | return errno; |
182 | |
183 | /* Minimize buffer sizes to avoid a large number |
184 | * of signaling bytes to accumulate when |
185 | * io-signalled queue is not being served for a while. */ |
186 | #ifdef F_SETPIPE_SZ |
187 | /* Linux automatically rounds the pipe size up |
188 | * to the minimum size. */ |
189 | fcntl(fds[0], F_SETPIPE_SZ, 100); |
190 | fcntl(fds[1], F_SETPIPE_SZ, 100); |
191 | #endif |
192 | return 0; |
193 | } |
194 | #define rd_pipe(fds) pipe(fds) |
195 | #define rd_read(fd,buf,sz) read(fd,buf,sz) |
196 | #define rd_write(fd,buf,sz) write(fd,buf,sz) |
197 | #define rd_close(fd) close(fd) |
198 | |
199 | #endif /* _RDPOSIX_H_ */ |
200 | |