+XPTHREAD_FUNC2(pthread_setspecific, pthread_key_t, const void *);
+
+static void
+ovs_mutex_init__(const struct ovs_mutex *l_, int type)
+{
+ struct ovs_mutex *l = CONST_CAST(struct ovs_mutex *, l_);
+ pthread_mutexattr_t attr;
+ int error;
+
+ l->where = NULL;
+ xpthread_mutexattr_init(&attr);
+ xpthread_mutexattr_settype(&attr, type);
+ error = pthread_mutex_init(&l->lock, &attr);
+ if (OVS_UNLIKELY(error)) {
+ ovs_abort(error, "pthread_mutex_init failed");
+ }
+ xpthread_mutexattr_destroy(&attr);
+}
+
+/* Initializes 'mutex' as a normal (non-recursive) mutex. */
+void
+ovs_mutex_init(const struct ovs_mutex *mutex)
+{
+ ovs_mutex_init__(mutex, PTHREAD_MUTEX_ERRORCHECK);
+}
+
+/* Initializes 'mutex' as a recursive mutex. */
+void
+ovs_mutex_init_recursive(const struct ovs_mutex *mutex)
+{
+ ovs_mutex_init__(mutex, PTHREAD_MUTEX_RECURSIVE);
+}
+
+void
+ovs_rwlock_init(const struct ovs_rwlock *l_)
+{
+ struct ovs_rwlock *l = CONST_CAST(struct ovs_rwlock *, l_);
+ int error;
+
+ l->where = NULL;
+ error = pthread_rwlock_init(&l->lock, NULL);
+ if (OVS_UNLIKELY(error)) {
+ ovs_abort(error, "pthread_rwlock_init failed");
+ }
+}
+
+void
+ovs_mutex_cond_wait(pthread_cond_t *cond, const struct ovs_mutex *mutex_)
+{
+ struct ovs_mutex *mutex = CONST_CAST(struct ovs_mutex *, mutex_);
+ int error = pthread_cond_wait(cond, &mutex->lock);
+ if (OVS_UNLIKELY(error)) {
+ ovs_abort(error, "pthread_cond_wait failed");
+ }
+}
+\f
+DEFINE_EXTERN_PER_THREAD_DATA(ovsthread_id, 0);
+
+struct ovsthread_aux {
+ void *(*start)(void *);
+ void *arg;
+};
+
+static void *
+ovsthread_wrapper(void *aux_)
+{
+ static atomic_uint next_id = ATOMIC_VAR_INIT(1);
+
+ struct ovsthread_aux *auxp = aux_;
+ struct ovsthread_aux aux;
+ unsigned int id;
+
+ atomic_add(&next_id, 1, &id);
+ *ovsthread_id_get() = id;
+
+ aux = *auxp;
+ free(auxp);
+
+ return aux.start(aux.arg);
+}