From 195d273ca6c09a4d76bdde09ff6ada0631c9847d Mon Sep 17 00:00:00 2001 From: minqi Date: Wed, 26 Feb 2014 15:20:41 -0800 Subject: [PATCH] 6498581: ThreadInterruptTest3 produces wrong output on Windows Summary: There is race condition between os::interrupt and os::is_interrupted on Windows. In JVM_Sleep(Thread.sleep), check if thread gets interrupted, it may see interrupted but not really interrupted so cause spurious waking up (early return from sleep). Fix by checking if interrupt event really gets set thus prevent false return. For intrinsic of _isInterrupted, on Windows, go fastpath only on bit not set. Reviewed-by: acorn, kvn Contributed-by: david.holmes@oracle.com, yumin.qi@oracle.com --- src/os/windows/vm/os_windows.cpp | 5 +++-- src/share/vm/opto/library_call.cpp | 8 +++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/os/windows/vm/os_windows.cpp b/src/os/windows/vm/os_windows.cpp index 4a540b66e..c09312143 100644 --- a/src/os/windows/vm/os_windows.cpp +++ b/src/os/windows/vm/os_windows.cpp @@ -3633,13 +3633,14 @@ bool os::is_interrupted(Thread* thread, bool clear_interrupted) { "possibility of dangling Thread pointer"); OSThread* osthread = thread->osthread(); - bool interrupted = osthread->interrupted(); // There is no synchronization between the setting of the interrupt // and it being cleared here. It is critical - see 6535709 - that // we only clear the interrupt state, and reset the interrupt event, // if we are going to report that we were indeed interrupted - else // an interrupt can be "lost", leading to spurious wakeups or lost wakeups - // depending on the timing + // depending on the timing. By checking thread interrupt event to see + // if the thread gets real interrupt thus prevent spurious wakeup. + bool interrupted = osthread->interrupted() && (WaitForSingleObject(osthread->interrupt_event(), 0) == WAIT_OBJECT_0); if (interrupted && clear_interrupted) { osthread->set_interrupted(false); ResetEvent(osthread->interrupt_event()); diff --git a/src/share/vm/opto/library_call.cpp b/src/share/vm/opto/library_call.cpp index 564aa7c1f..1630c6881 100644 --- a/src/share/vm/opto/library_call.cpp +++ b/src/share/vm/opto/library_call.cpp @@ -3237,7 +3237,8 @@ bool LibraryCallKit::inline_native_currentThread() { // private native boolean java.lang.Thread.isInterrupted(boolean ClearInterrupted); bool LibraryCallKit::inline_native_isInterrupted() { // Add a fast path to t.isInterrupted(clear_int): - // (t == Thread.current() && (!TLS._osthread._interrupted || !clear_int)) + // (t == Thread.current() && + // (!TLS._osthread._interrupted || WINDOWS_ONLY(false) NOT_WINDOWS(!clear_int))) // ? TLS._osthread._interrupted : /*slow path:*/ t.isInterrupted(clear_int) // So, in the common case that the interrupt bit is false, // we avoid making a call into the VM. Even if the interrupt bit @@ -3294,6 +3295,7 @@ bool LibraryCallKit::inline_native_isInterrupted() { // drop through to next case set_control( _gvn.transform(new (C) IfTrueNode(iff_bit))); +#ifndef TARGET_OS_FAMILY_windows // (c) Or, if interrupt bit is set and clear_int is false, use 2nd fast path. Node* clr_arg = argument(1); Node* cmp_arg = _gvn.transform(new (C) CmpINode(clr_arg, intcon(0))); @@ -3307,6 +3309,10 @@ bool LibraryCallKit::inline_native_isInterrupted() { // drop through to next case set_control( _gvn.transform(new (C) IfTrueNode(iff_arg))); +#else + // To return true on Windows you must read the _interrupted field + // and check the the event state i.e. take the slow path. +#endif // TARGET_OS_FAMILY_windows // (d) Otherwise, go to the slow path. slow_region->add_req(control()); -- GitLab