1 /*
   2  * Copyright (c) 2013 SAP SE. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  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  * @test
  26  * @bug 8007898
  27  * @summary Incorrect optimization of Memory Barriers in Matcher::post_store_load_barrier().
  28  * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:CICompilerCount=1 -XX:+StressGCM -XX:+StressLCM DekkerTest
  29  * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:CICompilerCount=1 -XX:+StressGCM -XX:+StressLCM DekkerTest
  30  * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:CICompilerCount=1 -XX:+StressGCM -XX:+StressLCM DekkerTest
  31  * @author Martin Doerr martin DOT doerr AT sap DOT com
  32  *
  33  * Run 3 times since the failure is intermittent.
  34  */
  35 
  36 public class DekkerTest {
  37 
  38     /*
  39       Read After Write Test (basically a simple Dekker test with volatile variables)
  40       Derived from the original jcstress test, available at:
  41         http://hg.openjdk.java.net/code-tools/jcstress/file/6c339a5aa00d/
  42         tests-custom/src/main/java/org/openjdk/jcstress/tests/volatiles/DekkerTest.java
  43      */
  44 
  45     static final int ITERATIONS = 1000000;
  46 
  47     static class TestData {
  48         public volatile int a;
  49         public volatile int b;
  50     }
  51 
  52     static class ResultData {
  53         public int a;
  54         public int b;
  55     }
  56 
  57     TestData[]   testDataArray;
  58     ResultData[] results;
  59 
  60     volatile boolean start;
  61 
  62     public DekkerTest() {
  63         testDataArray = new TestData[ITERATIONS];
  64         results = new ResultData[ITERATIONS];
  65         for (int i = 0; i < ITERATIONS; ++i) {
  66             testDataArray[i] = new TestData();
  67             results[i] = new ResultData();
  68         }
  69         start = false;
  70     }
  71 
  72     public void reset() {
  73         for (int i = 0; i < ITERATIONS; ++i) {
  74             testDataArray[i].a = 0;
  75             testDataArray[i].b = 0;
  76             results[i].a = 0;
  77             results[i].b = 0;
  78         }
  79         start = false;
  80     }
  81 
  82     int actor1(TestData t) {
  83         t.a = 1;
  84         return t.b;
  85     }
  86 
  87     int actor2(TestData t) {
  88         t.b = 1;
  89         return t.a;
  90     }
  91 
  92     class Runner1 extends Thread {
  93         public void run() {
  94             do {} while (!start);
  95             for (int i = 0; i < ITERATIONS; ++i) {
  96                 results[i].a = actor1(testDataArray[i]);
  97             }
  98         }
  99     }
 100 
 101     class Runner2 extends Thread {
 102         public void run() {
 103             do {} while (!start);
 104             for (int i = 0; i < ITERATIONS; ++i) {
 105                 results[i].b = actor2(testDataArray[i]);
 106             }
 107         }
 108     }
 109 
 110     void testRunner() {
 111         Thread thread1 = new Runner1();
 112         Thread thread2 = new Runner2();
 113         thread1.start();
 114         thread2.start();
 115         do {} while (!thread1.isAlive());
 116         do {} while (!thread2.isAlive());
 117         start = true;
 118         Thread.yield();
 119         try {
 120             thread1.join();
 121             thread2.join();
 122         } catch (InterruptedException e) {
 123             System.out.println("interrupted!");
 124             System.exit(1);
 125         }
 126     }
 127 
 128     boolean printResult() {
 129         int[] count = new int[4];
 130         for (int i = 0; i < ITERATIONS; ++i) {
 131             int event_kind = (results[i].a << 1) + results[i].b;
 132             ++count[event_kind];
 133         }
 134         if (count[0] == 0 && count[3] == 0) {
 135             System.out.println("[not interesting]");
 136             return false; // not interesting
 137         }
 138         String error = (count[0] == 0) ? " ok" : " disallowed!";
 139         System.out.println("[0,0] " + count[0] + error);
 140         System.out.println("[0,1] " + count[1]);
 141         System.out.println("[1,0] " + count[2]);
 142         System.out.println("[1,1] " + count[3]);
 143         return (count[0] != 0);
 144     }
 145 
 146     public static void main(String args[]) {
 147         DekkerTest test = new DekkerTest();
 148         final int runs = 30;
 149         int failed = 0;
 150         for (int c = 0; c < runs; ++c) {
 151             test.testRunner();
 152             if (test.printResult()) {
 153                 failed++;
 154             }
 155             test.reset();
 156         }
 157         if (failed > 0) {
 158             throw new InternalError("FAILED. Got " + failed + " failed ITERATIONS");
 159         }
 160         System.out.println("PASSED.");
 161     }
 162 
 163 }