summaryrefslogtreecommitdiff
path: root/lib/compiler.h
blob: daca32dd70b6b9085bea6f1a022345e15efe838a (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
/*
 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 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 COMPILER_H
#define COMPILER_H 1

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

#if __GNUC__ && !__CHECKER__
#define NO_RETURN __attribute__((__noreturn__))
#define OVS_UNUSED __attribute__((__unused__))
#define PRINTF_FORMAT(FMT, ARG1) __attribute__((__format__(printf, FMT, ARG1)))
#define SCANF_FORMAT(FMT, ARG1) __attribute__((__format__(scanf, FMT, ARG1)))
#define STRFTIME_FORMAT(FMT) __attribute__((__format__(__strftime__, FMT, 0)))
#define MALLOC_LIKE __attribute__((__malloc__))
#define ALWAYS_INLINE __attribute__((always_inline))
#define WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
#define SENTINEL(N) __attribute__((sentinel(N)))
#define OVS_LIKELY(CONDITION) __builtin_expect(!!(CONDITION), 1)
#define OVS_UNLIKELY(CONDITION) __builtin_expect(!!(CONDITION), 0)
#else
#define NO_RETURN
#define OVS_UNUSED
#define PRINTF_FORMAT(FMT, ARG1)
#define SCANF_FORMAT(FMT, ARG1)
#define STRFTIME_FORMAT(FMT)
#define MALLOC_LIKE
#define ALWAYS_INLINE
#define WARN_UNUSED_RESULT
#define SENTINEL(N)
#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_LOCKS_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_LOCKS_EXCLUDED   OVS_LOCKS_EXCLUDED   OVS_LOCKS_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__))
#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

#ifdef _MSC_VER
#define CCALL __cdecl
#pragma section(".CRT$XCU",read)
#define OVS_CONSTRUCTOR(f) \
    static void __cdecl f(void); \
    __declspec(allocate(".CRT$XCU")) 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

#endif /* compiler.h */