21
21
#include <stddef.h>
22
22
#include <sys/types.h>
23
23
#include "ovs-atomic.h"
24
#include "openvswitch/thread.h"
29
struct OVS_LOCKABLE ovs_mutex {
31
const char *where; /* NULL if and only if uninitialized. */
34
29
/* Poll-block()-able barrier similar to pthread_barrier_t. */
35
30
struct ovs_barrier {
36
31
uint32_t size; /* Number of threads to wait. */
37
atomic_uint32_t count; /* Number of threads already hit the barrier. */
32
atomic_count count; /* Number of threads already hit the barrier. */
41
/* "struct ovs_mutex" initializer. */
42
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
43
#define OVS_MUTEX_INITIALIZER { PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, \
46
#define OVS_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, "<unlocked>" }
49
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
50
#define OVS_ADAPTIVE_MUTEX_INITIALIZER \
51
{ PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP, "<unlocked>" }
53
#define OVS_ADAPTIVE_MUTEX_INITIALIZER OVS_MUTEX_INITIALIZER
56
/* ovs_mutex functions analogous to pthread_mutex_*() functions.
58
* Most of these functions abort the process with an error message on any
59
* error. ovs_mutex_trylock() is an exception: it passes through a 0 or EBUSY
60
* return value to the caller and aborts on any other error. */
61
void ovs_mutex_init(const struct ovs_mutex *);
62
void ovs_mutex_init_recursive(const struct ovs_mutex *);
63
void ovs_mutex_init_adaptive(const struct ovs_mutex *);
64
void ovs_mutex_destroy(const struct ovs_mutex *);
65
void ovs_mutex_unlock(const struct ovs_mutex *mutex) OVS_RELEASES(mutex);
66
void ovs_mutex_lock_at(const struct ovs_mutex *mutex, const char *where)
68
#define ovs_mutex_lock(mutex) \
69
ovs_mutex_lock_at(mutex, SOURCE_LOCATOR)
71
int ovs_mutex_trylock_at(const struct ovs_mutex *mutex, const char *where)
72
OVS_TRY_LOCK(0, mutex);
73
#define ovs_mutex_trylock(mutex) \
74
ovs_mutex_trylock_at(mutex, SOURCE_LOCATOR)
76
void ovs_mutex_cond_wait(pthread_cond_t *, const struct ovs_mutex *);
78
36
/* Wrappers for pthread_mutex_*() that abort the process on any error.
79
37
* This is still needed when ovs-atomic-pthreads.h is used. */
80
38
void xpthread_mutex_lock(pthread_mutex_t *mutex);
130
88
void ovs_rwlock_wrlock_at(const struct ovs_rwlock *rwlock, const char *where)
131
89
OVS_ACQ_WRLOCK(rwlock);
132
90
#define ovs_rwlock_wrlock(rwlock) \
133
ovs_rwlock_wrlock_at(rwlock, SOURCE_LOCATOR)
91
ovs_rwlock_wrlock_at(rwlock, OVS_SOURCE_LOCATOR)
135
93
int ovs_rwlock_trywrlock_at(const struct ovs_rwlock *rwlock, const char *where)
136
94
OVS_TRY_WRLOCK(0, rwlock);
137
95
#define ovs_rwlock_trywrlock(rwlock) \
138
ovs_rwlock_trywrlock_at(rwlock, SOURCE_LOCATOR)
96
ovs_rwlock_trywrlock_at(rwlock, OVS_SOURCE_LOCATOR)
140
98
void ovs_rwlock_rdlock_at(const struct ovs_rwlock *rwlock, const char *where)
141
99
OVS_ACQ_RDLOCK(rwlock);
142
100
#define ovs_rwlock_rdlock(rwlock) \
143
ovs_rwlock_rdlock_at(rwlock, SOURCE_LOCATOR)
101
ovs_rwlock_rdlock_at(rwlock, OVS_SOURCE_LOCATOR)
145
103
int ovs_rwlock_tryrdlock_at(const struct ovs_rwlock *rwlock, const char *where)
146
104
OVS_TRY_RDLOCK(0, rwlock);
147
105
#define ovs_rwlock_tryrdlock(rwlock) \
148
ovs_rwlock_tryrdlock_at(rwlock, SOURCE_LOCATOR)
106
ovs_rwlock_tryrdlock_at(rwlock, OVS_SOURCE_LOCATOR)
150
108
/* ovs_barrier functions analogous to pthread_barrier_*() functions. */
151
109
void ovs_barrier_init(struct ovs_barrier *, uint32_t count);
164
122
void xpthread_key_delete(pthread_key_t);
165
123
void xpthread_setspecific(pthread_key_t, const void *);
126
void xpthread_sigmask(int, const sigset_t *, sigset_t *);
167
129
pthread_t ovs_thread_create(const char *name, void *(*)(void *), void *);
168
130
void xpthread_join(pthread_t, void **);
496
458
void ovsthread_setspecific(ovsthread_key_t, const void *);
497
459
void *ovsthread_getspecific(ovsthread_key_t);
499
/* Convenient once-only execution.
505
* POSIX provides pthread_once_t and pthread_once() as primitives for running a
506
* set of code only once per process execution. They are used like this:
508
* static void run_once(void) { ...initialization... }
509
* static pthread_once_t once = PTHREAD_ONCE_INIT;
511
* pthread_once(&once, run_once);
513
* pthread_once() does not allow passing any parameters to the initialization
514
* function, which is often inconvenient, because it means that the function
515
* can only access data declared at file scope.
521
* Use ovsthread_once, like this, instead:
523
* static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
525
* if (ovsthread_once_start(&once)) {
526
* ...initialization...
527
* ovsthread_once_done(&once);
531
struct ovsthread_once {
533
struct ovs_mutex mutex;
536
#define OVSTHREAD_ONCE_INITIALIZER \
538
ATOMIC_VAR_INIT(false), \
539
OVS_MUTEX_INITIALIZER, \
542
static inline bool ovsthread_once_start(struct ovsthread_once *once)
543
OVS_TRY_LOCK(true, once->mutex);
544
void ovsthread_once_done(struct ovsthread_once *once)
545
OVS_RELEASES(once->mutex);
547
bool ovsthread_once_start__(struct ovsthread_once *once)
548
OVS_TRY_LOCK(false, once->mutex);
551
ovsthread_once_is_done__(struct ovsthread_once *once)
555
atomic_read_explicit(&once->done, &done, memory_order_relaxed);
559
/* Returns true if this is the first call to ovsthread_once_start() for
560
* 'once'. In this case, the caller should perform whatever initialization
561
* actions it needs to do, then call ovsthread_once_done() for 'once'.
563
* Returns false if this is not the first call to ovsthread_once_start() for
564
* 'once'. In this case, the call will not return until after
565
* ovsthread_once_done() has been called. */
567
ovsthread_once_start(struct ovsthread_once *once)
569
return OVS_UNLIKELY(!ovsthread_once_is_done__(once)
570
&& !ovsthread_once_start__(once));
575
463
* pthread_t isn't so nice for some purposes. Its size and representation are
622
510
bool single_threaded(void);
624
512
void assert_single_threaded_at(const char *where);
625
#define assert_single_threaded() assert_single_threaded_at(SOURCE_LOCATOR)
513
#define assert_single_threaded() assert_single_threaded_at(OVS_SOURCE_LOCATOR)
628
516
pid_t xfork_at(const char *where);
629
#define xfork() xfork_at(SOURCE_LOCATOR)
517
#define xfork() xfork_at(OVS_SOURCE_LOCATOR)
632
520
void forbid_forking(const char *reason);