From 05bf6d3c62e1d19e192d264682e8239196a56ee9 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Thu, 24 Apr 2014 16:49:05 -0700 Subject: [PATCH] ovs-thread: Add checking for mutex and rwlock initialization. With glibc, a mutex or rwlock filled with all-zero-bytes is properly initialized for use, but this is not true for any other libc that OVS supports. However, OVS gets a lot more testing with glibc than any other libc. This means that developers keep introducing bugs that do not manifest on the main development platform. This commit should help avoid the problem, by reusing the existing 'where' members to indicate whether a mutex or rwlock has been initialized. Signed-off-by: Ben Pfaff --- lib/ovs-thread.c | 36 +++++++++++++++++++++++++----------- lib/ovs-thread.h | 13 +++++++------ 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/lib/ovs-thread.c b/lib/ovs-thread.c index 19edf8ff1..fbdd7fce0 100644 --- a/lib/ovs-thread.c +++ b/lib/ovs-thread.c @@ -52,12 +52,17 @@ static bool multithreaded; OVS_NO_THREAD_SAFETY_ANALYSIS \ { \ struct ovs_##TYPE *l = CONST_CAST(struct ovs_##TYPE *, l_); \ - int error = pthread_##TYPE##_##FUN(&l->lock); \ + int error; \ + \ + /* Verify that 'l' was initialized. */ \ + ovs_assert(l->where); \ + \ + error = pthread_##TYPE##_##FUN(&l->lock); \ if (OVS_UNLIKELY(error)) { \ ovs_abort(error, "pthread_%s_%s failed", #TYPE, #FUN); \ } \ l->where = where; \ - } + } LOCK_FUNCTION(mutex, lock); LOCK_FUNCTION(rwlock, rdlock); LOCK_FUNCTION(rwlock, wrlock); @@ -69,7 +74,12 @@ LOCK_FUNCTION(rwlock, wrlock); OVS_NO_THREAD_SAFETY_ANALYSIS \ { \ struct ovs_##TYPE *l = CONST_CAST(struct ovs_##TYPE *, l_); \ - int error = pthread_##TYPE##_##FUN(&l->lock); \ + int error; \ + \ + /* Verify that 'l' was initialized. */ \ + ovs_assert(l->where); \ + \ + error = pthread_##TYPE##_##FUN(&l->lock); \ if (OVS_UNLIKELY(error) && error != EBUSY) { \ ovs_abort(error, "pthread_%s_%s failed", #TYPE, #FUN); \ } \ @@ -82,23 +92,27 @@ TRY_LOCK_FUNCTION(mutex, trylock); TRY_LOCK_FUNCTION(rwlock, tryrdlock); TRY_LOCK_FUNCTION(rwlock, trywrlock); -#define UNLOCK_FUNCTION(TYPE, FUN) \ +#define UNLOCK_FUNCTION(TYPE, FUN, WHERE) \ void \ ovs_##TYPE##_##FUN(const struct ovs_##TYPE *l_) \ OVS_NO_THREAD_SAFETY_ANALYSIS \ { \ struct ovs_##TYPE *l = CONST_CAST(struct ovs_##TYPE *, l_); \ int error; \ - l->where = NULL; \ + \ + /* Verify that 'l' was initialized. */ \ + ovs_assert(l->where); \ + \ + l->where = WHERE; \ error = pthread_##TYPE##_##FUN(&l->lock); \ if (OVS_UNLIKELY(error)) { \ ovs_abort(error, "pthread_%s_%sfailed", #TYPE, #FUN); \ } \ } -UNLOCK_FUNCTION(mutex, unlock); -UNLOCK_FUNCTION(mutex, destroy); -UNLOCK_FUNCTION(rwlock, unlock); -UNLOCK_FUNCTION(rwlock, destroy); +UNLOCK_FUNCTION(mutex, unlock, ""); +UNLOCK_FUNCTION(mutex, destroy, NULL); +UNLOCK_FUNCTION(rwlock, unlock, ""); +UNLOCK_FUNCTION(rwlock, destroy, NULL); #define XPTHREAD_FUNC1(FUNCTION, PARAM1) \ void \ @@ -164,7 +178,7 @@ ovs_mutex_init__(const struct ovs_mutex *l_, int type) pthread_mutexattr_t attr; int error; - l->where = NULL; + l->where = ""; xpthread_mutexattr_init(&attr); xpthread_mutexattr_settype(&attr, type); error = pthread_mutex_init(&l->lock, &attr); @@ -206,7 +220,7 @@ ovs_rwlock_init(const struct ovs_rwlock *l_) pthread_rwlockattr_t attr; int error; - l->where = NULL; + l->where = ""; xpthread_rwlockattr_init(&attr); #ifdef PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP diff --git a/lib/ovs-thread.h b/lib/ovs-thread.h index 9527843f0..180b66f89 100644 --- a/lib/ovs-thread.h +++ b/lib/ovs-thread.h @@ -27,14 +27,15 @@ /* Mutex. */ struct OVS_LOCKABLE ovs_mutex { pthread_mutex_t lock; - const char *where; + const char *where; /* NULL if and only if uninitialized. */ }; /* "struct ovs_mutex" initializer. */ #ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP -#define OVS_MUTEX_INITIALIZER { PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, NULL } +#define OVS_MUTEX_INITIALIZER { PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, \ + "" } #else -#define OVS_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, NULL } +#define OVS_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, "" } #endif #ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP @@ -91,15 +92,15 @@ void xpthread_mutexattr_gettype(pthread_mutexattr_t *, int *typep); * than exposing them only to porters. */ struct OVS_LOCKABLE ovs_rwlock { pthread_rwlock_t lock; - const char *where; + const char *where; /* NULL if and only if uninitialized. */ }; /* Initializer. */ #ifdef PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP #define OVS_RWLOCK_INITIALIZER \ - { PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP, NULL } + { PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP, "" } #else -#define OVS_RWLOCK_INITIALIZER { PTHREAD_RWLOCK_INITIALIZER, NULL } +#define OVS_RWLOCK_INITIALIZER { PTHREAD_RWLOCK_INITIALIZER, "" } #endif /* ovs_rwlock functions analogous to pthread_rwlock_*() functions. -- 2.43.0