changeset 429:4ece888be604

7902465: Many jcstress tests wrongly assume long/double access atomicity
author shade
date Fri, 10 May 2019 00:18:40 +0200
parents 7e407984a7db
children 96d2a23d4b7b
files jcstress-test-gen/src/main/java/org/openjdk/jcstress/chapters/Chapter0eTestGenerator.java jcstress-test-gen/src/main/java/org/openjdk/jcstress/chapters/Chapter1dTestGenerator.java jcstress-test-gen/src/main/resources/acqrel/X-ArrayAcqRelTest.java.template jcstress-test-gen/src/main/resources/acqrel/X-FieldAcqRelTest.java.template jcstress-test-gen/src/main/resources/coherence/X-ArrayCoherenceTest.java.template jcstress-test-gen/src/main/resources/coherence/X-FieldCoherenceTest.java.template jcstress-test-gen/src/main/resources/coherence/X-VarHandleArrayCoherenceTest.java.template jcstress-test-gen/src/main/resources/coherence/X-VarHandleByteArrayViewCoherenceTest.java.template jcstress-test-gen/src/main/resources/coherence/X-VarHandleDirectByteBufferViewCoherenceTest.java.template jcstress-test-gen/src/main/resources/coherence/X-VarHandleFieldCoherenceTest.java.template jcstress-test-gen/src/main/resources/coherence/X-VarHandleHeapByteBufferViewCoherenceTest.java.template
diffstat 11 files changed, 54 insertions(+), 120 deletions(-) [+]
line wrap: on
line diff
--- a/jcstress-test-gen/src/main/java/org/openjdk/jcstress/chapters/Chapter0eTestGenerator.java	Mon Apr 29 23:19:54 2019 +0200
+++ b/jcstress-test-gen/src/main/java/org/openjdk/jcstress/chapters/Chapter0eTestGenerator.java	Fri May 10 00:18:40 2019 +0200
@@ -37,8 +37,11 @@
 public class Chapter0eTestGenerator {
 
     public static final String PREFIX = "org.openjdk.jcstress.tests";
-    public static final String[] TYPES = new String[]{"byte", "boolean", "char", "short", "int", "float", "long", "double", "String"};
-    public static final String[] MODIFIERS = new String[]{ "", "volatile" };
+
+    public static final String[] TYPES_G = new String[]{"byte", "boolean", "char", "short", "int", "float", "long", "double", "String"};
+
+    // Test makes little sense with non-access-atomic values. Access atomicity is verified elsewhere.
+    public static final String[] TYPES_V = new String[]{"byte", "boolean", "char", "short", "int", "float", "String"};
 
     public static void main(String... args) throws IOException {
         if (args.length < 1) {
@@ -51,32 +54,22 @@
                 GeneratorUtils.readFromResource("/acqrel/X-FieldAcqRelTest.java.template"),
                 "acqrel.fields"
         );
-
-        makeTests(
-                dest,
-                GeneratorUtils.readFromResource("/acqrel/X-ArrayAcqRelTest.java.template"),
-                "acqrel.arrays"
-        );
-
     }
 
     private static void makeTests(String dest, String template, String label) throws IOException {
-        for (String modifier : MODIFIERS) {
-            String pack = PREFIX + "." + label + "." + (modifier.equals("") ? "plain" : modifier + "s");
-            for (String typeV : TYPES) {
-                for (String typeG : TYPES) {
-                    String name = testName(typeG, typeV);
-                    String res = Spp.spp(template,
-                            keys(modifier, typeG, label),
-                            vars(modifier, typeG, typeV, pack, name));
+        String pack = PREFIX + "." + label + ".volatiles";
+        for (String typeV : TYPES_V) {
+            for (String typeG : TYPES_G) {
+                String name = testName(typeG, typeV);
+                String res = Spp.spp(template,
+                        keys("volatile", typeG, label),
+                        vars("volatile", typeG, typeV, pack, name));
 
-                    GeneratorUtils.writeOut(dest, pack, name, res);
-                }
+                GeneratorUtils.writeOut(dest, pack, name, res);
             }
         }
     }
 
-
     private static Map<String, String> vars(String modifier, String typeG, String typeV, String pack, String name) {
         Map<String, String> map = new HashMap<>();
         map.put("typeG", typeG);
@@ -104,17 +97,10 @@
     private static Set<String> keys(String modifier, String type, String label) {
         Set<String> set = new HashSet<>();
         set.add(type);
-        if (racy(modifier, type, label)) {
-            set.add("racy");
-        }
         set.add(modifier);
         return set;
     }
 
-    private static boolean racy(String modifier, String type, String label) {
-        return (!modifier.equals("volatile") || label.contains("array"));
-    }
-
     private static String testName(String typeG, String typeV) {
         return StringUtils.upcaseFirst(typeG) + StringUtils.upcaseFirst(typeV) + "Test";
     }
--- a/jcstress-test-gen/src/main/java/org/openjdk/jcstress/chapters/Chapter1dTestGenerator.java	Mon Apr 29 23:19:54 2019 +0200
+++ b/jcstress-test-gen/src/main/java/org/openjdk/jcstress/chapters/Chapter1dTestGenerator.java	Fri May 10 00:18:40 2019 +0200
@@ -38,7 +38,12 @@
 public class Chapter1dTestGenerator {
 
     public static final String PREFIX = "org.openjdk.jcstress.tests";
-    public static final String[] TYPES_ALL = new String[]{"byte", "boolean", "char", "short", "int", "float", "long", "double", "String"};
+
+    public static final String[] TYPES_G = new String[]{"byte", "boolean", "char", "short", "int", "float", "long", "double", "String"};
+
+    // Test makes little sense with non-access-atomic types. Access atomicity is verified elsewhere.
+    public static final String[] TYPES_V = new String[]{"byte", "boolean", "char", "short", "int", "float", "String"};
+
     public static final String[] TYPES_VIEWS = new String[]{"char", "short", "int", "float", "long", "double"};
 
     public static void main(String... args) throws IOException {
@@ -98,10 +103,11 @@
     }
 
     private static void makeTests(String dest, String template, String label) throws IOException {
-        for (VarHandleMode gs : VarHandleMode.values()) {
+        // Only care about the access-atomic guards
+        for (VarHandleMode gs : new VarHandleMode[] { VarHandleMode.OPAQUE, VarHandleMode.ACQ_REL, VarHandleMode.VOLATILE } ) {
             String pack = PREFIX + "." + label + "." + gs;
-            for (String typeG : TYPES_ALL) {
-                for (String typeV : TYPES_ALL) {
+            for (String typeG : TYPES_G) {
+                for (String typeV : TYPES_V) {
                     String name = testName(typeG, typeV);
                     String res = Spp.spp(template,
                             keys(typeG, typeV, gs),
@@ -114,11 +120,12 @@
     }
 
     private static void makeBufferTests(String dest, String template, String label) throws IOException {
-        for (VarHandleMode gs : VarHandleMode.values()) {
+        // Only care about the access-atomic guards
+        for (VarHandleMode gs : new VarHandleMode[] { VarHandleMode.OPAQUE, VarHandleMode.ACQ_REL, VarHandleMode.VOLATILE } ) {
             for (ByteOrder bo : new ByteOrder[] { ByteOrder.BIG_ENDIAN, ByteOrder.LITTLE_ENDIAN }) {
                 String pack = PREFIX + "." + label + "." + bo.toString().toLowerCase().replace("_endian", "") + "." + gs;
                 for (String typeG : TYPES_VIEWS) {
-                    for (String typeV : TYPES_ALL) {
+                    for (String typeV : TYPES_V) {
                         String name = testName(typeG, typeV);
                         String res = Spp.spp(template,
                                 keys(typeG, typeV, gs),
--- a/jcstress-test-gen/src/main/resources/acqrel/X-ArrayAcqRelTest.java.template	Mon Apr 29 23:19:54 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2017, Red Hat Inc. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package $package$;
-
-import org.openjdk.jcstress.annotations.*;
-import org.openjdk.jcstress.infra.results.*;
-
-#warn
-
-/**
- * Tests if fields experience memory consistency problems.
- */
-@JCStressTest
-@Outcome(id = {
-        "$defaultV$, $defaultV$, $defaultG$",
-        "$setV$, $defaultV$, $defaultG$",
-        "$defaultV$, $setV$, $defaultG$",
-        "$setV$, $setV$, $defaultG$",
-    }, expect = Expect.ACCEPTABLE, desc = "Default value for guard, allowed to see anything.")
-@Outcome(id = {
-        "$defaultV$, $setV$, $setG$",
-        "$setV$, $setV$, $setG$",
-    }, expect = Expect.ACCEPTABLE, desc = "Observing the value for guard, allowed to see latest value.")
-#if[racy]
-@Outcome(id = {
-        "$defaultV$, $defaultV$, $setG$",
-        "$setV$, $defaultV$, $setG$",
-    }, expect = Expect.ACCEPTABLE, desc = "Seeing previous writes, allowed with racy guard.")
-#else[racy]
-@Outcome(id = {
-        "$defaultV$, $defaultV$, $setG$",
-        "$setV$, $defaultV$, $setG$",
-    }, expect = Expect.FORBIDDEN, desc = "Seeing previous writes, forbidden with proper guard.")
-#end[racy]
-@State
-public class $name$ {
-
-    $typeV$ v;
-    $modifier$$typeG$[] g = new $typeG$[1];
-
-    @Actor
-    public void actor1() {
-        v = $defaultVLiteral$;
-        v = $setVLiteral$;
-        g[0] = $setGLiteral$;
-    }
-
-    @Actor
-    public void actor2($TV$$TV$$TG$_Result r) {
-        $typeV$ v1 = v;
-        $typeG$ g1 = g[0];
-        $typeV$ v2 = v;
-        r.r1 = v1;
-        r.r2 = v2;
-        r.r3 = g1;
-    }
-
-}
--- a/jcstress-test-gen/src/main/resources/acqrel/X-FieldAcqRelTest.java.template	Mon Apr 29 23:19:54 2019 +0200
+++ b/jcstress-test-gen/src/main/resources/acqrel/X-FieldAcqRelTest.java.template	Fri May 10 00:18:40 2019 +0200
@@ -43,17 +43,10 @@
         "$defaultV$, $setV$, $setG$",
         "$setV$, $setV$, $setG$",
     }, expect = Expect.ACCEPTABLE, desc = "Observing the value for guard, allowed to see latest value.")
-#if[racy]
-@Outcome(id = {
-        "$defaultV$, $defaultV$, $setG$",
-        "$setV$, $defaultV$, $setG$",
-    }, expect = Expect.ACCEPTABLE, desc = "Seeing previous writes, allowed with racy guard.")
-#else[racy]
 @Outcome(id = {
         "$defaultV$, $defaultV$, $setG$",
         "$setV$, $defaultV$, $setG$",
     }, expect = Expect.FORBIDDEN, desc = "Seeing previous writes, forbidden with proper guard.")
-#end[racy]
 @State
 public class $name$ {
 
--- a/jcstress-test-gen/src/main/resources/coherence/X-ArrayCoherenceTest.java.template	Mon Apr 29 23:19:54 2019 +0200
+++ b/jcstress-test-gen/src/main/resources/coherence/X-ArrayCoherenceTest.java.template	Fri May 10 00:18:40 2019 +0200
@@ -36,11 +36,15 @@
 @Outcome(id = "$default$, $default$", expect = Expect.ACCEPTABLE, desc = "Default value for the fields. Allowed to see this: data race.")
 @Outcome(id = "$default$, $set$", expect = Expect.ACCEPTABLE, desc = "Observe second read, but not first: sequential consistency.")
 @Outcome(id = "$set$, $set$", expect = Expect.ACCEPTABLE, desc = "Observers sees both read.")
+#if[alwaysAtomic]
 #if[coherent]
 @Outcome(id = "$set$, $default$", expect = Expect.FORBIDDEN, desc = "Seeing first read, but not second: coherence violation.")
 #else[coherent]
 @Outcome(id = "$set$, $default$", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Seeing first read, but not second: non-coherent.")
 #end[coherent]
+#else[alwaysAtomic]
+@Outcome(id = ".*, .*", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Non-atomic accesses are allowed.")
+#end[alwaysAtomic]
 @State
 public class $name$ {
 
--- a/jcstress-test-gen/src/main/resources/coherence/X-FieldCoherenceTest.java.template	Mon Apr 29 23:19:54 2019 +0200
+++ b/jcstress-test-gen/src/main/resources/coherence/X-FieldCoherenceTest.java.template	Fri May 10 00:18:40 2019 +0200
@@ -36,11 +36,15 @@
 @Outcome(id = "$default$, $default$", expect = Expect.ACCEPTABLE, desc = "Default value for the fields. Allowed to see this: data race.")
 @Outcome(id = "$default$, $set$", expect = Expect.ACCEPTABLE, desc = "Observe second read, but not first: sequential consistency.")
 @Outcome(id = "$set$, $set$", expect = Expect.ACCEPTABLE, desc = "Observers sees both read.")
+#if[alwaysAtomic]
 #if[coherent]
 @Outcome(id = "$set$, $default$", expect = Expect.FORBIDDEN, desc = "Seeing first read, but not second: coherence violation.")
 #else[coherent]
 @Outcome(id = "$set$, $default$", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Seeing first read, but not second: non-coherent.")
 #end[coherent]
+#else[alwaysAtomic]
+@Outcome(id = ".*, .*", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Non-atomic accesses are allowed.")
+#end[alwaysAtomic]
 @State
 public class $name$ {
 
--- a/jcstress-test-gen/src/main/resources/coherence/X-VarHandleArrayCoherenceTest.java.template	Mon Apr 29 23:19:54 2019 +0200
+++ b/jcstress-test-gen/src/main/resources/coherence/X-VarHandleArrayCoherenceTest.java.template	Fri May 10 00:18:40 2019 +0200
@@ -39,11 +39,15 @@
 @Outcome(id = "$default$, $default$", expect = Expect.ACCEPTABLE, desc = "Default value for the fields. Allowed to see this: data race.")
 @Outcome(id = "$default$, $set$", expect = Expect.ACCEPTABLE, desc = "Observe second read, but not first: sequential consistency.")
 @Outcome(id = "$set$, $set$", expect = Expect.ACCEPTABLE, desc = "Observers sees both read.")
+#if[alwaysAtomic]
 #if[coherent]
 @Outcome(id = "$set$, $default$", expect = Expect.FORBIDDEN, desc = "Seeing first read, but not second: coherence violation.")
 #else[coherent]
 @Outcome(id = "$set$, $default$", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Seeing first read, but not second: non-coherent.")
 #end[coherent]
+#else[alwaysAtomic]
+@Outcome(id = ".*, .*", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Non-atomic accesses are allowed.")
+#end[alwaysAtomic]
 @State
 public class $name$ {
 
--- a/jcstress-test-gen/src/main/resources/coherence/X-VarHandleByteArrayViewCoherenceTest.java.template	Mon Apr 29 23:19:54 2019 +0200
+++ b/jcstress-test-gen/src/main/resources/coherence/X-VarHandleByteArrayViewCoherenceTest.java.template	Fri May 10 00:18:40 2019 +0200
@@ -41,11 +41,15 @@
 @Outcome(id = "$default$, $default$", expect = Expect.ACCEPTABLE, desc = "Default value for the fields. Allowed to see this: data race.")
 @Outcome(id = "$default$, $set$", expect = Expect.ACCEPTABLE, desc = "Observe second read, but not first: sequential consistency.")
 @Outcome(id = "$set$, $set$", expect = Expect.ACCEPTABLE, desc = "Observers sees both read.")
+#if[alwaysAtomic]
 #if[coherent]
 @Outcome(id = "$set$, $default$", expect = Expect.FORBIDDEN, desc = "Seeing first read, but not second: coherence violation.")
 #else[coherent]
 @Outcome(id = "$set$, $default$", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Seeing first read, but not second: non-coherent.")
 #end[coherent]
+#else[alwaysAtomic]
+@Outcome(id = ".*, .*", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Non-atomic accesses are allowed.")
+#end[alwaysAtomic]
 @State
 public class $name$ {
 
--- a/jcstress-test-gen/src/main/resources/coherence/X-VarHandleDirectByteBufferViewCoherenceTest.java.template	Mon Apr 29 23:19:54 2019 +0200
+++ b/jcstress-test-gen/src/main/resources/coherence/X-VarHandleDirectByteBufferViewCoherenceTest.java.template	Fri May 10 00:18:40 2019 +0200
@@ -41,11 +41,15 @@
 @Outcome(id = "$default$, $default$", expect = Expect.ACCEPTABLE, desc = "Default value for the fields. Allowed to see this: data race.")
 @Outcome(id = "$default$, $set$", expect = Expect.ACCEPTABLE, desc = "Observe second read, but not first: sequential consistency.")
 @Outcome(id = "$set$, $set$", expect = Expect.ACCEPTABLE, desc = "Observers sees both read.")
+#if[alwaysAtomic]
 #if[coherent]
 @Outcome(id = "$set$, $default$", expect = Expect.FORBIDDEN, desc = "Seeing first read, but not second: coherence violation.")
 #else[coherent]
 @Outcome(id = "$set$, $default$", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Seeing first read, but not second: non-coherent.")
 #end[coherent]
+#else[alwaysAtomic]
+@Outcome(id = ".*, .*", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Non-atomic accesses are allowed.")
+#end[alwaysAtomic]
 @State
 public class $name$ {
 
--- a/jcstress-test-gen/src/main/resources/coherence/X-VarHandleFieldCoherenceTest.java.template	Mon Apr 29 23:19:54 2019 +0200
+++ b/jcstress-test-gen/src/main/resources/coherence/X-VarHandleFieldCoherenceTest.java.template	Fri May 10 00:18:40 2019 +0200
@@ -39,11 +39,15 @@
 @Outcome(id = "$default$, $default$", expect = Expect.ACCEPTABLE, desc = "Default value for the fields. Allowed to see this: data race.")
 @Outcome(id = "$default$, $set$", expect = Expect.ACCEPTABLE, desc = "Observe second read, but not first: sequential consistency.")
 @Outcome(id = "$set$, $set$", expect = Expect.ACCEPTABLE, desc = "Observers sees both read.")
+#if[alwaysAtomic]
 #if[coherent]
 @Outcome(id = "$set$, $default$", expect = Expect.FORBIDDEN, desc = "Seeing first read, but not second: coherence violation.")
 #else[coherent]
 @Outcome(id = "$set$, $default$", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Seeing first read, but not second: non-coherent.")
 #end[coherent]
+#else[alwaysAtomic]
+@Outcome(id = ".*, .*", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Non-atomic accesses are allowed.")
+#end[alwaysAtomic]
 @State
 public class $name$ {
 
--- a/jcstress-test-gen/src/main/resources/coherence/X-VarHandleHeapByteBufferViewCoherenceTest.java.template	Mon Apr 29 23:19:54 2019 +0200
+++ b/jcstress-test-gen/src/main/resources/coherence/X-VarHandleHeapByteBufferViewCoherenceTest.java.template	Fri May 10 00:18:40 2019 +0200
@@ -41,11 +41,15 @@
 @Outcome(id = "$default$, $default$", expect = Expect.ACCEPTABLE, desc = "Default value for the fields. Allowed to see this: data race.")
 @Outcome(id = "$default$, $set$", expect = Expect.ACCEPTABLE, desc = "Observe second read, but not first: sequential consistency.")
 @Outcome(id = "$set$, $set$", expect = Expect.ACCEPTABLE, desc = "Observers sees both read.")
+#if[alwaysAtomic]
 #if[coherent]
 @Outcome(id = "$set$, $default$", expect = Expect.FORBIDDEN, desc = "Seeing first read, but not second: coherence violation.")
 #else[coherent]
 @Outcome(id = "$set$, $default$", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Seeing first read, but not second: non-coherent.")
 #end[coherent]
+#else[alwaysAtomic]
+@Outcome(id = ".*, .*", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Non-atomic accesses are allowed.")
+#end[alwaysAtomic]
 @State
 public class $name$ {