# HG changeset patch # User mgronlun # Date 1394787870 -3600 # Node ID b35969abf3934381c70332703ecac2daa4ffc6c9 # Parent 9b06054cb7b908451b0314ac866df7fcc72ad2e1 8037340: Linux semaphores are associated with CLOCK_REALTIME and need relative to absolute time conversion utility Reviewed-by: diff --git a/src/os/linux/vm/os_linux.cpp b/src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp +++ b/src/os/linux/vm/os_linux.cpp @@ -154,6 +154,7 @@ // Declarations static void unpackTime(timespec* absTime, bool isAbsolute, jlong time); +static void absoluteRealTimeForRelativeTime(timespec* absTime, jlong relTime); #ifdef JAVASE_EMBEDDED class MemNotifyThread: public Thread { @@ -2434,7 +2435,6 @@ sem_t _semaphore; }; - Semaphore::Semaphore() { sem_init(&_semaphore, 0, 0); } @@ -2457,7 +2457,8 @@ bool Semaphore::timedwait(unsigned int sec, int nsec) { struct timespec ts; - unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec); + // Semaphore's are always associated with CLOCK_REALTIME + absoluteRealTimeForRelativeTime(&ts, (sec * NANOSECS_PER_SEC) + nsec); while (1) { int result = sem_timedwait(&_semaphore, &ts); @@ -5734,6 +5735,63 @@ assert(absTime->tv_nsec < NANOSECS_PER_SEC, "tv_nsec >= nanos_per_sec"); } +/* +* Certain structures, for example Semaphores, are always associated +* with CLOCK_REALTIME derived absolute time representations. +* This helper will yield an absolute realtime representation for the passed +* in relative time. We should be able to use clock_gettime for most +* supported Linux's, but if that is not possible we will fallback to use +* gettimeofday. +* +* utility to compute the abstime argument using CLOCK_REALTIME where possible. +* +* relTime is the relative time in nanoseconds. +* absTime will be the absolute time in seconds and nanoseconds. +*/ +static void absoluteRealTimeForRelativeTime(timespec* absTime, jlong relTime) { + assert(absTime != NULL, "invariant"); + assert(relTime > 0, "invariant"); + + time_t max_secs = 0; + jlong secs = relTime / NANOSECS_PER_SEC; + + if (os::supports_monotonic_clock()) { // check avail of clock_gettime + struct timespec now; + int status = os::Linux::clock_gettime(CLOCK_REALTIME, &now); + assert_status(status == 0, status, "clock_gettime"); + max_secs = now.tv_sec + MAX_SECS; + if (secs >= MAX_SECS) { + absTime->tv_sec = max_secs; + absTime->tv_nsec = 0; + } else { + absTime->tv_sec = now.tv_sec + secs; + absTime->tv_nsec = (relTime % NANOSECS_PER_SEC) + now.tv_nsec; + } + } else { + struct timeval now; + int status = gettimeofday(&now, NULL); + assert(status == 0, "gettimeofday"); + max_secs = now.tv_sec + MAX_SECS; + if (secs >= MAX_SECS) { + absTime->tv_sec = max_secs; + absTime->tv_nsec = 0; + } else { + absTime->tv_sec = now.tv_sec + secs; + absTime->tv_nsec = (relTime % NANOSECS_PER_SEC) + now.tv_usec*1000; + } + } + + if (absTime->tv_nsec >= NANOSECS_PER_SEC) { + absTime->tv_nsec -= NANOSECS_PER_SEC; + ++absTime->tv_sec; // note: this must be <= max_secs + } + + assert(absTime->tv_sec >= 0, "tv_sec < 0"); + assert(absTime->tv_sec <= max_secs, "tv_sec > max_secs"); + assert(absTime->tv_nsec >= 0, "tv_nsec < 0"); + assert(absTime->tv_nsec < NANOSECS_PER_SEC, "tv_nsec >= nanos_per_sec"); +} + void Parker::park(bool isAbsolute, jlong time) { // Ideally we'd do something useful while spinning, such // as calling unpackTime().