use of com.oracle.truffle.api.ThreadLocalAction in project graal by oracle.
the class TruffleSafepointTest method testHasPendingSideEffectingActions.
@Test
public void testHasPendingSideEffectingActions() {
AtomicReference<Thread> thread = new AtomicReference<>();
CountDownLatch waitSideEffectsDisabled = new CountDownLatch(1);
CountDownLatch waitSubmitted = new CountDownLatch(1);
try (TestSetup setup = setupSafepointLoop(1, (s, node) -> {
testHasPendingSideEffectingActionsBoundary(thread, waitSideEffectsDisabled, waitSubmitted, node);
return true;
})) {
waitSideEffectsDisabled.await();
setup.env.submitThreadLocal(new Thread[] { thread.get() }, new ThreadLocalAction(true, false) {
@Override
protected void perform(Access access) {
throw new RuntimeException("interrupt");
}
});
waitSubmitted.countDown();
setup.stopAndAwait();
} catch (InterruptedException e) {
throw new AssertionError(e);
}
}
use of com.oracle.truffle.api.ThreadLocalAction in project graal by oracle.
the class TruffleSafepointTest method testNoSafepointAfterThreadDispose.
@Test
public void testNoSafepointAfterThreadDispose() {
final ThreadLocal<Boolean> tl = new ThreadLocal<>();
ProxyLanguage.setDelegate(new ProxyLanguage() {
@Override
@TruffleBoundary
protected void initializeThread(LanguageContext context, Thread thread) {
tl.set(Boolean.TRUE);
}
@Override
@TruffleBoundary
protected void disposeThread(LanguageContext context, Thread thread) {
tl.set(Boolean.FALSE);
}
@Override
protected boolean isThreadAccessAllowed(Thread thread, boolean singleThreaded) {
return true;
}
});
forEachConfig((threads, events) -> {
CountDownLatch awaitThreadStart = new CountDownLatch(1);
AtomicBoolean threadsStopped = new AtomicBoolean();
try (TestSetup setup = setupSafepointLoop(threads, new NodeCallable() {
@TruffleBoundary
public boolean call(@SuppressWarnings("hiding") TestSetup setup, TestRootNode node) {
try {
List<Throwable> errors = Collections.synchronizedList(new ArrayList<>());
List<Thread> polyglotThreads = new ArrayList<>();
try {
for (int i = 0; i < threads; i++) {
Thread t = node.setup.env.createThread(() -> {
do {
TruffleContext context = node.setup.env.getContext();
TruffleSafepoint safepoint = TruffleSafepoint.getCurrent();
boolean prevSideEffects = safepoint.setAllowSideEffects(false);
try {
context.leaveAndEnter(null, () -> {
// cached thread local
return null;
});
} finally {
safepoint.setAllowSideEffects(prevSideEffects);
}
} while (!threadsStopped.get());
});
t.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
public void uncaughtException(@SuppressWarnings("hiding") Thread t, Throwable e) {
threadsStopped.set(true);
e.printStackTrace();
errors.add(e);
}
});
t.start();
polyglotThreads.add(t);
}
} finally {
awaitThreadStart.countDown();
}
for (Thread thread : polyglotThreads) {
thread.join();
}
for (Throwable t : errors) {
throw new AssertionError("thread threw error ", t);
}
return true;
} catch (InterruptedException e1) {
throw new AssertionError(e1);
}
}
})) {
try {
awaitThreadStart.await();
// important to let leaving and submitting race against each other
threadsStopped.set(true);
List<Future<?>> futures = new ArrayList<>();
for (int i = 0; i < events; i++) {
futures.add(setup.env.submitThreadLocal(null, new ThreadLocalAction(true, false) {
@Override
protected void perform(Access access) {
assertEquals(Boolean.TRUE, tl.get());
}
}));
}
for (Future<?> future : futures) {
try {
future.get();
} catch (ExecutionException e) {
throw new AssertionError(e);
}
}
} catch (InterruptedException e) {
throw new AssertionError(e);
}
setup.stopAndAwait();
}
});
ProxyLanguage.setDelegate(new ProxyLanguage());
}
use of com.oracle.truffle.api.ThreadLocalAction in project graal by oracle.
the class PolyglotThreadLocalActions method notifyThreadActivation.
Set<ThreadLocalAction> notifyThreadActivation(PolyglotThreadInfo info, boolean active) {
assert !active || info.getEnteredCount() == 1 : "must be currently entered successfully";
assert Thread.holdsLock(context);
if (activeEvents.isEmpty()) {
// fast common path
return Collections.emptySet();
}
Set<ThreadLocalAction> updatedActions = new HashSet<>();
// we cannot process the events while the context lock is held
// so we need to collect them first.
TruffleSafepoint s = TruffleSafepoint.getCurrent();
/*
* The set can be modified during the subsequent iteration.
*/
ArrayList<AbstractTLHandshake> activeEventsList = new ArrayList<>(activeEvents.keySet());
for (AbstractTLHandshake handshake : activeEventsList) {
if (!handshake.isEnabledForThread(Thread.currentThread())) {
continue;
}
Future<?> f = handshake.future;
if (f instanceof RecurringFuture) {
f = ((RecurringFuture) f).getCurrentFuture();
assert f != null : "current future must never be null";
}
if (active) {
if (traceActions) {
log("activate", handshake, "");
}
if (f == COMPLETED_FUTURE) {
assert handshake.future instanceof RecurringFuture;
handshake.resubmitRecurring();
} else {
if (TL_HANDSHAKE.activateThread(s, f)) {
updatedActions.add(handshake.action);
}
}
} else {
if (traceActions) {
log("deactivate", handshake, "");
}
if (f == COMPLETED_FUTURE) {
assert handshake.future instanceof RecurringFuture;
// nothing to do, wait for reactivation
} else {
if (TL_HANDSHAKE.deactivateThread(s, f)) {
updatedActions.add(handshake.action);
}
}
}
}
return updatedActions;
}
use of com.oracle.truffle.api.ThreadLocalAction in project graal by oracle.
the class ContextPreInitializationTest method testThreadLocalActions.
@Test
public void testThreadLocalActions() throws Exception {
BaseLanguage.registerAction(ContextPreInitializationTestFirstLanguage.class, ActionKind.ON_EXECUTE, (env) -> {
env.submitThreadLocal(new Thread[] { Thread.currentThread() }, new ThreadLocalAction(false, false) {
@Override
protected void perform(Access access) {
// Empty action just to do TraceStackTraceInterval logging
}
});
});
setPatchable(FIRST);
doContextPreinitialize(FIRST);
List<CountingContext> contexts = new ArrayList<>(emittedContexts);
assertEquals(1, contexts.size());
CountingContext firstLangCtx = findContext(FIRST, contexts);
assertNotNull(firstLangCtx);
assertEquals(1, firstLangCtx.createContextCount);
assertEquals(1, firstLangCtx.initializeContextCount);
TestHandler handler = new TestHandler("engine");
try (Context ctx = Context.newBuilder().allowExperimentalOptions(true).logHandler(handler).option("engine.TraceThreadLocalActions", "true").build()) {
Value res = ctx.eval(Source.create(FIRST, "test"));
assertEquals("test", res.asString());
contexts = new ArrayList<>(emittedContexts);
assertEquals(1, contexts.size());
assertEquals(1, firstLangCtx.createContextCount);
assertEquals(1, firstLangCtx.initializeContextCount);
assertEquals(1, firstLangCtx.patchContextCount);
}
Optional<String> message = handler.logs.stream().map((r) -> r.getMessage()).filter((m) -> m.contains("[tl]")).findAny();
assertTrue(message.isPresent());
}
Aggregations