Search in sources :

Example 11 with ThreadLocalAction

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

the class TruffleSafepointTest method testRecursiveBlockingProcessingSubmitAllBeforePoll.

@Test
public void testRecursiveBlockingProcessingSubmitAllBeforePoll() throws InterruptedException {
    /*
         * Specfies the number of recursive blocking actions.
         */
    int[] tests = new int[] { 1, 2, 3, 7, 16, 128, 256 };
    for (int blockingActions : tests) {
        Semaphore waitForSafepoint = new Semaphore(0);
        Semaphore[] leaveBlocked = createSemaphores(blockingActions, 0);
        try (TestSetup setup = setupSafepointLoop(1, (s, node) -> {
            acquire(waitForSafepoint);
            TruffleSafepoint.poll(node);
            return false;
        })) {
            AtomicBoolean performed = new AtomicBoolean();
            AtomicBoolean[] inBlockingAction = createBooleans(blockingActions);
            Semaphore[] awaitBlocked = createSemaphores(blockingActions, 0);
            Future<?>[] blockingFutures = new Future<?>[blockingActions];
            for (int i = 0; i < blockingActions; i++) {
                final int actionIndex = i;
                blockingFutures[actionIndex] = setup.env.submitThreadLocal(null, new ThreadLocalAction(true, false) {

                    @Override
                    protected void perform(Access access) {
                        if (actionIndex > 0) {
                            assertTrue(inBlockingAction[actionIndex - 1].get());
                        }
                        inBlockingAction[actionIndex].set(true);
                        try {
                            awaitBlocked[actionIndex].release();
                            TruffleSafepoint.setBlockedThreadInterruptible(access.getLocation(), (e) -> {
                                leaveBlocked[actionIndex].acquire();
                            }, null);
                        } finally {
                            inBlockingAction[actionIndex].set(false);
                        }
                    }
                });
            }
            Future<?> f = setup.env.submitThreadLocal(null, new ThreadLocalAction(true, false) {

                @Override
                protected void perform(Access innerAccess) {
                    assertTrue(inBlockingAction[blockingActions - 1].get());
                    if (performed.get()) {
                        throw new AssertionError("already performed");
                    }
                    performed.set(true);
                }
            });
            // start processing safepoints now
            waitForSafepoint.release(Integer.MAX_VALUE);
            for (int actionIndex = 0; actionIndex < blockingActions; actionIndex++) {
                awaitBlocked[actionIndex].acquire();
            }
            waitOrFail(f);
            assertTrue(performed.get());
            for (int actionIndex = 0; actionIndex < blockingActions; actionIndex++) {
                leaveBlocked[actionIndex].release();
            }
            for (Future<?> blockingFuture : blockingFutures) {
                waitOrFail(blockingFuture);
            }
        }
    }
}
Also used : Semaphore(java.util.concurrent.Semaphore) ThreadLocalAction(com.oracle.truffle.api.ThreadLocalAction) TruffleSafepoint(com.oracle.truffle.api.TruffleSafepoint) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Future(java.util.concurrent.Future) AbstractPolyglotTest(com.oracle.truffle.api.test.polyglot.AbstractPolyglotTest) Test(org.junit.Test)

Example 12 with ThreadLocalAction

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

the class TruffleSafepointTest method testRecursiveBlockingProcessingSubmitPollSubmit.

@Test
public void testRecursiveBlockingProcessingSubmitPollSubmit() throws InterruptedException {
    /*
         * Specfies the number of recursive blocking actions.
         */
    int[] tests = new int[] { 1, 2, 3, 7, 16, 128, 256 };
    for (int blockingActions : tests) {
        Semaphore waitForSafepoint = new Semaphore(0);
        Semaphore[] leaveBlocked = createSemaphores(blockingActions, 0);
        try (TestSetup setup = setupSafepointLoop(1, (s, node) -> {
            acquire(waitForSafepoint);
            TruffleSafepoint.poll(node);
            return false;
        })) {
            AtomicBoolean performed = new AtomicBoolean();
            AtomicBoolean[] inBlockingAction = createBooleans(blockingActions);
            Semaphore[] awaitBlocked = createSemaphores(blockingActions, 0);
            Future<?>[] blockingFutures = new Future<?>[blockingActions];
            for (int i = 0; i < blockingActions; i++) {
                final int actionIndex = i;
                blockingFutures[actionIndex] = setup.env.submitThreadLocal(null, new ThreadLocalAction(true, false) {

                    @Override
                    protected void perform(Access access) {
                        if (actionIndex > 0) {
                            assertTrue(inBlockingAction[actionIndex - 1].get());
                        }
                        inBlockingAction[actionIndex].set(true);
                        try {
                            if (actionIndex < blockingActions - 1) {
                                awaitBlocked[actionIndex].release();
                            }
                            TruffleSafepoint.setBlockedThreadInterruptible(access.getLocation(), (e) -> {
                                /*
                                     * The last blocking action must be interrupted in order for the
                                     * subsequently submitted action to get processed.
                                     */
                                if (actionIndex == blockingActions - 1) {
                                    awaitBlocked[actionIndex].release();
                                }
                                leaveBlocked[actionIndex].acquire();
                            }, null);
                        } finally {
                            inBlockingAction[actionIndex].set(false);
                        }
                    }
                });
            }
            // start processing safepoints now
            waitForSafepoint.release(Integer.MAX_VALUE);
            for (int actionIndex = 0; actionIndex < blockingActions; actionIndex++) {
                awaitBlocked[actionIndex].acquire();
            }
            Future<?> f = setup.env.submitThreadLocal(null, new ThreadLocalAction(true, false) {

                @Override
                protected void perform(Access innerAccess) {
                    assertTrue(inBlockingAction[blockingActions - 1].get());
                    if (performed.get()) {
                        throw new AssertionError("already performed");
                    }
                    performed.set(true);
                }
            });
            waitOrFail(f);
            assertTrue(performed.get());
            for (int actionIndex = 0; actionIndex < blockingActions; actionIndex++) {
                leaveBlocked[actionIndex].release();
            }
            for (Future<?> blockingFuture : blockingFutures) {
                waitOrFail(blockingFuture);
            }
        }
    }
}
Also used : Semaphore(java.util.concurrent.Semaphore) ThreadLocalAction(com.oracle.truffle.api.ThreadLocalAction) TruffleSafepoint(com.oracle.truffle.api.TruffleSafepoint) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Future(java.util.concurrent.Future) AbstractPolyglotTest(com.oracle.truffle.api.test.polyglot.AbstractPolyglotTest) Test(org.junit.Test)

Example 13 with ThreadLocalAction

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

the class TruffleSafepointTest method testSynchronousRecursiveError.

@Test
public void testSynchronousRecursiveError() throws InterruptedException, AssertionError, ExecutionException {
    try (TestSetup setup = setupSafepointLoop(1, (s, node) -> {
        sleepNanosBoundary(50000);
        TruffleSafepoint.poll(node);
        return false;
    })) {
        Future<Boolean> future = setup.futures.get(0);
        AtomicBoolean error = new AtomicBoolean();
        setup.env.submitThreadLocal(null, new ThreadLocalAction(true, true) {

            @Override
            protected void perform(Access outer) {
                ThreadLocalAction action = new ThreadLocalAction(true, true) {

                    @Override
                    protected void perform(Access inner) {
                    }
                };
                try {
                    setup.env.submitThreadLocal(null, action);
                    fail();
                } catch (IllegalStateException e) {
                    /*
                         * Synchronous inner safe point scheduling is disallowed as this is prone
                         * for deadlocks.
                         */
                    assertTrue(e.getMessage(), e.getMessage().startsWith("Recursive synchronous thread local action detected."));
                    error.set(true);
                }
            }
        });
        setup.stopped.set(true);
        future.get();
        assertTrue(isStopped(error));
    }
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ThreadLocalAction(com.oracle.truffle.api.ThreadLocalAction) AbstractPolyglotTest(com.oracle.truffle.api.test.polyglot.AbstractPolyglotTest) Test(org.junit.Test)

Example 14 with ThreadLocalAction

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

the class TruffleSafepointTest method testStackTrace.

@Test
public void testStackTrace() {
    forEachConfig((threads, events) -> {
        try (TestSetup setup = setupSafepointLoop(threads, (s, node) -> {
            sleepNanosBoundary(50000);
            TruffleSafepoint.poll(node);
            return false;
        })) {
            AtomicInteger eventCounter = new AtomicInteger();
            List<List<List<TruffleStackTraceElement>>> lists = new ArrayList<>();
            for (int i = 0; i < events; i++) {
                List<List<TruffleStackTraceElement>> stackTraces = new ArrayList<>();
                setup.env.submitThreadLocal(null, new ThreadLocalAction(true, true) {

                    @Override
                    protected void perform(Access access) {
                        RuntimeException e = new RuntimeException();
                        TruffleStackTrace.fillIn(e);
                        synchronized (stackTraces) {
                            stackTraces.add(TruffleStackTrace.getStackTrace(e));
                        }
                    }
                });
                lists.add(stackTraces);
            }
            assertEquals(0, eventCounter.get());
            setup.stopAndAwait();
            for (List<List<TruffleStackTraceElement>> eventList : lists) {
                assertEquals(threads, eventList.size());
                for (List<TruffleStackTraceElement> list : eventList) {
                    assertEquals(1, list.size());
                    for (TruffleStackTraceElement element : list) {
                        assertSame(setup.target, element.getTarget());
                    }
                }
            }
        }
    });
}
Also used : TruffleStackTraceElement(com.oracle.truffle.api.TruffleStackTraceElement) ArrayList(java.util.ArrayList) ThreadLocalAction(com.oracle.truffle.api.ThreadLocalAction) TruffleSafepoint(com.oracle.truffle.api.TruffleSafepoint) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) List(java.util.List) ArrayList(java.util.ArrayList) AbstractPolyglotTest(com.oracle.truffle.api.test.polyglot.AbstractPolyglotTest) Test(org.junit.Test)

Example 15 with ThreadLocalAction

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

the class TruffleSafepointTest method testNonSideEffectInvalidErrorThrown.

@Test
public void testNonSideEffectInvalidErrorThrown() throws InterruptedException {
    try (TestSetup setup = setupSafepointLoop(1, (s, node) -> {
        sleepNanosBoundary(50000);
        TruffleSafepoint.poll(node);
        return false;
    })) {
        setup.env.submitThreadLocal(null, new ThreadLocalAction(false, false) {

            @Override
            protected void perform(Access outer) {
                throw new GuestException();
            }
        });
        setup.stopped.set(true);
        setup.futures.get(0).get();
        fail();
    } catch (ExecutionException e) {
        assertTrue(e.getCause().toString(), e.getCause() instanceof AssertionError);
        assertEquals("Throwing Truffle exception is disallowed in non-side-effecting thread local actions.", e.getCause().getMessage());
    }
}
Also used : ExecutionException(java.util.concurrent.ExecutionException) ThreadLocalAction(com.oracle.truffle.api.ThreadLocalAction) AbstractPolyglotTest(com.oracle.truffle.api.test.polyglot.AbstractPolyglotTest) Test(org.junit.Test)

Aggregations

ThreadLocalAction (com.oracle.truffle.api.ThreadLocalAction)19 Test (org.junit.Test)14 AbstractPolyglotTest (com.oracle.truffle.api.test.polyglot.AbstractPolyglotTest)13 TruffleSafepoint (com.oracle.truffle.api.TruffleSafepoint)12 ArrayList (java.util.ArrayList)9 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)9 Future (java.util.concurrent.Future)7 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)6 CountDownLatch (java.util.concurrent.CountDownLatch)5 TruffleContext (com.oracle.truffle.api.TruffleContext)4 List (java.util.List)4 Semaphore (java.util.concurrent.Semaphore)4 AtomicReference (java.util.concurrent.atomic.AtomicReference)4 Env (com.oracle.truffle.api.TruffleLanguage.Env)3 LanguageContext (com.oracle.truffle.api.test.polyglot.ProxyLanguage.LanguageContext)3 ExecutionException (java.util.concurrent.ExecutionException)3 TruffleBoundary (com.oracle.truffle.api.CompilerDirectives.TruffleBoundary)2 ProxyLanguage (com.oracle.truffle.api.test.polyglot.ProxyLanguage)2 HashSet (java.util.HashSet)2 Context (org.graalvm.polyglot.Context)2