mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 06:14:49 +02:00
6900441: PlatformEvent.park(millis) on Linux could still be affected by changes to the time-of-day clock
Associate CLOCK_MONOTONIC with the pthread_cond_t objects used for relative timed waits Reviewed-by: dcubed, shade
This commit is contained in:
parent
59a89ae1e1
commit
139c3e6621
2 changed files with 128 additions and 45 deletions
|
@ -131,6 +131,7 @@ 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;
|
||||
|
||||
|
@ -1399,12 +1400,15 @@ void os::Linux::clock_init() {
|
|||
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
|
||||
|
@ -4709,6 +4713,26 @@ void os::init(void) {
|
|||
|
||||
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
|
||||
|
@ -5519,21 +5543,36 @@ void os::pause() {
|
|||
|
||||
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;
|
||||
}
|
||||
abstime->tv_sec = now.tv_sec + seconds;
|
||||
long usec = now.tv_usec + millis * 1000;
|
||||
if (usec >= 1000000) {
|
||||
abstime->tv_sec += 1;
|
||||
usec -= 1000000;
|
||||
|
||||
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;
|
||||
}
|
||||
abstime->tv_nsec = usec * 1000;
|
||||
return abstime;
|
||||
}
|
||||
|
||||
|
@ -5625,7 +5664,7 @@ int os::PlatformEvent::park(jlong millis) {
|
|||
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,
|
||||
|
@ -5726,32 +5765,50 @@ void os::PlatformEvent::unpark() {
|
|||
|
||||
static void unpackTime(timespec* absTime, bool isAbsolute, jlong time) {
|
||||
assert (time > 0, "convertTime");
|
||||
time_t max_secs = 0;
|
||||
|
||||
struct timeval now;
|
||||
int status = gettimeofday(&now, NULL);
|
||||
assert(status == 0, "gettimeofday");
|
||||
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;
|
||||
if (isAbsolute) {
|
||||
jlong secs = time / 1000;
|
||||
if (secs > max_secs) {
|
||||
absTime->tv_sec = max_secs;
|
||||
} else {
|
||||
absTime->tv_sec = secs;
|
||||
}
|
||||
absTime->tv_nsec = (time % 1000) * NANOSECS_PER_MILLISEC;
|
||||
} else {
|
||||
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_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 {
|
||||
absTime->tv_sec = secs;
|
||||
}
|
||||
absTime->tv_nsec = (time % 1000) * NANOSECS_PER_MILLISEC;
|
||||
}
|
||||
else {
|
||||
} 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 {
|
||||
} else {
|
||||
absTime->tv_sec = now.tv_sec + secs;
|
||||
absTime->tv_nsec = (time % NANOSECS_PER_SEC) + now.tv_usec*1000;
|
||||
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
|
||||
|
@ -5831,15 +5888,19 @@ void Parker::park(bool isAbsolute, jlong time) {
|
|||
jt->set_suspend_equivalent();
|
||||
// cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
|
||||
|
||||
assert(_cur_index == -1, "invariant");
|
||||
if (time == 0) {
|
||||
status = pthread_cond_wait (_cond, _mutex) ;
|
||||
_cur_index = REL_INDEX; // arbitrary choice when not timed
|
||||
status = pthread_cond_wait (&_cond[_cur_index], _mutex) ;
|
||||
} else {
|
||||
status = os::Linux::safe_cond_timedwait (_cond, _mutex, &absTime) ;
|
||||
_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) ;
|
||||
pthread_cond_init (_cond, NULL);
|
||||
pthread_cond_destroy (&_cond[_cur_index]) ;
|
||||
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");
|
||||
|
@ -5868,17 +5929,24 @@ void Parker::unpark() {
|
|||
s = _counter;
|
||||
_counter = 1;
|
||||
if (s < 1) {
|
||||
if (WorkAroundNPTLTimedWaitHang) {
|
||||
status = pthread_cond_signal (_cond) ;
|
||||
assert (status == 0, "invariant") ;
|
||||
// thread might be parked
|
||||
if (_cur_index != -1) {
|
||||
// thread is definitely parked
|
||||
if (WorkAroundNPTLTimedWaitHang) {
|
||||
status = pthread_cond_signal (&_cond[_cur_index]);
|
||||
assert (status == 0, "invariant");
|
||||
status = pthread_mutex_unlock(_mutex);
|
||||
assert (status == 0, "invariant") ;
|
||||
} else {
|
||||
assert (status == 0, "invariant");
|
||||
} else {
|
||||
status = pthread_mutex_unlock(_mutex);
|
||||
assert (status == 0, "invariant") ;
|
||||
status = pthread_cond_signal (_cond) ;
|
||||
assert (status == 0, "invariant") ;
|
||||
}
|
||||
assert (status == 0, "invariant");
|
||||
status = pthread_cond_signal (&_cond[_cur_index]);
|
||||
assert (status == 0, "invariant");
|
||||
}
|
||||
} else {
|
||||
pthread_mutex_unlock(_mutex);
|
||||
assert (status == 0, "invariant") ;
|
||||
}
|
||||
} else {
|
||||
pthread_mutex_unlock(_mutex);
|
||||
assert (status == 0, "invariant") ;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue