8305092: Improve Thread.sleep(millis, nanos) for sub-millisecond granularity

Reviewed-by: dholmes, alanb
This commit is contained in:
Aleksey Shipilev 2023-05-03 09:39:57 +00:00
parent 891530fbc9
commit fcb280a48b
11 changed files with 245 additions and 28 deletions

View file

@ -1982,11 +1982,24 @@ Klass* JavaThread::security_get_caller_class(int depth) {
return nullptr;
}
// Internal convenience function for millisecond resolution sleeps.
bool JavaThread::sleep(jlong millis) {
jlong nanos;
if (millis > max_jlong / NANOUNITS_PER_MILLIUNIT) {
// Conversion to nanos would overflow, saturate at max
nanos = max_jlong;
} else {
nanos = millis * NANOUNITS_PER_MILLIUNIT;
}
return sleep_nanos(nanos);
}
// java.lang.Thread.sleep support
// Returns true if sleep time elapsed as expected, and false
// if the thread was interrupted.
bool JavaThread::sleep(jlong millis) {
bool JavaThread::sleep_nanos(jlong nanos) {
assert(this == Thread::current(), "thread consistency check");
assert(nanos >= 0, "nanos are in range");
ParkEvent * const slp = this->_SleepEvent;
// Because there can be races with thread interruption sending an unpark()
@ -2000,20 +2013,22 @@ bool JavaThread::sleep(jlong millis) {
jlong prevtime = os::javaTimeNanos();
jlong nanos_remaining = nanos;
for (;;) {
// interruption has precedence over timing out
if (this->is_interrupted(true)) {
return false;
}
if (millis <= 0) {
if (nanos_remaining <= 0) {
return true;
}
{
ThreadBlockInVM tbivm(this);
OSThreadWaitState osts(this->osthread(), false /* not Object.wait() */);
slp->park(millis);
slp->park_nanos(nanos_remaining);
}
// Update elapsed time tracking
@ -2024,7 +2039,7 @@ bool JavaThread::sleep(jlong millis) {
assert(false,
"unexpected time moving backwards detected in JavaThread::sleep()");
} else {
millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC;
nanos_remaining -= (newtime - prevtime);
}
prevtime = newtime;
}