Use Mach built-ins in lieu of clock_gettime(3) and friends.
authorPeter Griess <pgriess@fb.com>
Mon, 23 Sep 2013 21:22:58 +0000 (16:22 -0500)
committerSara Golemon <sgolemon@fb.com>
Thu, 24 Oct 2013 21:53:41 +0000 (14:53 -0700)
Summary:
- Mach doesn't support clock_getres(3) or clock_gettime(3). Provide our
own implementations by wrapping mach_timebase_info() and
mach_absolute_time().
- Detect availability of of -lrt at configure time and don't link with
it if it's not available. On Linux, this is what provides
clock_gettime(3) and friends.

Test Plan:
- fbconfig -r folly && fbmake runtests
- ./configure && make check on Ubuntu/FC/Mac

Reviewed By: meyering@fb.com

FB internal diff: D999131

folly/Benchmark.h
folly/Makefile.am
folly/Portability.h
folly/configure.ac
folly/detail/Clock.cpp [new file with mode: 0644]
folly/detail/Clock.h [new file with mode: 0644]
folly/test/Makefile.am

index 5e155f2851f3b726ecf246411e3e75a232abce71..7d35bcd7c39ff279153631baf704c60ba02379bc 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef FOLLY_BENCHMARK_H_
 #define FOLLY_BENCHMARK_H_
 
+#include "folly/Portability.h"
 #include "folly/Preprocessor.h" // for FB_ANONYMOUS_VARIABLE
 #include <cassert>
 #include <ctime>
@@ -28,7 +29,6 @@
 
 DECLARE_bool(benchmark);
 
-
 namespace folly {
 
 /**
index 195ceb9e15e8678692d8f819a099eeda3aec0032..6b2965cea4f303542d23f200013723753d8f1117 100644 (file)
@@ -112,6 +112,11 @@ libfolly_la_SOURCES = \
        SpookyHashV1.cpp \
        SpookyHashV2.cpp
 
+if !HAVE_LINUX
+nobase_follyinclude_HEADERS += detail/Clock.h
+libfolly_la_SOURCES += detail/Clock.cpp
+endif
+
 FingerprintTables.cpp: generate_fingerprint_tables
        ./generate_fingerprint_tables
 
@@ -120,7 +125,7 @@ libfollyfingerprint_la_SOURCES = \
 libfollyfingerprint_la_LIBADD = libfolly.la
 
 libfollybenchmark_la_SOURCES = Benchmark.cpp
-libfollybenchmark_la_LIBADD = -lrt libfolly.la
+libfollybenchmark_la_LIBADD = libfolly.la
 
 libfollytimeout_queue_la_SOURCES = TimeoutQueue.cpp
 libfollytimeout_queue_la_LIBADD = libfolly.la
index 9b77b5f5e985d0d7079868430e2901ac2465106a..608c1d9b873d4d1aaab712c94d4722c289cf2011 100644 (file)
@@ -129,4 +129,12 @@ struct MaxAlign { char c; } __attribute__((aligned));
 #define FOLLY_NAMESPACE_STD_END       }
 #endif
 
+// Some platforms lack clock_gettime(2) and clock_getres(2). Inject our own
+// versions of these into the global namespace.
+#if FOLLY_HAVE_CLOCK_GETTIME
+#include <time.h>
+#else
+#include "folly/detail/Clock.h"
+#endif
+
 #endif // FOLLY_PORTABILITY_H_
index 6d9fb1e52c91574aa3e11d09b43c4483b4e18909..2dc854aaaa9232debf6317ccbd123cf09b7a68f9 100644 (file)
@@ -79,6 +79,15 @@ AC_COMPILE_IFELSE(
              [Define to "override" if the compiler supports C++11 "override"])]
 )
 
+# Check for clock_gettime(2). This is not in an AC_CHECK_FUNCS() because we
+# want to link with librt if necessary.
+AC_SEARCH_LIBS([clock_gettime], [rt],
+  AC_DEFINE(
+    [HAVE_CLOCK_GETTIME],
+    [1],
+    [Define to 1 if we support clock_gettime(2).]),
+  [])
+
 # Checks for library functions.
 AC_CHECK_FUNCS([getdelim \
                 gettimeofday \
diff --git a/folly/detail/Clock.cpp b/folly/detail/Clock.cpp
new file mode 100644 (file)
index 0000000..d6c4b12
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2013 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/detail/Clock.h"
+
+#if __MACH__
+#include <errno.h>
+#include <mach/mach_time.h>
+
+static mach_timebase_info_data_t tb_info;
+static bool tb_init = mach_timebase_info(&tb_info) == KERN_SUCCESS;
+
+int clock_gettime(clockid_t clk_id, struct timespec* ts) {
+  if (!tb_init) {
+    errno = EINVAL;
+    return -1;
+  }
+
+  uint64_t now_ticks = mach_absolute_time();
+  uint64_t now_ns = (now_ticks * tb_info.numer) / tb_info.denom;
+  ts->tv_sec = now_ns / 1000000000;
+  ts->tv_nsec = now_ns % 1000000000;
+
+  return 0;
+}
+
+int clock_getres(clockid_t clk_id, struct timespec* ts) {
+  if (!tb_init) {
+    errno = EINVAL;
+    return -1;
+  }
+
+  ts->tv_sec = 0;
+  ts->tv_nsec = tb_info.numer / tb_info.denom;
+
+  return 0;
+}
+#else
+#error No clock_gettime(2) compatibility wrapper available for this platform.
+#endif
diff --git a/folly/detail/Clock.h b/folly/detail/Clock.h
new file mode 100644 (file)
index 0000000..8f6e6a4
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2013 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.
+ */
+
+#ifndef FOLLY_DETAIL_CLOCK_H_
+#define FOLLY_DETAIL_CLOCK_H_
+
+#include <ctime>
+#include <cstdint>
+
+#include "folly/folly-config.h"
+
+#if FOLLY_HAVE_CLOCK_GETTIME
+#error This should only be used as a workaround for platforms \
+          that do not support clock_gettime(2).
+#endif
+
+typedef uint8_t clockid_t;
+#define CLOCK_REALTIME 0
+
+int clock_gettime(clockid_t clk_id, struct timespec* ts);
+int clock_getres(clockid_t clk_id, struct timespec* ts);
+
+#endif /* FOLLY_DETAIL_CLOCK_H_ */
index 3680960eaae583cecf8a49c87219e908d0a9b68d..57494e3251497ba0dbb1b1b0137a106c38d0fd91 100644 (file)
@@ -177,11 +177,11 @@ cpuid_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la
 TESTS += cpuid_test
 
 spooky_hash_v1_test_SOURCES = SpookyHashV1Test.cpp
-spooky_hash_v1_test_LDADD = -lrt $(top_builddir)/libfolly.la $(top_builddir)/libfollybenchmark.la
+spooky_hash_v1_test_LDADD = $(top_builddir)/libfolly.la $(top_builddir)/libfollybenchmark.la
 TESTS += spooky_hash_v1_test
 
 spooky_hash_v2_test_SOURCES = SpookyHashV2Test.cpp
-spooky_hash_v2_test_LDADD = -lrt $(top_builddir)/libfolly.la $(top_builddir)/libfollybenchmark.la
+spooky_hash_v2_test_LDADD = $(top_builddir)/libfolly.la $(top_builddir)/libfollybenchmark.la
 TESTS += spooky_hash_v2_test
 
 check_PROGRAMS= $(TESTS)