47
47
import java .util .concurrent .atomic .AtomicBoolean ;
48
48
import java .util .concurrent .atomic .AtomicInteger ;
49
49
50
- import jdk .graal .compiler .word .Word ;
51
50
import org .graalvm .nativeimage .CurrentIsolate ;
52
51
import org .graalvm .nativeimage .ImageInfo ;
53
52
import org .graalvm .nativeimage .ImageSingletons ;
89
88
import com .oracle .svm .core .heap .VMOperationInfos ;
90
89
import com .oracle .svm .core .jdk .StackTraceUtils ;
91
90
import com .oracle .svm .core .jdk .UninterruptibleUtils ;
91
+ import com .oracle .svm .core .locks .VMCondition ;
92
92
import com .oracle .svm .core .locks .VMMutex ;
93
93
import com .oracle .svm .core .log .Log ;
94
94
import com .oracle .svm .core .memory .NativeMemory ;
109
109
110
110
import jdk .graal .compiler .api .replacements .Fold ;
111
111
import jdk .graal .compiler .core .common .SuppressFBWarnings ;
112
+ import jdk .graal .compiler .word .Word ;
112
113
import jdk .internal .misc .Unsafe ;
113
114
114
115
/**
@@ -544,7 +545,11 @@ public void closeOSThreadHandle(OSThreadHandle threadHandle) {
544
545
FORK_JOIN_POOL_TRY_TERMINATE_METHOD = ReflectionUtil .lookupMethod (ForkJoinPool .class , "tryTerminate" , boolean .class , boolean .class );
545
546
}
546
547
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
+ */
548
553
public static boolean tearDownOtherThreads () {
549
554
final Log trace = Log .noopLog ().string ("[PlatformThreads.tearDownPlatformThreads:" ).newline ().flush ();
550
555
@@ -557,9 +562,9 @@ public static boolean tearDownOtherThreads() {
557
562
*/
558
563
VMThreads .setTearingDown ();
559
564
560
- /* Fetch all running application threads and interrupt them. */
565
+ /* Fetch threads and interrupt them. */
561
566
ArrayList <Thread > threads = new ArrayList <>();
562
- FetchApplicationThreadsOperation operation = new FetchApplicationThreadsOperation (threads );
567
+ FetchThreadsForTeardownOperation operation = new FetchThreadsForTeardownOperation (threads );
563
568
operation .enqueue ();
564
569
565
570
Set <ExecutorService > pools = Collections .newSetFromMap (new IdentityHashMap <>());
@@ -626,9 +631,9 @@ public static boolean tearDownOtherThreads() {
626
631
return result ;
627
632
}
628
633
629
- /** Wait (im)patiently for the VMThreads list to drain. */
634
+ /** Wait (im)patiently for the thread list to drain. */
630
635
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" ;
632
637
633
638
final Log trace = Log .noopLog ().string ("[PlatformThreads.waitForTearDown:" ).newline ();
634
639
final long warningNanos = SubstrateOptions .getTearDownWarningNanos ();
@@ -666,8 +671,8 @@ private static boolean waitForTearDown() {
666
671
}
667
672
}
668
673
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 );
671
676
}
672
677
673
678
@ 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() {
762
767
assert numThreads > 0 ;
763
768
}
764
769
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
+ */
766
774
@ Uninterruptible (reason = CALLED_FROM_UNINTERRUPTIBLE_CODE , mayBeInlined = true )
767
775
private static void decrementNonDaemonThreads () {
768
776
int numThreads = nonDaemonThreads .decrementAndGet ();
@@ -1127,14 +1135,15 @@ protected void operate() {
1127
1135
}
1128
1136
1129
1137
/**
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}.
1132
1141
*/
1133
- private static class FetchApplicationThreadsOperation extends JavaVMOperation {
1142
+ private static class FetchThreadsForTeardownOperation extends JavaVMOperation {
1134
1143
private final List <Thread > list ;
1135
1144
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 ));
1138
1147
this .list = list ;
1139
1148
}
1140
1149
@@ -1144,11 +1153,13 @@ public void operate() {
1144
1153
VMMutex lock = VMThreads .THREAD_MUTEX .lock ();
1145
1154
try {
1146
1155
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 );
1152
1163
}
1153
1164
}
1154
1165
} finally {
@@ -1185,24 +1196,26 @@ public void operate() {
1185
1196
VMMutex lock = VMThreads .THREAD_MUTEX .lock ();
1186
1197
try {
1187
1198
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 ();
1203
1216
}
1204
- trace .newline ().flush ();
1205
1217
}
1218
+ trace .newline ().flush ();
1206
1219
}
1207
1220
}
1208
1221
0 commit comments