summaryrefslogtreecommitdiff
path: root/include/openvswitch/compiler.h
blob: 5289a70f6eadc6b5535afc71b175b4c20df5696a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
/*
 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016, 2017 Nicira, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef OPENVSWITCH_COMPILER_H
#define OPENVSWITCH_COMPILER_H 1

#include <stddef.h>
#include <stdbool.h>

#ifndef __has_feature
  #define __has_feature(x) 0
#endif
#ifndef __has_extension
  #define __has_extension(x) 0
#endif

/* To make OVS_NO_RETURN portable across gcc/clang and MSVC, it should be
 * added at the beginning of the function declaration. */
#if __GNUC__ && !__CHECKER__
#define OVS_NO_RETURN __attribute__((__noreturn__))
#elif _MSC_VER
#define OVS_NO_RETURN __declspec(noreturn)
#else
#define OVS_NO_RETURN
#endif

#if __GNUC__ && !__CHECKER__
#define OVS_UNUSED __attribute__((__unused__))
#define OVS_PRINTF_FORMAT(FMT, ARG1) __attribute__((__format__(printf, FMT, ARG1)))
#define OVS_SCANF_FORMAT(FMT, ARG1) __attribute__((__format__(scanf, FMT, ARG1)))
#define OVS_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
#define OVS_LIKELY(CONDITION) __builtin_expect(!!(CONDITION), 1)
#define OVS_UNLIKELY(CONDITION) __builtin_expect(!!(CONDITION), 0)
#else
#define OVS_UNUSED
#define OVS_PRINTF_FORMAT(FMT, ARG1)
#define OVS_SCANF_FORMAT(FMT, ARG1)
#define OVS_WARN_UNUSED_RESULT
#define OVS_LIKELY(CONDITION) (!!(CONDITION))
#define OVS_UNLIKELY(CONDITION) (!!(CONDITION))
#endif

#if __has_feature(c_thread_safety_attributes)
/* "clang" annotations for thread safety check.
 *
 * OVS_LOCKABLE indicates that the struct contains mutex element
 * which can be locked by functions like ovs_mutex_lock().
 *
 * Below, the word MUTEX stands for the name of an object with an OVS_LOCKABLE
 * struct type.  It can also be a comma-separated list of multiple structs,
 * e.g. to require a function to hold multiple locks while invoked.
 *
 *
 * On a variable:
 *
 *    - OVS_GUARDED indicates that the variable may only be accessed some mutex
 *      is held.
 *
 *    - OVS_GUARDED_BY(MUTEX) indicates that the variable may only be accessed
 *      while the specific MUTEX is held.
 *
 *
 * On a variable A of mutex type:
 *
 *    - OVS_ACQ_BEFORE(B), where B is a mutex or a comma-separated list of
 *      mutexes, declare that if both A and B are acquired at the same time,
 *      then A must be acquired before B.  That is, B nests inside A.
 *
 *    - OVS_ACQ_AFTER(B) is the opposite of OVS_ACQ_BEFORE(B), that is, it
 *      declares that A nests inside B.
 *
 *
 * On a function, the following attributes apply to mutexes:
 *
 *    - OVS_ACQUIRES(MUTEX) indicate that the function must be called without
 *      holding MUTEX and that it returns holding MUTEX.
 *
 *    - OVS_RELEASES(MUTEX) indicates that the function may only be called with
 *      MUTEX held and that it returns with MUTEX released.  It can be used for
 *      all types of MUTEX.
 *
 *    - OVS_TRY_LOCK(RETVAL, MUTEX) indicate that the function will try to
 *      acquire MUTEX.  RETVAL is an integer or boolean value specifying the
 *      return value of a successful lock acquisition.
 *
 *    - OVS_REQUIRES(MUTEX) indicate that the function may only be called with
 *      MUTEX held and that the function does not release MUTEX.
 *
 *    - OVS_EXCLUDED(MUTEX) indicates that the function may only be called when
 *      MUTEX is not held.
 *
 *
 * The following variants, with the same syntax, apply to reader-writer locks:
 *
 *    mutex                rwlock, for reading  rwlock, for writing
 *    -------------------  -------------------  -------------------
 *    OVS_ACQUIRES         OVS_ACQ_RDLOCK       OVS_ACQ_WRLOCK
 *    OVS_RELEASES         OVS_RELEASES         OVS_RELEASES
 *    OVS_TRY_LOCK         OVS_TRY_RDLOCK       OVS_TRY_WRLOCK
 *    OVS_REQUIRES         OVS_REQ_RDLOCK       OVS_REQ_WRLOCK
 *    OVS_EXCLUDED         OVS_EXCLUDED         OVS_EXCLUDED
 */
#define OVS_LOCKABLE __attribute__((lockable))
#define OVS_REQ_RDLOCK(...) __attribute__((shared_locks_required(__VA_ARGS__)))
#define OVS_ACQ_RDLOCK(...) __attribute__((shared_lock_function(__VA_ARGS__)))
#define OVS_REQ_WRLOCK(...) \
    __attribute__((exclusive_locks_required(__VA_ARGS__)))
#define OVS_ACQ_WRLOCK(...) \
    __attribute__((exclusive_lock_function(__VA_ARGS__)))
#define OVS_REQUIRES(...) \
    __attribute__((exclusive_locks_required(__VA_ARGS__)))
#define OVS_ACQUIRES(...) \
    __attribute__((exclusive_lock_function(__VA_ARGS__)))
#define OVS_TRY_WRLOCK(RETVAL, ...)                              \
    __attribute__((exclusive_trylock_function(RETVAL, __VA_ARGS__)))
#define OVS_TRY_RDLOCK(RETVAL, ...)                          \
    __attribute__((shared_trylock_function(RETVAL, __VA_ARGS__)))
#define OVS_TRY_LOCK(RETVAL, ...)                                \
    __attribute__((exclusive_trylock_function(RETVAL, __VA_ARGS__)))
#define OVS_GUARDED __attribute__((guarded_var))
#define OVS_GUARDED_BY(...) __attribute__((guarded_by(__VA_ARGS__)))
#define OVS_RELEASES(...) __attribute__((unlock_function(__VA_ARGS__)))
#define OVS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__)))
#define OVS_ACQ_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__)))
#define OVS_ACQ_AFTER(...) __attribute__((acquired_after(__VA_ARGS__)))
#define OVS_NO_THREAD_SAFETY_ANALYSIS \
    __attribute__((no_thread_safety_analysis))
#else  /* not Clang */
#define OVS_LOCKABLE
#define OVS_REQ_RDLOCK(...)
#define OVS_ACQ_RDLOCK(...)
#define OVS_REQ_WRLOCK(...)
#define OVS_ACQ_WRLOCK(...)
#define OVS_REQUIRES(...)
#define OVS_ACQUIRES(...)
#define OVS_TRY_WRLOCK(...)
#define OVS_TRY_RDLOCK(...)
#define OVS_TRY_LOCK(...)
#define OVS_GUARDED
#define OVS_GUARDED_BY(...)
#define OVS_EXCLUDED(...)
#define OVS_RELEASES(...)
#define OVS_ACQ_BEFORE(...)
#define OVS_ACQ_AFTER(...)
#define OVS_NO_THREAD_SAFETY_ANALYSIS
#endif

/* ISO C says that a C implementation may choose any integer type for an enum
 * that is sufficient to hold all of its values.  Common ABIs (such as the
 * System V ABI used on i386 GNU/Linux) always use a full-sized "int", even
 * when a smaller type would suffice.
 *
 * In GNU C, "enum __attribute__((packed)) name { ... }" defines 'name' as an
 * enum compatible with a type that is no bigger than necessary.  This is the
 * intended use of OVS_PACKED_ENUM.
 *
 * OVS_PACKED_ENUM is intended for use only as a space optimization, since it
 * only works with GCC.  That means that it must not be used in wire protocols
 * or otherwise exposed outside of a single process. */
#if __GNUC__ && !__CHECKER__
#define OVS_PACKED_ENUM __attribute__((__packed__))
#define HAVE_PACKED_ENUM
#else
#define OVS_PACKED_ENUM
#endif

#ifndef _MSC_VER
#define OVS_PACKED(DECL) DECL __attribute__((__packed__))
#else
#define OVS_PACKED(DECL) __pragma(pack(push, 1)) DECL __pragma(pack(pop))
#endif

/* OVS_ALIGNED_STRUCT may be used to define a structure whose instances should
 * aligned on an N-byte boundary.  This:
 *     OVS_ALIGNED_STRUCT(64, mystruct) { ... };
 * is equivalent to the following except that it specifies 64-byte alignment:
 *     struct mystruct { ... };
 *
 * OVS_ALIGNED_VAR defines a variable aligned on an N-byte boundary.  For
 * example,
 *     OVS_ALIGNED_VAR(64) int x;
 * defines a "int" variable that is aligned on a 64-byte boundary.
 */
#ifndef _MSC_VER
#define OVS_ALIGNED_STRUCT(N, TAG) struct __attribute__((aligned(N))) TAG
#define OVS_ALIGNED_VAR(N) __attribute__((aligned(N)))
#else
#define OVS_ALIGNED_STRUCT(N, TAG) __declspec(align(N)) struct TAG
#define OVS_ALIGNED_VAR(N) __declspec(align(N))
#endif

/* Supplies code to be run at startup time before invoking main().
 * Use as:
 *
 *     OVS_CONSTRUCTOR(my_constructor) {
 *         ...some code...
 *     }
 */
#ifdef _MSC_VER
#define CCALL __cdecl
#pragma section(".CRT$XCU",read)
#define OVS_CONSTRUCTOR(f) \
    static void __cdecl f(void); \
    __declspec(allocate(".CRT$XCU")) static void (__cdecl*f##_)(void) = f; \
    static void __cdecl f(void)
#else
#define OVS_CONSTRUCTOR(f) \
    static void f(void) __attribute__((constructor)); \
    static void f(void)
#endif

/* OVS_PREFETCH() can be used to instruct the CPU to fetch the cache
 * line containing the given address to a CPU cache.
 * OVS_PREFETCH_WRITE() should be used when the memory is going to be
 * written to.  Depending on the target CPU, this can generate the same
 * instruction as OVS_PREFETCH(), or bring the data into the cache in an
 * exclusive state. */
#if __GNUC__
#define OVS_PREFETCH(addr) __builtin_prefetch((addr))
#define OVS_PREFETCH_WRITE(addr) __builtin_prefetch((addr), 1)
#else
#define OVS_PREFETCH(addr)
#define OVS_PREFETCH_WRITE(addr)
#endif

/* Since Visual Studio 2015 there has been an effort to make offsetof a
 * builtin_offsetof, unfortunately both implementation (the regular define and
 * the built in one) are buggy and cause issues when using them via
 * the C compiler.
 * e.g.: https://bit.ly/2UvWwti
 */
#if _MSC_VER >= 1900
#undef offsetof
#define offsetof(type, member) \
    ((size_t)((char *)&(((type *)0)->member) - (char *)0))
#endif

/* Build assertions.
 *
 * Use BUILD_ASSERT_DECL as a declaration or a statement, or BUILD_ASSERT as
 * part of an expression. */
#ifdef __CHECKER__
#define BUILD_ASSERT(EXPR) ((void) 0)
#define BUILD_ASSERT_DECL(EXPR) extern int (*build_assert(void))[1]
#elif defined(__cplusplus) && __cplusplus >= 201103L
#define BUILD_ASSERT(EXPR) static_assert(EXPR, "assertion failed")
#define BUILD_ASSERT_DECL(EXPR) static_assert(EXPR, "assertion failed")
#elif defined(__cplusplus) && __cplusplus < 201103L
#include <boost/static_assert.hpp>
#define BUILD_ASSERT BOOST_STATIC_ASSERT
#define BUILD_ASSERT_DECL BOOST_STATIC_ASSERT
#elif (__GNUC__ * 256 + __GNUC_MINOR__ >= 0x403 \
       || __has_extension(c_static_assert))
#define BUILD_ASSERT_DECL(EXPR) _Static_assert(EXPR, #EXPR)
#define BUILD_ASSERT(EXPR) (void) ({ _Static_assert(EXPR, #EXPR); })
#else
#define BUILD_ASSERT__(EXPR) \
        sizeof(struct { unsigned int build_assert_failed : (EXPR) ? 1 : -1; })
#define BUILD_ASSERT(EXPR) (void) BUILD_ASSERT__(EXPR)
#define BUILD_ASSERT_DECL(EXPR) \
        extern int (*build_assert(void))[BUILD_ASSERT__(EXPR)]
#endif

#ifdef __GNUC__
#define BUILD_ASSERT_GCCONLY(EXPR) BUILD_ASSERT(EXPR)
#define BUILD_ASSERT_DECL_GCCONLY(EXPR) BUILD_ASSERT_DECL(EXPR)
#else
#define BUILD_ASSERT_GCCONLY(EXPR) ((void) 0)
#define BUILD_ASSERT_DECL_GCCONLY(EXPR) ((void) 0)
#endif


#endif /* compiler.h */