diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp index 5d20c287584..687b06c524c 100644 --- a/src/hotspot/share/classfile/classFileParser.cpp +++ b/src/hotspot/share/classfile/classFileParser.cpp @@ -6603,14 +6603,14 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st } } - if (_class_name == vmSymbols::java_lang_NonTearable() && _loader_data->class_loader() == NULL) { + if (_class_name == vmSymbols::java_lang_AtomicAccess() && _loader_data->class_loader() == NULL) { // This is the original source of this condition. - // It propagates by inheritance, as if testing "instanceof NonTearable". + // It propagates by inheritance, as if testing "instanceof AtomicAccess". _is_declared_atomic = true; - } else if (*ForceNonTearable != '\0') { + } else if (*ForceAtomicAccess != '\0') { // Allow a command line switch to force the same atomicity property: const char* class_name_str = _class_name->as_C_string(); - if (StringUtils::class_list_match(ForceNonTearable, class_name_str)) { + if (StringUtils::class_list_match(ForceAtomicAccess, class_name_str)) { _is_declared_atomic = true; } } diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp index a4033f4ef65..d289b8ed1f7 100644 --- a/src/hotspot/share/classfile/vmSymbols.hpp +++ b/src/hotspot/share/classfile/vmSymbols.hpp @@ -66,7 +66,7 @@ template(java_lang_Thread, "java/lang/Thread") \ template(java_lang_ThreadGroup, "java/lang/ThreadGroup") \ template(java_lang_Cloneable, "java/lang/Cloneable") \ - template(java_lang_NonTearable, "java/lang/NonTearable") \ + template(java_lang_AtomicAccess, "java/lang/AtomicAccess") \ template(java_lang_Throwable, "java/lang/Throwable") \ template(java_lang_ClassLoader, "java/lang/ClassLoader") \ template(java_lang_ThreadDeath, "java/lang/ThreadDeath") \ diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp index ee9be15139a..5cd7d82e0d4 100644 --- a/src/hotspot/share/oops/instanceKlass.hpp +++ b/src/hotspot/share/oops/instanceKlass.hpp @@ -286,7 +286,7 @@ class InstanceKlass: public Klass { _misc_has_inline_type_fields = 1 << 16, // has inline fields and related embedded section is not empty _misc_is_empty_inline_type = 1 << 17, // empty inline type (*) _misc_is_naturally_atomic = 1 << 18, // loaded/stored in one instruction - _misc_is_declared_atomic = 1 << 19, // implements jl.NonTearable + _misc_is_declared_atomic = 1 << 19, // implements j.l.AtomicAccess _misc_invalid_inline_super = 1 << 20, // invalid super type for an inline type _misc_invalid_identity_super = 1 << 21, // invalid super type for an identity type _misc_has_injected_identityObject = 1 << 22, // IdentityObject has been injected by the JVM @@ -446,11 +446,11 @@ class InstanceKlass: public Klass { _misc_flags |= _misc_is_naturally_atomic; } - // Query if this class implements jl.NonTearable or was - // mentioned in the JVM option ForceNonTearable. + // Query if this class implements j.l.AtomicAccess or was + // mentioned in the JVM option ForceAtomicAccess. // This bit can occur anywhere, but is only significant // for inline classes *and* their super types. - // It inherits from supers along with NonTearable. + // It inherits from supers along with AtomicAccess. bool is_declared_atomic() const { return (_misc_flags & _misc_is_declared_atomic) != 0; } diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index b6fde3e6a41..341f457dc81 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -2077,8 +2077,8 @@ const intx ObjectAlignmentInBytes = 8; product(bool, UseArrayMarkWordCheck, NOT_LP64(false) LP64_ONLY(true), \ "Use bits in the mark word to check for flat/null-free arrays") \ \ - product(ccstrlist, ForceNonTearable, "", DIAGNOSTIC, \ - "List of inline classes which are forced to be atomic " \ + product(ccstrlist, ForceAtomicAccess, "", DIAGNOSTIC, \ + "List of inline classes which are forced to be atomic access " \ "(whitespace and commas separate names, " \ "and leading and trailing stars '*' are wildcards)") \ \ diff --git a/src/java.base/share/classes/java/lang/NonTearable.java b/src/java.base/share/classes/java/lang/AtomicAccess.java similarity index 50% rename from src/java.base/share/classes/java/lang/NonTearable.java rename to src/java.base/share/classes/java/lang/AtomicAccess.java index a65588dce50..20117dbf2c9 100644 --- a/src/java.base/share/classes/java/lang/NonTearable.java +++ b/src/java.base/share/classes/java/lang/AtomicAccess.java @@ -26,38 +26,52 @@ package java.lang; /** - * A primitive class implements the {@code NonTearable} interface to - * request that the JVM take extra care to avoid structure tearing + * A primitive class implements the {@code AtomicAccess} interface to + * request that the JVM take extra care to avoid non-atomic operations * when loading or storing any value of the class to a field or array - * element. Normally, only fields declared {@code volatile} are - * protected against structure tearing, but a class that implements - * this marker interface will never have its values torn, even when + * element. Normally, only naturally atomic fields and fields declared + * {@code volatile} are always atomic, but a class that implements + * this marker interface will always be accessed atomically, even when * they are stored in array elements or in non-{@code volatile} * fields, and even when multiple threads perform racing writes. * - *
An primitive instance of multiple components is said to be "torn" - * when two racing threads compete to write those components, and one - * thread writes some components while another thread writes other - * components, so a subsequent observer will read a hybrid composed, - * as if "out of thin air", of field values from both racing writes. - * Tearing can also occur when the effects of two non-racing writes - * are observed by a racing read. In general, structure tearing - * requires a read and two writes (initialization counting as a write) - * of a multi-component value, with a race between any two of the - * accesses. The effect can also be described as if the Java memory - * model break up primitive classinstance reads and writes into reads and + *
A primitive instance of multiple components can experience both + * transient and persistent access atomicity failures. + * + *
Transient failures usually arise from write-read conflicts: + * when one thread writes the components one-by-one, and another + * thread reads the components one-by-one. In doing so, reader + * observes the intermediate state of the primitive instance. + * This failure is transient, since "after" (in memory model sense) + * the writer finishes its writes, the instance is observed in full + * by any subsequent observer. + * + *
Permanent failures usually arise from write-write conflicts: + * when two threads compete to write the components, and one thread + * writes some components while another thread writes other + * components. This failure is permanent: as every subsequent observer + * will read a hybrid composed of field values from both racing writes. + * + * Both these effects can be described as if the Java memory model + * break up primitive class instance reads and writes into reads and * writes of their various fields, as it does with longs and doubles * (JLS 17.7). * - *
In extreme cases, the hybrid observed after structure tearing + *
In extreme cases, the hybrid observed under non-atomic access * might be a value which is impossible to construct by normal means. * If data integrity or security depends on proper construction, - * the class should be declared as implementing {@code NonTearable}. + * the class should be declared as implementing {@code AtomicAccess}. + * + *
Note this atomicity guarantee only relates to the individual + * accesses, not the compound operations over the values. The + * read-modify-write operation over {@code AtomicAccess} would still + * be non-atomic, unless specifically written with appropriate + * synchronization. * * @author John Rose * @since (valhalla) */ -public interface NonTearable { +public interface AtomicAccess { // TO DO: Finalize name. // TO DO: Decide whether and how to restrict this type to // primitive classes only, or if not, whether to document its diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBufferTearing.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBufferAtomicAccess.java similarity index 88% rename from test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBufferTearing.java rename to test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBufferAtomicAccess.java index 17500842a54..cf0339792fa 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBufferTearing.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBufferAtomicAccess.java @@ -31,27 +31,27 @@ import jdk.internal.misc.Unsafe; /** - * @test TestBufferTearing + * @test TestBufferAtomicAccess * @key randomness - * @summary Detect tearing on inline type buffer writes due to missing barriers. + * @summary Detect atomic access violations on inline type buffer writes due to missing barriers. * @library /testlibrary /test/lib /compiler/whitebox / * @modules java.base/jdk.internal.misc * @run main/othervm -XX:InlineFieldMaxFlatSize=0 -XX:FlatArrayElementMaxSize=0 * -XX:+UnlockDiagnosticVMOptions -XX:+StressGCM -XX:+StressLCM - * compiler.valhalla.inlinetypes.TestBufferTearing + * compiler.valhalla.inlinetypes.TestBufferAtomicAccess * @run main/othervm -XX:InlineFieldMaxFlatSize=0 -XX:FlatArrayElementMaxSize=0 * -XX:+UnlockDiagnosticVMOptions -XX:+StressGCM -XX:+StressLCM * -XX:+IgnoreUnrecognizedVMOptions -XX:+AlwaysIncrementalInline - * compiler.valhalla.inlinetypes.TestBufferTearing + * compiler.valhalla.inlinetypes.TestBufferAtomicAccess * @run main/othervm -XX:InlineFieldMaxFlatSize=0 -XX:FlatArrayElementMaxSize=0 * -XX:CompileCommand=dontinline,*::incrementAndCheck* * -XX:+UnlockDiagnosticVMOptions -XX:+StressGCM -XX:+StressLCM - * compiler.valhalla.inlinetypes.TestBufferTearing + * compiler.valhalla.inlinetypes.TestBufferAtomicAccess * @run main/othervm -XX:InlineFieldMaxFlatSize=0 -XX:FlatArrayElementMaxSize=0 * -XX:CompileCommand=dontinline,*::incrementAndCheck* * -XX:+UnlockDiagnosticVMOptions -XX:+StressGCM -XX:+StressLCM * -XX:+IgnoreUnrecognizedVMOptions -XX:+AlwaysIncrementalInline - * compiler.valhalla.inlinetypes.TestBufferTearing + * compiler.valhalla.inlinetypes.TestBufferAtomicAccess */ primitive class MyValue { @@ -91,7 +91,7 @@ MyValue incrementAndCheckUnsafe() { } } -public class TestBufferTearing { +public class TestBufferAtomicAccess { static MyValue vtField1; MyValue vtField2; @@ -113,9 +113,9 @@ public class TestBufferTearing { } static class Runner extends Thread { - TestBufferTearing test; + TestBufferAtomicAccess test; - public Runner(TestBufferTearing test) { + public Runner(TestBufferAtomicAccess test) { this.test = test; } @@ -142,8 +142,9 @@ public void run() { public static void main(String[] args) throws Exception { // Create threads that concurrently update some inline type (array) fields - // and check the fields of the inline types for consistency to detect tearing. - TestBufferTearing test = new TestBufferTearing(); + // and check the fields of the inline types for consistency to detect access + // atomicity violations. + TestBufferAtomicAccess test = new TestBufferAtomicAccess(); Thread runner = null; for (int i = 0; i < 10; ++i) { runner = new Runner(test); diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBufferTearingC1.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBufferAtomicAccessC1.java similarity index 94% rename from test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBufferTearingC1.java rename to test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBufferAtomicAccessC1.java index e0d65c81519..1d6bdff2084 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBufferTearingC1.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBufferAtomicAccessC1.java @@ -25,12 +25,12 @@ package compiler.valhalla.inlinetypes; /** - * @test TestBufferTearingC1 + * @test TestBufferAtomicAccessC1 * @key randomness * @summary Additional tests for C1 missing barriers when buffering inline types. * @run main/othervm -XX:InlineFieldMaxFlatSize=-1 -XX:FlatArrayElementMaxSize=-1 * -XX:TieredStopAtLevel=1 - * compiler.valhalla.inlinetypes.TestBufferTearingC1 + * compiler.valhalla.inlinetypes.TestBufferAtomicAccessC1 */ primitive class Point { @@ -51,7 +51,7 @@ public Rect(Point a, Point b) { } } -public class TestBufferTearingC1 { +public class TestBufferAtomicAccessC1 { public static Point[] points = new Point[] { new Point(1, 1) }; public static Rect rect = new Rect(new Point(1, 1), new Point(2, 2)); @@ -99,7 +99,7 @@ private static void checkMissingBarrier() { public static void main(String[] args) throws InterruptedException { Thread[] threads = new Thread[10]; for (int i = 0; i < 10; i++) { - threads[i] = new Thread(TestBufferTearingC1::checkMissingBarrier); + threads[i] = new Thread(TestBufferAtomicAccessC1::checkMissingBarrier); threads[i].start(); } diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/FlattenableSemanticTest.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/FlattenableSemanticTest.java index 53db5a934bc..00be71f2053 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/FlattenableSemanticTest.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/FlattenableSemanticTest.java @@ -32,9 +32,9 @@ * @compile -XDallowWithFieldOperator Point.java JumboInline.java * @compile -XDallowWithFieldOperator FlattenableSemanticTest.java * @run main/othervm -Xint -XX:InlineFieldMaxFlatSize=64 runtime.valhalla.inlinetypes.FlattenableSemanticTest - * @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:ForceNonTearable=* runtime.valhalla.inlinetypes.FlattenableSemanticTest + * @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:ForceAtomicAccess=* runtime.valhalla.inlinetypes.FlattenableSemanticTest * @run main/othervm -Xcomp -XX:InlineFieldMaxFlatSize=64 runtime.valhalla.inlinetypes.FlattenableSemanticTest - * @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:ForceNonTearable=* runtime.valhalla.inlinetypes.FlattenableSemanticTest + * @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:ForceAtomicAccess=* runtime.valhalla.inlinetypes.FlattenableSemanticTest * // debug: -XX:+PrintInlineLayout -XX:-ShowMessageBoxOnError */ public class FlattenableSemanticTest { diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypeArray.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypeArray.java index 6535d264257..3739af8a1bc 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypeArray.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypeArray.java @@ -39,7 +39,7 @@ * @run main/othervm -Xint -XX:FlatArrayElementMaxSize=0 runtime.valhalla.inlinetypes.InlineTypeArray * @run main/othervm -Xcomp -XX:FlatArrayElementMaxSize=-1 runtime.valhalla.inlinetypes.InlineTypeArray * @run main/othervm -Xcomp -XX:FlatArrayElementMaxSize=0 runtime.valhalla.inlinetypes.InlineTypeArray - * @run main/othervm -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:ForceNonTearable=* runtime.valhalla.inlinetypes.InlineTypeArray + * @run main/othervm -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:ForceAtomicAccess=* runtime.valhalla.inlinetypes.InlineTypeArray */ public class InlineTypeArray { public static void main(String[] args) { diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypeDensity.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypeDensity.java index 9e9e67ba778..7e51a021c66 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypeDensity.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypeDensity.java @@ -43,14 +43,14 @@ * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI InlineTypeDensity * @run main/othervm -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:FlatArrayElementMaxSize=-1 - * -Xbootclasspath/a:. -XX:ForceNonTearable=* + * -Xbootclasspath/a:. -XX:ForceAtomicAccess=* * -XX:+WhiteBoxAPI InlineTypeDensity */ public class InlineTypeDensity { private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); - private static final boolean VM_FLAG_FORCENONTEARABLE = WHITE_BOX.getStringVMFlag("ForceNonTearable").equals("*"); + private static final boolean VM_FLAG_FORCEATOMICACCESS = WHITE_BOX.getStringVMFlag("ForceAtomicAccess").equals("*"); public InlineTypeDensity() { if (WHITE_BOX.getIntxVMFlag("FlatArrayElementMaxSize") != -1) { @@ -306,7 +306,7 @@ void testAlignedSize() { public void test() { ensureArraySizeWin(); testPrimitiveArraySizesSame(); - if (!VM_FLAG_FORCENONTEARABLE) { + if (!VM_FLAG_FORCEATOMICACCESS) { testAlignedSize(); } } diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypesTest.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypesTest.java index c06637f05f4..941740481a9 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypesTest.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypesTest.java @@ -64,7 +64,7 @@ * -XX:+ExplicitGCInvokesConcurrent * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -Djava.lang.invoke.MethodHandle.DUMP_CLASS_FILES=false - * -XX:ForceNonTearable=* + * -XX:ForceAtomicAccess=* * runtime.valhalla.inlinetypes.InlineTypesTest */ public class InlineTypesTest { diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/ValueTearing.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/ValueAtomicAccess.java similarity index 81% rename from test/hotspot/jtreg/runtime/valhalla/inlinetypes/ValueTearing.java rename to test/hotspot/jtreg/runtime/valhalla/inlinetypes/ValueAtomicAccess.java index c5f0e4f0359..b6b2d68c821 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/ValueTearing.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/ValueAtomicAccess.java @@ -36,81 +36,81 @@ import static jdk.test.lib.Asserts.*; /* - * @test ValueTearing - * @summary Test tearing of inline fields and array elements + * @test ValueAtomicAccess + * @summary Test atomicity of inline fields and array elements * @modules java.base/jdk.internal.misc * @library /test/lib - * @compile ValueTearing.java + * @compile ValueAtomicAccess.java * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:ForceNonTearable= + * @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:ForceAtomicAccess= * -DSTEP_COUNT=10000 -XX:InlineFieldMaxFlatSize=128 -XX:FlatArrayElementMaxSize=-1 * -Xbootclasspath/a:. -XX:+WhiteBoxAPI - * runtime.valhalla.inlinetypes.ValueTearing - * @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:ForceNonTearable=* + * runtime.valhalla.inlinetypes.ValueAtomicAccess + * @run main/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:ForceAtomicAccess=* * -DSTEP_COUNT=10000 -XX:InlineFieldMaxFlatSize=128 -XX:FlatArrayElementMaxSize=-1 * -Xbootclasspath/a:. -XX:+WhiteBoxAPI - * runtime.valhalla.inlinetypes.ValueTearing + * runtime.valhalla.inlinetypes.ValueAtomicAccess * @run main/othervm -Xbatch -DSTEP_COUNT=10000000 -XX:InlineFieldMaxFlatSize=128 -XX:FlatArrayElementMaxSize=-1 * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * runtime.valhalla.inlinetypes.ValueTearing - * @run main/othervm -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:ForceNonTearable= + * runtime.valhalla.inlinetypes.ValueAtomicAccess + * @run main/othervm -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:ForceAtomicAccess= * -DTEAR_MODE=fieldonly -XX:InlineFieldMaxFlatSize=128 -XX:FlatArrayElementMaxSize=-1 * -Xbootclasspath/a:. -XX:+WhiteBoxAPI - * runtime.valhalla.inlinetypes.ValueTearing - * @run main/othervm -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:ForceNonTearable= + * runtime.valhalla.inlinetypes.ValueAtomicAccess + * @run main/othervm -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:ForceAtomicAccess= * -DTEAR_MODE=arrayonly -XX:InlineFieldMaxFlatSize=128 -XX:FlatArrayElementMaxSize=-1 * -Xbootclasspath/a:. -XX:+WhiteBoxAPI - * runtime.valhalla.inlinetypes.ValueTearing - * @run main/othervm -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:ForceNonTearable=* + * runtime.valhalla.inlinetypes.ValueAtomicAccess + * @run main/othervm -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:ForceAtomicAccess=* * -DTEAR_MODE=both -XX:InlineFieldMaxFlatSize=128 -XX:FlatArrayElementMaxSize=-1 * -Xbootclasspath/a:. -XX:+WhiteBoxAPI - * runtime.valhalla.inlinetypes.ValueTearing + * runtime.valhalla.inlinetypes.ValueAtomicAccess */ -public class ValueTearing { +public class ValueAtomicAccess { private static final Unsafe UNSAFE = Unsafe.getUnsafe(); private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); private static final boolean USE_COMPILER = WHITE_BOX.getBooleanVMFlag("UseCompiler"); - private static final boolean ALWAYS_ATOMIC = WHITE_BOX.getStringVMFlag("ForceNonTearable").contains("*"); + private static final boolean ALWAYS_ATOMIC = WHITE_BOX.getStringVMFlag("ForceAtomicAccess").contains("*"); private static final String TEAR_MODE = System.getProperty("TEAR_MODE", "both"); private static final boolean TEAR_FIELD = !TEAR_MODE.equals("arrayonly"); private static final boolean TEAR_ARRAY = !TEAR_MODE.equals("fieldonly"); private static final int STEP_COUNT = Integer.getInteger("STEP_COUNT", 100_000); private static final boolean TFIELD_FLAT, TARRAY_FLAT; - private static final boolean NTFIELD_FLAT, NTARRAY_FLAT; + private static final boolean AAFIELD_FLAT, AAARRAY_FLAT; static { try { Field TPB_field = TPointBox.class.getDeclaredField("field"); Field TPB_array = TPointBox.class.getDeclaredField("array"); - Field NTPB_field = NTPointBox.class.getDeclaredField("field"); - Field NTPB_array = NTPointBox.class.getDeclaredField("array"); + Field AAPB_field = AAPointBox.class.getDeclaredField("field"); + Field AAPB_array = AAPointBox.class.getDeclaredField("array"); TFIELD_FLAT = UNSAFE.isFlattened(TPB_field); TARRAY_FLAT = UNSAFE.isFlattenedArray(TPB_array.getType()); - NTFIELD_FLAT = UNSAFE.isFlattened(NTPB_field); - NTARRAY_FLAT = UNSAFE.isFlattenedArray(NTPB_array.getType()); + AAFIELD_FLAT = UNSAFE.isFlattened(AAPB_field); + AAARRAY_FLAT = UNSAFE.isFlattenedArray(AAPB_array.getType()); } catch (ReflectiveOperationException ex) { throw new AssertionError(ex); } } private static final String SETTINGS = - String.format("USE_COMPILER=%s ALWAYS_ATOMIC=%s TEAR_MODE=%s STEP_COUNT=%s FLAT TF/TA=%s/%s NTF/NTA=%s/%s", + String.format("USE_COMPILER=%s ALWAYS_ATOMIC=%s TEAR_MODE=%s STEP_COUNT=%s FLAT TF/TA=%s/%s AAF/AAA=%s/%s", USE_COMPILER, ALWAYS_ATOMIC, TEAR_MODE, STEP_COUNT, - TFIELD_FLAT, TARRAY_FLAT, NTFIELD_FLAT, NTARRAY_FLAT); + TFIELD_FLAT, TARRAY_FLAT, AAFIELD_FLAT, AAARRAY_FLAT); private static final String NOTE_TORN_POINT = "Note: torn point"; public static void main(String[] args) throws Exception { System.out.println(SETTINGS); - ValueTearing valueTearing = new ValueTearing(); + ValueAtomicAccess valueTearing = new ValueAtomicAccess(); valueTearing.run(); // Extra representation check: - assert(!NTFIELD_FLAT) : "NT field must be indirect not flat"; - assert(!NTARRAY_FLAT) : "NT array must be indirect not flat"; + assert(!AAFIELD_FLAT) : "AA field must be indirect not flat"; + assert(!AAARRAY_FLAT) : "AA array must be indirect not flat"; if (ALWAYS_ATOMIC) { assert(!TFIELD_FLAT) : "field must be indirect not flat"; assert(!TARRAY_FLAT) : "array must be indirect not flat"; } } - // A normally tearable inline value. + // A normally non-atomic inline value. static primitive class TPoint { TPoint(long x, long y) { this.x = x; this.y = y; } final long x, y; @@ -173,23 +173,23 @@ public String toString() { } // Add an indirection, as an extra test. - interface NT extends NonTearable { } + interface AA extends AtomicAccess { } - // A hardened, non-tearable version of TPoint. - static primitive class NTPoint implements NT { - NTPoint(long x, long y) { this.x = x; this.y = y; } + // A hardened, always atomic version of TPoint. + static primitive class AAPoint implements AA { + AAPoint(long x, long y) { this.x = x; this.y = y; } final long x, y; public String toString() { return String.format("(%d,%d)", x, y); } } - class NTPointBox implements PointBox { - NTPoint field; - NTPoint[] array = new NTPoint[1]; + class AAPointBox implements PointBox { + AAPoint field; + AAPoint[] array = new AAPoint[1]; // Step the points forward by incrementing their components // "simultaneously". A racing thread will catch flaws in the // simultaneity. - NTPoint step(NTPoint p) { - return new NTPoint(p.x + 1, p.y + 1); + AAPoint step(AAPoint p) { + return new AAPoint(p.x + 1, p.y + 1); } public @Override void step() { @@ -203,15 +203,15 @@ void check() { check(field, "field"); check(array[0], "array element"); } - void check(NTPoint p, String where) { + void check(AAPoint p, String where) { if (p.x == p.y) return; - String msg = String.format("%s *NonTearable* %s in %s; settings = %s", + String msg = String.format("%s *AlwaysAtomic* %s in %s; settings = %s", NOTE_TORN_POINT, p, where, SETTINGS); throw new TooTearable(msg, p); } public String toString() { - return String.format("NTPB[%s, {%s}]", field, array[0]); + return String.format("AAPB[%s, {%s}]", field, array[0]); } } @@ -233,7 +233,7 @@ public void run() { done = true; badPointObserved = ex.badPoint; System.out.println(ex); - if (ALWAYS_ATOMIC || ex.badPoint instanceof NonTearable) { + if (ALWAYS_ATOMIC || ex.badPoint instanceof AtomicAccess) { throw ex; } } @@ -241,14 +241,14 @@ public void run() { } public void run() throws Exception { - System.out.println("Test for tearing of NTPoint, which must not happen..."); - run(new NTPointBox(), false); - System.out.println("Test for tearing of TPoint, which "+ + System.out.println("Test for access atomicity of AAPoint, which must not be broken..."); + run(new AAPointBox(), false); + System.out.println("Test for access atomicity of TPoint, which "+ (ALWAYS_ATOMIC ? "must not" : "is allowed to")+ - " happen..."); + " be broken..."); run(new TPointBox(), ALWAYS_ATOMIC ? false : true); } - public void run(PointBox pointBox, boolean canTear) throws Exception { + public void run(PointBox pointBox, boolean nonAtomic) throws Exception { var observer = new AsyncObserver(pointBox); observer.start(); for (int i = 0; i < STEP_COUNT; i++) { @@ -262,9 +262,9 @@ public void run(PointBox pointBox, boolean canTear) throws Exception { System.out.println(String.format("finished after %d observations at %s; %s", obCount, pointBox, (badPoint == null - ? "no tearing observed" + ? "no access atomicity problems observed" : "bad point = " + badPoint))); - if (canTear && badPoint == null) { + if (nonAtomic && badPoint == null) { var complain = String.format("%s NOT observed after %d observations", NOTE_TORN_POINT, obCount); System.out.println("?????? "+complain); @@ -273,7 +273,7 @@ public void run(PointBox pointBox, boolean canTear) throws Exception { throw new AssertionError(complain + ", but it should have been"); } } - if (!canTear && badPoint != null) { + if (!nonAtomic && badPoint != null) { throw new AssertionError("should not reach here; other thread must throw"); } }