summaryrefslogtreecommitdiff
path: root/src/third_party/wiredtiger/src/os_posix/os_mtx_cond.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/third_party/wiredtiger/src/os_posix/os_mtx_cond.c')
-rw-r--r--src/third_party/wiredtiger/src/os_posix/os_mtx_cond.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/src/third_party/wiredtiger/src/os_posix/os_mtx_cond.c b/src/third_party/wiredtiger/src/os_posix/os_mtx_cond.c
new file mode 100644
index 00000000000..3a76cceb3f0
--- /dev/null
+++ b/src/third_party/wiredtiger/src/os_posix/os_mtx_cond.c
@@ -0,0 +1,157 @@
+/*-
+ * Copyright (c) 2008-2014 WiredTiger, Inc.
+ * All rights reserved.
+ *
+ * See the file LICENSE for redistribution information.
+ */
+
+#include "wt_internal.h"
+
+/*
+ * __wt_cond_alloc --
+ * Allocate and initialize a condition variable.
+ */
+int
+__wt_cond_alloc(WT_SESSION_IMPL *session,
+ const char *name, int is_signalled, WT_CONDVAR **condp)
+{
+ WT_CONDVAR *cond;
+ WT_DECL_RET;
+
+ /*
+ * !!!
+ * This function MUST handle a NULL session handle.
+ */
+ WT_RET(__wt_calloc(session, 1, sizeof(WT_CONDVAR), &cond));
+
+ WT_ERR(pthread_mutex_init(&cond->mtx, NULL));
+
+ /* Initialize the condition variable to permit self-blocking. */
+ WT_ERR(pthread_cond_init(&cond->cond, NULL));
+
+ cond->name = name;
+ cond->waiters = is_signalled ? -1 : 0;
+
+ *condp = cond;
+ return (0);
+
+err: __wt_free(session, cond);
+ return (ret);
+}
+
+/*
+ * __wt_cond_wait --
+ * Wait on a mutex, optionally timing out.
+ */
+int
+__wt_cond_wait(WT_SESSION_IMPL *session, WT_CONDVAR *cond, long usecs)
+{
+ struct timespec ts;
+ WT_DECL_RET;
+ int locked;
+
+ locked = 0;
+ WT_ASSERT(session, usecs >= 0);
+
+ /* Fast path if already signalled. */
+ if (WT_ATOMIC_ADD4(cond->waiters, 1) == 0)
+ return (0);
+
+ /*
+ * !!!
+ * This function MUST handle a NULL session handle.
+ */
+ if (session != NULL) {
+ WT_RET(__wt_verbose(session, WT_VERB_MUTEX,
+ "wait %s cond (%p)", cond->name, cond));
+ WT_STAT_FAST_CONN_INCR(session, cond_wait);
+ }
+
+ WT_ERR(pthread_mutex_lock(&cond->mtx));
+ locked = 1;
+
+ if (usecs > 0) {
+ WT_ERR(__wt_epoch(session, &ts));
+ ts.tv_sec += (ts.tv_nsec + 1000 * usecs) / WT_BILLION;
+ ts.tv_nsec = (ts.tv_nsec + 1000 * usecs) % WT_BILLION;
+ ret = pthread_cond_timedwait(&cond->cond, &cond->mtx, &ts);
+ } else
+ ret = pthread_cond_wait(&cond->cond, &cond->mtx);
+
+ /*
+ * Check pthread_cond_wait() return for EINTR, ETIME and
+ * ETIMEDOUT, some systems return these errors.
+ */
+ if (ret == EINTR ||
+#ifdef ETIME
+ ret == ETIME ||
+#endif
+ ret == ETIMEDOUT)
+ ret = 0;
+
+ (void)WT_ATOMIC_SUB4(cond->waiters, 1);
+
+err: if (locked)
+ WT_TRET(pthread_mutex_unlock(&cond->mtx));
+ if (ret == 0)
+ return (0);
+ WT_RET_MSG(session, ret, "pthread_cond_wait");
+}
+
+/*
+ * __wt_cond_signal --
+ * Signal a waiting thread.
+ */
+int
+__wt_cond_signal(WT_SESSION_IMPL *session, WT_CONDVAR *cond)
+{
+ WT_DECL_RET;
+ int locked;
+
+ locked = 0;
+
+ /*
+ * !!!
+ * This function MUST handle a NULL session handle.
+ */
+ if (session != NULL)
+ WT_RET(__wt_verbose(session, WT_VERB_MUTEX,
+ "signal %s cond (%p)", cond->name, cond));
+
+ /* Fast path if already signalled. */
+ if (cond->waiters == -1)
+ return (0);
+
+ if (cond->waiters > 0 || !WT_ATOMIC_CAS4(cond->waiters, 0, -1)) {
+ WT_ERR(pthread_mutex_lock(&cond->mtx));
+ locked = 1;
+ WT_ERR(pthread_cond_broadcast(&cond->cond));
+ }
+
+err: if (locked)
+ WT_TRET(pthread_mutex_unlock(&cond->mtx));
+ if (ret == 0)
+ return (0);
+ WT_RET_MSG(session, ret, "pthread_cond_broadcast");
+}
+
+/*
+ * __wt_cond_destroy --
+ * Destroy a condition variable.
+ */
+int
+__wt_cond_destroy(WT_SESSION_IMPL *session, WT_CONDVAR **condp)
+{
+ WT_CONDVAR *cond;
+ WT_DECL_RET;
+
+ cond = *condp;
+ if (cond == NULL)
+ return (0);
+
+ ret = pthread_cond_destroy(&cond->cond);
+ WT_TRET(pthread_mutex_destroy(&cond->mtx));
+ __wt_free(session, *condp);
+
+ return (ret);
+}