test/compiler/testlibrary/rtm/AbortProvoker.java

Print this page




  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 package rtm;
  26 
  27 import java.util.Objects;
  28 import java.util.concurrent.BrokenBarrierException;
  29 import java.util.concurrent.CyclicBarrier;
  30 
  31 import com.oracle.java.testlibrary.Asserts;
  32 import com.oracle.java.testlibrary.Utils;
  33 import sun.misc.Unsafe;
  34 
  35 /**
  36  * Base class for different transactional execution abortion
  37  * provokers aimed to force abort due to specified reason.
  38  */
  39 public abstract class AbortProvoker implements CompilableTest {
  40     public static final long DEFAULT_ITERATIONS = 10000L;



  41     /**
  42      * Inflates monitor associated with object {@code monitor}.
  43      * Inflation is forced by entering the same monitor from
  44      * two different threads.
  45      *
  46      * @param monitor monitor to be inflated.
  47      * @return inflated monitor.
  48      * @throws Exception if something went wrong.
  49      */
  50     public static Object inflateMonitor(Object monitor) throws Exception {
  51         Unsafe unsafe = Utils.getUnsafe();
  52         CyclicBarrier barrier = new CyclicBarrier(2);
  53 
  54         Runnable inflatingRunnable = () -> {
  55             unsafe.monitorEnter(monitor);
  56             try {
  57                 barrier.await();
  58                 barrier.await();
  59             } catch (InterruptedException | BrokenBarrierException e) {
  60                 throw new RuntimeException(
  61                         "Synchronization issue occurred.", e);
  62             } finally {
  63                 unsafe.monitorExit(monitor);






  64             }
  65         };
  66 
  67         Thread t = new Thread(inflatingRunnable);

  68         t.start();
  69         // Wait until thread t enters the monitor.
  70         barrier.await();
  71         // At this point monitor will be owned by thread t,
  72         // so our attempt to enter the same monitor will force
  73         // monitor inflation.
  74         Asserts.assertFalse(unsafe.tryMonitorEnter(monitor),
  75                             "Not supposed to enter the monitor first");
  76         barrier.await();
  77         t.join();
  78         return monitor;
  79     }
  80 




































  81 
  82     /**
  83      * Get instance of specified AbortProvoker, inflate associated monitor
  84      * if needed and then invoke forceAbort method in a loop.
  85      *
  86      * Usage:
  87      * AbortProvoker <AbortType name> [<inflate monitor&gt
  88      * [<iterations> [ <delay>]]]
  89      *
  90      *  Default parameters are:
  91      *  <ul>
  92      *  <li>inflate monitor = <b>true</b></li>
  93      *  <li>iterations = {@code AbortProvoker.DEFAULT_ITERATIONS}</li>
  94      *  <li>delay = <b>0</b></li>
  95      *  </ul>
  96      */
  97     public static void main(String args[]) throws Throwable {
  98         Asserts.assertGT(args.length, 0, "At least one argument is required.");
  99 
 100         AbortType abortType = AbortType.lookup(Integer.valueOf(args[0]));


 103 
 104         if (args.length > 1) {
 105             monitorShouldBeInflated = Boolean.valueOf(args[1]);
 106 
 107             if (args.length > 2) {
 108                 iterations = Long.valueOf(args[2]);
 109 
 110                 if (args.length > 3) {
 111                     Thread.sleep(Integer.valueOf(args[3]));
 112                 }
 113             }
 114         }
 115 
 116         AbortProvoker provoker = abortType.provoker();
 117 
 118         if (monitorShouldBeInflated) {
 119             provoker.inflateMonitor();
 120         }
 121 
 122         for (long i = 0; i < iterations; i++) {

 123             provoker.forceAbort();
 124         }
 125     }
 126 
 127     protected final Object monitor;
 128 
 129     protected AbortProvoker() {
 130         this(new Object());
 131     }
 132 
 133     protected AbortProvoker(Object monitor) {
 134         this.monitor = Objects.requireNonNull(monitor);
 135     }
 136 
 137     /**
 138      * Inflates monitor used by this AbortProvoker instance.
 139      * @throws Exception
 140      */
 141     public void inflateMonitor() throws Exception {
 142         AbortProvoker.inflateMonitor(monitor);




  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 package rtm;
  26 
  27 import java.util.Objects;
  28 import java.util.concurrent.BrokenBarrierException;
  29 import java.util.concurrent.CyclicBarrier;
  30 
  31 import com.oracle.java.testlibrary.Asserts;
  32 import sun.hotspot.WhiteBox;

  33 
  34 /**
  35  * Base class for different transactional execution abortion
  36  * provokers aimed to force abort due to specified reason.
  37  */
  38 public abstract class AbortProvoker implements CompilableTest {
  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;
  43     /**
  44      * Inflates monitor associated with object {@code monitor}.
  45      * Inflation is forced by entering the same monitor from
  46      * two different threads.
  47      *
  48      * @param monitor monitor to be inflated.
  49      * @return inflated monitor.
  50      * @throws Exception if something went wrong.
  51      */
  52     public static Object inflateMonitor(Object monitor) throws Exception {

  53         CyclicBarrier barrier = new CyclicBarrier(2);
  54 
  55         Runnable inflatingRunnable = () -> {
  56             synchronized (monitor) {
  57                 try {
  58                     barrier.await();
  59                 } catch (BrokenBarrierException  | InterruptedException e) {

  60                     throw new RuntimeException(
  61                             "Synchronization issue occurred.", e);
  62                 }
  63                 try {
  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                 }
  70             }
  71         };
  72 
  73         Thread t = new Thread(inflatingRunnable);
  74         t.setDaemon(true);
  75         t.start();
  76         // Wait until thread t enters the monitor.
  77         barrier.await();
  78         synchronized (monitor) {
  79             // At this point thread t is already waiting on the monitor.
  80             // Modifying static field just to avoid lock's elimination.
  81             sharedState++;
  82         }
  83         verifyMonitorState(monitor, true /* inflated */);

  84         return monitor;
  85     }
  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     }
 123 
 124     /**
 125      * Get instance of specified AbortProvoker, inflate associated monitor
 126      * if needed and then invoke forceAbort method in a loop.
 127      *
 128      * Usage:
 129      * AbortProvoker &lt;AbortType name&gt; [&lt;inflate monitor&gt
 130      * [&lt;iterations&gt; [ &lt;delay&gt;]]]
 131      *
 132      *  Default parameters are:
 133      *  <ul>
 134      *  <li>inflate monitor = <b>true</b></li>
 135      *  <li>iterations = {@code AbortProvoker.DEFAULT_ITERATIONS}</li>
 136      *  <li>delay = <b>0</b></li>
 137      *  </ul>
 138      */
 139     public static void main(String args[]) throws Throwable {
 140         Asserts.assertGT(args.length, 0, "At least one argument is required.");
 141 
 142         AbortType abortType = AbortType.lookup(Integer.valueOf(args[0]));


 145 
 146         if (args.length > 1) {
 147             monitorShouldBeInflated = Boolean.valueOf(args[1]);
 148 
 149             if (args.length > 2) {
 150                 iterations = Long.valueOf(args[2]);
 151 
 152                 if (args.length > 3) {
 153                     Thread.sleep(Integer.valueOf(args[3]));
 154                 }
 155             }
 156         }
 157 
 158         AbortProvoker provoker = abortType.provoker();
 159 
 160         if (monitorShouldBeInflated) {
 161             provoker.inflateMonitor();
 162         }
 163 
 164         for (long i = 0; i < iterations; i++) {
 165             AbortProvoker.verifyMonitorState(provoker, monitorShouldBeInflated);
 166             provoker.forceAbort();
 167         }
 168     }
 169 
 170     protected final Object monitor;
 171 
 172     protected AbortProvoker() {
 173         this(new Object());
 174     }
 175 
 176     protected AbortProvoker(Object monitor) {
 177         this.monitor = Objects.requireNonNull(monitor);
 178     }
 179 
 180     /**
 181      * Inflates monitor used by this AbortProvoker instance.
 182      * @throws Exception
 183      */
 184     public void inflateMonitor() throws Exception {
 185         AbortProvoker.inflateMonitor(monitor);