--- /dev/null
+/*
+ * Copyright 2016 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <folly/ClockGettimeWrappers.h>
+#include <folly/Likely.h>
+#include <folly/portability/Time.h>
+
+#include <chrono>
+
+#include <time.h>
+
+#ifndef _WIN32
+#define _GNU_SOURCE 1
+#include <dlfcn.h>
+#endif
+
+namespace folly {
+namespace chrono {
+
+static int64_t clock_gettime_ns_fallback(clockid_t clock) {
+ struct timespec ts;
+ int r = clock_gettime(clock, &ts);
+ if (UNLIKELY(r != 0)) {
+ // Mimic what __clock_gettime_ns does (even though this can be a legit
+ // value).
+ return -1;
+ }
+ std::chrono::nanoseconds result =
+ std::chrono::seconds(ts.tv_sec) + std::chrono::nanoseconds(ts.tv_nsec);
+ return result.count();
+}
+
+// Initialize with default behavior, which we might override on Linux hosts
+// with VDSO support.
+int (*clock_gettime)(clockid_t, timespec* ts) = &::clock_gettime;
+int64_t (*clock_gettime_ns)(clockid_t) = &clock_gettime_ns_fallback;
+
+#ifdef __linux__
+
+namespace {
+
+struct VdsoInitializer {
+ VdsoInitializer() {
+ m_handle = dlopen("linux-vdso.so.1", RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
+ if (!m_handle) {
+ return;
+ }
+
+ void* p = dlsym(m_handle, "__vdso_clock_gettime");
+ if (p) {
+ folly::chrono::clock_gettime = (int (*)(clockid_t, timespec*))p;
+ }
+ p = dlsym(m_handle, "__vdso_clock_gettime_ns");
+ if (p) {
+ folly::chrono::clock_gettime_ns = (int64_t(*)(clockid_t))p;
+ }
+ }
+
+ ~VdsoInitializer() {
+ if (m_handle) {
+ clock_gettime = &::clock_gettime;
+ clock_gettime_ns = &clock_gettime_ns_fallback;
+ dlclose(m_handle);
+ }
+ }
+
+ private:
+ void* m_handle;
+};
+
+static const VdsoInitializer vdso_initializer;
+}
+
+#endif
+}
+}
--- /dev/null
+/*
+ * Copyright 2016 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <folly/portability/Time.h>
+
+#include <time.h>
+
+namespace folly {
+namespace chrono {
+
+extern int (*clock_gettime)(clockid_t, timespec* ts);
+extern int64_t (*clock_gettime_ns)(clockid_t);
+}
+}
Bits.h \
CallOnce.h \
Checksum.h \
+ ClockGettimeWrappers.h \
ConcurrentSkipList.h \
ConcurrentSkipList-inl.h \
ConditionallyExistent.h \
libfolly_la_SOURCES = \
Bits.cpp \
Checksum.cpp \
+ ClockGettimeWrappers.cpp \
detail/CacheLocality.cpp \
detail/IPAddress.cpp \
dynamic.cpp \
--- /dev/null
+/*
+ * Copyright 2016 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <folly/ClockGettimeWrappers.h>
+
+#include <folly/test/TestUtils.h>
+
+#include <chrono>
+
+#include <gtest/gtest.h>
+
+static constexpr auto kAcceptableDeltaSecs = std::chrono::seconds(120);
+
+using folly::test::AreWithinSecs;
+
+#ifdef CLOCK_REALTIME
+
+TEST(ClockGettimeWrappers, clockGettimeWrapperIsWithin120SecsOfSystemClock) {
+ struct timespec ts;
+ auto ret = folly::chrono::clock_gettime(CLOCK_REALTIME, &ts);
+ ASSERT_EQ(0, ret);
+
+ auto gettimeResult =
+ std::chrono::seconds(ts.tv_sec) + std::chrono::nanoseconds(ts.tv_nsec);
+ auto stdChronoSystemClockNow =
+ std::chrono::system_clock::now().time_since_epoch();
+ ASSERT_TRUE(AreWithinSecs(
+ gettimeResult, stdChronoSystemClockNow, kAcceptableDeltaSecs));
+}
+
+TEST(ClockGettimeWrappers, clockGettimeNsWrapperIsWithin120SecsOfSystemClock) {
+ auto now_ns = folly::chrono::clock_gettime_ns(CLOCK_REALTIME);
+ auto stdChronoSystemClockNow =
+ std::chrono::system_clock::now().time_since_epoch();
+ ASSERT_TRUE(AreWithinSecs(
+ std::chrono::nanoseconds(now_ns),
+ stdChronoSystemClockNow,
+ kAcceptableDeltaSecs));
+}
+
+#endif /* CLOCK_REALTIME */
indestructible_test_LDADD = libfollytestmain.la
TESTS += indestructible_test
+portability_clock_gettime_wrappers_test_SOURCES = ClockGettimeWrappersTest.cpp
+portability_clock_gettime_wrappers_test_LDADD = libfollytestmain.la
+TESTS += portability_clock_gettime_wrappers_test
+
portability_time_test_SOURCES = ../portability/test/TimeTest.cpp
portability_time_test_LDADD = libfollytestmain.la
TESTS += portability_time_test