summaryrefslogtreecommitdiff
path: root/lib/ovs-thread.h
diff options
context:
space:
mode:
authorBen Pfaff <blp@nicira.com>2013-08-20 13:40:02 -0700
committerBen Pfaff <blp@nicira.com>2013-08-20 13:40:02 -0700
commit834d6cafe4797861b7547966b4dcc95b374331be (patch)
treec4a3e3b60ce4d4438da6ff8c7e84898c75b613ed /lib/ovs-thread.h
parent0891637f67671c0654b9ff6b4c25a654375d24e2 (diff)
downloadopenvswitch-834d6cafe4797861b7547966b4dcc95b374331be.tar.gz
Use "error-checking" mutexes in place of other kinds wherever possible.
We've seen a number of deadlocks in the tree since thread safety was introduced. So far, all of these are self-deadlocks, that is, a single thread acquiring a lock and then attempting to re-acquire the same lock recursively. When this has happened, the process simply hung, and it was somewhat difficult to find the cause. POSIX "error-checking" mutexes check for this specific problem (and others). This commit switches from other types of mutexes to error-checking mutexes everywhere that we can, that is, everywhere that we're not using recursive mutexes. This ought to help find problems more quickly in the future. There might be performance advantages to other kinds of mutexes in some cases. However, the existing mutex type choices were just guesses, so I'd rather go for easy detection of errors until we know that other mutex types actually perform better in specific cases. Also, I did a quick microbenchmark of glibc mutex types on my host and found that the error checking mutexes weren't any slower than the other types, at least when the mutex is uncontended. Signed-off-by: Ben Pfaff <blp@nicira.com> Acked-by: Ethan Jackson <ethan@nicira.com>
Diffstat (limited to 'lib/ovs-thread.h')
-rw-r--r--lib/ovs-thread.h38
1 files changed, 6 insertions, 32 deletions
diff --git a/lib/ovs-thread.h b/lib/ovs-thread.h
index b7bc5d198..f10bc28bf 100644
--- a/lib/ovs-thread.h
+++ b/lib/ovs-thread.h
@@ -30,38 +30,11 @@ struct OVS_LOCKABLE ovs_mutex {
const char *where;
};
-/* "struct ovs_mutex" initializers:
- *
- * - OVS_MUTEX_INITIALIZER: common case.
- *
- * - OVS_ADAPTIVE_MUTEX_INITIALIZER for a mutex that spins briefly then goes
- * to sleeps after some number of iterations.
- *
- * - OVS_ERRORCHECK_MUTEX_INITIALIZER for a mutex that is used for
- * error-checking. */
-#define OVS_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, NULL }
-#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
-#define OVS_ADAPTIVE_MUTEX_INITIALIZER \
- { PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP, NULL }
-#else
-#define OVS_ADAPTIVE_MUTEX_INITIALIZER OVS_MUTEX_INITIALIZER
-#endif
+/* "struct ovs_mutex" initializer. */
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
-#define OVS_ERRORCHECK_MUTEX_INITIALIZER \
- { PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, NULL }
+#define OVS_MUTEX_INITIALIZER { PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, NULL }
#else
-#define OVS_ERRORCHECK_MUTEX_INITIALIZER OVS_MUTEX_INITIALIZER
-#endif
-
-/* Mutex types, suitable for use with pthread_mutexattr_settype().
- * There is only one nonstandard type:
- *
- * - PTHREAD_MUTEX_ADAPTIVE_NP, the type used for
- * OVS_ADAPTIVE_MUTEX_INITIALIZER. */
-#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
-#define OVS_MUTEX_ADAPTIVE PTHREAD_MUTEX_ADAPTIVE_NP
-#else
-#define OVS_MUTEX_ADAPTIVE PTHREAD_MUTEX_NORMAL
+#define OVS_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, NULL }
#endif
/* ovs_mutex functions analogous to pthread_mutex_*() functions.
@@ -69,7 +42,8 @@ struct OVS_LOCKABLE ovs_mutex {
* Most of these functions abort the process with an error message on any
* error. ovs_mutex_trylock() is an exception: it passes through a 0 or EBUSY
* return value to the caller and aborts on any other error. */
-void ovs_mutex_init(const struct ovs_mutex *, int type);
+void ovs_mutex_init(const struct ovs_mutex *);
+void ovs_mutex_init_recursive(const struct ovs_mutex *);
void ovs_mutex_destroy(const struct ovs_mutex *);
void ovs_mutex_unlock(const struct ovs_mutex *mutex) OVS_RELEASES(mutex);
void ovs_mutex_lock_at(const struct ovs_mutex *mutex, const char *where)
@@ -463,7 +437,7 @@ struct ovsthread_once {
#define OVSTHREAD_ONCE_INITIALIZER \
{ \
ATOMIC_VAR_INIT(false), \
- OVS_ADAPTIVE_MUTEX_INITIALIZER, \
+ OVS_MUTEX_INITIALIZER, \
}
static inline bool ovsthread_once_start(struct ovsthread_once *once)