8211175: Remove temporary clock initialization duplication
authordholmes
Tue, 02 Oct 2018 17:12:13 -0400
changeset 51989 7ac0ac1e57b6
parent 51988 1bf7a2919e06
child 51990 6003e034cdd8
8211175: Remove temporary clock initialization duplication Reviewed-by: rehn, mikael
src/hotspot/os/linux/os_linux.cpp
src/hotspot/os/linux/os_linux.hpp
src/hotspot/os/linux/os_linux.inline.hpp
src/hotspot/os/posix/os_posix.cpp
src/hotspot/os/posix/os_posix.hpp
--- a/src/hotspot/os/linux/os_linux.cpp	Tue Oct 02 12:08:51 2018 -0700
+++ b/src/hotspot/os/linux/os_linux.cpp	Tue Oct 02 17:12:13 2018 -0400
@@ -137,7 +137,6 @@
 address   os::Linux::_initial_thread_stack_bottom = NULL;
 uintptr_t os::Linux::_initial_thread_stack_size   = 0;
 
-int (*os::Linux::_clock_gettime)(clockid_t, struct timespec *) = NULL;
 int (*os::Linux::_pthread_getcpuclockid)(pthread_t, clockid_t *) = NULL;
 int (*os::Linux::_pthread_setname_np)(pthread_t, const char*) = NULL;
 Mutex* os::Linux::_createThread_lock = NULL;
@@ -1173,6 +1172,10 @@
 ////////////////////////////////////////////////////////////////////////////////
 // time support
 
+#ifndef SUPPORTS_CLOCK_MONOTONIC
+#error "Build platform doesn't support clock_gettime and related functionality"
+#endif
+
 // Time since start-up in seconds to a fine granularity.
 // Used by VMSelfDestructTimer and the MemProfiler.
 double os::elapsedTime() {
@@ -1218,62 +1221,6 @@
   nanos = jlong(time.tv_usec) * 1000;
 }
 
-
-#ifndef CLOCK_MONOTONIC
-  #define CLOCK_MONOTONIC (1)
-#endif
-
-void os::Linux::clock_init() {
-  // we do dlopen's in this particular order due to bug in linux
-  // dynamical loader (see 6348968) leading to crash on exit
-  void* handle = dlopen("librt.so.1", RTLD_LAZY);
-  if (handle == NULL) {
-    handle = dlopen("librt.so", RTLD_LAZY);
-  }
-
-  if (handle) {
-    int (*clock_getres_func)(clockid_t, struct timespec*) =
-           (int(*)(clockid_t, struct timespec*))dlsym(handle, "clock_getres");
-    int (*clock_gettime_func)(clockid_t, struct timespec*) =
-           (int(*)(clockid_t, struct timespec*))dlsym(handle, "clock_gettime");
-    if (clock_getres_func && clock_gettime_func) {
-      // See if monotonic clock is supported by the kernel. Note that some
-      // early implementations simply return kernel jiffies (updated every
-      // 1/100 or 1/1000 second). It would be bad to use such a low res clock
-      // for nano time (though the monotonic property is still nice to have).
-      // It's fixed in newer kernels, however clock_getres() still returns
-      // 1/HZ. We check if clock_getres() works, but will ignore its reported
-      // resolution for now. Hopefully as people move to new kernels, this
-      // won't be a problem.
-      struct timespec res;
-      struct timespec tp;
-      if (clock_getres_func (CLOCK_MONOTONIC, &res) == 0 &&
-          clock_gettime_func(CLOCK_MONOTONIC, &tp)  == 0) {
-        // yes, monotonic clock is supported
-        _clock_gettime = clock_gettime_func;
-        return;
-      } else {
-        // close librt if there is no monotonic clock
-        dlclose(handle);
-      }
-    }
-  }
-  warning("No monotonic clock was available - timed services may " \
-          "be adversely affected if the time-of-day clock changes");
-}
-
-#ifndef SYS_clock_getres
-  #if defined(X86) || defined(PPC64) || defined(S390)
-    #define SYS_clock_getres AMD64_ONLY(229) IA32_ONLY(266) PPC64_ONLY(247) S390_ONLY(261)
-    #define sys_clock_getres(x,y)  ::syscall(SYS_clock_getres, x, y)
-  #else
-    #warning "SYS_clock_getres not defined for this platform, disabling fast_thread_cpu_time"
-    #define sys_clock_getres(x,y)  -1
-  #endif
-#else
-  #define sys_clock_getres(x,y)  ::syscall(SYS_clock_getres, x, y)
-#endif
-
 void os::Linux::fast_thread_clock_init() {
   if (!UseLinuxPosixThreadCPUClocks) {
     return;
@@ -1284,17 +1231,17 @@
       (int(*)(pthread_t, clockid_t *)) dlsym(RTLD_DEFAULT, "pthread_getcpuclockid");
 
   // Switch to using fast clocks for thread cpu time if
-  // the sys_clock_getres() returns 0 error code.
+  // the clock_getres() returns 0 error code.
   // Note, that some kernels may support the current thread
   // clock (CLOCK_THREAD_CPUTIME_ID) but not the clocks
   // returned by the pthread_getcpuclockid().
-  // If the fast Posix clocks are supported then the sys_clock_getres()
+  // If the fast Posix clocks are supported then the clock_getres()
   // must return at least tp.tv_sec == 0 which means a resolution
   // better than 1 sec. This is extra check for reliability.
 
   if (pthread_getcpuclockid_func &&
       pthread_getcpuclockid_func(_main_thread, &clockid) == 0 &&
-      sys_clock_getres(clockid, &tp) == 0 && tp.tv_sec == 0) {
+      os::Posix::clock_getres(clockid, &tp) == 0 && tp.tv_sec == 0) {
     _supports_fast_thread_cpu_time = true;
     _pthread_getcpuclockid = pthread_getcpuclockid_func;
   }
@@ -1303,7 +1250,7 @@
 jlong os::javaTimeNanos() {
   if (os::supports_monotonic_clock()) {
     struct timespec tp;
-    int status = Linux::clock_gettime(CLOCK_MONOTONIC, &tp);
+    int status = os::Posix::clock_gettime(CLOCK_MONOTONIC, &tp);
     assert(status == 0, "gettime error");
     jlong result = jlong(tp.tv_sec) * (1000 * 1000 * 1000) + jlong(tp.tv_nsec);
     return result;
@@ -2482,7 +2429,7 @@
 static struct timespec create_semaphore_timespec(unsigned int sec, int nsec) {
   struct timespec ts;
   // Semaphore's are always associated with CLOCK_REALTIME
-  os::Linux::clock_gettime(CLOCK_REALTIME, &ts);
+  os::Posix::clock_gettime(CLOCK_REALTIME, &ts);
   // see os_posix.cpp for discussion on overflow checking
   if (sec >= MAX_SECS) {
     ts.tv_sec += MAX_SECS;
@@ -4715,7 +4662,7 @@
 
 jlong os::Linux::fast_thread_cpu_time(clockid_t clockid) {
   struct timespec tp;
-  int rc = os::Linux::clock_gettime(clockid, &tp);
+  int rc = os::Posix::clock_gettime(clockid, &tp);
   assert(rc == 0, "clock_gettime is expected to return 0 code");
 
   return (tp.tv_sec * NANOSECS_PER_SEC) + tp.tv_nsec;
@@ -4987,14 +4934,19 @@
   // _main_thread points to the thread that created/loaded the JVM.
   Linux::_main_thread = pthread_self();
 
-  Linux::clock_init();
-  initial_time_count = javaTimeNanos();
-
   // retrieve entry point for pthread_setname_np
   Linux::_pthread_setname_np =
     (int(*)(pthread_t, const char*))dlsym(RTLD_DEFAULT, "pthread_setname_np");
 
   os::Posix::init();
+
+  initial_time_count = javaTimeNanos();
+
+  // Always warn if no monotonic clock available
+  if (!os::Posix::supports_monotonic_clock()) {
+    warning("No monotonic clock was available - timed services may "    \
+            "be adversely affected if the time-of-day clock changes");
+  }
 }
 
 // To install functions for atexit system call
--- a/src/hotspot/os/linux/os_linux.hpp	Tue Oct 02 12:08:51 2018 -0700
+++ b/src/hotspot/os/linux/os_linux.hpp	Tue Oct 02 17:12:13 2018 -0400
@@ -43,7 +43,6 @@
 
   static void check_signal_handler(int sig);
 
-  static int (*_clock_gettime)(clockid_t, struct timespec *);
   static int (*_pthread_getcpuclockid)(pthread_t, clockid_t *);
   static int (*_pthread_setname_np)(pthread_t, const char*);
 
@@ -190,16 +189,9 @@
   static bool manually_expand_stack(JavaThread * t, address addr);
   static int max_register_window_saves_before_flushing();
 
-  // Real-time clock functions
-  static void clock_init(void);
-
   // fast POSIX clocks support
   static void fast_thread_clock_init(void);
 
-  static int clock_gettime(clockid_t clock_id, struct timespec *tp) {
-    return _clock_gettime ? _clock_gettime(clock_id, tp) : -1;
-  }
-
   static int pthread_getcpuclockid(pthread_t tid, clockid_t *clock_id) {
     return _pthread_getcpuclockid ? _pthread_getcpuclockid(tid, clock_id) : -1;
   }
--- a/src/hotspot/os/linux/os_linux.inline.hpp	Tue Oct 02 12:08:51 2018 -0700
+++ b/src/hotspot/os/linux/os_linux.inline.hpp	Tue Oct 02 17:12:13 2018 -0400
@@ -141,7 +141,7 @@
 }
 
 inline bool os::supports_monotonic_clock() {
-  return Linux::_clock_gettime != NULL;
+  return os::Posix::supports_monotonic_clock();
 }
 
 inline void os::exit(int num) {
--- a/src/hotspot/os/posix/os_posix.cpp	Tue Oct 02 12:08:51 2018 -0700
+++ b/src/hotspot/os/posix/os_posix.cpp	Tue Oct 02 17:12:13 2018 -0400
@@ -1609,10 +1609,25 @@
 // This means we have clockid_t, clock_gettime et al and CLOCK_MONOTONIC
 
 static int (*_clock_gettime)(clockid_t, struct timespec *);
+static int (*_clock_getres)(clockid_t, struct timespec *);
 static int (*_pthread_condattr_setclock)(pthread_condattr_t *, clockid_t);
 
 static bool _use_clock_monotonic_condattr;
 
+// Exported clock functionality
+
+int os::Posix::clock_gettime(clockid_t clock_id, struct timespec *tp) {
+  return _clock_gettime != NULL ? _clock_gettime(clock_id, tp) : -1;
+}
+
+int os::Posix::clock_getres(clockid_t clock_id, struct timespec *tp) {
+  return _clock_getres != NULL ? _clock_getres(clock_id, tp) : -1;
+}
+
+bool os::Posix::supports_monotonic_clock() {
+  return _clock_gettime != NULL;
+}
+
 // Determine what POSIX API's are present and do appropriate
 // configuration.
 void os::Posix::init(void) {
@@ -1620,8 +1635,6 @@
   // NOTE: no logging available when this is called. Put logging
   // statements in init_2().
 
-  // Copied from os::Linux::clock_init(). The duplication is temporary.
-
   // 1. Check for CLOCK_MONOTONIC support.
 
   void* handle = NULL;
@@ -1642,6 +1655,7 @@
   }
 
   _clock_gettime = NULL;
+  _clock_getres = NULL;
 
   int (*clock_getres_func)(clockid_t, struct timespec*) =
     (int(*)(clockid_t, struct timespec*))dlsym(handle, "clock_getres");
@@ -1656,6 +1670,7 @@
         clock_gettime_func(CLOCK_MONOTONIC, &tp) == 0) {
       // Yes, monotonic clock is supported.
       _clock_gettime = clock_gettime_func;
+      _clock_getres = clock_getres_func;
     } else {
 #ifdef NEEDS_LIBRT
       // Close librt if there is no monotonic clock.
--- a/src/hotspot/os/posix/os_posix.hpp	Tue Oct 02 12:08:51 2018 -0700
+++ b/src/hotspot/os/posix/os_posix.hpp	Tue Oct 02 17:12:13 2018 -0400
@@ -116,6 +116,18 @@
   // Returns true if either given uid is effective uid and given gid is
   // effective gid, or if given uid is root.
   static bool matches_effective_uid_and_gid_or_root(uid_t uid, gid_t gid);
+
+#ifdef SUPPORTS_CLOCK_MONOTONIC
+
+  static bool supports_monotonic_clock();
+  static int clock_gettime(clockid_t clock_id, struct timespec *tp);
+  static int clock_getres(clockid_t clock_id, struct timespec *tp);
+
+#else
+
+  static bool supports_monotonic_clock() { return false; }
+
+#endif
 };
 
 // On POSIX platforms the signal handler is global so we just do the write.