+/* ovs_rwlock functions analogous to pthread_rwlock_*() functions.
+ *
+ * Most of these functions abort the process with an error message on any
+ * error. The "trylock" functions are exception: they pass through a 0 or
+ * EBUSY return value to the caller and abort on any other error. */
+void ovs_rwlock_init(const struct ovs_rwlock *);
+void ovs_rwlock_destroy(const struct ovs_rwlock *);
+void ovs_rwlock_unlock(const struct ovs_rwlock *rwlock) OVS_RELEASES(rwlock);
+
+/* Wrappers for pthread_rwlockattr_*() that abort the process on any error. */
+void xpthread_rwlockattr_init(pthread_rwlockattr_t *);
+void xpthread_rwlockattr_destroy(pthread_rwlockattr_t *);
+#ifdef PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
+void xpthread_rwlockattr_setkind_np(pthread_rwlockattr_t *, int kind);
+#endif
+
+void ovs_rwlock_wrlock_at(const struct ovs_rwlock *rwlock, const char *where)
+ OVS_ACQ_WRLOCK(rwlock);
+#define ovs_rwlock_wrlock(rwlock) \
+ ovs_rwlock_wrlock_at(rwlock, SOURCE_LOCATOR)
+
+int ovs_rwlock_trywrlock_at(const struct ovs_rwlock *rwlock, const char *where)
+ OVS_TRY_WRLOCK(0, rwlock);
+#define ovs_rwlock_trywrlock(rwlock) \
+ ovs_rwlock_trywrlock_at(rwlock, SOURCE_LOCATOR)
+
+void ovs_rwlock_rdlock_at(const struct ovs_rwlock *rwlock, const char *where)
+ OVS_ACQ_RDLOCK(rwlock);
+#define ovs_rwlock_rdlock(rwlock) \
+ ovs_rwlock_rdlock_at(rwlock, SOURCE_LOCATOR)
+
+int ovs_rwlock_tryrdlock_at(const struct ovs_rwlock *rwlock, const char *where)
+ OVS_TRY_RDLOCK(0, rwlock);
+#define ovs_rwlock_tryrdlock(rwlock) \
+ ovs_rwlock_tryrdlock_at(rwlock, SOURCE_LOCATOR)
+
+/* Wrappers for xpthread_cond_*() that abort the process on any error.
+ *
+ * Use ovs_mutex_cond_wait() to wait for a condition. */