src/hotspot/os/posix/os_posix.cpp
changeset 53461 08d6edeb3145
parent 53266 57d8566a2732
child 53646 043ae846819f
--- a/src/hotspot/os/posix/os_posix.cpp	Wed Jan 23 14:10:31 2019 -0800
+++ b/src/hotspot/os/posix/os_posix.cpp	Wed Jan 23 21:17:51 2019 -0500
@@ -1619,11 +1619,9 @@
   }
 }
 
-
-// Shared pthread_mutex/cond based PlatformEvent implementation.
-// Not currently usable by Solaris.
-
-#ifndef SOLARIS
+// Shared clock/time and other supporting routines for pthread_mutex/cond
+// initialization. This is enabled on Solaris but only some of the clock/time
+// functionality is actually used there.
 
 // Shared condattr object for use with relative timed-waits. Will be associated
 // with CLOCK_MONOTONIC if available to avoid issues with time-of-day changes,
@@ -1661,11 +1659,11 @@
 
 // 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 int (*_clock_gettime)(clockid_t, struct timespec *) = NULL;
+static int (*_clock_getres)(clockid_t, struct timespec *) = NULL;
+static int (*_pthread_condattr_setclock)(pthread_condattr_t *, clockid_t) = NULL;
 
-static bool _use_clock_monotonic_condattr;
+static bool _use_clock_monotonic_condattr = false;
 
 // Exported clock functionality
 
@@ -1707,9 +1705,6 @@
     handle = RTLD_DEFAULT;
   }
 
-  _clock_gettime = NULL;
-  _clock_getres = NULL;
-
   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*) =
@@ -1736,8 +1731,6 @@
 
   // 2. Check for pthread_condattr_setclock support.
 
-  _pthread_condattr_setclock = NULL;
-
   // libpthread is already loaded.
   int (*condattr_setclock_func)(pthread_condattr_t*, clockid_t) =
     (int (*)(pthread_condattr_t*, clockid_t))dlsym(RTLD_DEFAULT,
@@ -1750,6 +1743,7 @@
 
   pthread_init_common();
 
+#ifndef SOLARIS
   int status;
   if (_pthread_condattr_setclock != NULL && _clock_gettime != NULL) {
     if ((status = _pthread_condattr_setclock(_condAttr, CLOCK_MONOTONIC)) != 0) {
@@ -1763,18 +1757,20 @@
     } else {
       _use_clock_monotonic_condattr = true;
     }
-  } else {
-    _use_clock_monotonic_condattr = false;
   }
+#endif // !SOLARIS
+
 }
 
 void os::Posix::init_2(void) {
+#ifndef SOLARIS
   log_info(os)("Use of CLOCK_MONOTONIC is%s supported",
                (_clock_gettime != NULL ? "" : " not"));
   log_info(os)("Use of pthread_condattr_setclock is%s supported",
                (_pthread_condattr_setclock != NULL ? "" : " not"));
   log_info(os)("Relative timed-wait using pthread_cond_timedwait is associated with %s",
                _use_clock_monotonic_condattr ? "CLOCK_MONOTONIC" : "the default clock");
+#endif // !SOLARIS
 }
 
 #else // !SUPPORTS_CLOCK_MONOTONIC
@@ -1784,30 +1780,25 @@
 }
 
 void os::Posix::init_2(void) {
+#ifndef SOLARIS
   log_info(os)("Use of CLOCK_MONOTONIC is not supported");
   log_info(os)("Use of pthread_condattr_setclock is not supported");
   log_info(os)("Relative timed-wait using pthread_cond_timedwait is associated with the default clock");
+#endif // !SOLARIS
 }
 
 #endif // SUPPORTS_CLOCK_MONOTONIC
 
-os::PlatformEvent::PlatformEvent() {
-  int status = pthread_cond_init(_cond, _condAttr);
-  assert_status(status == 0, status, "cond_init");
-  status = pthread_mutex_init(_mutex, _mutexAttr);
-  assert_status(status == 0, status, "mutex_init");
-  _event   = 0;
-  _nParked = 0;
-}
-
 // Utility to convert the given timeout to an absolute timespec
-// (based on the appropriate clock) to use with pthread_cond_timewait.
+// (based on the appropriate clock) to use with pthread_cond_timewait,
+// and sem_timedwait().
 // The clock queried here must be the clock used to manage the
-// timeout of the condition variable.
+// timeout of the condition variable or semaphore.
 //
 // The passed in timeout value is either a relative time in nanoseconds
 // or an absolute time in milliseconds. A relative timeout will be
-// associated with CLOCK_MONOTONIC if available; otherwise, or if absolute,
+// associated with CLOCK_MONOTONIC if available, unless the real-time clock
+// is explicitly requested; otherwise, or if absolute,
 // the default time-of-day clock will be used.
 
 // Given time is a 64-bit value and the time_t used in the timespec is
@@ -1824,7 +1815,7 @@
 
 // Calculate a new absolute time that is "timeout" nanoseconds from "now".
 // "unit" indicates the unit of "now_part_sec" (may be nanos or micros depending
-// on which clock is being used).
+// on which clock API is being used).
 static void calc_rel_time(timespec* abstime, jlong timeout, jlong now_sec,
                           jlong now_part_sec, jlong unit) {
   time_t max_secs = now_sec + MAX_SECS;
@@ -1849,6 +1840,7 @@
 
 // Unpack the given deadline in milliseconds since the epoch, into the given timespec.
 // The current time in seconds is also passed in to enforce an upper bound as discussed above.
+// This is only used with gettimeofday, when clock_gettime is not available.
 static void unpack_abs_time(timespec* abstime, jlong deadline, jlong now_sec) {
   time_t max_secs = now_sec + MAX_SECS;
 
@@ -1865,7 +1857,18 @@
   }
 }
 
-static void to_abstime(timespec* abstime, jlong timeout, bool isAbsolute) {
+static jlong millis_to_nanos(jlong millis) {
+  // We have to watch for overflow when converting millis to nanos,
+  // but if millis is that large then we will end up limiting to
+  // MAX_SECS anyway, so just do that here.
+  if (millis / MILLIUNITS > MAX_SECS) {
+    millis = jlong(MAX_SECS) * MILLIUNITS;
+  }
+  return millis * (NANOUNITS / MILLIUNITS);
+}
+
+static void to_abstime(timespec* abstime, jlong timeout,
+                       bool isAbsolute, bool isRealtime) {
   DEBUG_ONLY(int max_secs = MAX_SECS;)
 
   if (timeout < 0) {
@@ -1874,9 +1877,14 @@
 
 #ifdef SUPPORTS_CLOCK_MONOTONIC
 
-  if (_use_clock_monotonic_condattr && !isAbsolute) {
+  clockid_t clock = CLOCK_MONOTONIC;
+  // need to ensure we have a runtime check for clock_gettime support
+  if (!isAbsolute && _clock_gettime != NULL) {
+    if (!_use_clock_monotonic_condattr || isRealtime) {
+      clock = CLOCK_REALTIME;
+    }
     struct timespec now;
-    int status = _clock_gettime(CLOCK_MONOTONIC, &now);
+    int status = _clock_gettime(clock, &now);
     assert_status(status == 0, status, "clock_gettime");
     calc_rel_time(abstime, timeout, now.tv_sec, now.tv_nsec, NANOUNITS);
     DEBUG_ONLY(max_secs += now.tv_sec;)
@@ -1906,6 +1914,19 @@
   assert(abstime->tv_nsec < NANOUNITS, "tv_nsec >= NANOUNITS");
 }
 
+// Create an absolute time 'millis' milliseconds in the future, using the
+// real-time (time-of-day) clock. Used by PosixSemaphore.
+void os::Posix::to_RTC_abstime(timespec* abstime, int64_t millis) {
+  to_abstime(abstime, millis_to_nanos(millis),
+             false /* not absolute */,
+             true  /* use real-time clock */);
+}
+
+// Shared pthread_mutex/cond based PlatformEvent implementation.
+// Not currently usable by Solaris.
+
+#ifndef SOLARIS
+
 // PlatformEvent
 //
 // Assumption:
@@ -1921,6 +1942,15 @@
 //    Having three states allows for some detection of bad usage - see
 //    comments on unpark().
 
+os::PlatformEvent::PlatformEvent() {
+  int status = pthread_cond_init(_cond, _condAttr);
+  assert_status(status == 0, status, "cond_init");
+  status = pthread_mutex_init(_mutex, _mutexAttr);
+  assert_status(status == 0, status, "mutex_init");
+  _event   = 0;
+  _nParked = 0;
+}
+
 void os::PlatformEvent::park() {       // AKA "down()"
   // Transitions for _event:
   //   -1 => -1 : illegal
@@ -1982,13 +2012,7 @@
 
   if (v == 0) { // Do this the hard way by blocking ...
     struct timespec abst;
-    // We have to watch for overflow when converting millis to nanos,
-    // but if millis is that large then we will end up limiting to
-    // MAX_SECS anyway, so just do that here.
-    if (millis / MILLIUNITS > MAX_SECS) {
-      millis = jlong(MAX_SECS) * MILLIUNITS;
-    }
-    to_abstime(&abst, millis * (NANOUNITS / MILLIUNITS), false);
+    to_abstime(&abst, millis_to_nanos(millis), false, false);
 
     int ret = OS_TIMEOUT;
     int status = pthread_mutex_lock(_mutex);
@@ -2106,7 +2130,7 @@
     return;
   }
   if (time > 0) {
-    to_abstime(&absTime, time, isAbsolute);
+    to_abstime(&absTime, time, isAbsolute, false);
   }
 
   // Enter safepoint region