test/compiler/testlibrary/rtm/AbortProvoker.java
Print this page
*** 27,85 ****
import java.util.Objects;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import com.oracle.java.testlibrary.Asserts;
! import com.oracle.java.testlibrary.Utils;
! import sun.misc.Unsafe;
/**
* Base class for different transactional execution abortion
* provokers aimed to force abort due to specified reason.
*/
public abstract class AbortProvoker implements CompilableTest {
public static final long DEFAULT_ITERATIONS = 10000L;
/**
* Inflates monitor associated with object {@code monitor}.
* Inflation is forced by entering the same monitor from
* two different threads.
*
* @param monitor monitor to be inflated.
* @return inflated monitor.
* @throws Exception if something went wrong.
*/
public static Object inflateMonitor(Object monitor) throws Exception {
- Unsafe unsafe = Utils.getUnsafe();
CyclicBarrier barrier = new CyclicBarrier(2);
Runnable inflatingRunnable = () -> {
! unsafe.monitorEnter(monitor);
try {
barrier.await();
! barrier.await();
! } catch (InterruptedException | BrokenBarrierException e) {
throw new RuntimeException(
"Synchronization issue occurred.", e);
! } finally {
! unsafe.monitorExit(monitor);
}
};
Thread t = new Thread(inflatingRunnable);
t.start();
// Wait until thread t enters the monitor.
barrier.await();
! // At this point monitor will be owned by thread t,
! // so our attempt to enter the same monitor will force
! // monitor inflation.
! Asserts.assertFalse(unsafe.tryMonitorEnter(monitor),
! "Not supposed to enter the monitor first");
! barrier.await();
! t.join();
return monitor;
}
/**
* Get instance of specified AbortProvoker, inflate associated monitor
* if needed and then invoke forceAbort method in a loop.
*
--- 27,127 ----
import java.util.Objects;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import com.oracle.java.testlibrary.Asserts;
! import sun.hotspot.WhiteBox;
/**
* Base class for different transactional execution abortion
* provokers aimed to force abort due to specified reason.
*/
public abstract class AbortProvoker implements CompilableTest {
public static final long DEFAULT_ITERATIONS = 10000L;
+ private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+ @SuppressWarnings("unused")
+ private static int sharedState = 0;
/**
* Inflates monitor associated with object {@code monitor}.
* Inflation is forced by entering the same monitor from
* two different threads.
*
* @param monitor monitor to be inflated.
* @return inflated monitor.
* @throws Exception if something went wrong.
*/
public static Object inflateMonitor(Object monitor) throws Exception {
CyclicBarrier barrier = new CyclicBarrier(2);
Runnable inflatingRunnable = () -> {
! synchronized (monitor) {
try {
barrier.await();
! } catch (BrokenBarrierException | InterruptedException e) {
throw new RuntimeException(
"Synchronization issue occurred.", e);
! }
! try {
! monitor.wait();
! } catch (InterruptedException e) {
! throw new AssertionError("The thread waiting on an"
! + " inflated monitor was interrupted, thus test"
! + " results may be incorrect.", e);
! }
}
};
Thread t = new Thread(inflatingRunnable);
+ t.setDaemon(true);
t.start();
// Wait until thread t enters the monitor.
barrier.await();
! synchronized (monitor) {
! // At this point thread t is already waiting on the monitor.
! // Modifying static field just to avoid lock's elimination.
! sharedState++;
! }
! verifyMonitorState(monitor, true /* inflated */);
return monitor;
}
+ /**
+ * Verifies that {@code monitor} is a stack-lock or inflated lock depending
+ * on {@code shouldBeInflated} value. If {@code monitor} is inflated while
+ * it is expected that it should be a stack-lock, then this method attempts
+ * to deflate it by forcing a safepoint and then verifies the state once
+ * again.
+ *
+ * @param monitor monitor to be verified.
+ * @param shouldBeInflated flag indicating whether or not monitor is
+ * expected to be inflated.
+ * @throws RuntimeException if the {@code monitor} in a wrong state.
+ */
+ public static void verifyMonitorState(Object monitor,
+ boolean shouldBeInflated) {
+ if (!shouldBeInflated && WHITE_BOX.isMonitorInflated(monitor)) {
+ WHITE_BOX.forceSafepoint();
+ }
+ Asserts.assertEQ(WHITE_BOX.isMonitorInflated(monitor), shouldBeInflated,
+ "Monitor in a wrong state.");
+ }
+ /**
+ * Verifies that monitor used by the {@code provoker} is a stack-lock or
+ * inflated lock depending on {@code shouldBeInflated} value. If such
+ * monitor is inflated while it is expected that it should be a stack-lock,
+ * then this method attempts to deflate it by forcing a safepoint and then
+ * verifies the state once again.
+ *
+ * @param provoker AbortProvoker whose monitor's state should be verified.
+ * @param shouldBeInflated flag indicating whether or not monitor is
+ * expected to be inflated.
+ * @throws RuntimeException if the {@code monitor} in a wrong state.
+ */
+ public static void verifyMonitorState(AbortProvoker provoker,
+ boolean shouldBeInflated) {
+ verifyMonitorState(provoker.monitor, shouldBeInflated);
+ }
/**
* Get instance of specified AbortProvoker, inflate associated monitor
* if needed and then invoke forceAbort method in a loop.
*
*** 118,127 ****
--- 160,170 ----
if (monitorShouldBeInflated) {
provoker.inflateMonitor();
}
for (long i = 0; i < iterations; i++) {
+ AbortProvoker.verifyMonitorState(provoker, monitorShouldBeInflated);
provoker.forceAbort();
}
}
protected final Object monitor;