--- old/src/hotspot/share/runtime/thread.cpp 2019-09-08 23:48:12.253098912 -0400 +++ new/src/hotspot/share/runtime/thread.cpp 2019-09-08 23:48:11.074086805 -0400 @@ -291,7 +291,6 @@ // The stack would act as a cache to avoid calls to ParkEvent::Allocate() // and ::Release() _ParkEvent = ParkEvent::Allocate(this); - _SleepEvent = ParkEvent::Allocate(this); _MuxEvent = ParkEvent::Allocate(this); #ifdef CHECK_UNHANDLED_OOPS @@ -456,7 +455,6 @@ // It's possible we can encounter a null _ParkEvent, etc., in stillborn threads. // We NULL out the fields for good hygiene. ParkEvent::Release(_ParkEvent); _ParkEvent = NULL; - ParkEvent::Release(_SleepEvent); _SleepEvent = NULL; ParkEvent::Release(_MuxEvent); _MuxEvent = NULL; delete handle_area(); @@ -1700,7 +1698,7 @@ _do_not_unlock_if_synchronized = false; _cached_monitor_info = NULL; _parker = Parker::Allocate(this); - + _SleepEvent = ParkEvent::Allocate(this); // Setup safepoint state info for this thread ThreadSafepointState::create(this); @@ -1812,6 +1810,10 @@ Parker::Release(_parker); _parker = NULL; + // Return the sleep event to the free list + ParkEvent::Release(_SleepEvent); + _SleepEvent = NULL; + // Free any remaining previous UnrollBlock vframeArray* old_array = vframe_array_last(); @@ -3343,6 +3345,63 @@ return NULL; } +// 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) { + assert(this == Thread::current(), "thread consistency check"); + + ParkEvent * const slp = this->_SleepEvent; + // Because there can be races with thread interruption sending an unpark() + // to the event, we explicitly reset it here to avoid an immediate return. + // The actual interrupt state will be checked before we park(). + slp->reset(); + // Thread interruption establishes a happens-before ordering in the + // Java Memory Model, so we need to ensure we synchronize with the + // interrupt state. + OrderAccess::fence(); + + jlong prevtime = os::javaTimeNanos(); + + for (;;) { + // interruption has precedence over timing out + if (os::is_interrupted(this, true)) { + return false; + } + + if (millis <= 0) { + return true; + } + + { + ThreadBlockInVM tbivm(this); + OSThreadWaitState osts(this->osthread(), false /* not Object.wait() */); + + this->set_suspend_equivalent(); + // cleared by handle_special_suspend_equivalent_condition() or + // java_suspend_self() via check_and_wait_while_suspended() + + slp->park(millis); + + // were we externally suspended while we were waiting? + this->check_and_wait_while_suspended(); + } + + // Update elapsed time tracking + jlong newtime = os::javaTimeNanos(); + if (newtime - prevtime < 0) { + // time moving backwards, should only happen if no monotonic clock + // not a guarantee() because JVM should not abort on kernel/glibc bugs + assert(!os::supports_monotonic_clock(), + "unexpected time moving backwards detected in os::sleep()"); + } else { + millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC; + } + prevtime = newtime; + } +} + + static void compiler_thread_entry(JavaThread* thread, TRAPS) { assert(thread->is_Compiler_thread(), "must be compiler thread"); CompileBroker::compiler_thread_loop();