mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-30 13:08:24 +00:00
6498581: ThreadInterruptTest3 produces wrong output on Windows
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. Co-authored-by: David Holmes <david.holmes@oracle.com> Reviewed-by: acorn, kvn
This commit is contained in:
parent
e1e850a132
commit
bfb1c42657
@ -3619,13 +3619,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());
|
||||
|
||||
@ -3246,7 +3246,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
|
||||
@ -3303,6 +3304,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)));
|
||||
@ -3316,6 +3318,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());
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user