ClockGettimeWrappers.cpp 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. /*
  2. * Copyright 2016-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <folly/ClockGettimeWrappers.h>
  17. #include <folly/Likely.h>
  18. #include <folly/portability/Time.h>
  19. #include <chrono>
  20. #include <time.h>
  21. #ifndef _WIN32
  22. #define _GNU_SOURCE 1
  23. #include <dlfcn.h>
  24. #endif
  25. namespace folly {
  26. namespace chrono {
  27. static int64_t clock_gettime_ns_fallback(clockid_t clock) {
  28. struct timespec ts;
  29. int r = clock_gettime(clock, &ts);
  30. if (UNLIKELY(r != 0)) {
  31. // Mimic what __clock_gettime_ns does (even though this can be a legit
  32. // value).
  33. return -1;
  34. }
  35. std::chrono::nanoseconds result =
  36. std::chrono::seconds(ts.tv_sec) + std::chrono::nanoseconds(ts.tv_nsec);
  37. return result.count();
  38. }
  39. // Initialize with default behavior, which we might override on Linux hosts
  40. // with VDSO support.
  41. int (*clock_gettime)(clockid_t, timespec* ts) = &::clock_gettime;
  42. int64_t (*clock_gettime_ns)(clockid_t) = &clock_gettime_ns_fallback;
  43. #ifdef FOLLY_HAVE_LINUX_VDSO
  44. namespace {
  45. struct VdsoInitializer {
  46. VdsoInitializer() {
  47. m_handle = dlopen("linux-vdso.so.1", RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
  48. if (!m_handle) {
  49. return;
  50. }
  51. void* p = dlsym(m_handle, "__vdso_clock_gettime");
  52. if (p) {
  53. folly::chrono::clock_gettime = (int (*)(clockid_t, timespec*))p;
  54. }
  55. p = dlsym(m_handle, "__vdso_clock_gettime_ns");
  56. if (p) {
  57. folly::chrono::clock_gettime_ns = (int64_t(*)(clockid_t))p;
  58. }
  59. }
  60. ~VdsoInitializer() {
  61. if (m_handle) {
  62. clock_gettime = &::clock_gettime;
  63. clock_gettime_ns = &clock_gettime_ns_fallback;
  64. dlclose(m_handle);
  65. }
  66. }
  67. private:
  68. void* m_handle;
  69. };
  70. static const VdsoInitializer vdso_initializer;
  71. } // namespace
  72. #endif
  73. } // namespace chrono
  74. } // namespace folly