summaryrefslogtreecommitdiffstats
path: root/ipc/chromium/src/base/condition_variable_posix.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/chromium/src/base/condition_variable_posix.cc')
-rw-r--r--ipc/chromium/src/base/condition_variable_posix.cc119
1 files changed, 119 insertions, 0 deletions
diff --git a/ipc/chromium/src/base/condition_variable_posix.cc b/ipc/chromium/src/base/condition_variable_posix.cc
new file mode 100644
index 0000000000..891555389e
--- /dev/null
+++ b/ipc/chromium/src/base/condition_variable_posix.cc
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/condition_variable.h"
+
+#include <errno.h>
+#include <stdint.h>
+#include <sys/time.h>
+
+#include "base/lock.h"
+#include "base/logging.h"
+#include "base/time.h"
+#include "build/build_config.h"
+
+ConditionVariable::ConditionVariable(Lock* user_lock)
+ : user_mutex_(user_lock->lock_.native_handle()) {
+ int rv = 0;
+ // http://crbug.com/293736
+ // NaCl doesn't support monotonic clock based absolute deadlines.
+ // On older Android platform versions, it's supported through the
+ // non-standard pthread_cond_timedwait_monotonic_np. Newer platform
+ // versions have pthread_condattr_setclock.
+ // Mac can use relative time deadlines.
+#if !defined(OS_MACOSX) && !defined(OS_NACL) && \
+ !(defined(OS_ANDROID) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC))
+ pthread_condattr_t attrs;
+ rv = pthread_condattr_init(&attrs);
+ DCHECK_EQ(0, rv);
+ pthread_condattr_setclock(&attrs, CLOCK_MONOTONIC);
+ rv = pthread_cond_init(&condition_, &attrs);
+ pthread_condattr_destroy(&attrs);
+#else
+ rv = pthread_cond_init(&condition_, NULL);
+#endif
+ DCHECK_EQ(0, rv);
+}
+
+ConditionVariable::~ConditionVariable() {
+#if defined(OS_MACOSX)
+ // This hack is necessary to avoid a fatal pthreads subsystem bug in the
+ // Darwin kernel. http://crbug.com/517681.
+ {
+ Lock lock;
+ AutoLock l(lock);
+ struct timespec ts;
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1;
+ pthread_cond_timedwait_relative_np(&condition_, lock.lock_.native_handle(),
+ &ts);
+ }
+#endif
+
+ int rv = pthread_cond_destroy(&condition_);
+ DCHECK_EQ(0, rv);
+}
+
+void ConditionVariable::Wait() {
+ int rv = pthread_cond_wait(&condition_, user_mutex_);
+ DCHECK_EQ(0, rv);
+}
+
+void ConditionVariable::TimedWait(const base::TimeDelta& max_time) {
+ int64_t usecs = max_time.InMicroseconds();
+ struct timespec relative_time;
+ relative_time.tv_sec = usecs / base::Time::kMicrosecondsPerSecond;
+ relative_time.tv_nsec = (usecs % base::Time::kMicrosecondsPerSecond) *
+ base::Time::kNanosecondsPerMicrosecond;
+
+#if defined(OS_MACOSX)
+ int rv = pthread_cond_timedwait_relative_np(&condition_, user_mutex_,
+ &relative_time);
+#else
+ // The timeout argument to pthread_cond_timedwait is in absolute time.
+ struct timespec absolute_time;
+# if defined(OS_NACL)
+ // See comment in constructor for why this is different in NaCl.
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ absolute_time.tv_sec = now.tv_sec;
+ absolute_time.tv_nsec = now.tv_usec * base::Time::kNanosecondsPerMicrosecond;
+# else
+ struct timespec now;
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ absolute_time.tv_sec = now.tv_sec;
+ absolute_time.tv_nsec = now.tv_nsec;
+# endif
+
+ absolute_time.tv_sec += relative_time.tv_sec;
+ absolute_time.tv_nsec += relative_time.tv_nsec;
+ absolute_time.tv_sec +=
+ absolute_time.tv_nsec / base::Time::kNanosecondsPerSecond;
+ absolute_time.tv_nsec %= base::Time::kNanosecondsPerSecond;
+ DCHECK_GE(absolute_time.tv_sec, now.tv_sec); // Overflow paranoia
+
+# if defined(OS_ANDROID) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC)
+ int rv = pthread_cond_timedwait_monotonic_np(&condition_, user_mutex_,
+ &absolute_time);
+# else
+ int rv = pthread_cond_timedwait(&condition_, user_mutex_, &absolute_time);
+# endif // OS_ANDROID && HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC
+#endif // OS_MACOSX
+
+ // On failure, we only expect the CV to timeout. Any other error value means
+ // that we've unexpectedly woken up.
+ DCHECK(rv == 0 || rv == ETIMEDOUT);
+}
+
+void ConditionVariable::Broadcast() {
+ int rv = pthread_cond_broadcast(&condition_);
+ DCHECK_EQ(0, rv);
+}
+
+void ConditionVariable::Signal() {
+ int rv = pthread_cond_signal(&condition_);
+ DCHECK_EQ(0, rv);
+}