4747import java .util .concurrent .atomic .AtomicBoolean ;
4848import java .util .concurrent .atomic .AtomicInteger ;
4949
50- import jdk .graal .compiler .word .Word ;
5150import org .graalvm .nativeimage .CurrentIsolate ;
5251import org .graalvm .nativeimage .ImageInfo ;
5352import org .graalvm .nativeimage .ImageSingletons ;
8988import com .oracle .svm .core .heap .VMOperationInfos ;
9089import com .oracle .svm .core .jdk .StackTraceUtils ;
9190import com .oracle .svm .core .jdk .UninterruptibleUtils ;
91+ import com .oracle .svm .core .locks .VMCondition ;
9292import com .oracle .svm .core .locks .VMMutex ;
9393import com .oracle .svm .core .log .Log ;
9494import com .oracle .svm .core .memory .NativeMemory ;
109109
110110import jdk .graal .compiler .api .replacements .Fold ;
111111import jdk .graal .compiler .core .common .SuppressFBWarnings ;
112+ import jdk .graal .compiler .word .Word ;
112113import jdk .internal .misc .Unsafe ;
113114
114115/**
@@ -544,7 +545,11 @@ public void closeOSThreadHandle(OSThreadHandle threadHandle) {
544545 FORK_JOIN_POOL_TRY_TERMINATE_METHOD = ReflectionUtil .lookupMethod (ForkJoinPool .class , "tryTerminate" , boolean .class , boolean .class );
545546 }
546547
547- /** Have each thread, except this one, tear itself down. */
548+ /**
549+ * Interrupts all threads except for the current thread and any threads that require custom
550+ * teardown logic (see {@link #isVMInternalThread(IsolateThread)}). Waits until the interrupted
551+ * threads detach.
552+ */
548553 public static boolean tearDownOtherThreads () {
549554 final Log trace = Log .noopLog ().string ("[PlatformThreads.tearDownPlatformThreads:" ).newline ().flush ();
550555
@@ -557,9 +562,9 @@ public static boolean tearDownOtherThreads() {
557562 */
558563 VMThreads .setTearingDown ();
559564
560- /* Fetch all running application threads and interrupt them. */
565+ /* Fetch threads and interrupt them. */
561566 ArrayList <Thread > threads = new ArrayList <>();
562- FetchApplicationThreadsOperation operation = new FetchApplicationThreadsOperation (threads );
567+ FetchThreadsForTeardownOperation operation = new FetchThreadsForTeardownOperation (threads );
563568 operation .enqueue ();
564569
565570 Set <ExecutorService > pools = Collections .newSetFromMap (new IdentityHashMap <>());
@@ -626,9 +631,9 @@ public static boolean tearDownOtherThreads() {
626631 return result ;
627632 }
628633
629- /** Wait (im)patiently for the VMThreads list to drain. */
634+ /** Wait (im)patiently for the thread list to drain. */
630635 private static boolean waitForTearDown () {
631- assert isApplicationThread (CurrentIsolate .getCurrentThread ()) : "we count the application threads until only the current one remains" ;
636+ assert ! isVMInternalThread (CurrentIsolate .getCurrentThread ()) : "we count the threads until only the current one remains" ;
632637
633638 final Log trace = Log .noopLog ().string ("[PlatformThreads.waitForTearDown:" ).newline ();
634639 final long warningNanos = SubstrateOptions .getTearDownWarningNanos ();
@@ -666,8 +671,8 @@ private static boolean waitForTearDown() {
666671 }
667672 }
668673
669- private static boolean isApplicationThread (IsolateThread isolateThread ) {
670- return ! VMOperationControl .isDedicatedVMOperationThread (isolateThread );
674+ public static boolean isVMInternalThread (IsolateThread thread ) {
675+ return VMOperationControl .isDedicatedVMOperationThread (thread ) || ReferenceHandlerThread . isReferenceHandlerThread ( thread );
671676 }
672677
673678 @ SuppressFBWarnings (value = "NN" , justification = "notifyAll is necessary for Java semantics, no shared state needs to be modified beforehand" )
@@ -762,7 +767,10 @@ static void incrementNonDaemonThreads() {
762767 assert numThreads > 0 ;
763768 }
764769
765- /** A caller must call THREAD_LIST_CONDITION.broadcast() manually. */
770+ /**
771+ * Callers must manually invoke {@link VMCondition#broadcast()} on
772+ * {@link VMThreads#THREAD_LIST_CONDITION} to notify any threads waiting for changes.
773+ */
766774 @ Uninterruptible (reason = CALLED_FROM_UNINTERRUPTIBLE_CODE , mayBeInlined = true )
767775 private static void decrementNonDaemonThreads () {
768776 int numThreads = nonDaemonThreads .decrementAndGet ();
@@ -1127,14 +1135,15 @@ protected void operate() {
11271135 }
11281136
11291137 /**
1130- * Builds a list of all application threads. This must be done in a VM operation because only
1131- * there we are allowed to allocate Java memory while holding the {@link VMThreads#THREAD_MUTEX}
1138+ * Builds a list of all threads that don't need any custom teardown logic. This must be done in
1139+ * a VM operation because only there we are allowed to allocate Java memory while holding the
1140+ * {@link VMThreads#THREAD_MUTEX}.
11321141 */
1133- private static class FetchApplicationThreadsOperation extends JavaVMOperation {
1142+ private static class FetchThreadsForTeardownOperation extends JavaVMOperation {
11341143 private final List <Thread > list ;
11351144
1136- FetchApplicationThreadsOperation (List <Thread > list ) {
1137- super (VMOperationInfos .get (FetchApplicationThreadsOperation .class , "Fetch application threads" , SystemEffect .NONE ));
1145+ FetchThreadsForTeardownOperation (List <Thread > list ) {
1146+ super (VMOperationInfos .get (FetchThreadsForTeardownOperation .class , "Fetch threads for teardown " , SystemEffect .NONE ));
11381147 this .list = list ;
11391148 }
11401149
@@ -1144,11 +1153,13 @@ public void operate() {
11441153 VMMutex lock = VMThreads .THREAD_MUTEX .lock ();
11451154 try {
11461155 for (IsolateThread isolateThread = VMThreads .firstThread (); isolateThread .isNonNull (); isolateThread = VMThreads .nextThread (isolateThread )) {
1147- if (isApplicationThread (isolateThread )) {
1148- final Thread thread = PlatformThreads .fromVMThread (isolateThread );
1149- if (thread != null ) {
1150- list .add (thread );
1151- }
1156+ if (isVMInternalThread (isolateThread )) {
1157+ continue ;
1158+ }
1159+
1160+ Thread thread = PlatformThreads .fromVMThread (isolateThread );
1161+ if (thread != null ) {
1162+ list .add (thread );
11521163 }
11531164 }
11541165 } finally {
@@ -1185,24 +1196,26 @@ public void operate() {
11851196 VMMutex lock = VMThreads .THREAD_MUTEX .lock ();
11861197 try {
11871198 for (IsolateThread isolateThread = VMThreads .firstThread (); isolateThread .isNonNull (); isolateThread = VMThreads .nextThread (isolateThread )) {
1188- if (isApplicationThread (isolateThread )) {
1189- attachedCount ++;
1190- if (printLaggards .get () && trace .isEnabled () && isolateThread != queuingThread ) {
1191- trace .string (" laggard isolateThread: " ).hex (isolateThread );
1192- final Thread thread = PlatformThreads .fromVMThread (isolateThread );
1193- if (thread != null ) {
1194- final String name = thread .getName ();
1195- final Thread .State status = thread .getState ();
1196- final boolean interruptedStatus = JavaThreads .isInterrupted (thread );
1197- trace .string (" thread.getName(): " ).string (name )
1198- .string (" interruptedStatus: " ).bool (interruptedStatus )
1199- .string (" getState(): " ).string (status .name ()).newline ();
1200- for (StackTraceElement e : thread .getStackTrace ()) {
1201- trace .string (e .toString ()).newline ();
1202- }
1199+ if (isVMInternalThread (isolateThread )) {
1200+ continue ;
1201+ }
1202+
1203+ attachedCount ++;
1204+ if (printLaggards .get () && trace .isEnabled () && isolateThread != queuingThread ) {
1205+ trace .string (" laggard isolateThread: " ).hex (isolateThread );
1206+ final Thread thread = PlatformThreads .fromVMThread (isolateThread );
1207+ if (thread != null ) {
1208+ final String name = thread .getName ();
1209+ final Thread .State status = thread .getState ();
1210+ final boolean interruptedStatus = JavaThreads .isInterrupted (thread );
1211+ trace .string (" thread.getName(): " ).string (name )
1212+ .string (" interruptedStatus: " ).bool (interruptedStatus )
1213+ .string (" getState(): " ).string (status .name ()).newline ();
1214+ for (StackTraceElement e : thread .getStackTrace ()) {
1215+ trace .string (e .toString ()).newline ();
12031216 }
1204- trace .newline ().flush ();
12051217 }
1218+ trace .newline ().flush ();
12061219 }
12071220 }
12081221
0 commit comments