Projects
Mega:23.09
openjdk-1.8.0
_service:tar_scm:8191483.patch
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:8191483.patch of Package openjdk-1.8.0
From 20109e1a7f9941662abd5069d30ad693c181f415 Mon Sep 17 00:00:00 2001 Date: Fri, 22 Jan 2021 11:33:53 +0800 Subject: Backport of JDK-8191483 summary: AbstractQueuedSynchronizer cancel/cancel race LLT: Bug url: https://bugs.openjdk.java.net/browse/JDK-8191483 --- .../locks/AbstractQueuedLongSynchronizer.java | 34 +++++++++++-------- .../locks/AbstractQueuedSynchronizer.java | 34 +++++++++++-------- 2 files changed, 40 insertions(+), 28 deletions(-) diff --git a/jdk/src/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java b/jdk/src/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java index 47fdbfb94..8699fc9b8 100644 --- a/jdk/src/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java +++ b/jdk/src/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java @@ -531,7 +531,9 @@ public abstract class AbstractQueuedLongSynchronizer // predNext is the apparent node to unsplice. CASes below will // fail if not, in which case, we lost race vs another cancel - // or signal, so no further action is necessary. + // or signal, so no further action is necessary, although with + // a possibility that a cancelled node may transiently remain + // reachable. Node predNext = pred.next; // Can use unconditional write instead of CAS here. @@ -1131,13 +1133,13 @@ public abstract class AbstractQueuedLongSynchronizer * at any time, a {@code true} return does not guarantee that any * other thread will ever acquire. * - * <p>In this implementation, this operation returns in - * constant time. - * * @return {@code true} if there may be other threads waiting to acquire */ public final boolean hasQueuedThreads() { - return head != tail; + for (Node p = tail, h = head; p != h && p != null; p = p.prev) + if (p.waitStatus <= 0) + return true; + return false; } /** @@ -1288,17 +1290,21 @@ public abstract class AbstractQueuedLongSynchronizer * @since 1.7 */ public final boolean hasQueuedPredecessors() { - // The correctness of this depends on head being initialized - // before tail and on head.next being accurate if the current - // thread is first in queue. - Node t = tail; // Read fields in reverse initialization order - Node h = head; - Node s; - return h != t && - ((s = h.next) == null || s.thread != Thread.currentThread()); + Node h, s; + if ((h = head) != null) { + if ((s = h.next) == null || s.waitStatus > 0) { + s = null; // traverse in case of concurrent cancellation + for (Node p = tail; p != h && p != null; p = p.prev) { + if (p.waitStatus <= 0) + s = p; + } + } + if (s != null && s.thread != Thread.currentThread()) + return true; + } + return false; } - // Instrumentation and monitoring methods /** diff --git a/jdk/src/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java b/jdk/src/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java index dce35765d..9088e5894 100644 --- a/jdk/src/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java +++ b/jdk/src/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java @@ -753,7 +753,9 @@ public abstract class AbstractQueuedSynchronizer // predNext is the apparent node to unsplice. CASes below will // fail if not, in which case, we lost race vs another cancel - // or signal, so no further action is necessary. + // or signal, so no further action is necessary, although with + // a possibility that a cancelled node may transiently remain + // reachable. Node predNext = pred.next; // Can use unconditional write instead of CAS here. @@ -1353,13 +1355,13 @@ public abstract class AbstractQueuedSynchronizer * at any time, a {@code true} return does not guarantee that any * other thread will ever acquire. * - * <p>In this implementation, this operation returns in - * constant time. - * * @return {@code true} if there may be other threads waiting to acquire */ public final boolean hasQueuedThreads() { - return head != tail; + for (Node p = tail, h = head; p != h && p != null; p = p.prev) + if (p.waitStatus <= 0) + return true; + return false; } /** @@ -1510,17 +1512,21 @@ public abstract class AbstractQueuedSynchronizer * @since 1.7 */ public final boolean hasQueuedPredecessors() { - // The correctness of this depends on head being initialized - // before tail and on head.next being accurate if the current - // thread is first in queue. - Node t = tail; // Read fields in reverse initialization order - Node h = head; - Node s; - return h != t && - ((s = h.next) == null || s.thread != Thread.currentThread()); + Node h, s; + if ((h = head) != null) { + if ((s = h.next) == null || s.waitStatus > 0) { + s = null; // traverse in case of concurrent cancellation + for (Node p = tail; p != h && p != null; p = p.prev) { + if (p.waitStatus <= 0) + s = p; + } + } + if (s != null && s.thread != Thread.currentThread()) + return true; + } + return false; } - // Instrumentation and monitoring methods /** -- 2.19.0
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2