Skip to content

Commit

Permalink
[GR-30749] Only hold weak references to Truffle threads in thread con…
Browse files Browse the repository at this point in the history
…texts.

PullRequest: graal/8749
  • Loading branch information
fmorcos committed Apr 16, 2021
2 parents 78989a8 + f3ad26d commit 3a6a93e
Showing 1 changed file with 31 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
*/
package com.oracle.truffle.llvm.runtime.pthread;

import java.lang.ref.WeakReference;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.TruffleLanguage;
Expand All @@ -37,19 +42,32 @@
import com.oracle.truffle.llvm.runtime.nodes.intrinsics.multithreading.LLVMPThreadStart;
import com.oracle.truffle.llvm.runtime.pointer.LLVMPointer;

import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public final class LLVMPThreadContext {

// associated context for creating threads
private final TruffleLanguage.Env env;

// the long-key is the thread-id
private final Object threadLock;

/**
* TODO GR-30833: At pthread_join, return values need to be cleared from the map of thread
* return values.
*/
private final ConcurrentMap<Long, Object> threadReturnValueStorage;
private final ConcurrentMap<Long, Thread> threadStorage;

/**
* See doc on TruffleLanguage.initializeThread(Object, Thread).
* <p>
* When a thread is created with pthread_create and it completes execution, there are no more
* references held to the thread object and the GC will free it. It might happen that at some
* later point the user calls pthread_join on the thread but by that time there are no
* references held to the thread object anymore, so it cannot be joined on. If that is the case,
* the thread must have already terminated, and the join does not need to wait. The return value
* of the thread is stored in a separate map as well, so any reference to the thread object is
* really not needed anymore.
*/
private final ConcurrentMap<Long, WeakReference<Thread>> threadStorage;
private volatile boolean isCreateThreadAllowed;

private int pThreadKey;
Expand Down Expand Up @@ -78,14 +96,17 @@ public LLVMPThreadContext(TruffleLanguage.Env env, LLVMLanguage language, DataLa

@TruffleBoundary
public void joinAllThreads() {
final Collection<Thread> threadsToJoin;
final Collection<WeakReference<Thread>> threadsToJoin;
synchronized (threadLock) {
this.isCreateThreadAllowed = false;
threadsToJoin = threadStorage.values();
}
for (Thread createdThread : threadsToJoin) {
for (WeakReference<Thread> createdThread : threadsToJoin) {
try {
createdThread.join();
Thread t = createdThread.get();
if (t != null) {
t.join();
}
} catch (InterruptedException e) {
// ignored
}
Expand Down Expand Up @@ -170,7 +191,7 @@ public Thread createThread(Runnable runnable) {
synchronized (threadLock) {
if (isCreateThreadAllowed) {
final Thread thread = env.createThread(runnable);
threadStorage.put(thread.getId(), thread);
threadStorage.put(thread.getId(), new WeakReference<>(thread));
return thread;
} else {
return null;
Expand All @@ -180,7 +201,7 @@ public Thread createThread(Runnable runnable) {

@TruffleBoundary
public Thread getThread(long threadID) {
return threadStorage.get(threadID);
return threadStorage.get(threadID).get();
}

@TruffleBoundary
Expand Down

0 comments on commit 3a6a93e

Please sign in to comment.