pthread_spin_* wrappers to be used for extremely small critical sections. Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com> --- lib/ovs-thread.c | 56 ++++++++++++++++++++++++++++++++++++------------------ lib/ovs-thread.h | 26 +++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 19 deletions(-)
diff --git a/lib/ovs-thread.c b/lib/ovs-thread.c index a20b2fd..5809721 100644 --- a/lib/ovs-thread.c +++ b/lib/ovs-thread.c @@ -44,44 +44,46 @@ static const char *must_not_fork; /* True if we created any threads beyond the main initial thread. */ static bool multithreaded; -#define LOCK_FUNCTION(TYPE, FUN) \ +#define LOCK_FUNCTION(TYPE, PFNAME, FUN) \ void \ ovs_##TYPE##_##FUN##_at(const struct ovs_##TYPE *l_, \ const char *where) \ OVS_NO_THREAD_SAFETY_ANALYSIS \ { \ struct ovs_##TYPE *l = CONST_CAST(struct ovs_##TYPE *, l_); \ - int error = pthread_##TYPE##_##FUN(&l->lock); \ + int error = pthread_##PFNAME##_##FUN(&l->lock); \ if (OVS_UNLIKELY(error)) { \ - ovs_abort(error, "pthread_%s_%s failed", #TYPE, #FUN); \ + ovs_abort(error, "pthread_" #PFNAME "_" #FUN " failed"); \ } \ l->where = where; \ } -LOCK_FUNCTION(mutex, lock); -LOCK_FUNCTION(rwlock, rdlock); -LOCK_FUNCTION(rwlock, wrlock); +LOCK_FUNCTION(mutex, mutex, lock); +LOCK_FUNCTION(rwlock, rwlock, rdlock); +LOCK_FUNCTION(rwlock, rwlock, wrlock); +LOCK_FUNCTION(spinlock, spin, lock); -#define TRY_LOCK_FUNCTION(TYPE, FUN) \ +#define TRY_LOCK_FUNCTION(TYPE, PFNAME, FUN) \ int \ ovs_##TYPE##_##FUN##_at(const struct ovs_##TYPE *l_, \ const char *where) \ OVS_NO_THREAD_SAFETY_ANALYSIS \ { \ struct ovs_##TYPE *l = CONST_CAST(struct ovs_##TYPE *, l_); \ - int error = pthread_##TYPE##_##FUN(&l->lock); \ + int error = pthread_##PFNAME##_##FUN(&l->lock); \ if (OVS_UNLIKELY(error) && error != EBUSY) { \ - ovs_abort(error, "pthread_%s_%s failed", #TYPE, #FUN); \ + ovs_abort(error, "pthread_" #PFNAME "_" #FUN " failed"); \ } \ if (!error) { \ l->where = where; \ } \ return error; \ } -TRY_LOCK_FUNCTION(mutex, trylock); -TRY_LOCK_FUNCTION(rwlock, tryrdlock); -TRY_LOCK_FUNCTION(rwlock, trywrlock); +TRY_LOCK_FUNCTION(mutex, mutex, trylock); +TRY_LOCK_FUNCTION(rwlock, rwlock, tryrdlock); +TRY_LOCK_FUNCTION(rwlock, rwlock, trywrlock); +TRY_LOCK_FUNCTION(spinlock, spin, trylock); -#define UNLOCK_FUNCTION(TYPE, FUN) \ +#define UNLOCK_FUNCTION(TYPE, PFNAME, FUN) \ void \ ovs_##TYPE##_##FUN(const struct ovs_##TYPE *l_) \ OVS_NO_THREAD_SAFETY_ANALYSIS \ @@ -89,15 +91,17 @@ TRY_LOCK_FUNCTION(rwlock, trywrlock); struct ovs_##TYPE *l = CONST_CAST(struct ovs_##TYPE *, l_); \ int error; \ l->where = NULL; \ - error = pthread_##TYPE##_##FUN(&l->lock); \ + error = pthread_##PFNAME##_##FUN(&l->lock); \ if (OVS_UNLIKELY(error)) { \ - ovs_abort(error, "pthread_%s_%sfailed", #TYPE, #FUN); \ + ovs_abort(error, "pthread_" #PFNAME "_" #FUN " failed"); \ } \ } -UNLOCK_FUNCTION(mutex, unlock); -UNLOCK_FUNCTION(mutex, destroy); -UNLOCK_FUNCTION(rwlock, unlock); -UNLOCK_FUNCTION(rwlock, destroy); +UNLOCK_FUNCTION(mutex, mutex, unlock); +UNLOCK_FUNCTION(mutex, mutex, destroy); +UNLOCK_FUNCTION(rwlock, rwlock, unlock); +UNLOCK_FUNCTION(rwlock, rwlock, destroy); +UNLOCK_FUNCTION(spinlock, spin, unlock); +UNLOCK_FUNCTION(spinlock, spin, destroy); #define XPTHREAD_FUNC1(FUNCTION, PARAM1) \ void \ @@ -181,6 +185,20 @@ ovs_rwlock_init(const struct ovs_rwlock *l_) } } +/* Initializes 'lock' as a process private spinlock. */ +void +ovs_spinlock_init(const struct ovs_spinlock *l_) +{ + struct ovs_spinlock *l = CONST_CAST(struct ovs_spinlock *, l_); + int error; + + l->where = NULL; + error = pthread_spin_init(&l->lock, PTHREAD_PROCESS_PRIVATE); + if (OVS_UNLIKELY(error)) { + ovs_abort(error, "pthread_spin_init failed"); + } +} + void ovs_mutex_cond_wait(pthread_cond_t *cond, const struct ovs_mutex *mutex_) { diff --git a/lib/ovs-thread.h b/lib/ovs-thread.h index f031894..1115577 100644 --- a/lib/ovs-thread.h +++ b/lib/ovs-thread.h @@ -69,6 +69,32 @@ void xpthread_mutexattr_destroy(pthread_mutexattr_t *); void xpthread_mutexattr_settype(pthread_mutexattr_t *, int type); void xpthread_mutexattr_gettype(pthread_mutexattr_t *, int *typep); +/* Spinlock */ +struct OVS_LOCKABLE ovs_spinlock { + pthread_spinlock_t lock; + const char *where; +}; + +/* "struct ovs_spinlock" initializer. */ +#define OVS_SPINLOCK_INITIALIZER { PTHREAD_SPINLOCK_INITIALIZER, NULL } + +/* ovs_spinlock functions analogous to pthread_spin_*() functions. + * + * Most of these functions abort the process with an error message on any + * error. ovs_spinlock_trylock() is an exception: it passes through a 0 or + * EBUSY return value to the caller and aborts on any other error. */ +void ovs_spinlock_init(const struct ovs_spinlock *); +void ovs_spinlock_destroy(const struct ovs_spinlock *); +void ovs_spinlock_unlock(const struct ovs_spinlock *lock) OVS_RELEASES(lock); +void ovs_spinlock_lock_at(const struct ovs_spinlock *lock, const char *where) + OVS_ACQUIRES(lock); +#define ovs_spinlock_lock(lock) \ + ovs_spinlock_lock_at(lock, SOURCE_LOCATOR) +int ovs_spinlock_trylock_at(const struct ovs_spinlock *lock, const char *where) + OVS_TRY_LOCK(0, lock); +#define ovs_spinlock_trylock(lock) \ + ovs_spinlock_trylock_at(lock, SOURCE_LOCATOR) + /* Read-write lock. */ struct OVS_LOCKABLE ovs_rwlock { pthread_rwlock_t lock; -- 1.7.10.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev