hotspot/test/compiler/testlibrary/rtm/AbortProvoker.java
changeset 28394 6d382dc493e5
parent 24005 6841a4be0faa
child 30604 b8d532cb6420
equal deleted inserted replaced
28393:18701d7781e7 28394:6d382dc493e5
    27 import java.util.Objects;
    27 import java.util.Objects;
    28 import java.util.concurrent.BrokenBarrierException;
    28 import java.util.concurrent.BrokenBarrierException;
    29 import java.util.concurrent.CyclicBarrier;
    29 import java.util.concurrent.CyclicBarrier;
    30 
    30 
    31 import com.oracle.java.testlibrary.Asserts;
    31 import com.oracle.java.testlibrary.Asserts;
    32 import com.oracle.java.testlibrary.Utils;
    32 import sun.hotspot.WhiteBox;
    33 import sun.misc.Unsafe;
       
    34 
    33 
    35 /**
    34 /**
    36  * Base class for different transactional execution abortion
    35  * Base class for different transactional execution abortion
    37  * provokers aimed to force abort due to specified reason.
    36  * provokers aimed to force abort due to specified reason.
    38  */
    37  */
    39 public abstract class AbortProvoker implements CompilableTest {
    38 public abstract class AbortProvoker implements CompilableTest {
    40     public static final long DEFAULT_ITERATIONS = 10000L;
    39     public static final long DEFAULT_ITERATIONS = 10000L;
       
    40     private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
       
    41     @SuppressWarnings("unused")
       
    42     private static int sharedState = 0;
    41     /**
    43     /**
    42      * Inflates monitor associated with object {@code monitor}.
    44      * Inflates monitor associated with object {@code monitor}.
    43      * Inflation is forced by entering the same monitor from
    45      * Inflation is forced by entering the same monitor from
    44      * two different threads.
    46      * two different threads.
    45      *
    47      *
    46      * @param monitor monitor to be inflated.
    48      * @param monitor monitor to be inflated.
    47      * @return inflated monitor.
    49      * @return inflated monitor.
    48      * @throws Exception if something went wrong.
    50      * @throws Exception if something went wrong.
    49      */
    51      */
    50     public static Object inflateMonitor(Object monitor) throws Exception {
    52     public static Object inflateMonitor(Object monitor) throws Exception {
    51         Unsafe unsafe = Utils.getUnsafe();
       
    52         CyclicBarrier barrier = new CyclicBarrier(2);
    53         CyclicBarrier barrier = new CyclicBarrier(2);
    53 
    54 
    54         Runnable inflatingRunnable = () -> {
    55         Runnable inflatingRunnable = () -> {
    55             unsafe.monitorEnter(monitor);
    56             synchronized (monitor) {
    56             try {
    57                 try {
    57                 barrier.await();
    58                     barrier.await();
    58                 barrier.await();
    59                 } catch (BrokenBarrierException  | InterruptedException e) {
    59             } catch (InterruptedException | BrokenBarrierException e) {
    60                     throw new RuntimeException(
    60                 throw new RuntimeException(
    61                             "Synchronization issue occurred.", e);
    61                         "Synchronization issue occurred.", e);
    62                 }
    62             } finally {
    63                 try {
    63                 unsafe.monitorExit(monitor);
    64                     monitor.wait();
       
    65                 } catch (InterruptedException e) {
       
    66                     throw new AssertionError("The thread waiting on an"
       
    67                             + " inflated monitor was interrupted, thus test"
       
    68                             + " results may be incorrect.", e);
       
    69                 }
    64             }
    70             }
    65         };
    71         };
    66 
    72 
    67         Thread t = new Thread(inflatingRunnable);
    73         Thread t = new Thread(inflatingRunnable);
       
    74         t.setDaemon(true);
    68         t.start();
    75         t.start();
    69         // Wait until thread t enters the monitor.
    76         // Wait until thread t enters the monitor.
    70         barrier.await();
    77         barrier.await();
    71         // At this point monitor will be owned by thread t,
    78         synchronized (monitor) {
    72         // so our attempt to enter the same monitor will force
    79             // At this point thread t is already waiting on the monitor.
    73         // monitor inflation.
    80             // Modifying static field just to avoid lock's elimination.
    74         Asserts.assertFalse(unsafe.tryMonitorEnter(monitor),
    81             sharedState++;
    75                             "Not supposed to enter the monitor first");
    82         }
    76         barrier.await();
    83         verifyMonitorState(monitor, true /* inflated */);
    77         t.join();
       
    78         return monitor;
    84         return monitor;
    79     }
    85     }
    80 
    86 
       
    87     /**
       
    88      * Verifies that {@code monitor} is a stack-lock or inflated lock depending
       
    89      * on {@code shouldBeInflated} value. If {@code monitor} is inflated while
       
    90      * it is expected that it should be a stack-lock, then this method attempts
       
    91      * to deflate it by forcing a safepoint and then verifies the state once
       
    92      * again.
       
    93      *
       
    94      * @param monitor monitor to be verified.
       
    95      * @param shouldBeInflated flag indicating whether or not monitor is
       
    96      *                         expected to be inflated.
       
    97      * @throws RuntimeException if the {@code monitor} in a wrong state.
       
    98      */
       
    99     public static void verifyMonitorState(Object monitor,
       
   100             boolean shouldBeInflated) {
       
   101         if (!shouldBeInflated && WHITE_BOX.isMonitorInflated(monitor)) {
       
   102             WHITE_BOX.forceSafepoint();
       
   103         }
       
   104         Asserts.assertEQ(WHITE_BOX.isMonitorInflated(monitor), shouldBeInflated,
       
   105                 "Monitor in a wrong state.");
       
   106     }
       
   107     /**
       
   108      * Verifies that monitor used by the {@code provoker} is a stack-lock or
       
   109      * inflated lock depending on {@code shouldBeInflated} value. If such
       
   110      * monitor is inflated while it is expected that it should be a stack-lock,
       
   111      * then this method attempts to deflate it by forcing a safepoint and then
       
   112      * verifies the state once again.
       
   113      *
       
   114      * @param provoker AbortProvoker whose monitor's state should be verified.
       
   115      * @param shouldBeInflated flag indicating whether or not monitor is
       
   116      *                         expected to be inflated.
       
   117      * @throws RuntimeException if the {@code monitor} in a wrong state.
       
   118      */
       
   119     public static void verifyMonitorState(AbortProvoker provoker,
       
   120             boolean shouldBeInflated) {
       
   121         verifyMonitorState(provoker.monitor, shouldBeInflated);
       
   122     }
    81 
   123 
    82     /**
   124     /**
    83      * Get instance of specified AbortProvoker, inflate associated monitor
   125      * Get instance of specified AbortProvoker, inflate associated monitor
    84      * if needed and then invoke forceAbort method in a loop.
   126      * if needed and then invoke forceAbort method in a loop.
    85      *
   127      *
   118         if (monitorShouldBeInflated) {
   160         if (monitorShouldBeInflated) {
   119             provoker.inflateMonitor();
   161             provoker.inflateMonitor();
   120         }
   162         }
   121 
   163 
   122         for (long i = 0; i < iterations; i++) {
   164         for (long i = 0; i < iterations; i++) {
       
   165             AbortProvoker.verifyMonitorState(provoker, monitorShouldBeInflated);
   123             provoker.forceAbort();
   166             provoker.forceAbort();
   124         }
   167         }
   125     }
   168     }
   126 
   169 
   127     protected final Object monitor;
   170     protected final Object monitor;