Skip to content

Commit

Permalink
Monitors do not pin continuations because we implement them via Reent…
Browse files Browse the repository at this point in the history
…rantLock.
  • Loading branch information
peter-hofer committed Feb 1, 2022
1 parent 4a30be1 commit fb394b8
Show file tree
Hide file tree
Showing 8 changed files with 30 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import org.graalvm.nativeimage.ImageSingletons;

import com.oracle.svm.core.annotate.Uninterruptible;
import org.graalvm.nativeimage.IsolateThread;

/**
* This interface provides functions related to monitor operations (the Java "synchronized" keyword
Expand Down Expand Up @@ -79,8 +78,6 @@ public static MonitorSupport singleton() {
/** Determines whether the object's monitor is locked by the current or any other thread. */
public abstract boolean isLockedByAnyThread(Object obj);

public abstract int countThreadLock(IsolateThread vmThread);

/**
* Implements the semantics of {@link Object#wait}.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess;
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.compiler.word.BarrieredAccess;
import org.graalvm.nativeimage.IsolateThread;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;

Expand All @@ -58,11 +57,8 @@
import com.oracle.svm.core.hub.DynamicHubCompanion;
import com.oracle.svm.core.snippets.SubstrateForeignCallTarget;
import com.oracle.svm.core.stack.StackOverflowCheck;
import com.oracle.svm.core.thread.LoomSupport;
import com.oracle.svm.core.thread.ThreadStatus;
import com.oracle.svm.core.thread.VMOperationControl;
import com.oracle.svm.core.threadlocal.FastThreadLocalFactory;
import com.oracle.svm.core.threadlocal.FastThreadLocalInt;
import com.oracle.svm.core.util.VMError;

import sun.misc.Unsafe;
Expand Down Expand Up @@ -92,24 +88,6 @@ public class MultiThreadedMonitorSupport extends MonitorSupport {

private static final Unsafe UNSAFE = GraalUnsafeAccess.getUnsafe();

/**
* This is only used for preempting a continuation in the experimental Loom JDK support. There's
* performance impact in this solution.
*/
protected static final FastThreadLocalInt lockedMonitors = FastThreadLocalFactory.createInt("MultiThreadedMonitorSupport.lockedMonitors");

protected static void onMonitorLocked() {
if (LoomSupport.isEnabled()) {
lockedMonitors.set(lockedMonitors.get() + 1);
}
}

protected static void onMonitorUnlocked() {
if (LoomSupport.isEnabled()) {
lockedMonitors.set(lockedMonitors.get() - 1);
}
}

/**
* Types that are used to implement the secondary storage for monitor slots cannot themselves
* use the additionalMonitors map. That could result in recursive manipulation of the
Expand Down Expand Up @@ -266,8 +244,6 @@ private static void slowPathMonitorEnter(Object obj) {
public void monitorEnter(Object obj) {
ReentrantLock lockObject = getOrCreateMonitor(obj, true);
lockObject.lock();

onMonitorLocked();
}

@SubstrateForeignCallTarget(stubCallingConvention = false)
Expand Down Expand Up @@ -305,8 +281,6 @@ private static void slowPathMonitorExit(Object obj) {
public void monitorExit(Object obj) {
ReentrantLock lockObject = getOrCreateMonitor(obj, true);
lockObject.unlock();

onMonitorUnlocked();
}

@Override
Expand Down Expand Up @@ -377,12 +351,6 @@ public boolean isLockedByAnyThread(Object obj) {
return lockObject != null && lockObject.isLocked();
}

@Override
public int countThreadLock(IsolateThread vmThread) {
VMError.guarantee(LoomSupport.isEnabled(), "This method is only supported when continuations are enabled.");
return lockedMonitors.get(vmThread);
}

@SuppressFBWarnings(value = {"WA_AWAIT_NOT_IN_LOOP"}, justification = "This method is a wait implementation.")
@Override
protected void doWait(Object obj, long timeoutMillis) throws InterruptedException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
package com.oracle.svm.core.monitor;

import com.oracle.svm.core.annotate.Uninterruptible;
import org.graalvm.nativeimage.IsolateThread;

/**
* Without support for threads, there is no need for any monitor operations.
Expand Down Expand Up @@ -68,15 +67,6 @@ public boolean isLockedByAnyThread(Object obj) {
return isLockedByCurrentThread(obj);
}

@Override
public int countThreadLock(IsolateThread vmThread) {
/*
* Callers of currentThreadHaveLock want to know if it's safe to preempt a continuation
* which will not happen in single-threaded programs. It's safe to return any value.
*/
return 0;
}

@Override
protected void doWait(Object obj, long timeoutMillis) throws InterruptedException {
/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ public final class JavaContinuations {
public static final int YIELD_SUCCESS = 0;
public static final int PINNED_CRITICAL_SECTION = 1;
public static final int PINNED_NATIVE = 2;
public static final int PINNED_MONITOR = 3;

@Fold
public static boolean isSupported() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,17 @@ public static JavaThreads singleton() {
/** The platform {@link java.lang.Thread} for the {@link IsolateThread}. */
static final FastThreadLocalObject<Thread> platformThread = FastThreadLocalFactory.createObject(Thread.class, "JavaThreads.platformThread").setMaxOffset(FastThreadLocal.BYTE_OFFSET);

/**
* A thread-local helper object for locking. Use only if each {@link Thread} corresponds to an
* {@link IsolateThread}, otherwise use {@link Target_java_lang_Thread#lockHelper}.
*/
private static final FastThreadLocalObject<Object> lockHelper = FastThreadLocalFactory.createObject(Object.class, "JavaThreads.lockHelper").setMaxOffset(FastThreadLocal.BYTE_OFFSET);

/**
* The number of running non-daemon threads. The initial value accounts for the main thread,
* which is implicitly running when the isolate is created.
*/
static final UninterruptibleUtils.AtomicInteger nonDaemonThreads = new UninterruptibleUtils.AtomicInteger(1);
private static final UninterruptibleUtils.AtomicInteger nonDaemonThreads = new UninterruptibleUtils.AtomicInteger(1);

/**
* Tracks the number of threads that have been started, but are not yet executing Java code. For
Expand Down Expand Up @@ -1103,6 +1109,24 @@ static ThreadData getCurrentThreadData() {
return (ThreadData) toTarget(Thread.currentThread()).threadData;
}

@Uninterruptible(reason = "Called from uninterruptible code.")
public static void setCurrentThreadLockHelper(Object root) {
if (JavaContinuations.isSupported()) {
toTarget(Thread.currentThread()).lockHelper = root;
} else {
lockHelper.set(root);
}
}

@AlwaysInline("Locking fast path.")
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public static Object getCurrentThreadLockHelper() {
if (JavaContinuations.isSupported()) {
return toTarget(Thread.currentThread()).lockHelper;
}
return lockHelper.get();
}

/**
* Builds a list of all application threads. This must be done in a VM operation because only
* there we are allowed to allocate Java memory while holding the {@link VMThreads#THREAD_MUTEX}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@

import com.oracle.svm.core.SubstrateOptions;
import com.oracle.svm.core.SubstrateUtil;
import com.oracle.svm.core.monitor.MonitorSupport;
import com.oracle.svm.core.stack.JavaFrameAnchor;
import com.oracle.svm.core.stack.JavaFrameAnchors;
import com.oracle.svm.util.ReflectionUtil;
Expand All @@ -60,13 +59,9 @@ public static int isPinned(Target_java_lang_Thread thread, Target_java_lang_Cont
IsolateThread vmThread = isCurrentThread ? CurrentIsolate.getCurrentThread() : JavaThreads.getIsolateThread(SubstrateUtil.cast(thread, Thread.class));

if (cont != null) {
int threadMonitorCount = MonitorSupport.singleton().countThreadLock(vmThread);

while (true) {
if (cont.cs > 0) {
return JavaContinuations.PINNED_CRITICAL_SECTION;
} else if (threadMonitorCount > cont.monitorBefore) {
return JavaContinuations.PINNED_MONITOR;
}

if (cont.getParent() != null && cont.getScope() != scope) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,6 @@ public final class Target_java_lang_Continuation {
static byte FLAG_SAFEPOINT_YIELD = 1 << 1;
// Checkstyle: resume

@Inject @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset)//
int monitorBefore;

@SuppressWarnings("unused")
@Alias
public Target_java_lang_Continuation(Target_java_lang_ContinuationScope scope, Runnable target) {
Expand Down Expand Up @@ -171,7 +168,6 @@ private static void enter(Target_java_lang_Continuation cont, boolean isContinue
if (!isContinue) {
assert cont.internal == null;
cont.internal = new Continuation(cont::enter0);
cont.monitorBefore = 0;
}

cont.internal.enter();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,11 @@ public final class Target_java_lang_Thread {
@Alias @TargetElement(onlyWith = NotLoomJDK.class) //
volatile Target_sun_nio_ch_Interruptible blocker;

/** @see JavaThreads#setCurrentThreadLockHelper */
@Inject @TargetElement(onlyWith = ContinuationsSupported.class) //
@RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset) //
Object lockHelper;

@Alias
native void setPriority(int newPriority);

Expand Down

0 comments on commit fb394b8

Please sign in to comment.