common: macros: missing include of pthread.h
[lttng-tools.git] / src / common / macros.hpp
CommitLineData
990570ed 1/*
21cf9b6b 2 * Copyright (C) 2011 EfficiOS Inc.
ab5be9fa 3 * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
990570ed 4 *
ab5be9fa 5 * SPDX-License-Identifier: GPL-2.0-only
990570ed 6 *
990570ed
DG
7 */
8
9#ifndef _MACROS_H
10#define _MACROS_H
11
64803277
SM
12#include <common/compat/string.hpp>
13
93375aa6 14#include <stddef.h>
64803277 15#include <stdlib.h>
f6835b82 16#include <string.h>
64803277 17
f1ca0880
JG
18#include <memory>
19#include <pthread.h>
64803277 20#include <type_traits>
990570ed
DG
21
22/*
23 * Takes a pointer x and transform it so we can use it to access members
24 * without a function call. Here an example:
25 *
26 * #define GET_SIZE(x) LTTNG_REF(x)->size
27 *
28 * struct { int size; } s;
29 *
30 * printf("size : %d\n", GET_SIZE(&s));
31 *
32 * For this example we can't use something like this for compatibility purpose
33 * since this will fail:
34 *
35 * #define GET_SIZE(x) x->size;
36 *
37 * This is mostly use for the compatibility layer of lttng-tools. See
38 * poll/epoll for a good example. Since x can be on the stack or allocated
39 * memory using malloc(), we must use generic accessors for compat in order to
40 * *not* use a function to access members and not the variable name.
41 */
42#define LTTNG_REF(x) ((typeof(*x) *)(x))
43
64803277
SM
44#ifdef NDEBUG
45/*
46* Force usage of the assertion condition to prevent unused variable warnings
47* when `assert()` are disabled by the `NDEBUG` definition.
48*/
49# define LTTNG_ASSERT(_cond) ((void) sizeof((void) (_cond), 0))
50#else
51# include <assert.h>
52# define LTTNG_ASSERT(_cond) assert(_cond)
53#endif
54
990570ed
DG
55/*
56 * Memory allocation zeroed
57 */
64803277 58
4616a46c 59static inline
64803277
SM
60void *zmalloc_internal(size_t size)
61{
62 return calloc(1, size);
63}
64
65template <typename T>
66struct can_malloc
67{
f12e33ba
JG
68 /*
69 * gcc versions before 5.0 lack some type traits defined in C++11.
70 * Since in this instance we use the trait to prevent misuses
71 * of malloc (and statically assert) and not to generate different
72 * code based on this property, simply set value to true and allow
73 * the code to compile. Anyone using a contemporary compiler will
74 * catch the error.
75 */
76#if __GNUG__ && __GNUC__ < 5
77 static constexpr bool value = true;
78#else
64803277 79 static constexpr bool value = std::is_trivially_constructible<T>::value;
f12e33ba 80#endif
64803277
SM
81};
82
83/*
84 * Malloc and zero-initialize an object of type T, asserting that T can be
85 * safely malloc-ed (is trivially constructible).
86 */
87template<typename T>
88T *zmalloc()
89{
90 static_assert (can_malloc<T>::value, "type can be malloc'ed");
91 return (T *) zmalloc_internal(sizeof(T));
92}
93
94/*
95 * Malloc and zero-initialize a buffer of size `size`, asserting that type T
96 * can be safely malloc-ed (is trivially constructible).
97 */
98template<typename T>
99T *zmalloc(size_t size)
100{
101 static_assert (can_malloc<T>::value, "type can be malloc'ed");
102 LTTNG_ASSERT(size >= sizeof(T));
103 return (T *) zmalloc_internal(size);
104}
105
106/*
107 * Malloc and zero-initialize an array of `nmemb` elements of type T,
108 * asserting that T can be safely malloc-ed (is trivially constructible).
109 */
110template<typename T>
111T *calloc(size_t nmemb)
112{
113 static_assert (can_malloc<T>::value, "type can be malloc'ed");
114 return (T *) zmalloc_internal(nmemb * sizeof(T));
115}
116
117/*
118 * Malloc an object of type T, asserting that T can be safely malloc-ed (is
119 * trivially constructible).
120 */
121template<typename T>
122T *malloc()
4616a46c 123{
64803277
SM
124 static_assert (can_malloc<T>::value, "type can be malloc'ed");
125 return (T *) malloc(sizeof(T));
4616a46c 126}
990570ed 127
64803277
SM
128/*
129 * Malloc a buffer of size `size`, asserting that type T can be safely
130 * malloc-ed (is trivially constructible).
131 */
132template<typename T>
133T *malloc(size_t size)
134{
135 static_assert (can_malloc<T>::value, "type can be malloc'ed");
136 return (T *) malloc(size);
137}
138
139/*
140 * Prevent using `free` on types that are non-POD.
141 *
142 * Declare a delete prototype of free if the parameter type is not safe to free
143 * (non-POD).
144 *
145 * If the parameter is a pointer to void, we can't check if what is pointed
146 * to is safe to free or not, as we don't know what is pointed to. Ideally,
147 * all calls to free would be with a typed pointer, but there are too many
148 * instances of passing a pointer to void to enforce that right now. So allow
149 * pointers to void, these will not be checked.
150 */
151
152template<typename T>
a8e336c2 153struct can_free
64803277 154{
f12e33ba
JG
155 /*
156 * gcc versions before 5.0 lack some type traits defined in C++11.
157 * Since in this instance we use the trait to prevent misuses
158 * of free (and statically assert) and not to generate different
159 * code based on this property, simply set value to true and allow
160 * the code to compile. Anyone using a contemporary compiler will
161 * catch the error.
162 */
163#if __GNUG__ && __GNUC__ < 5
164 static constexpr bool value = true;
165#else
a8e336c2 166 static constexpr bool value = std::is_trivially_destructible<T>::value || std::is_void<T>::value;
f12e33ba 167#endif
64803277
SM
168};
169
a8e336c2 170template<typename T, typename = typename std::enable_if<!can_free<T>::value>::type>
64803277
SM
171void free(T *p) = delete;
172
a8e336c2
SM
173template<typename T>
174struct can_memset
175{
176 static constexpr bool value = std::is_pod<T>::value || std::is_void<T>::value;
177};
178
179template <typename T, typename = typename std::enable_if<!can_memset<T>::value>::type>
180void *memset(T *s, int c, size_t n) = delete;
181
182template<typename T>
183struct can_memcpy
184{
f12e33ba
JG
185 /*
186 * gcc versions before 5.0 lack some type traits defined in C++11.
187 * Since in this instance we use the trait to prevent misuses
188 * of memcpy (and statically assert) and not to generate different
189 * code based on this property, simply set value to true and allow
190 * the code to compile. Anyone using a contemporary compiler will
191 * catch the error.
192 */
193#if __GNUG__ && __GNUC__ < 5
194 static constexpr bool value = true;
195#else
a8e336c2 196 static constexpr bool value = std::is_trivially_copyable<T>::value;
f12e33ba 197#endif
a8e336c2
SM
198};
199
200template <typename T, typename U,
201 typename = typename std::enable_if<!can_memcpy<T>::value>::type,
202 typename = typename std::enable_if<!can_memcpy<U>::value>::type>
203void *memcpy(T *d, const U *s, size_t n) = delete;
204
205template<typename T>
206struct can_memmove
207{
f12e33ba
JG
208 /*
209 * gcc versions before 5.0 lack some type traits defined in C++11.
210 * Since in this instance we use the trait to prevent misuses
211 * of memmove (and statically assert) and not to generate different
212 * code based on this property, simply set value to true and allow
213 * the code to compile. Anyone using a contemporary compiler will
214 * catch the error.
215 */
216#if __GNUG__ && __GNUC__ < 5
217 static constexpr bool value = true;
218#else
a8e336c2 219 static constexpr bool value = std::is_trivially_copyable<T>::value;
f12e33ba 220#endif
a8e336c2
SM
221};
222
223template <typename T, typename U,
224 typename = typename std::enable_if<!can_memmove<T>::value>::type,
225 typename = typename std::enable_if<!can_memmove<U>::value>::type>
226void *memmove(T *d, const U *s, size_t n) = delete;
227
990570ed
DG
228#ifndef ARRAY_SIZE
229#define ARRAY_SIZE(array) (sizeof(array) / (sizeof((array)[0])))
230#endif
231
93375aa6
JG
232#ifndef container_of
233#define container_of(ptr, type, member) \
234 ({ \
235 const typeof(((type *)NULL)->member) * __ptr = (ptr); \
236 (type *)((char *)__ptr - offsetof(type, member)); \
237 })
238#endif
239
54c90d10
DG
240#ifndef LTTNG_PACKED
241#define LTTNG_PACKED __attribute__((__packed__))
242#endif
243
1405051a
FD
244#ifndef LTTNG_NO_SANITIZE_ADDRESS
245#if defined(__clang__) || defined (__GNUC__)
246#define LTTNG_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
247#else
248#define LTTNG_NO_SANITIZE_ADDRESS
249#endif
250#endif
251
f8f3885c
MD
252#define member_sizeof(type, field) sizeof(((type *) 0)->field)
253
a0377dfe 254#define ASSERT_LOCKED(lock) LTTNG_ASSERT(pthread_mutex_trylock(&lock))
48b7cdc2 255#define ASSERT_RCU_READ_LOCKED(lock) LTTNG_ASSERT(rcu_read_ongoing())
5e5c14ce 256
d22ad5f8
SM
257/* Attribute suitable to tag functions as having printf()-like arguments. */
258#define ATTR_FORMAT_PRINTF(_string_index, _first_to_check) \
259 __attribute__((format(printf, _string_index, _first_to_check)))
260
411b3154
SM
261/* Attribute suitable to tag functions as having strftime()-like arguments. */
262#define ATTR_FORMAT_STRFTIME(_string_index) \
263 __attribute__((format(strftime, _string_index, 0)))
264
d22ad5f8
SM
265/* Macros used to ignore specific compiler diagnostics. */
266
267#define DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
268#define DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
269
270#if defined(__clang__)
271 /* Clang */
272# define DIAGNOSTIC_IGNORE_SUGGEST_ATTRIBUTE_FORMAT
411b3154
SM
273# define DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL \
274 _Pragma("GCC diagnostic ignored \"-Wformat-nonliteral\"")
942003e5 275# define DIAGNOSTIC_IGNORE_LOGICAL_OP
05aa7e19 276# define DIAGNOSTIC_IGNORE_DUPLICATED_BRANCHES
bd2c951e
JG
277# define DIAGNOSTIC_IGNORE_INVALID_OFFSETOF
278 _Pragma("GCC diagnostic ignored \"-Winvalid-offsetof\"")
d22ad5f8
SM
279#else
280 /* GCC */
281# define DIAGNOSTIC_IGNORE_SUGGEST_ATTRIBUTE_FORMAT \
282 _Pragma("GCC diagnostic ignored \"-Wsuggest-attribute=format\"")
411b3154
SM
283# define DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL \
284 _Pragma("GCC diagnostic ignored \"-Wformat-nonliteral\"")
942003e5
MJ
285# define DIAGNOSTIC_IGNORE_LOGICAL_OP \
286 _Pragma("GCC diagnostic ignored \"-Wlogical-op\"")
05aa7e19
JG
287# define DIAGNOSTIC_IGNORE_DUPLICATED_BRANCHES \
288 _Pragma("GCC diagnostic ignored \"-Wduplicated-branches\"")
bd2c951e
JG
289# define DIAGNOSTIC_IGNORE_INVALID_OFFSETOF \
290 _Pragma("GCC diagnostic ignored \"-Winvalid-offsetof\"")
d22ad5f8
SM
291#endif
292
d50d200a
SM
293/* Used to make specific C++ functions to C code. */
294#ifdef __cplusplus
295#define C_LINKAGE extern "C"
296#else
297#define C_LINKAGE
298#endif
299
f6835b82
MD
300/*
301 * lttng_strncpy returns 0 on success, or nonzero on failure.
302 * It checks that the @src string fits into @dst_len before performing
303 * the copy. On failure, no copy has been performed.
304 *
b25a5991
JG
305 * Assumes that 'src' is null-terminated.
306 *
f6835b82
MD
307 * dst_len includes the string's trailing NULL.
308 */
309static inline
310int lttng_strncpy(char *dst, const char *src, size_t dst_len)
311{
b25a5991 312 if (strlen(src) >= dst_len) {
f6835b82
MD
313 /* Fail since copying would result in truncation. */
314 return -1;
315 }
c3ef76cd 316 strcpy(dst, src);
f6835b82
MD
317 return 0;
318}
319
990570ed 320#endif /* _MACROS_H */
This page took 0.084322 seconds and 4 git commands to generate.