# HG changeset patch # User dholmes # Date 1568254145 14400 # Node ID adc72cd1d1f2d48f4d1396f686a3a17567947dde # Parent 0f6c749acd1554f4ecef3a9d9e8247d4fe5e1cdd 8230423: Move os::sleep to JavaThread::sleep Reviewed-by: rehn, dcubed diff -r 0f6c749acd15 -r adc72cd1d1f2 src/hotspot/cpu/x86/rdtsc_x86.cpp --- a/src/hotspot/cpu/x86/rdtsc_x86.cpp Thu Sep 12 03:21:11 2019 +0200 +++ b/src/hotspot/cpu/x86/rdtsc_x86.cpp Wed Sep 11 22:09:05 2019 -0400 @@ -62,7 +62,7 @@ fstart = os::rdtsc(); // use sleep to prevent compiler from optimizing - os::sleep(JavaThread::current(), FT_SLEEP_MILLISECS); + JavaThread::current()->sleep(FT_SLEEP_MILLISECS); end = os::elapsed_counter(); OrderAccess::fence(); diff -r 0f6c749acd15 -r adc72cd1d1f2 src/hotspot/os/posix/os_posix.cpp --- a/src/hotspot/os/posix/os_posix.cpp Thu Sep 12 03:21:11 2019 +0200 +++ b/src/hotspot/os/posix/os_posix.cpp Wed Sep 11 22:09:05 2019 -0400 @@ -645,7 +645,8 @@ void os::interrupt(Thread* thread) { debug_only(Thread::check_for_dangling_thread_pointer(thread);) - + assert(thread->is_Java_thread(), "invariant"); + JavaThread* jt = (JavaThread*) thread; OSThread* osthread = thread->osthread(); if (!osthread->interrupted()) { @@ -654,13 +655,12 @@ // resulting in multiple notifications. We do, however, want the store // to interrupted() to be visible to other threads before we execute unpark(). OrderAccess::fence(); - ParkEvent * const slp = thread->_SleepEvent ; + ParkEvent * const slp = jt->_SleepEvent ; if (slp != NULL) slp->unpark() ; } // For JSR166. Unpark even if interrupt status already was set - if (thread->is_Java_thread()) - ((JavaThread*)thread)->parker()->unpark(); + jt->parker()->unpark(); ParkEvent * ev = thread->_ParkEvent ; if (ev != NULL) ev->unpark() ; @@ -682,7 +682,7 @@ // is allowed and not harmful, and the possibility is so rare that // it is not worth the added complexity to add yet another lock. // For the sleep event an explicit reset is performed on entry - // to os::sleep, so there is no early return. It has also been + // to JavaThread::sleep, so there is no early return. It has also been // recommended not to put the interrupted flag into the "event" // structure because it hides the issue. if (interrupted && clear_interrupted) { @@ -2049,7 +2049,7 @@ // shake out uses of park() and unpark() without checking state conditions // properly. This spurious return doesn't manifest itself in any user code // but only in the correctly written condition checking loops of ObjectMonitor, - // Mutex/Monitor, Thread::muxAcquire and os::sleep + // Mutex/Monitor, Thread::muxAcquire and JavaThread::sleep if (Atomic::xchg(1, &_event) >= 0) return; diff -r 0f6c749acd15 -r adc72cd1d1f2 src/hotspot/os/windows/os_windows.cpp --- a/src/hotspot/os/windows/os_windows.cpp Thu Sep 12 03:21:11 2019 +0200 +++ b/src/hotspot/os/windows/os_windows.cpp Wed Sep 11 22:09:05 2019 -0400 @@ -3595,7 +3595,8 @@ void os::interrupt(Thread* thread) { debug_only(Thread::check_for_dangling_thread_pointer(thread);) - + assert(thread->is_Java_thread(), "invariant"); + JavaThread* jt = (JavaThread*) thread; OSThread* osthread = thread->osthread(); osthread->set_interrupted(true); // More than one thread can get here with the same value of osthread, @@ -3605,14 +3606,12 @@ OrderAccess::release(); SetEvent(osthread->interrupt_event()); // For JSR166: unpark after setting status - if (thread->is_Java_thread()) { - ((JavaThread*)thread)->parker()->unpark(); - } + jt->parker()->unpark(); ParkEvent * ev = thread->_ParkEvent; if (ev != NULL) ev->unpark(); - ev = thread->_SleepEvent; + ev = jt->_SleepEvent; if (ev != NULL) ev->unpark(); } diff -r 0f6c749acd15 -r adc72cd1d1f2 src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp Thu Sep 12 03:21:11 2019 +0200 +++ b/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp Wed Sep 11 22:09:05 2019 -0400 @@ -242,7 +242,7 @@ } cur = MAX2(1, cur); - os::sleep(JavaThread::current(), cur); + JavaThread::current()->sleep(cur); double end = os::elapsedTime(); total = (size_t)((end - start) * 1000); diff -r 0f6c749acd15 -r adc72cd1d1f2 src/hotspot/share/jvmci/jvmciCompiler.cpp --- a/src/hotspot/share/jvmci/jvmciCompiler.cpp Thu Sep 12 03:21:11 2019 +0200 +++ b/src/hotspot/share/jvmci/jvmciCompiler.cpp Wed Sep 11 22:09:05 2019 -0400 @@ -81,7 +81,7 @@ do { // Loop until there is something in the queue. do { - os::sleep((JavaThread*)THREAD, 100); + ((JavaThread*)THREAD)->sleep(100); qsize = CompileBroker::queue_size(CompLevel_full_optimization); } while (!_bootstrap_compilation_request_handled && first_round && qsize == 0); first_round = false; diff -r 0f6c749acd15 -r adc72cd1d1f2 src/hotspot/share/jvmci/jvmciRuntime.cpp --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp Thu Sep 12 03:21:11 2019 +0200 +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp Wed Sep 11 22:09:05 2019 -0400 @@ -942,7 +942,7 @@ } } else { // Allow error reporting thread to print the stack trace. - os::sleep(THREAD, 200); + THREAD->sleep(200); } before_exit(THREAD); diff -r 0f6c749acd15 -r adc72cd1d1f2 src/hotspot/share/prims/jvm.cpp --- a/src/hotspot/share/prims/jvm.cpp Thu Sep 12 03:21:11 2019 +0200 +++ b/src/hotspot/share/prims/jvm.cpp Wed Sep 11 22:09:05 2019 -0400 @@ -2990,7 +2990,7 @@ } else { ThreadState old_state = thread->osthread()->get_state(); thread->osthread()->set_state(SLEEPING); - if (os::sleep(thread, millis) == OS_INTRPT) { + if (!thread->sleep(millis)) { // interrupted // An asynchronous exception (e.g., ThreadDeathException) could have been thrown on // us while we were sleeping. We do not overwrite those. if (!HAS_PENDING_EXCEPTION) { diff -r 0f6c749acd15 -r adc72cd1d1f2 src/hotspot/share/runtime/os.cpp --- a/src/hotspot/share/runtime/os.cpp Thu Sep 12 03:21:11 2019 +0200 +++ b/src/hotspot/share/runtime/os.cpp Wed Sep 11 22:09:05 2019 -0400 @@ -1844,57 +1844,3 @@ } naked_short_sleep(millis); } - -int os::sleep(JavaThread* thread, jlong millis) { - assert(thread == Thread::current(), "thread consistency check"); - - ParkEvent * const slp = thread->_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 = javaTimeNanos(); - - for (;;) { - // interruption has precedence over timing out - if (os::is_interrupted(thread, true)) { - return OS_INTRPT; - } - - jlong newtime = 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; - } - - if (millis <= 0) { - return OS_OK; - } - - prevtime = newtime; - - { - ThreadBlockInVM tbivm(thread); - OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */); - - thread->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? - thread->check_and_wait_while_suspended(); - } - } -} diff -r 0f6c749acd15 -r adc72cd1d1f2 src/hotspot/share/runtime/os.hpp --- a/src/hotspot/share/runtime/os.hpp Thu Sep 12 03:21:11 2019 +0200 +++ b/src/hotspot/share/runtime/os.hpp Wed Sep 11 22:09:05 2019 -0400 @@ -464,8 +464,7 @@ // thread id on Linux/64bit is 64bit, on Windows and Solaris, it's 32bit static intx current_thread_id(); static int current_process_id(); - // Implementation of java.lang.Thread.sleep for JavaThreads - static int sleep(JavaThread* thread, jlong ms); + // Short standalone OS sleep routines suitable for slow path spin loop. // Ignores safepoints/suspension/Thread.interrupt() (so keep it short). // ms/ns = 0, will sleep for the least amount of time allowed by the OS. diff -r 0f6c749acd15 -r adc72cd1d1f2 src/hotspot/share/runtime/thread.cpp --- a/src/hotspot/share/runtime/thread.cpp Thu Sep 12 03:21:11 2019 +0200 +++ b/src/hotspot/share/runtime/thread.cpp Wed Sep 11 22:09:05 2019 -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(); @@ -1696,7 +1694,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); @@ -1808,6 +1806,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(); @@ -3339,6 +3341,62 @@ 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(); diff -r 0f6c749acd15 -r adc72cd1d1f2 src/hotspot/share/runtime/thread.hpp --- a/src/hotspot/share/runtime/thread.hpp Thu Sep 12 03:21:11 2019 +0200 +++ b/src/hotspot/share/runtime/thread.hpp Wed Sep 11 22:09:05 2019 -0400 @@ -789,7 +789,6 @@ volatile intptr_t _Stalled; volatile int _TypeTag; ParkEvent * _ParkEvent; // for synchronized() - ParkEvent * _SleepEvent; // for Thread.sleep ParkEvent * _MuxEvent; // for low-level muxAcquire-muxRelease int NativeSyncRecursion; // diagnostic @@ -2055,6 +2054,10 @@ private: InstanceKlass* _class_to_be_initialized; + // java.lang.Thread.sleep support +public: + ParkEvent * _SleepEvent; + bool sleep(jlong millis); }; // Inline implementation of JavaThread::current diff -r 0f6c749acd15 -r adc72cd1d1f2 test/hotspot/gtest/gc/g1/test_g1FreeIdSet.cpp --- a/test/hotspot/gtest/gc/g1/test_g1FreeIdSet.cpp Thu Sep 12 03:21:11 2019 +0200 +++ b/test/hotspot/gtest/gc/g1/test_g1FreeIdSet.cpp Wed Sep 11 22:09:05 2019 -0400 @@ -145,7 +145,7 @@ tty->print_cr("Stressing G1FreeIdSet for %u ms", milliseconds_to_run); { ThreadInVMfromNative invm(this_thread); - os::sleep(this_thread, milliseconds_to_run); + this_thread->sleep(milliseconds_to_run); } OrderAccess::release_store(&continue_running, false); for (uint i = 0; i < nthreads; ++i) { diff -r 0f6c749acd15 -r adc72cd1d1f2 test/hotspot/gtest/gc/shared/test_ptrQueueBufferAllocator.cpp --- a/test/hotspot/gtest/gc/shared/test_ptrQueueBufferAllocator.cpp Thu Sep 12 03:21:11 2019 +0200 +++ b/test/hotspot/gtest/gc/shared/test_ptrQueueBufferAllocator.cpp Wed Sep 11 22:09:05 2019 -0400 @@ -224,7 +224,7 @@ tty->print_cr("Stressing allocator for %u ms", milliseconds_to_run); { ThreadInVMfromNative invm(this_thread); - os::sleep(this_thread, milliseconds_to_run); + this_thread->sleep(milliseconds_to_run); } OrderAccess::release_store(&allocator_running, false); for (uint i = 0; i < nthreads; ++i) { diff -r 0f6c749acd15 -r adc72cd1d1f2 test/hotspot/gtest/utilities/test_singleWriterSynchronizer.cpp --- a/test/hotspot/gtest/utilities/test_singleWriterSynchronizer.cpp Thu Sep 12 03:21:11 2019 +0200 +++ b/test/hotspot/gtest/utilities/test_singleWriterSynchronizer.cpp Wed Sep 11 22:09:05 2019 -0400 @@ -136,7 +136,7 @@ JavaThread* cur = JavaThread::current(); { ThreadInVMfromNative invm(cur); - os::sleep(cur, milliseconds_to_run); + cur->sleep(milliseconds_to_run); } continue_running = 0; for (uint i = 0; i < nreaders + 1; ++i) {