src/os/linux/vm/os_linux.cpp

Print this page
rev 6079 : 8037340: Linux semaphores are associated with CLOCK_REALTIME and need relative to absolute time conversion utility
Reviewed-by:

*** 152,161 **** --- 152,162 ---- /* Used to protect dlsym() calls */ static pthread_mutex_t dl_mutex; // Declarations static void unpackTime(timespec* absTime, bool isAbsolute, jlong time); + static void absoluteRealTimeForRelativeTime(timespec* absTime, jlong relTime); #ifdef JAVASE_EMBEDDED class MemNotifyThread: public Thread { friend class VMStructs; public:
*** 2432,2442 **** bool timedwait(unsigned int sec, int nsec); private: sem_t _semaphore; }; - Semaphore::Semaphore() { sem_init(&_semaphore, 0, 0); } Semaphore::~Semaphore() { --- 2433,2442 ----
*** 2455,2465 **** return sem_trywait(&_semaphore) == 0; } bool Semaphore::timedwait(unsigned int sec, int nsec) { struct timespec ts; ! unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec); while (1) { int result = sem_timedwait(&_semaphore, &ts); if (result == 0) { return true; --- 2455,2466 ---- return sem_trywait(&_semaphore) == 0; } bool Semaphore::timedwait(unsigned int sec, int nsec) { struct timespec ts; ! // Semaphore's are always associated with CLOCK_REALTIME ! absoluteRealTimeForRelativeTime(&ts, (sec * NANOSECS_PER_SEC) + nsec); while (1) { int result = sem_timedwait(&_semaphore, &ts); if (result == 0) { return true;
*** 5732,5741 **** --- 5733,5799 ---- 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"); } + /* + * 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(). // Optional fast-path check: