Skip to content

Commit 8d28c76

Browse files
committed
Don't join the current thread if SubstrateTruffleRuntime#teardown that waits for all truffle compilation threads is executed from one of the compilation threads.
1 parent 9ab5967 commit 8d28c76

File tree

1 file changed

+61
-10
lines changed

1 file changed

+61
-10
lines changed

truffle/src/com.oracle.truffle.runtime/src/com/oracle/truffle/runtime/BackgroundCompileQueue.java

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
import java.util.Collection;
4646
import java.util.Collections;
4747
import java.util.List;
48+
import java.util.Set;
49+
import java.util.WeakHashMap;
4850
import java.util.concurrent.BlockingQueue;
4951
import java.util.concurrent.Callable;
5052
import java.util.concurrent.ExecutorService;
@@ -145,15 +147,9 @@ private ExecutorService getExecutorService(OptimizedCallTarget callTarget) {
145147
long keepAliveTime = compilerIdleDelay >= 0 ? compilerIdleDelay : 0;
146148

147149
this.compilationQueue = createQueue(callTarget, threads);
148-
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(threads, threads,
150+
ThreadPoolExecutor threadPoolExecutor = new TruffleThreadPoolExecutor(threads, threads,
149151
keepAliveTime, TimeUnit.MILLISECONDS,
150-
compilationQueue, factory) {
151-
@Override
152-
@SuppressWarnings({"unchecked"})
153-
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
154-
return (RunnableFuture<T>) new CompilationTask.ExecutorServiceWrapper((CompilationTask) callable);
155-
}
156-
};
152+
compilationQueue, factory);
157153

158154
if (compilerIdleDelay > 0) {
159155
// There are two mechanisms to signal idleness: if core threads can timeout, then
@@ -247,7 +243,6 @@ public void shutdownAndAwaitTermination(long timeout) {
247243
return;
248244
}
249245
}
250-
251246
threadPool.shutdownNow();
252247
try {
253248
threadPool.awaitTermination(timeout, TimeUnit.MILLISECONDS);
@@ -282,9 +277,40 @@ public enum Tier {
282277

283278
}
284279

285-
private final class TruffleCompilerThreadFactory implements ThreadFactory {
280+
private final class TruffleThreadPoolExecutor extends ThreadPoolExecutor {
281+
private TruffleThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
282+
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
283+
}
284+
285+
@Override
286+
@SuppressWarnings({"unchecked"})
287+
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
288+
return (RunnableFuture<T>) new CompilationTask.ExecutorServiceWrapper((CompilationTask) callable);
289+
}
290+
291+
@Override
292+
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
293+
ThreadFactory threadFactory = getThreadFactory();
294+
if (threadFactory instanceof JoinableThreadFactory) {
295+
return ((JoinableThreadFactory) threadFactory).joinOtherThreads(timeout, unit);
296+
} else {
297+
return super.awaitTermination(timeout, unit);
298+
}
299+
}
300+
}
301+
302+
public interface JoinableThreadFactory extends ThreadFactory {
303+
/**
304+
* Join all but the current thread. If the current thread belongs to this thread factory,
305+
* its interrupted status is just cleared instead of joining it.
306+
*/
307+
boolean joinOtherThreads(long timeout, TimeUnit unit) throws InterruptedException;
308+
}
309+
310+
private final class TruffleCompilerThreadFactory implements JoinableThreadFactory {
286311
private final String namePrefix;
287312
private final OptimizedTruffleRuntime runtime;
313+
private final Set<Thread> threads = Collections.synchronizedSet(Collections.newSetFromMap(new WeakHashMap<>()));
288314

289315
TruffleCompilerThreadFactory(final String namePrefix, OptimizedTruffleRuntime runtime) {
290316
this.namePrefix = namePrefix;
@@ -315,8 +341,33 @@ public void run() {
315341
t.setName(namePrefix + "-" + t.getId());
316342
t.setPriority(Thread.MAX_PRIORITY);
317343
t.setDaemon(true);
344+
threads.add(t);
318345
return t;
319346
}
347+
348+
@Override
349+
public boolean joinOtherThreads(long timeout, TimeUnit unit) throws InterruptedException {
350+
long timeoutNanos = unit.toNanos(timeout);
351+
synchronized (threads) {
352+
if (threads.contains(Thread.currentThread())) {
353+
// clear interrupt status
354+
Thread.interrupted();
355+
}
356+
for (Thread thread : threads) {
357+
if (thread == Thread.currentThread()) {
358+
continue;
359+
}
360+
long joinStart = System.nanoTime();
361+
TimeUnit.NANOSECONDS.timedJoin(thread, timeoutNanos);
362+
long joinEnd = System.nanoTime();
363+
timeoutNanos -= (joinEnd - joinStart);
364+
if (timeoutNanos <= 0) {
365+
return false;
366+
}
367+
}
368+
return true;
369+
}
370+
}
320371
}
321372

322373
/**

0 commit comments

Comments
 (0)