#include <unistd.h>
#include "compiler.h"
#include "hash.h"
+#include "ovs-rcu.h"
#include "poll-loop.h"
#include "socket-util.h"
#include "util.h"
ovs_abort(error, "%s failed", #FUNCTION); \
} \
}
+#define XPTHREAD_FUNC3(FUNCTION, PARAM1, PARAM2, PARAM3)\
+ void \
+ x##FUNCTION(PARAM1 arg1, PARAM2 arg2, PARAM3 arg3) \
+ { \
+ int error = FUNCTION(arg1, arg2, arg3); \
+ if (OVS_UNLIKELY(error)) { \
+ ovs_abort(error, "%s failed", #FUNCTION); \
+ } \
+ }
XPTHREAD_FUNC1(pthread_mutex_lock, pthread_mutex_t *);
XPTHREAD_FUNC1(pthread_mutex_unlock, pthread_mutex_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 *);
XPTHREAD_FUNC1(pthread_cond_broadcast, pthread_cond_t *);
+XPTHREAD_FUNC3(pthread_barrier_init, pthread_barrier_t *,
+ pthread_barrierattr_t *, unsigned int);
+XPTHREAD_FUNC1(pthread_barrier_destroy, pthread_barrier_t *);
+
XPTHREAD_FUNC2(pthread_join, pthread_t, void **);
typedef void destructor_func(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
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);
+ int error;
+
+ ovsrcu_quiesce_start();
+ error = pthread_cond_wait(cond, &mutex->lock);
+ ovsrcu_quiesce_end();
+
if (OVS_UNLIKELY(error)) {
ovs_abort(error, "pthread_cond_wait failed");
}
}
+
+int
+xpthread_barrier_wait(pthread_barrier_t *barrier)
+{
+ int error;
+
+ error = pthread_barrier_wait(barrier);
+ if (error && OVS_UNLIKELY(error != PTHREAD_BARRIER_SERIAL_THREAD)) {
+ ovs_abort(error, "pthread_barrier_wait failed");
+ }
+
+ return error;
+}
\f
DEFINE_EXTERN_PER_THREAD_DATA(ovsthread_id, 0);
aux = *auxp;
free(auxp);
+ ovsrcu_quiesce_end();
return aux.start(aux.arg);
}
forbid_forking("multiple threads exist");
multithreaded = true;
+ ovsrcu_quiesce_end();
aux = xmalloc(sizeof *aux);
aux->start = start;
ovs_mutex_unlock(&once->mutex);
}
\f
+bool
+single_threaded(void)
+{
+ return !multithreaded;
+}
+
/* Asserts that the process has not yet created any threads (beyond the initial
* thread).
*
}
}
+#ifndef _WIN32
/* Forks the current process (checking that this is allowed). Aborts with
* VLOG_FATAL if fork() returns an error, and otherwise returns the value
* returned by fork().
}
return pid;
}
+#endif
/* Notes that the process must not call fork() from now on, for the specified
* 'reason'. (The process may still fork() if it execs itself immediately
static long int n_cores;
if (ovsthread_once_start(&once)) {
+#ifndef _WIN32
parse_cpuinfo(&n_cores);
if (!n_cores) {
n_cores = sysconf(_SC_NPROCESSORS_ONLN);
}
+#else
+ SYSTEM_INFO sysinfo;
+ GetSystemInfo(&sysinfo);
+ n_cores = sysinfo.dwNumberOfProcessors;
+#endif
ovsthread_once_done(&once);
}