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);
}
}
}
}
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);
}
}
}
}
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));
}
}
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());
}
}
}
}
});
}
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());
}
}
Aggregations