Prepare for 2.3.1.
[cascardo/ovs.git] / lib / ovs-atomic.h
1 /*
2  * Copyright (c) 2013, 2014 Nicira, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef OVS_ATOMIC_H
18 #define OVS_ATOMIC_H 1
19
20 /* Atomic operations.
21  *
22  * This library implements atomic operations with an API based on the one
23  * defined in C11.  It includes multiple implementations for compilers and
24  * libraries with varying degrees of built-in support for C11, including a
25  * fallback implementation for systems that have pthreads but no other support
26  * for atomics.
27  *
28  * This comment describes the common features of all the implementations.
29  *
30  *
31  * Types
32  * =====
33  *
34  * The following atomic types are supported as typedefs for atomic versions of
35  * the listed ordinary types:
36  *
37  *     ordinary type            atomic version
38  *     -------------------      ----------------------
39  *     bool                     atomic_bool
40  *
41  *     char                     atomic_char
42  *     signed char              atomic_schar
43  *     unsigned char            atomic_uchar
44  *
45  *     short                    atomic_short
46  *     unsigned short           atomic_ushort
47  *
48  *     int                      atomic_int
49  *     unsigned int             atomic_uint
50  *
51  *     long                     atomic_long
52  *     unsigned long            atomic_ulong
53  *
54  *     long long                atomic_llong
55  *     unsigned long long       atomic_ullong
56  *
57  *     size_t                   atomic_size_t
58  *     ptrdiff_t                atomic_ptrdiff_t
59  *
60  *     intmax_t                 atomic_intmax_t
61  *     uintmax_t                atomic_uintmax_t
62  *
63  *     intptr_t                 atomic_intptr_t
64  *     uintptr_t                atomic_uintptr_t
65  *
66  *     uint8_t                  atomic_uint8_t     (*)
67  *     uint16_t                 atomic_uint16_t    (*)
68  *     uint32_t                 atomic_uint32_t    (*)
69  *     int8_t                   atomic_int8_t      (*)
70  *     int16_t                  atomic_int16_t     (*)
71  *     int32_t                  atomic_int32_t     (*)
72  *
73  *     (*) Not specified by C11.
74  *
75  * Atomic types may also be obtained via ATOMIC(TYPE), e.g. ATOMIC(void *).
76  * Only basic integer types and pointer types can be made atomic this way,
77  * e.g. atomic structs are not supported.
78  *
79  * The atomic version of a type doesn't necessarily have the same size or
80  * representation as the ordinary version; for example, atomic_int might be a
81  * typedef for a struct.  The range of an atomic type does match the range of
82  * the corresponding ordinary type.
83  *
84  * C11 says that one may use the _Atomic keyword in place of the typedef name,
85  * e.g. "_Atomic int" instead of "atomic_int".  This library doesn't support
86  * that.
87  *
88  *
89  * Life Cycle
90  * ==========
91  *
92  * To initialize an atomic variable at its point of definition, use
93  * ATOMIC_VAR_INIT:
94  *
95  *     static atomic_int ai = ATOMIC_VAR_INIT(123);
96  *
97  * To initialize an atomic variable in code, use atomic_init():
98  *
99  *     static atomic_int ai;
100  * ...
101  *     atomic_init(&ai, 123);
102  *
103  *
104  * Barriers
105  * ========
106  *
107  * enum memory_order specifies the strictness of a memory barrier.  It has the
108  * following values:
109  *
110  *    memory_order_relaxed:
111  *
112  *        Compiler barrier only.  Does not imply any CPU memory ordering.
113  *
114  *    memory_order_acquire:
115  *
116  *        Memory accesses after an acquire barrier cannot be moved before the
117  *        barrier.  Memory accesses before an acquire barrier *can* be moved
118  *        after it.
119  *
120  *    memory_order_release:
121  *
122  *        Memory accesses before a release barrier cannot be moved after the
123  *        barrier.  Memory accesses after a release barrier *can* be moved
124  *        before it.
125  *
126  *    memory_order_acq_rel:
127  *
128  *        Memory accesses cannot be moved across an acquire-release barrier in
129  *        either direction.
130  *
131  *    memory_order_seq_cst:
132  *
133  *        Prevents movement of memory accesses like an acquire-release barrier,
134  *        but whereas acquire-release synchronizes cooperating threads,
135  *        sequential-consistency synchronizes the whole system.
136  *
137  *    memory_order_consume:
138  *
139  *        A slight relaxation of memory_order_acquire.
140  *
141  * The following functions insert explicit barriers.  Most of the other atomic
142  * functions also include barriers.
143  *
144  *     void atomic_thread_fence(memory_order order);
145  *
146  *         Inserts a barrier of the specified type.
147  *
148  *         For memory_order_relaxed, this is a no-op.
149  *
150  *     void atomic_signal_fence(memory_order order);
151  *
152  *         Inserts a barrier of the specified type, but only with respect to
153  *         signal handlers in the same thread as the barrier.  This is
154  *         basically a compiler optimization barrier, except for
155  *         memory_order_relaxed, which is a no-op.
156  *
157  *
158  * Atomic Operations
159  * =================
160  *
161  * In this section, A is an atomic type and C is the corresponding non-atomic
162  * type.
163  *
164  * The "store" primitives match C11:
165  *
166  *     void atomic_store(A *object, C value);
167  *     void atomic_store_explicit(A *object, C value, memory_order);
168  *
169  *         Atomically stores 'value' into '*object', respecting the given
170  *         memory order (or memory_order_seq_cst for atomic_store()).
171  *
172  * The following primitives differ from the C11 ones (and have different names)
173  * because there does not appear to be a way to implement the standard
174  * primitives in standard C:
175  *
176  *     void atomic_read(A *src, C *dst);
177  *     void atomic_read_explicit(A *src, C *dst, memory_order);
178  *
179  *         Atomically loads a value from 'src', writing the value read into
180  *         '*dst', respecting the given memory order (or memory_order_seq_cst
181  *         for atomic_read()).
182  *
183  *     void atomic_add(A *rmw, C arg, C *orig);
184  *     void atomic_sub(A *rmw, C arg, C *orig);
185  *     void atomic_or(A *rmw, C arg, C *orig);
186  *     void atomic_xor(A *rmw, C arg, C *orig);
187  *     void atomic_and(A *rmw, C arg, C *orig);
188  *     void atomic_add_explicit(A *rmw, C arg, C *orig, memory_order);
189  *     void atomic_sub_explicit(A *rmw, C arg, C *orig, memory_order);
190  *     void atomic_or_explicit(A *rmw, C arg, C *orig, memory_order);
191  *     void atomic_xor_explicit(A *rmw, C arg, C *orig, memory_order);
192  *     void atomic_and_explicit(A *rmw, C arg, C *orig, memory_order);
193  *
194  *         Atomically applies the given operation, with 'arg' as the second
195  *         operand, to '*rmw', and stores the original value of '*rmw' into
196  *         '*orig', respecting the given memory order (or memory_order_seq_cst
197  *         if none is specified).
198  *
199  *         The results are similar to those that would be obtained with +=, -=,
200  *         |=, ^=, or |= on non-atomic types.
201  *
202  *
203  * atomic_flag
204  * ===========
205  *
206  * atomic_flag is a typedef for a type with two states, set and clear, that
207  * provides atomic test-and-set functionality.
208  *
209  *
210  * Life Cycle
211  * ----------
212  *
213  * ATOMIC_FLAG_INIT is an initializer for atomic_flag.  The initial state is
214  * "clear".
215  *
216  * An atomic_flag may also be initialized at runtime with atomic_flag_clear().
217  *
218  *
219  * Operations
220  * ----------
221  *
222  * The following functions are available.
223  *
224  *     bool atomic_flag_test_and_set(atomic_flag *object)
225  *     bool atomic_flag_test_and_set_explicit(atomic_flag *object,
226  *                                            memory_order);
227  *
228  *         Atomically sets '*object', respsecting the given memory order (or
229  *         memory_order_seq_cst for atomic_flag_test_and_set()).  Returns the
230  *         previous value of the flag (false for clear, true for set).
231  *
232  *     void atomic_flag_clear(atomic_flag *object);
233  *     void atomic_flag_clear_explicit(atomic_flag *object, memory_order);
234  *
235  *         Atomically clears '*object', respecting the given memory order (or
236  *         memory_order_seq_cst for atomic_flag_clear()).
237  */
238
239 #include <limits.h>
240 #include <pthread.h>
241 #include <stdbool.h>
242 #include <stddef.h>
243 #include <stdint.h>
244 #include "compiler.h"
245 #include "util.h"
246
247 #define IN_OVS_ATOMIC_H
248     #if __CHECKER__
249         /* sparse doesn't understand some GCC extensions we use. */
250         #include "ovs-atomic-pthreads.h"
251     #elif HAVE_STDATOMIC_H
252         #include "ovs-atomic-c11.h"
253     #elif __has_extension(c_atomic)
254         #include "ovs-atomic-clang.h"
255     #elif __GNUC__ >= 4 && __GNUC_MINOR__ >= 7
256         #include "ovs-atomic-gcc4.7+.h"
257     #elif HAVE_GCC4_ATOMICS
258         #include "ovs-atomic-gcc4+.h"
259     #else
260         #include "ovs-atomic-pthreads.h"
261     #endif
262 #undef IN_OVS_ATOMIC_H
263
264 #ifndef OMIT_STANDARD_ATOMIC_TYPES
265 typedef ATOMIC(bool)               atomic_bool;
266
267 typedef ATOMIC(char)               atomic_char;
268 typedef ATOMIC(signed char)        atomic_schar;
269 typedef ATOMIC(unsigned char)      atomic_uchar;
270
271 typedef ATOMIC(short)              atomic_short;
272 typedef ATOMIC(unsigned short)     atomic_ushort;
273
274 typedef ATOMIC(int)                atomic_int;
275 typedef ATOMIC(unsigned int)       atomic_uint;
276
277 typedef ATOMIC(long)               atomic_long;
278 typedef ATOMIC(unsigned long)      atomic_ulong;
279
280 typedef ATOMIC(long long)          atomic_llong;
281 typedef ATOMIC(unsigned long long) atomic_ullong;
282
283 typedef ATOMIC(size_t)             atomic_size_t;
284 typedef ATOMIC(ptrdiff_t)          atomic_ptrdiff_t;
285
286 typedef ATOMIC(intmax_t)           atomic_intmax_t;
287 typedef ATOMIC(uintmax_t)          atomic_uintmax_t;
288
289 typedef ATOMIC(intptr_t)           atomic_intptr_t;
290 typedef ATOMIC(uintptr_t)          atomic_uintptr_t;
291 #endif  /* !OMIT_STANDARD_ATOMIC_TYPES */
292
293 /* Nonstandard atomic types. */
294 typedef ATOMIC(uint8_t)   atomic_uint8_t;
295 typedef ATOMIC(uint16_t)  atomic_uint16_t;
296 typedef ATOMIC(uint32_t)  atomic_uint32_t;
297
298 typedef ATOMIC(int8_t)    atomic_int8_t;
299 typedef ATOMIC(int16_t)   atomic_int16_t;
300 typedef ATOMIC(int32_t)   atomic_int32_t;
301
302 /* Reference count. */
303 struct ovs_refcount {
304     atomic_uint count;
305 };
306
307 /* Initializes 'refcount'.  The reference count is initially 1. */
308 static inline void
309 ovs_refcount_init(struct ovs_refcount *refcount)
310 {
311     atomic_init(&refcount->count, 1);
312 }
313
314 /* Increments 'refcount'. */
315 static inline void
316 ovs_refcount_ref(struct ovs_refcount *refcount)
317 {
318     unsigned int old_refcount;
319
320     atomic_add(&refcount->count, 1, &old_refcount);
321     ovs_assert(old_refcount > 0);
322 }
323
324 /* Decrements 'refcount' and returns the previous reference count.  Often used
325  * in this form:
326  *
327  * if (ovs_refcount_unref(&object->ref_cnt) == 1) {
328  *     // ...uninitialize object...
329  *     free(object);
330  * }
331  */
332 static inline unsigned int
333 ovs_refcount_unref(struct ovs_refcount *refcount)
334 {
335     unsigned int old_refcount;
336
337     atomic_sub(&refcount->count, 1, &old_refcount);
338     ovs_assert(old_refcount > 0);
339     return old_refcount;
340 }
341
342 /* Reads and returns 'ref_count_''s current reference count.
343  *
344  * Rarely useful. */
345 static inline unsigned int
346 ovs_refcount_read(const struct ovs_refcount *refcount_)
347 {
348     struct ovs_refcount *refcount
349         = CONST_CAST(struct ovs_refcount *, refcount_);
350     unsigned int count;
351
352     atomic_read(&refcount->count, &count);
353     return count;
354 }
355
356 #endif /* ovs-atomic.h */