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
99static 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 */
134static RD_INLINE RD_UNUSED
135void 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 */
165static 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 */
177static 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