Search in sources :

Example 6 with TruffleSafepoint

use of com.oracle.truffle.api.TruffleSafepoint in project graal by oracle.

the class BlockingSupport method enterBlockingRegion.

/**
 * Same as {@link #enterBlockingRegion(Interruptible, Node, Object)}, but allows providing
 * something to execute before and/or after the thread is interrupted and safepoints are
 * processed.
 *
 * @throws GuestInterruptedException if the current thread was guest-interrupted.
 */
@TruffleBoundary
public <U> void enterBlockingRegion(Interruptible<U> blockingRegion, Node location, U object, Runnable beforeSafepoint, Consumer<Throwable> afterSafepoint) throws GuestInterruptedException {
    TruffleSafepoint safepoint = TruffleSafepoint.getCurrent();
    safepoint.setBlockedWithException(location, guestInterrupter, blockingRegion, object, beforeSafepoint, (ex) -> {
        if (afterSafepoint != null) {
            afterSafepoint.accept(ex);
        }
        guestInterrupter.afterInterrupt(ex);
    });
}
Also used : TruffleSafepoint(com.oracle.truffle.api.TruffleSafepoint) TruffleBoundary(com.oracle.truffle.api.CompilerDirectives.TruffleBoundary)

Example 7 with TruffleSafepoint

use of com.oracle.truffle.api.TruffleSafepoint 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());
}
Also used : ArrayList(java.util.ArrayList) LanguageContext(com.oracle.truffle.api.test.polyglot.ProxyLanguage.LanguageContext) ThreadLocalAction(com.oracle.truffle.api.ThreadLocalAction) TruffleBoundary(com.oracle.truffle.api.CompilerDirectives.TruffleBoundary) List(java.util.List) ArrayList(java.util.ArrayList) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) UncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler) ExecutionException(java.util.concurrent.ExecutionException) TruffleSafepoint(com.oracle.truffle.api.TruffleSafepoint) TruffleContext(com.oracle.truffle.api.TruffleContext) CountDownLatch(java.util.concurrent.CountDownLatch) TruffleSafepoint(com.oracle.truffle.api.TruffleSafepoint) ProxyLanguage(com.oracle.truffle.api.test.polyglot.ProxyLanguage) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Future(java.util.concurrent.Future) AbstractPolyglotTest(com.oracle.truffle.api.test.polyglot.AbstractPolyglotTest) Test(org.junit.Test)

Example 8 with TruffleSafepoint

use of com.oracle.truffle.api.TruffleSafepoint in project graal by oracle.

the class TruffleSafepointTest method testHasPendingSideEffectingActionsBoundary.

@TruffleBoundary
private static void testHasPendingSideEffectingActionsBoundary(AtomicReference<Thread> thread, CountDownLatch waitSideEffectsDisabled, CountDownLatch waitSubmitted, TestRootNode node) throws AssertionError {
    TruffleSafepoint safepoint = TruffleSafepoint.getCurrent();
    assertFalse(safepoint.hasPendingSideEffectingActions());
    boolean prev = safepoint.setAllowSideEffects(false);
    try {
        thread.set(Thread.currentThread());
        waitSideEffectsDisabled.countDown();
        try {
            waitSubmitted.await();
        } catch (InterruptedException e) {
            throw new AssertionError(e);
        }
        assertTrue(safepoint.hasPendingSideEffectingActions());
    } finally {
        safepoint.setAllowSideEffects(prev);
    }
    assertFalse("always false when side effects enabled", safepoint.hasPendingSideEffectingActions());
    try {
        TruffleSafepoint.pollHere(node);
        fail();
    } catch (RuntimeException e) {
        assertEquals("interrupt", e.getMessage());
        assertFalse(safepoint.hasPendingSideEffectingActions());
    }
}
Also used : TruffleSafepoint(com.oracle.truffle.api.TruffleSafepoint) TruffleBoundary(com.oracle.truffle.api.CompilerDirectives.TruffleBoundary)

Example 9 with TruffleSafepoint

use of com.oracle.truffle.api.TruffleSafepoint in project graal by oracle.

the class TruffleSafepointTest method testAllowActions.

@Test
public void testAllowActions() {
    forEachConfig((threads, events) -> {
        AtomicBoolean stopped = new AtomicBoolean(false);
        try (TestSetup setup = setupSafepointLoop(threads, (s, node) -> {
            TruffleSafepoint config = TruffleSafepoint.getCurrent();
            TL_HANDSHAKE.setChangeAllowActions(config, true);
            boolean prev = config.setAllowActions(false);
            try {
                while (true) {
                    TruffleSafepoint.poll(node);
                    if (isStopped(stopped)) {
                        return true;
                    }
                }
            } finally {
                config.setAllowActions(prev);
                TL_HANDSHAKE.setChangeAllowActions(config, false);
            }
        })) {
            AtomicInteger eventCounter = new AtomicInteger();
            ActionCollector runnable = new ActionCollector(setup, eventCounter, false, false);
            for (int i = 0; i < events; i++) {
                setup.env.submitThreadLocal(null, runnable);
            }
            assertEquals(0, eventCounter.get());
            stopped.set(true);
            setup.stopAndAwait();
            assertActionsAnyOrder(threads, events, runnable);
        }
    });
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) TruffleSafepoint(com.oracle.truffle.api.TruffleSafepoint) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) TruffleSafepoint(com.oracle.truffle.api.TruffleSafepoint) AbstractPolyglotTest(com.oracle.truffle.api.test.polyglot.AbstractPolyglotTest) Test(org.junit.Test)

Example 10 with TruffleSafepoint

use of com.oracle.truffle.api.TruffleSafepoint 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;
}
Also used : TruffleSafepoint(com.oracle.truffle.api.TruffleSafepoint) ArrayList(java.util.ArrayList) ThreadLocalAction(com.oracle.truffle.api.ThreadLocalAction) HashSet(java.util.HashSet)

Aggregations

TruffleSafepoint (com.oracle.truffle.api.TruffleSafepoint)11 AbstractPolyglotTest (com.oracle.truffle.api.test.polyglot.AbstractPolyglotTest)5 Test (org.junit.Test)5 TruffleBoundary (com.oracle.truffle.api.CompilerDirectives.TruffleBoundary)4 ThreadLocalAction (com.oracle.truffle.api.ThreadLocalAction)4 ArrayList (java.util.ArrayList)4 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)4 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)4 Future (java.util.concurrent.Future)3 TruffleContext (com.oracle.truffle.api.TruffleContext)1 ProxyLanguage (com.oracle.truffle.api.test.polyglot.ProxyLanguage)1 LanguageContext (com.oracle.truffle.api.test.polyglot.ProxyLanguage.LanguageContext)1 UncaughtExceptionHandler (java.lang.Thread.UncaughtExceptionHandler)1 HashSet (java.util.HashSet)1 List (java.util.List)1 CountDownLatch (java.util.concurrent.CountDownLatch)1 ExecutionException (java.util.concurrent.ExecutionException)1 Semaphore (java.util.concurrent.Semaphore)1 Condition (java.util.concurrent.locks.Condition)1 ReentrantLock (java.util.concurrent.locks.ReentrantLock)1