summaryrefslogtreecommitdiff
path: root/absl/synchronization
diff options
context:
space:
mode:
authorGravatar Derek Mauro <dmauro@google.com>2023-04-06 08:19:11 -0700
committerGravatar Copybara-Service <copybara-worker@google.com>2023-04-06 08:19:57 -0700
commita880427b38b2eca647a6eb0a09b241dbd962a4b9 (patch)
tree78b48493f26979a7ac308554372399e7e57b7440 /absl/synchronization
parentd7228036ab2a191462c532b914a99c3a8d10a171 (diff)
Synchronization: Support true relative timeouts on Apple platforms
using the non-portable pthread_cond_timedwait_relative_np() PiperOrigin-RevId: 522340555 Change-Id: I08682f74d8d94965330f12274c7a92632b1a29f1
Diffstat (limited to 'absl/synchronization')
-rw-r--r--absl/synchronization/internal/pthread_waiter.cc35
-rw-r--r--absl/synchronization/internal/pthread_waiter.h2
2 files changed, 31 insertions, 6 deletions
diff --git a/absl/synchronization/internal/pthread_waiter.cc b/absl/synchronization/internal/pthread_waiter.cc
index 52587827..a8dafd94 100644
--- a/absl/synchronization/internal/pthread_waiter.cc
+++ b/absl/synchronization/internal/pthread_waiter.cc
@@ -20,6 +20,7 @@
#include <sys/time.h>
#include <unistd.h>
+#include <cassert>
#include <cerrno>
#include "absl/base/config.h"
@@ -73,12 +74,34 @@ PthreadWaiter::PthreadWaiter() : waiter_count_(0), wakeup_count_(0) {
}
}
-bool PthreadWaiter::Wait(KernelTimeout t) {
- struct timespec abs_timeout;
- if (t.has_timeout()) {
- abs_timeout = t.MakeAbsTimespec();
+#ifdef __APPLE__
+#define ABSL_INTERNAL_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP 1
+#endif
+
+// Calls pthread_cond_timedwait() or possibly something else like
+// pthread_cond_timedwait_relative_np() depending on the platform and
+// KernelTimeout requested. The return value is the same as the return
+// value of pthread_cond_timedwait().
+int PthreadWaiter::TimedWait(KernelTimeout t) {
+#ifndef __GOOGLE_GRTE_VERSION__
+ constexpr bool kRelativeTimeoutSupported = true;
+#else
+ constexpr bool kRelativeTimeoutSupported = false;
+#endif
+
+ assert(t.has_timeout());
+ if (kRelativeTimeoutSupported && t.is_relative_timeout()) {
+#ifdef ABSL_INTERNAL_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP
+ const auto rel_timeout = t.MakeRelativeTimespec();
+ return pthread_cond_timedwait_relative_np(&cv_, &mu_, &rel_timeout);
+#endif
}
+ const auto abs_timeout = t.MakeAbsTimespec();
+ return pthread_cond_timedwait(&cv_, &mu_, &abs_timeout);
+}
+
+bool PthreadWaiter::Wait(KernelTimeout t) {
PthreadMutexHolder h(&mu_);
++waiter_count_;
// Loop until we find a wakeup to consume or timeout.
@@ -94,13 +117,13 @@ bool PthreadWaiter::Wait(KernelTimeout t) {
ABSL_RAW_LOG(FATAL, "pthread_cond_wait failed: %d", err);
}
} else {
- const int err = pthread_cond_timedwait(&cv_, &mu_, &abs_timeout);
+ const int err = TimedWait(t);
if (err == ETIMEDOUT) {
--waiter_count_;
return false;
}
if (err != 0) {
- ABSL_RAW_LOG(FATAL, "pthread_cond_timedwait failed: %d", err);
+ ABSL_RAW_LOG(FATAL, "PthreadWaiter::TimedWait() failed: %d", err);
}
}
first_pass = false;
diff --git a/absl/synchronization/internal/pthread_waiter.h b/absl/synchronization/internal/pthread_waiter.h
index a930a9e8..206aefa4 100644
--- a/absl/synchronization/internal/pthread_waiter.h
+++ b/absl/synchronization/internal/pthread_waiter.h
@@ -40,6 +40,8 @@ class PthreadWaiter : public WaiterCrtp<PthreadWaiter> {
static constexpr char kName[] = "PthreadWaiter";
private:
+ int TimedWait(KernelTimeout t);
+
// REQUIRES: mu_ must be held.
void InternalCondVarPoke();