]>
Commit | Line | Data |
---|---|---|
ec68790f BP |
1 | /* |
2 | * Copyright (c) 2013 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_THREAD_H | |
18 | #define OVS_THREAD_H 1 | |
19 | ||
20 | #include <pthread.h> | |
728a8b14 BP |
21 | #include <stddef.h> |
22 | #include <sys/types.h> | |
1514b275 | 23 | #include "ovs-atomic.h" |
ec68790f BP |
24 | #include "util.h" |
25 | ||
97be1538 EJ |
26 | |
27 | /* Mutex. */ | |
28 | struct OVS_LOCKABLE ovs_mutex { | |
29 | pthread_mutex_t lock; | |
30 | const char *where; | |
31 | }; | |
32 | ||
33 | /* "struct ovs_mutex" initializers: | |
ec68790f | 34 | * |
97be1538 | 35 | * - OVS_MUTEX_INITIALIZER: common case. |
ec68790f | 36 | * |
97be1538 EJ |
37 | * - OVS_ADAPTIVE_MUTEX_INITIALIZER for a mutex that spins briefly then goes |
38 | * to sleeps after some number of iterations. | |
ec68790f | 39 | * |
97be1538 EJ |
40 | * - OVS_ERRORCHECK_MUTEX_INITIALIZER for a mutex that is used for |
41 | * error-checking. */ | |
42 | #define OVS_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, NULL } | |
ec68790f | 43 | #ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP |
97be1538 EJ |
44 | #define OVS_ADAPTIVE_MUTEX_INITIALIZER \ |
45 | { PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP, NULL } | |
ec68790f | 46 | #else |
97be1538 | 47 | #define OVS_ADAPTIVE_MUTEX_INITIALIZER OVS_MUTEX_INITIALIZER |
ec68790f | 48 | #endif |
ec68790f | 49 | #ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP |
97be1538 EJ |
50 | #define OVS_ERRORCHECK_MUTEX_INITIALIZER \ |
51 | { PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, NULL } | |
ec68790f | 52 | #else |
97be1538 | 53 | #define OVS_ERRORCHECK_MUTEX_INITIALIZER OVS_MUTEX_INITIALIZER |
ec68790f BP |
54 | #endif |
55 | \f | |
97be1538 EJ |
56 | /* Mutex types, suitable for use with pthread_mutexattr_settype(). |
57 | * There is only one nonstandard type: | |
58 | * | |
59 | * - PTHREAD_MUTEX_ADAPTIVE_NP, the type used for | |
60 | * OVS_ADAPTIVE_MUTEX_INITIALIZER. */ | |
61 | #ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP | |
62 | #define OVS_MUTEX_ADAPTIVE PTHREAD_MUTEX_ADAPTIVE_NP | |
63 | #else | |
64 | #define OVS_MUTEX_ADAPTIVE PTHREAD_MUTEX_NORMAL | |
65 | #endif | |
66 | ||
67 | /* ovs_mutex functions analogous to pthread_mutex_*() functions. | |
68 | * | |
69 | * Most of these functions abort the process with an error message on any | |
70 | * error. ovs_mutex_trylock() is an exception: it passes through a 0 or EBUSY | |
71 | * return value to the caller and aborts on any other error. */ | |
72 | void ovs_mutex_init(const struct ovs_mutex *, int type); | |
73 | void ovs_mutex_destroy(const struct ovs_mutex *); | |
74 | void ovs_mutex_unlock(const struct ovs_mutex *mutex) OVS_RELEASES(mutex); | |
75 | void ovs_mutex_lock_at(const struct ovs_mutex *mutex, const char *where) | |
76 | OVS_ACQUIRES(mutex); | |
77 | #define ovs_mutex_lock(mutex) \ | |
78 | ovs_mutex_lock_at(mutex, SOURCE_LOCATOR) | |
b847adc6 | 79 | |
97be1538 EJ |
80 | int ovs_mutex_trylock_at(const struct ovs_mutex *mutex, const char *where) |
81 | OVS_TRY_LOCK(0, mutex); | |
82 | #define ovs_mutex_trylock(mutex) \ | |
83 | ovs_mutex_trylock_at(mutex, SOURCE_LOCATOR) | |
ec68790f | 84 | |
97be1538 EJ |
85 | void ovs_mutex_cond_wait(pthread_cond_t *, const struct ovs_mutex *); |
86 | ||
13d94ee9 AW |
87 | /* Wrappers for pthread_mutex_*() that abort the process on any error. |
88 | * This is still needed when ovs-atomic-pthreads.h is used. */ | |
89 | void xpthread_mutex_lock(pthread_mutex_t *mutex); | |
90 | void xpthread_mutex_unlock(pthread_mutex_t *mutex); | |
91 | ||
97be1538 | 92 | /* Wrappers for pthread_mutexattr_*() that abort the process on any error. */ |
b847adc6 BP |
93 | void xpthread_mutexattr_init(pthread_mutexattr_t *); |
94 | void xpthread_mutexattr_destroy(pthread_mutexattr_t *); | |
95 | void xpthread_mutexattr_settype(pthread_mutexattr_t *, int type); | |
96 | void xpthread_mutexattr_gettype(pthread_mutexattr_t *, int *typep); | |
97 | ||
97be1538 EJ |
98 | /* Read-write lock. */ |
99 | struct OVS_LOCKABLE ovs_rwlock { | |
100 | pthread_rwlock_t lock; | |
101 | const char *where; | |
102 | }; | |
103 | ||
104 | /* Initializer. */ | |
105 | #define OVS_RWLOCK_INITIALIZER { PTHREAD_RWLOCK_INITIALIZER, NULL } | |
106 | ||
107 | /* ovs_rwlock functions analogous to pthread_rwlock_*() functions. | |
108 | * | |
109 | * Most of these functions abort the process with an error message on any | |
110 | * error. The "trylock" functions are exception: they pass through a 0 or | |
111 | * EBUSY return value to the caller and abort on any other error. */ | |
112 | void ovs_rwlock_init(const struct ovs_rwlock *); | |
113 | void ovs_rwlock_destroy(const struct ovs_rwlock *); | |
114 | void ovs_rwlock_unlock(const struct ovs_rwlock *rwlock) OVS_RELEASES(rwlock); | |
115 | ||
116 | void ovs_rwlock_wrlock_at(const struct ovs_rwlock *rwlock, const char *where) | |
117 | OVS_ACQ_WRLOCK(rwlock); | |
118 | #define ovs_rwlock_wrlock(rwlock) \ | |
d87d523d | 119 | ovs_rwlock_wrlock_at(rwlock, SOURCE_LOCATOR) |
ec68790f | 120 | |
97be1538 EJ |
121 | int ovs_rwlock_trywrlock_at(const struct ovs_rwlock *rwlock, const char *where) |
122 | OVS_TRY_WRLOCK(0, rwlock); | |
123 | #define ovs_rwlock_trywrlock(rwlock) \ | |
124 | ovs_rwlock_trywrlock_at(rwlock, SOURCE_LOCATOR) | |
125 | ||
126 | void ovs_rwlock_rdlock_at(const struct ovs_rwlock *rwlock, const char *where) | |
127 | OVS_ACQ_RDLOCK(rwlock); | |
128 | #define ovs_rwlock_rdlock(rwlock) \ | |
d87d523d | 129 | ovs_rwlock_rdlock_at(rwlock, SOURCE_LOCATOR) |
97be1538 EJ |
130 | |
131 | int ovs_rwlock_tryrdlock_at(const struct ovs_rwlock *rwlock, const char *where) | |
132 | OVS_TRY_RDLOCK(0, rwlock); | |
133 | #define ovs_rwlock_tryrdlock(rwlock) \ | |
134 | ovs_rwlock_tryrdlock_at(rwlock, SOURCE_LOCATOR) | |
135 | ||
136 | /* Wrappers for xpthread_cond_*() that abort the process on any error. | |
137 | * | |
138 | * Use ovs_mutex_cond_wait() to wait for a condition. */ | |
ec68790f | 139 | void xpthread_cond_init(pthread_cond_t *, pthread_condattr_t *); |
a8e736a8 | 140 | void xpthread_cond_destroy(pthread_cond_t *); |
ec68790f BP |
141 | void xpthread_cond_signal(pthread_cond_t *); |
142 | void xpthread_cond_broadcast(pthread_cond_t *); | |
ec68790f BP |
143 | |
144 | #ifdef __CHECKER__ | |
145 | /* Replace these functions by the macros already defined in the <pthread.h> | |
146 | * annotations, because the macro definitions have correct semantics for the | |
147 | * conditional acquisition that can't be captured in a function annotation. | |
148 | * The difference in semantics from pthread_*() to xpthread_*() does not matter | |
149 | * because sparse is not a compiler. */ | |
150 | #define xpthread_mutex_trylock pthread_mutex_trylock | |
151 | #define xpthread_rwlock_tryrdlock pthread_rwlock_tryrdlock | |
152 | #define xpthread_rwlock_trywrlock pthread_rwlock_trywrlock | |
153 | #endif | |
154 | ||
155 | void xpthread_key_create(pthread_key_t *, void (*destructor)(void *)); | |
9c4c45ed | 156 | void xpthread_setspecific(pthread_key_t, const void *); |
ec68790f BP |
157 | |
158 | void xpthread_create(pthread_t *, pthread_attr_t *, void *(*)(void *), void *); | |
ec2905a8 | 159 | void xpthread_join(pthread_t, void **); |
c22095a5 BP |
160 | \f |
161 | /* Per-thread data. | |
162 | * | |
163 | * Multiple forms of per-thread data exist, each with its own pluses and | |
164 | * minuses: | |
165 | * | |
166 | * - POSIX per-thread data via pthread_key_t is portable to any pthreads | |
167 | * implementation, and allows a destructor function to be defined. It | |
168 | * only (directly) supports per-thread pointers, which are always | |
169 | * initialized to NULL. It requires once-only allocation of a | |
170 | * pthread_key_t value. It is relatively slow. | |
171 | * | |
172 | * - The thread_local feature newly defined in C11 <threads.h> works with | |
173 | * any data type and initializer, and it is fast. thread_local does not | |
174 | * require once-only initialization like pthread_key_t. C11 does not | |
175 | * define what happens if one attempts to access a thread_local object | |
176 | * from a thread other than the one to which that object belongs. There | |
177 | * is no provision to call a user-specified destructor when a thread | |
178 | * ends. | |
179 | * | |
180 | * - The __thread keyword is a GCC extension similar to thread_local but | |
181 | * with a longer history. __thread is not portable to every GCC version | |
182 | * or environment. __thread does not restrict the use of a thread-local | |
183 | * object outside its own thread. | |
184 | * | |
185 | * Here's a handy summary: | |
186 | * | |
187 | * pthread_key_t thread_local __thread | |
188 | * ------------- ------------ ------------- | |
189 | * portability high low medium | |
190 | * speed low high high | |
191 | * supports destructors? yes no no | |
192 | * needs key allocation? yes no no | |
193 | * arbitrary initializer? no yes yes | |
194 | * cross-thread access? yes no yes | |
195 | */ | |
196 | ||
2ba4f163 BP |
197 | /* For static data, use this macro in a source file: |
198 | * | |
199 | * DEFINE_STATIC_PER_THREAD_DATA(TYPE, NAME, INITIALIZER). | |
200 | * | |
201 | * For global data, "declare" the data in the header and "define" it in | |
202 | * the source file, with: | |
203 | * | |
204 | * DECLARE_EXTERN_PER_THREAD_DATA(TYPE, NAME). | |
205 | * DEFINE_EXTERN_PER_THREAD_DATA(NAME, INITIALIZER). | |
c22095a5 BP |
206 | * |
207 | * One should prefer to use POSIX per-thread data, via pthread_key_t, when its | |
208 | * performance is acceptable, because of its portability (see the table above). | |
209 | * This macro is an alternatives that takes advantage of thread_local (and | |
210 | * __thread), for its performance, when it is available, and falls back to | |
211 | * POSIX per-thread data otherwise. | |
212 | * | |
213 | * Defines per-thread variable NAME with the given TYPE, initialized to | |
214 | * INITIALIZER (which must be valid as an initializer for a variable with | |
215 | * static lifetime). | |
216 | * | |
217 | * The public interface to the variable is: | |
218 | * | |
219 | * TYPE *NAME_get(void) | |
220 | * TYPE *NAME_get_unsafe(void) | |
221 | * | |
222 | * Returns the address of this thread's instance of NAME. | |
223 | * | |
224 | * Use NAME_get() in a context where this might be the first use of the | |
225 | * per-thread variable in the program. Use NAME_get_unsafe(), which | |
226 | * avoids a conditional test and is thus slightly faster, in a context | |
227 | * where one knows that NAME_get() has already been called previously. | |
228 | * | |
229 | * There is no "NAME_set()" (or "NAME_set_unsafe()") function. To set the | |
230 | * value of the per-thread variable, dereference the pointer returned by | |
231 | * TYPE_get() or TYPE_get_unsafe(), e.g. *TYPE_get() = 0. | |
232 | */ | |
233 | #if HAVE_THREAD_LOCAL || HAVE___THREAD | |
234 | ||
235 | #if HAVE_THREAD_LOCAL | |
236 | #include <threads.h> | |
237 | #elif HAVE___THREAD | |
238 | #define thread_local __thread | |
239 | #else | |
240 | #error | |
241 | #endif | |
242 | ||
2ba4f163 BP |
243 | #define DEFINE_STATIC_PER_THREAD_DATA(TYPE, NAME, ...) \ |
244 | typedef TYPE NAME##_type; \ | |
245 | \ | |
246 | static NAME##_type * \ | |
247 | NAME##_get_unsafe(void) \ | |
248 | { \ | |
249 | static thread_local NAME##_type var = __VA_ARGS__; \ | |
250 | return &var; \ | |
251 | } \ | |
252 | \ | |
253 | static NAME##_type * \ | |
254 | NAME##_get(void) \ | |
255 | { \ | |
256 | return NAME##_get_unsafe(); \ | |
c22095a5 | 257 | } |
2ba4f163 BP |
258 | #define DECLARE_EXTERN_PER_THREAD_DATA(TYPE, NAME) \ |
259 | typedef TYPE NAME##_type; \ | |
260 | extern thread_local NAME##_type NAME##_var; \ | |
261 | \ | |
262 | static inline NAME##_type * \ | |
263 | NAME##_get_unsafe(void) \ | |
264 | { \ | |
265 | return &NAME##_var; \ | |
266 | } \ | |
267 | \ | |
268 | static inline NAME##_type * \ | |
269 | NAME##_get(void) \ | |
270 | { \ | |
271 | return NAME##_get_unsafe(); \ | |
272 | } | |
273 | #define DEFINE_EXTERN_PER_THREAD_DATA(NAME, ...) \ | |
274 | thread_local NAME##_type NAME##_var = __VA_ARGS__; | |
c22095a5 | 275 | #else /* no C implementation support for thread-local storage */ |
2ba4f163 | 276 | #define DEFINE_STATIC_PER_THREAD_DATA(TYPE, NAME, ...) \ |
c22095a5 BP |
277 | typedef TYPE NAME##_type; \ |
278 | static pthread_key_t NAME##_key; \ | |
279 | \ | |
280 | static NAME##_type * \ | |
281 | NAME##_get_unsafe(void) \ | |
282 | { \ | |
283 | return pthread_getspecific(NAME##_key); \ | |
284 | } \ | |
285 | \ | |
286 | static void \ | |
287 | NAME##_once_init(void) \ | |
288 | { \ | |
289 | if (pthread_key_create(&NAME##_key, free)) { \ | |
290 | abort(); \ | |
291 | } \ | |
292 | } \ | |
293 | \ | |
294 | static NAME##_type * \ | |
295 | NAME##_get(void) \ | |
2ba4f163 BP |
296 | { \ |
297 | static pthread_once_t once = PTHREAD_ONCE_INIT; \ | |
298 | NAME##_type *value; \ | |
299 | \ | |
300 | pthread_once(&once, NAME##_once_init); \ | |
301 | value = NAME##_get_unsafe(); \ | |
302 | if (!value) { \ | |
303 | static const NAME##_type initial_value = __VA_ARGS__; \ | |
304 | \ | |
305 | value = xmalloc(sizeof *value); \ | |
306 | *value = initial_value; \ | |
307 | xpthread_setspecific(NAME##_key, value); \ | |
308 | } \ | |
309 | return value; \ | |
310 | } | |
311 | #define DECLARE_EXTERN_PER_THREAD_DATA(TYPE, NAME) \ | |
312 | typedef TYPE NAME##_type; \ | |
313 | static pthread_key_t NAME##_key; \ | |
314 | \ | |
315 | static inline NAME##_type * \ | |
316 | NAME##_get_unsafe(void) \ | |
317 | { \ | |
318 | return pthread_getspecific(NAME##_key); \ | |
319 | } \ | |
320 | \ | |
321 | NAME##_type *NAME##_get(void); | |
322 | #define DEFINE_EXTERN_PER_THREAD_DATA(NAME, ...) \ | |
323 | static void \ | |
324 | NAME##_once_init(void) \ | |
325 | { \ | |
326 | if (pthread_key_create(&NAME##_key, free)) { \ | |
327 | abort(); \ | |
328 | } \ | |
329 | } \ | |
330 | \ | |
331 | NAME##_type * \ | |
332 | NAME##_get(void) \ | |
c22095a5 BP |
333 | { \ |
334 | static pthread_once_t once = PTHREAD_ONCE_INIT; \ | |
335 | NAME##_type *value; \ | |
336 | \ | |
337 | pthread_once(&once, NAME##_once_init); \ | |
338 | value = NAME##_get_unsafe(); \ | |
339 | if (!value) { \ | |
340 | static const NAME##_type initial_value = __VA_ARGS__; \ | |
341 | \ | |
342 | value = xmalloc(sizeof *value); \ | |
343 | *value = initial_value; \ | |
9c4c45ed | 344 | xpthread_setspecific(NAME##_key, value); \ |
c22095a5 BP |
345 | } \ |
346 | return value; \ | |
347 | } | |
348 | #endif | |
349 | ||
350 | /* DEFINE_PER_THREAD_MALLOCED_DATA(TYPE, NAME). | |
351 | * | |
352 | * This is a simple wrapper around POSIX per-thread data primitives. It | |
353 | * defines per-thread variable NAME with the given TYPE, which must be a | |
354 | * pointer type. In each thread, the per-thread variable is initialized to | |
355 | * NULL. When a thread terminates, the variable is freed with free(). | |
356 | * | |
357 | * The public interface to the variable is: | |
358 | * | |
359 | * TYPE NAME_get(void) | |
360 | * TYPE NAME_get_unsafe(void) | |
361 | * | |
362 | * Returns the value of per-thread variable NAME in this thread. | |
363 | * | |
364 | * Use NAME_get() in a context where this might be the first use of the | |
365 | * per-thread variable in the program. Use NAME_get_unsafe(), which | |
366 | * avoids a conditional test and is thus slightly faster, in a context | |
367 | * where one knows that NAME_get() has already been called previously. | |
368 | * | |
369 | * TYPE NAME_set(TYPE new_value) | |
370 | * TYPE NAME_set_unsafe(TYPE new_value) | |
371 | * | |
372 | * Sets the value of per-thread variable NAME to 'new_value' in this | |
373 | * thread, and returns its previous value. | |
374 | * | |
375 | * Use NAME_set() in a context where this might be the first use of the | |
376 | * per-thread variable in the program. Use NAME_set_unsafe(), which | |
377 | * avoids a conditional test and is thus slightly faster, in a context | |
378 | * where one knows that NAME_set() has already been called previously. | |
379 | */ | |
380 | #define DEFINE_PER_THREAD_MALLOCED_DATA(TYPE, NAME) \ | |
381 | static pthread_key_t NAME##_key; \ | |
382 | \ | |
383 | static void \ | |
384 | NAME##_once_init(void) \ | |
385 | { \ | |
386 | if (pthread_key_create(&NAME##_key, free)) { \ | |
387 | abort(); \ | |
388 | } \ | |
389 | } \ | |
390 | \ | |
391 | static void \ | |
392 | NAME##_init(void) \ | |
393 | { \ | |
394 | static pthread_once_t once = PTHREAD_ONCE_INIT; \ | |
395 | pthread_once(&once, NAME##_once_init); \ | |
396 | } \ | |
397 | \ | |
398 | static TYPE \ | |
399 | NAME##_get_unsafe(void) \ | |
400 | { \ | |
401 | return pthread_getspecific(NAME##_key); \ | |
402 | } \ | |
403 | \ | |
404 | static OVS_UNUSED TYPE \ | |
405 | NAME##_get(void) \ | |
406 | { \ | |
407 | NAME##_init(); \ | |
408 | return NAME##_get_unsafe(); \ | |
409 | } \ | |
410 | \ | |
411 | static TYPE \ | |
412 | NAME##_set_unsafe(TYPE value) \ | |
413 | { \ | |
414 | TYPE old_value = NAME##_get_unsafe(); \ | |
9c4c45ed | 415 | xpthread_setspecific(NAME##_key, value); \ |
c22095a5 BP |
416 | return old_value; \ |
417 | } \ | |
418 | \ | |
419 | static OVS_UNUSED TYPE \ | |
420 | NAME##_set(TYPE value) \ | |
421 | { \ | |
422 | NAME##_init(); \ | |
423 | return NAME##_set_unsafe(value); \ | |
424 | } | |
425 | \f | |
1514b275 BP |
426 | /* Convenient once-only execution. |
427 | * | |
428 | * | |
429 | * Problem | |
430 | * ======= | |
431 | * | |
432 | * POSIX provides pthread_once_t and pthread_once() as primitives for running a | |
433 | * set of code only once per process execution. They are used like this: | |
434 | * | |
435 | * static void run_once(void) { ...initialization... } | |
436 | * static pthread_once_t once = PTHREAD_ONCE_INIT; | |
437 | * ... | |
438 | * pthread_once(&once, run_once); | |
439 | * | |
440 | * pthread_once() does not allow passing any parameters to the initialization | |
441 | * function, which is often inconvenient, because it means that the function | |
442 | * can only access data declared at file scope. | |
443 | * | |
444 | * | |
445 | * Solution | |
446 | * ======== | |
447 | * | |
448 | * Use ovsthread_once, like this, instead: | |
449 | * | |
450 | * static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER; | |
451 | * | |
452 | * if (ovsthread_once_start(&once)) { | |
453 | * ...initialization... | |
454 | * ovsthread_once_done(&once); | |
455 | * } | |
456 | */ | |
457 | ||
458 | struct ovsthread_once { | |
459 | atomic_bool done; | |
97be1538 | 460 | struct ovs_mutex mutex; |
1514b275 BP |
461 | }; |
462 | ||
463 | #define OVSTHREAD_ONCE_INITIALIZER \ | |
464 | { \ | |
465 | ATOMIC_VAR_INIT(false), \ | |
97be1538 | 466 | OVS_ADAPTIVE_MUTEX_INITIALIZER, \ |
1514b275 BP |
467 | } |
468 | ||
97be1538 EJ |
469 | static inline bool ovsthread_once_start(struct ovsthread_once *once) |
470 | OVS_TRY_LOCK(true, &once->mutex); | |
471 | void ovsthread_once_done(struct ovsthread_once *once) | |
472 | OVS_RELEASES(&once->mutex); | |
1514b275 | 473 | |
97be1538 EJ |
474 | bool ovsthread_once_start__(struct ovsthread_once *once) |
475 | OVS_TRY_LOCK(false, &once->mutex); | |
1514b275 BP |
476 | |
477 | static inline bool | |
478 | ovsthread_once_is_done__(const struct ovsthread_once *once) | |
479 | { | |
480 | bool done; | |
481 | ||
482 | atomic_read_explicit(&once->done, &done, memory_order_relaxed); | |
483 | return done; | |
484 | } | |
485 | ||
486 | /* Returns true if this is the first call to ovsthread_once_start() for | |
487 | * 'once'. In this case, the caller should perform whatever initialization | |
488 | * actions it needs to do, then call ovsthread_once_done() for 'once'. | |
489 | * | |
490 | * Returns false if this is not the first call to ovsthread_once_start() for | |
491 | * 'once'. In this case, the call will not return until after | |
492 | * ovsthread_once_done() has been called. */ | |
493 | static inline bool | |
494 | ovsthread_once_start(struct ovsthread_once *once) | |
495 | { | |
496 | return OVS_UNLIKELY(!ovsthread_once_is_done__(once) | |
497 | && !ovsthread_once_start__(once)); | |
498 | } | |
499 | ||
500 | #ifdef __CHECKER__ | |
501 | #define ovsthread_once_start(ONCE) \ | |
97be1538 | 502 | ((ONCE)->done ? false : ({ OVS_MACRO_LOCK((&ONCE->mutex)); true; })) |
1514b275 | 503 | #endif |
728a8b14 | 504 | \f |
6878fada BP |
505 | /* Thread ID. |
506 | * | |
507 | * pthread_t isn't so nice for some purposes. Its size and representation are | |
508 | * implementation dependent, which means that there is no way to hash it. | |
509 | * This thread ID avoids the problem. | |
510 | */ | |
511 | ||
512 | DECLARE_EXTERN_PER_THREAD_DATA(unsigned int, ovsthread_id); | |
513 | ||
514 | /* Returns a per-thread identifier unique within the lifetime of the | |
515 | * process. */ | |
516 | static inline unsigned int | |
517 | ovsthread_id_self(void) | |
518 | { | |
519 | return *ovsthread_id_get(); | |
520 | } | |
521 | \f | |
5453ae20 BP |
522 | void assert_single_threaded_at(const char *where); |
523 | #define assert_single_threaded() assert_single_threaded_at(SOURCE_LOCATOR) | |
728a8b14 | 524 | |
5453ae20 BP |
525 | pid_t xfork_at(const char *where); |
526 | #define xfork() xfork_at(SOURCE_LOCATOR) | |
728a8b14 BP |
527 | |
528 | void forbid_forking(const char *reason); | |
529 | bool may_fork(void); | |
ec68790f BP |
530 | |
531 | #endif /* ovs-thread.h */ |