src/os/linux/vm/os_linux.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File
*** old/src/os/linux/vm/os_linux.cpp	Wed Sep 11 19:08:42 2013
--- new/src/os/linux/vm/os_linux.cpp	Wed Sep 11 19:08:41 2013

*** 129,138 **** --- 129,139 ---- bool os::Linux::_is_floating_stack = false; bool os::Linux::_is_NPTL = false; bool os::Linux::_supports_fast_thread_cpu_time = false; const char * os::Linux::_glibc_version = NULL; const char * os::Linux::_libpthread_version = NULL; + pthread_condattr_t os::Linux::_condattr[1]; static jlong initial_time_count=0; static int clock_tics_per_sec = 100;
*** 1397,1412 **** --- 1398,1416 ---- 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(IA32) || defined(AMD64)
*** 4692,4701 **** --- 4696,4725 ---- // main_thread points to the aboriginal thread Linux::_main_thread = pthread_self(); Linux::clock_init(); initial_time_count = os::elapsed_counter(); + + // pthread_condattr initialization for monotonic clock + int status; + pthread_condattr_t* _condattr = os::Linux::condAttr(); + if ((status = pthread_condattr_init(_condattr)) != 0) { + fatal(err_msg("pthread_condattr_init: %s", strerror(status))); + } + // Only set the clock if CLOCK_MONOTONIC is available + if (Linux::supports_monotonic_clock()) { + if ((status = pthread_condattr_setclock(_condattr, CLOCK_MONOTONIC)) != 0) { + if (status == EINVAL) { + warning("Unable to use monotonic clock with relative timed-waits" \ + " - changes to the time-of-day clock may have adverse affects"); + } else { + fatal(err_msg("pthread_condattr_setclock: %s", strerror(status))); + } + } + } + // else it defaults to CLOCK_REALTIME + pthread_mutex_init(&dl_mutex, NULL); // If the pagesize of the VM is greater than 8K determine the appropriate // number of initial guard pages. The user can change this with the // command line arguments, if needed.
*** 5502,5526 **** --- 5526,5565 ---- // abstime will be the absolute timeout time // TODO: replace compute_abstime() with unpackTime() static struct timespec* compute_abstime(timespec* abstime, jlong millis) { if (millis < 0) millis = 0; struct timeval now; int status = gettimeofday(&now, NULL); assert(status == 0, "gettimeofday"); + jlong seconds = millis / 1000; millis %= 1000; if (seconds > 50000000) { // see man cond_timedwait(3T) seconds = 50000000; } + + if (os::Linux::supports_monotonic_clock()) { + struct timespec now; + int status = os::Linux::clock_gettime(CLOCK_MONOTONIC, &now); + assert_status(status == 0, status, "clock_gettime"); + abstime->tv_sec = now.tv_sec + seconds; + long nanos = now.tv_nsec + millis * NANOSECS_PER_MILLISEC; + if (nanos >= NANOSECS_PER_SEC) { + abstime->tv_sec += 1; + nanos -= NANOSECS_PER_SEC; + } + abstime->tv_nsec = nanos; + } else { + struct timeval now; + int status = gettimeofday(&now, NULL); + assert(status == 0, "gettimeofday"); abstime->tv_sec = now.tv_sec + seconds; long usec = now.tv_usec + millis * 1000; if (usec >= 1000000) { abstime->tv_sec += 1; usec -= 1000000; } abstime->tv_nsec = usec * 1000; + } return abstime; } // Test-and-clear _Event, always leaves _Event set to 0, returns immediately.
*** 5608,5618 **** --- 5647,5657 ---- while (_Event < 0) { status = os::Linux::safe_cond_timedwait(_cond, _mutex, &abst); if (status != 0 && WorkAroundNPTLTimedWaitHang) { pthread_cond_destroy (_cond); ! pthread_cond_init (_cond, NULL) ; ! pthread_cond_init (_cond, os::Linux::condAttr()) ; } assert_status(status == 0 || status == EINTR || status == ETIME || status == ETIMEDOUT, status, "cond_timedwait"); if (!FilterSpuriousWakeups) break ; // previous semantics
*** 5709,5750 **** --- 5748,5807 ---- * years from "now". */ static void unpackTime(timespec* absTime, bool isAbsolute, jlong time) { assert (time > 0, "convertTime"); + time_t max_secs = 0; + if (!os::Linux::supports_monotonic_clock() || isAbsolute) { struct timeval now; int status = gettimeofday(&now, NULL); assert(status == 0, "gettimeofday"); ! time_t max_secs = now.tv_sec + MAX_SECS; ! max_secs = now.tv_sec + MAX_SECS; if (isAbsolute) { jlong secs = time / 1000; if (secs > max_secs) { absTime->tv_sec = max_secs; ! } else { else { absTime->tv_sec = secs; } absTime->tv_nsec = (time % 1000) * NANOSECS_PER_MILLISEC; ! } else { else { jlong secs = time / NANOSECS_PER_SEC; if (secs >= MAX_SECS) { absTime->tv_sec = max_secs; absTime->tv_nsec = 0; ! } else { else { absTime->tv_sec = now.tv_sec + secs; absTime->tv_nsec = (time % 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 } } } + } else { + // must be relative using monotonic clock + struct timespec now; + int status = os::Linux::clock_gettime(CLOCK_MONOTONIC, &now); + assert_status(status == 0, status, "clock_gettime"); + max_secs = now.tv_sec + MAX_SECS; + jlong secs = time / NANOSECS_PER_SEC; + if (secs >= MAX_SECS) { + absTime->tv_sec = max_secs; + absTime->tv_nsec = 0; + } else { + absTime->tv_sec = now.tv_sec + secs; + absTime->tv_nsec = (time % NANOSECS_PER_SEC) + now.tv_nsec; + 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"); }
*** 5817,5831 **** --- 5874,5891 ---- // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self() if (time == 0) { status = pthread_cond_wait (_cond, _mutex) ; } else { ! status = os::Linux::safe_cond_timedwait (_cond, _mutex, &absTime) ; ! assert(_cur_index == -1, "invariant"); + _cur_index = isAbsolute ? ABS_INDEX : REL_INDEX; + status = os::Linux::safe_cond_timedwait (&_cond[_cur_index], _mutex, &absTime) ; if (status != 0 && WorkAroundNPTLTimedWaitHang) { ! pthread_cond_destroy (&_cond[_cur_index]) ; ! pthread_cond_init (_cond, NULL); ! pthread_cond_init (&_cond[_cur_index], isAbsolute ? NULL : os::Linux::condAttr()); } + _cur_index = -1; } assert_status(status == 0 || status == EINTR || status == ETIME || status == ETIMEDOUT, status, "cond_timedwait");
*** 5851,5870 **** --- 5911,5931 ---- status = pthread_mutex_lock(_mutex); assert (status == 0, "invariant") ; s = _counter; _counter = 1; if (s < 1) { + assert(_cur_index != -1, "invariant"); if (WorkAroundNPTLTimedWaitHang) { ! status = pthread_cond_signal (_cond) ; - assert (status == 0, "invariant") ; ! status = pthread_cond_signal (&_cond[_cur_index]); ! assert (status == 0, "invariant"); status = pthread_mutex_unlock(_mutex); - assert (status == 0, "invariant") ; } else { status = pthread_mutex_unlock(_mutex); - assert (status == 0, "invariant") ; ! status = pthread_cond_signal (_cond) ; - assert (status == 0, "invariant") ; ! status = pthread_cond_signal (&_cond[_cur_index]); ! assert (status == 0, "invariant"); } } else { pthread_mutex_unlock(_mutex); assert (status == 0, "invariant") ; }

src/os/linux/vm/os_linux.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File