aboutsummaryrefslogtreecommitdiff
path: root/absl/synchronization/internal/kernel_timeout.cc
diff options
context:
space:
mode:
authorDerek Mauro <dmauro@google.com>2023-04-08 09:52:09 -0700
committerCopybara-Service <copybara-worker@google.com>2023-04-08 09:52:56 -0700
commit1a72ea7bb8ba27679dd8b179a4671d7d9b099d4b (patch)
treef1e4c715e0e99bbe4206fd91c5b207bb297be4f5 /absl/synchronization/internal/kernel_timeout.cc
parent42a3c030c958e6e099162b746ada04792b3a1c67 (diff)
downloadabseil-1a72ea7bb8ba27679dd8b179a4671d7d9b099d4b.tar.gz
abseil-1a72ea7bb8ba27679dd8b179a4671d7d9b099d4b.tar.bz2
abseil-1a72ea7bb8ba27679dd8b179a4671d7d9b099d4b.zip
Synchronization: Support true relative timeouts using the POSIX
proposed standard pthread_cond_clockwait() and sem_clockwait(). These are currently implemented in glibc >= 2.30. These methods take a clock and use an absolute time with reference to that clock, so KernelTimeout now can produce these values. PiperOrigin-RevId: 522824226 Change-Id: Ife98713f6f95d800b1f8e52d5364a3dbebc4f8a6
Diffstat (limited to 'absl/synchronization/internal/kernel_timeout.cc')
-rw-r--r--absl/synchronization/internal/kernel_timeout.cc35
1 files changed, 33 insertions, 2 deletions
diff --git a/absl/synchronization/internal/kernel_timeout.cc b/absl/synchronization/internal/kernel_timeout.cc
index 2e485097..bfbf282f 100644
--- a/absl/synchronization/internal/kernel_timeout.cc
+++ b/absl/synchronization/internal/kernel_timeout.cc
@@ -14,6 +14,10 @@
#include "absl/synchronization/internal/kernel_timeout.h"
+#ifndef _WIN32
+#include <sys/types.h>
+#endif
+
#include <algorithm>
#include <chrono> // NOLINT(build/c++11)
#include <cstdint>
@@ -101,7 +105,7 @@ int64_t KernelTimeout::MakeAbsNanos() const {
return kMaxNanos;
}
- int64_t nanos = RawNanos();
+ int64_t nanos = RawAbsNanos();
if (is_relative_timeout()) {
// We need to change epochs, because the relative timeout might be
@@ -128,7 +132,7 @@ int64_t KernelTimeout::InNanosecondsFromNow() const {
return kMaxNanos;
}
- int64_t nanos = RawNanos();
+ int64_t nanos = RawAbsNanos();
if (is_absolute_timeout()) {
return std::max<int64_t>(nanos - absl::GetCurrentTimeNanos(), 0);
}
@@ -143,6 +147,33 @@ struct timespec KernelTimeout::MakeRelativeTimespec() const {
return absl::ToTimespec(absl::Nanoseconds(InNanosecondsFromNow()));
}
+#ifndef _WIN32
+struct timespec KernelTimeout::MakeClockAbsoluteTimespec(clockid_t c) const {
+ if (!has_timeout()) {
+ return absl::ToTimespec(absl::Nanoseconds(kMaxNanos));
+ }
+
+ int64_t nanos = RawAbsNanos();
+ if (is_absolute_timeout()) {
+ nanos -= absl::GetCurrentTimeNanos();
+ } else {
+ nanos -= SteadyClockNow();
+ }
+
+ struct timespec now;
+ ABSL_RAW_CHECK(clock_gettime(c, &now) == 0, "clock_gettime() failed");
+ absl::Duration from_clock_epoch =
+ absl::DurationFromTimespec(now) + absl::Nanoseconds(nanos);
+ if (from_clock_epoch <= absl::ZeroDuration()) {
+ // Some callers have assumed that 0 means no timeout, so instead we return a
+ // time of 1 nanosecond after the epoch. For safety we also do not return
+ // negative values.
+ return absl::ToTimespec(absl::Nanoseconds(1));
+ }
+ return absl::ToTimespec(from_clock_epoch);
+}
+#endif
+
KernelTimeout::DWord KernelTimeout::InMillisecondsFromNow() const {
constexpr DWord kInfinite = std::numeric_limits<DWord>::max();