Commit a880427b by Derek Mauro Committed by Copybara-Service

Synchronization: Support true relative timeouts on Apple platforms

using the non-portable pthread_cond_timedwait_relative_np()

PiperOrigin-RevId: 522340555
Change-Id: I08682f74d8d94965330f12274c7a92632b1a29f1
parent d7228036
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <sys/time.h> #include <sys/time.h>
#include <unistd.h> #include <unistd.h>
#include <cassert>
#include <cerrno> #include <cerrno>
#include "absl/base/config.h" #include "absl/base/config.h"
...@@ -73,12 +74,34 @@ PthreadWaiter::PthreadWaiter() : waiter_count_(0), wakeup_count_(0) { ...@@ -73,12 +74,34 @@ PthreadWaiter::PthreadWaiter() : waiter_count_(0), wakeup_count_(0) {
} }
} }
bool PthreadWaiter::Wait(KernelTimeout t) { #ifdef __APPLE__
struct timespec abs_timeout; #define ABSL_INTERNAL_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP 1
if (t.has_timeout()) { #endif
abs_timeout = t.MakeAbsTimespec();
// 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_); PthreadMutexHolder h(&mu_);
++waiter_count_; ++waiter_count_;
// Loop until we find a wakeup to consume or timeout. // Loop until we find a wakeup to consume or timeout.
...@@ -94,13 +117,13 @@ bool PthreadWaiter::Wait(KernelTimeout t) { ...@@ -94,13 +117,13 @@ bool PthreadWaiter::Wait(KernelTimeout t) {
ABSL_RAW_LOG(FATAL, "pthread_cond_wait failed: %d", err); ABSL_RAW_LOG(FATAL, "pthread_cond_wait failed: %d", err);
} }
} else { } else {
const int err = pthread_cond_timedwait(&cv_, &mu_, &abs_timeout); const int err = TimedWait(t);
if (err == ETIMEDOUT) { if (err == ETIMEDOUT) {
--waiter_count_; --waiter_count_;
return false; return false;
} }
if (err != 0) { 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; first_pass = false;
......
...@@ -40,6 +40,8 @@ class PthreadWaiter : public WaiterCrtp<PthreadWaiter> { ...@@ -40,6 +40,8 @@ class PthreadWaiter : public WaiterCrtp<PthreadWaiter> {
static constexpr char kName[] = "PthreadWaiter"; static constexpr char kName[] = "PthreadWaiter";
private: private:
int TimedWait(KernelTimeout t);
// REQUIRES: mu_ must be held. // REQUIRES: mu_ must be held.
void InternalCondVarPoke(); void InternalCondVarPoke();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment