summaryrefslogtreecommitdiff
path: root/lib/ovs-thread.c
diff options
context:
space:
mode:
authorBen Pfaff <blp@nicira.com>2014-02-21 10:53:49 -0800
committerBen Pfaff <blp@nicira.com>2014-02-21 16:27:10 -0800
commit6b59b543c840ac82acc4d57f865c0b5e331ac590 (patch)
tree6da0af0a46ab13351c99257981ac5103f650b553 /lib/ovs-thread.c
parent5a0702383b61d329f0640b5b4da4869a4b4f1384 (diff)
downloadopenvswitch-6b59b543c840ac82acc4d57f865c0b5e331ac590.tar.gz
ovs-thread: Use fair (but nonrecursive) rwlocks on glibc.
glibc supports two kinds of rwlocks: - The default kind of rwlock always allows recursive read-locks to succeed, but threads blocked on acquiring the write-lock are treated unfairly, causing them to be delayed indefinitely as long as new readers continue to come along. - An alternative "writer nonrecursive" rwlock allows recursive read-locks to succeed only if there are no threads waiting for the write-lock. Otherwise, recursive read-lock attempts deadlock in the presence of blocking write-lock attempts. However, this kind of rwlock is fair to writer. POSIX allows the latter behavior, which essentially means that any portable pthread program cannot try to take read-locks recursively. Since that's true, we might as well use the latter kind of rwlock with glibc and get the benefit of fairness of writers. Signed-off-by: Ben Pfaff <blp@nicira.com> Acked-by: Joe Stringer <joestringer@nicira.com>
Diffstat (limited to 'lib/ovs-thread.c')
-rw-r--r--lib/ovs-thread.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/lib/ovs-thread.c b/lib/ovs-thread.c
index f0b1e9e81..4dfccaf3e 100644
--- a/lib/ovs-thread.c
+++ b/lib/ovs-thread.c
@@ -125,6 +125,12 @@ XPTHREAD_FUNC1(pthread_mutexattr_destroy, pthread_mutexattr_t *);
XPTHREAD_FUNC2(pthread_mutexattr_settype, pthread_mutexattr_t *, int);
XPTHREAD_FUNC2(pthread_mutexattr_gettype, pthread_mutexattr_t *, int *);
+XPTHREAD_FUNC1(pthread_rwlockattr_init, pthread_rwlockattr_t *);
+XPTHREAD_FUNC1(pthread_rwlockattr_destroy, pthread_rwlockattr_t *);
+#ifdef PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
+XPTHREAD_FUNC2(pthread_rwlockattr_setkind_np, pthread_rwlockattr_t *, int);
+#endif
+
XPTHREAD_FUNC2(pthread_cond_init, pthread_cond_t *, pthread_condattr_t *);
XPTHREAD_FUNC1(pthread_cond_destroy, pthread_cond_t *);
XPTHREAD_FUNC1(pthread_cond_signal, pthread_cond_t *);
@@ -183,13 +189,21 @@ void
ovs_rwlock_init(const struct ovs_rwlock *l_)
{
struct ovs_rwlock *l = CONST_CAST(struct ovs_rwlock *, l_);
+ pthread_rwlockattr_t attr;
int error;
l->where = NULL;
+
+ xpthread_rwlockattr_init(&attr);
+#ifdef PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
+ xpthread_rwlockattr_setkind_np(
+ &attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
+#endif
error = pthread_rwlock_init(&l->lock, NULL);
if (OVS_UNLIKELY(error)) {
ovs_abort(error, "pthread_rwlock_init failed");
}
+ xpthread_rwlockattr_destroy(&attr);
}
void