10e54c0160c84894696c05af6cad9eae3690f9496Aart Bik/* 20e54c0160c84894696c05af6cad9eae3690f9496Aart Bik * Copyright (C) 2016 The Android Open Source Project 30e54c0160c84894696c05af6cad9eae3690f9496Aart Bik * 40e54c0160c84894696c05af6cad9eae3690f9496Aart Bik * Licensed under the Apache License, Version 2.0 (the "License"); 50e54c0160c84894696c05af6cad9eae3690f9496Aart Bik * you may not use this file except in compliance with the License. 60e54c0160c84894696c05af6cad9eae3690f9496Aart Bik * You may obtain a copy of the License at 70e54c0160c84894696c05af6cad9eae3690f9496Aart Bik * 80e54c0160c84894696c05af6cad9eae3690f9496Aart Bik * http://www.apache.org/licenses/LICENSE-2.0 90e54c0160c84894696c05af6cad9eae3690f9496Aart Bik * 100e54c0160c84894696c05af6cad9eae3690f9496Aart Bik * Unless required by applicable law or agreed to in writing, software 110e54c0160c84894696c05af6cad9eae3690f9496Aart Bik * distributed under the License is distributed on an "AS IS" BASIS, 120e54c0160c84894696c05af6cad9eae3690f9496Aart Bik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130e54c0160c84894696c05af6cad9eae3690f9496Aart Bik * See the License for the specific language governing permissions and 140e54c0160c84894696c05af6cad9eae3690f9496Aart Bik * limitations under the License. 150e54c0160c84894696c05af6cad9eae3690f9496Aart Bik */ 160e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 170e54c0160c84894696c05af6cad9eae3690f9496Aart Bikimport java.lang.reflect.Field; 18700ae4071cc297e2c567322661704d5eb5af76aeAart Bikimport java.util.concurrent.atomic.AtomicBoolean; 190e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 200e54c0160c84894696c05af6cad9eae3690f9496Aart Bikimport sun.misc.Unsafe; 210e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 220e54c0160c84894696c05af6cad9eae3690f9496Aart Bik/** 230e54c0160c84894696c05af6cad9eae3690f9496Aart Bik * Checker test on the 1.8 unsafe operations. Note, this is by no means an 240e54c0160c84894696c05af6cad9eae3690f9496Aart Bik * exhaustive unit test for these CAS (compare-and-swap) and fence operations. 250e54c0160c84894696c05af6cad9eae3690f9496Aart Bik * Instead, this test ensures the methods are recognized as intrinsic and behave 260e54c0160c84894696c05af6cad9eae3690f9496Aart Bik * as expected. 270e54c0160c84894696c05af6cad9eae3690f9496Aart Bik */ 280e54c0160c84894696c05af6cad9eae3690f9496Aart Bikpublic class Main { 290e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 300e54c0160c84894696c05af6cad9eae3690f9496Aart Bik private static final Unsafe unsafe = getUnsafe(); 310e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 320e54c0160c84894696c05af6cad9eae3690f9496Aart Bik private static Thread[] sThreads = new Thread[10]; 330e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 340e54c0160c84894696c05af6cad9eae3690f9496Aart Bik // 35700ae4071cc297e2c567322661704d5eb5af76aeAart Bik // Fields accessed by setters and adders, and by memory fence tests. 360e54c0160c84894696c05af6cad9eae3690f9496Aart Bik // 370e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 380e54c0160c84894696c05af6cad9eae3690f9496Aart Bik public int i = 0; 390e54c0160c84894696c05af6cad9eae3690f9496Aart Bik public long l = 0; 400e54c0160c84894696c05af6cad9eae3690f9496Aart Bik public Object o = null; 410e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 42700ae4071cc297e2c567322661704d5eb5af76aeAart Bik public int x_value; 43700ae4071cc297e2c567322661704d5eb5af76aeAart Bik public int y_value; 44700ae4071cc297e2c567322661704d5eb5af76aeAart Bik public volatile boolean running; 45700ae4071cc297e2c567322661704d5eb5af76aeAart Bik 460e54c0160c84894696c05af6cad9eae3690f9496Aart Bik // 470e54c0160c84894696c05af6cad9eae3690f9496Aart Bik // Setters. 480e54c0160c84894696c05af6cad9eae3690f9496Aart Bik // 490e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 500e54c0160c84894696c05af6cad9eae3690f9496Aart Bik /// CHECK-START: int Main.set32(java.lang.Object, long, int) intrinsics_recognition (after) 510e54c0160c84894696c05af6cad9eae3690f9496Aart Bik /// CHECK-DAG: <<Result:i\d+>> InvokeVirtual intrinsic:UnsafeGetAndSetInt 520e54c0160c84894696c05af6cad9eae3690f9496Aart Bik /// CHECK-DAG: Return [<<Result>>] 530e54c0160c84894696c05af6cad9eae3690f9496Aart Bik private static int set32(Object o, long offset, int newValue) { 540e54c0160c84894696c05af6cad9eae3690f9496Aart Bik return unsafe.getAndSetInt(o, offset, newValue); 550e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 560e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 570e54c0160c84894696c05af6cad9eae3690f9496Aart Bik /// CHECK-START: long Main.set64(java.lang.Object, long, long) intrinsics_recognition (after) 580e54c0160c84894696c05af6cad9eae3690f9496Aart Bik /// CHECK-DAG: <<Result:j\d+>> InvokeVirtual intrinsic:UnsafeGetAndSetLong 590e54c0160c84894696c05af6cad9eae3690f9496Aart Bik /// CHECK-DAG: Return [<<Result>>] 600e54c0160c84894696c05af6cad9eae3690f9496Aart Bik private static long set64(Object o, long offset, long newValue) { 610e54c0160c84894696c05af6cad9eae3690f9496Aart Bik return unsafe.getAndSetLong(o, offset, newValue); 620e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 630e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 640e54c0160c84894696c05af6cad9eae3690f9496Aart Bik /// CHECK-START: java.lang.Object Main.setObj(java.lang.Object, long, java.lang.Object) intrinsics_recognition (after) 650e54c0160c84894696c05af6cad9eae3690f9496Aart Bik /// CHECK-DAG: <<Result:l\d+>> InvokeVirtual intrinsic:UnsafeGetAndSetObject 660e54c0160c84894696c05af6cad9eae3690f9496Aart Bik /// CHECK-DAG: Return [<<Result>>] 670e54c0160c84894696c05af6cad9eae3690f9496Aart Bik private static Object setObj(Object o, long offset, Object newValue) { 680e54c0160c84894696c05af6cad9eae3690f9496Aart Bik return unsafe.getAndSetObject(o, offset, newValue); 690e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 700e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 710e54c0160c84894696c05af6cad9eae3690f9496Aart Bik // 720e54c0160c84894696c05af6cad9eae3690f9496Aart Bik // Adders. 730e54c0160c84894696c05af6cad9eae3690f9496Aart Bik // 740e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 750e54c0160c84894696c05af6cad9eae3690f9496Aart Bik /// CHECK-START: int Main.add32(java.lang.Object, long, int) intrinsics_recognition (after) 760e54c0160c84894696c05af6cad9eae3690f9496Aart Bik /// CHECK-DAG: <<Result:i\d+>> InvokeVirtual intrinsic:UnsafeGetAndAddInt 770e54c0160c84894696c05af6cad9eae3690f9496Aart Bik /// CHECK-DAG: Return [<<Result>>] 780e54c0160c84894696c05af6cad9eae3690f9496Aart Bik private static int add32(Object o, long offset, int delta) { 790e54c0160c84894696c05af6cad9eae3690f9496Aart Bik return unsafe.getAndAddInt(o, offset, delta); 800e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 810e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 820e54c0160c84894696c05af6cad9eae3690f9496Aart Bik /// CHECK-START: long Main.add64(java.lang.Object, long, long) intrinsics_recognition (after) 830e54c0160c84894696c05af6cad9eae3690f9496Aart Bik /// CHECK-DAG: <<Result:j\d+>> InvokeVirtual intrinsic:UnsafeGetAndAddLong 840e54c0160c84894696c05af6cad9eae3690f9496Aart Bik /// CHECK-DAG: Return [<<Result>>] 850e54c0160c84894696c05af6cad9eae3690f9496Aart Bik private static long add64(Object o, long offset, long delta) { 860e54c0160c84894696c05af6cad9eae3690f9496Aart Bik return unsafe.getAndAddLong(o, offset, delta); 870e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 880e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 890e54c0160c84894696c05af6cad9eae3690f9496Aart Bik // 900e54c0160c84894696c05af6cad9eae3690f9496Aart Bik // Fences (native). 910e54c0160c84894696c05af6cad9eae3690f9496Aart Bik // 920e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 930e54c0160c84894696c05af6cad9eae3690f9496Aart Bik /// CHECK-START: void Main.load() intrinsics_recognition (after) 940e54c0160c84894696c05af6cad9eae3690f9496Aart Bik /// CHECK-DAG: InvokeVirtual intrinsic:UnsafeLoadFence 951193259cb37c9763a111825aa04718a409d07145Aart Bik // 961193259cb37c9763a111825aa04718a409d07145Aart Bik /// CHECK-START: void Main.load() instruction_simplifier (after) 971193259cb37c9763a111825aa04718a409d07145Aart Bik /// CHECK-NOT: InvokeVirtual intrinsic:UnsafeLoadFence 981193259cb37c9763a111825aa04718a409d07145Aart Bik // 991193259cb37c9763a111825aa04718a409d07145Aart Bik /// CHECK-START: void Main.load() instruction_simplifier (after) 1001193259cb37c9763a111825aa04718a409d07145Aart Bik /// CHECK-DAG: MemoryBarrier kind:LoadAny 1010e54c0160c84894696c05af6cad9eae3690f9496Aart Bik private static void load() { 1020e54c0160c84894696c05af6cad9eae3690f9496Aart Bik unsafe.loadFence(); 1030e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 1040e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 1050e54c0160c84894696c05af6cad9eae3690f9496Aart Bik /// CHECK-START: void Main.store() intrinsics_recognition (after) 1060e54c0160c84894696c05af6cad9eae3690f9496Aart Bik /// CHECK-DAG: InvokeVirtual intrinsic:UnsafeStoreFence 1071193259cb37c9763a111825aa04718a409d07145Aart Bik // 1081193259cb37c9763a111825aa04718a409d07145Aart Bik /// CHECK-START: void Main.store() instruction_simplifier (after) 1091193259cb37c9763a111825aa04718a409d07145Aart Bik /// CHECK-NOT: InvokeVirtual intrinsic:UnsafeStoreFence 1101193259cb37c9763a111825aa04718a409d07145Aart Bik // 1111193259cb37c9763a111825aa04718a409d07145Aart Bik /// CHECK-START: void Main.store() instruction_simplifier (after) 1121193259cb37c9763a111825aa04718a409d07145Aart Bik /// CHECK-DAG: MemoryBarrier kind:AnyStore 1130e54c0160c84894696c05af6cad9eae3690f9496Aart Bik private static void store() { 1140e54c0160c84894696c05af6cad9eae3690f9496Aart Bik unsafe.storeFence(); 1150e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 1160e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 1170e54c0160c84894696c05af6cad9eae3690f9496Aart Bik /// CHECK-START: void Main.full() intrinsics_recognition (after) 1180e54c0160c84894696c05af6cad9eae3690f9496Aart Bik /// CHECK-DAG: InvokeVirtual intrinsic:UnsafeFullFence 1191193259cb37c9763a111825aa04718a409d07145Aart Bik // 1201193259cb37c9763a111825aa04718a409d07145Aart Bik /// CHECK-START: void Main.full() instruction_simplifier (after) 1211193259cb37c9763a111825aa04718a409d07145Aart Bik /// CHECK-NOT: InvokeVirtual intrinsic:UnsafeFullFence 1221193259cb37c9763a111825aa04718a409d07145Aart Bik // 1231193259cb37c9763a111825aa04718a409d07145Aart Bik /// CHECK-START: void Main.full() instruction_simplifier (after) 1241193259cb37c9763a111825aa04718a409d07145Aart Bik /// CHECK-DAG: MemoryBarrier kind:AnyAny 1250e54c0160c84894696c05af6cad9eae3690f9496Aart Bik private static void full() { 1260e54c0160c84894696c05af6cad9eae3690f9496Aart Bik unsafe.fullFence(); 1270e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 1280e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 1290e54c0160c84894696c05af6cad9eae3690f9496Aart Bik // 1300e54c0160c84894696c05af6cad9eae3690f9496Aart Bik // Thread fork/join. 1310e54c0160c84894696c05af6cad9eae3690f9496Aart Bik // 1320e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 1330e54c0160c84894696c05af6cad9eae3690f9496Aart Bik private static void fork(Runnable r) { 1340e54c0160c84894696c05af6cad9eae3690f9496Aart Bik for (int i = 0; i < 10; i++) { 1350e54c0160c84894696c05af6cad9eae3690f9496Aart Bik sThreads[i] = new Thread(r); 136d07453889fd9f314849df8c172afadb477e46d64Aart Bik } 137d07453889fd9f314849df8c172afadb477e46d64Aart Bik // Start the threads only after the full array has been written with new threads, 138d07453889fd9f314849df8c172afadb477e46d64Aart Bik // because one test relies on the contents of this array to be consistent. 139d07453889fd9f314849df8c172afadb477e46d64Aart Bik for (int i = 0; i < 10; i++) { 1400e54c0160c84894696c05af6cad9eae3690f9496Aart Bik sThreads[i].start(); 1410e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 1420e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 1430e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 1440e54c0160c84894696c05af6cad9eae3690f9496Aart Bik private static void join() { 1450e54c0160c84894696c05af6cad9eae3690f9496Aart Bik try { 1460e54c0160c84894696c05af6cad9eae3690f9496Aart Bik for (int i = 0; i < 10; i++) { 1470e54c0160c84894696c05af6cad9eae3690f9496Aart Bik sThreads[i].join(); 1480e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 1490e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } catch (InterruptedException e) { 1500e54c0160c84894696c05af6cad9eae3690f9496Aart Bik throw new Error("Failed join: " + e); 1510e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 1520e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 1530e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 1540e54c0160c84894696c05af6cad9eae3690f9496Aart Bik // 1550e54c0160c84894696c05af6cad9eae3690f9496Aart Bik // Driver. 1560e54c0160c84894696c05af6cad9eae3690f9496Aart Bik // 1570e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 1580e54c0160c84894696c05af6cad9eae3690f9496Aart Bik public static void main(String[] args) { 1590e54c0160c84894696c05af6cad9eae3690f9496Aart Bik System.out.println("starting"); 1600e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 1610e54c0160c84894696c05af6cad9eae3690f9496Aart Bik final Main m = new Main(); 1620e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 1630e54c0160c84894696c05af6cad9eae3690f9496Aart Bik // Get the offsets. 1640e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 1650e54c0160c84894696c05af6cad9eae3690f9496Aart Bik final long intOffset, longOffset, objOffset; 1660e54c0160c84894696c05af6cad9eae3690f9496Aart Bik try { 1670e54c0160c84894696c05af6cad9eae3690f9496Aart Bik Field intField = Main.class.getDeclaredField("i"); 1680e54c0160c84894696c05af6cad9eae3690f9496Aart Bik Field longField = Main.class.getDeclaredField("l"); 1690e54c0160c84894696c05af6cad9eae3690f9496Aart Bik Field objField = Main.class.getDeclaredField("o"); 1700e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 1710e54c0160c84894696c05af6cad9eae3690f9496Aart Bik intOffset = unsafe.objectFieldOffset(intField); 1720e54c0160c84894696c05af6cad9eae3690f9496Aart Bik longOffset = unsafe.objectFieldOffset(longField); 1730e54c0160c84894696c05af6cad9eae3690f9496Aart Bik objOffset = unsafe.objectFieldOffset(objField); 1740e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 1750e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } catch (NoSuchFieldException e) { 1760e54c0160c84894696c05af6cad9eae3690f9496Aart Bik throw new Error("No offset: " + e); 1770e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 1780e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 179700ae4071cc297e2c567322661704d5eb5af76aeAart Bik // Some sanity on setters and adders within same thread. 1800e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 1810e54c0160c84894696c05af6cad9eae3690f9496Aart Bik set32(m, intOffset, 3); 182700ae4071cc297e2c567322661704d5eb5af76aeAart Bik expectEqual32(3, m.i); 1830e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 1840e54c0160c84894696c05af6cad9eae3690f9496Aart Bik set64(m, longOffset, 7L); 185700ae4071cc297e2c567322661704d5eb5af76aeAart Bik expectEqual64(7L, m.l); 1860e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 1870e54c0160c84894696c05af6cad9eae3690f9496Aart Bik setObj(m, objOffset, m); 188700ae4071cc297e2c567322661704d5eb5af76aeAart Bik expectEqualObj(m, m.o); 1890e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 1900e54c0160c84894696c05af6cad9eae3690f9496Aart Bik add32(m, intOffset, 11); 191700ae4071cc297e2c567322661704d5eb5af76aeAart Bik expectEqual32(14, m.i); 1920e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 1930e54c0160c84894696c05af6cad9eae3690f9496Aart Bik add64(m, longOffset, 13L); 194700ae4071cc297e2c567322661704d5eb5af76aeAart Bik expectEqual64(20L, m.l); 1950e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 1960e54c0160c84894696c05af6cad9eae3690f9496Aart Bik // Some sanity on setters within different threads. 1970e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 1980e54c0160c84894696c05af6cad9eae3690f9496Aart Bik fork(new Runnable() { 1990e54c0160c84894696c05af6cad9eae3690f9496Aart Bik public void run() { 2000e54c0160c84894696c05af6cad9eae3690f9496Aart Bik for (int i = 0; i < 10; i++) 2010e54c0160c84894696c05af6cad9eae3690f9496Aart Bik set32(m, intOffset, i); 2020e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 2030e54c0160c84894696c05af6cad9eae3690f9496Aart Bik }); 2040e54c0160c84894696c05af6cad9eae3690f9496Aart Bik join(); 205700ae4071cc297e2c567322661704d5eb5af76aeAart Bik expectEqual32(9, m.i); // one thread's last value wins 2060e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 2070e54c0160c84894696c05af6cad9eae3690f9496Aart Bik fork(new Runnable() { 2080e54c0160c84894696c05af6cad9eae3690f9496Aart Bik public void run() { 2090e54c0160c84894696c05af6cad9eae3690f9496Aart Bik for (int i = 0; i < 10; i++) 2100e54c0160c84894696c05af6cad9eae3690f9496Aart Bik set64(m, longOffset, (long) (100 + i)); 2110e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 2120e54c0160c84894696c05af6cad9eae3690f9496Aart Bik }); 2130e54c0160c84894696c05af6cad9eae3690f9496Aart Bik join(); 214700ae4071cc297e2c567322661704d5eb5af76aeAart Bik expectEqual64(109L, m.l); // one thread's last value wins 2150e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 2160e54c0160c84894696c05af6cad9eae3690f9496Aart Bik fork(new Runnable() { 2170e54c0160c84894696c05af6cad9eae3690f9496Aart Bik public void run() { 2180e54c0160c84894696c05af6cad9eae3690f9496Aart Bik for (int i = 0; i < 10; i++) 2190e54c0160c84894696c05af6cad9eae3690f9496Aart Bik setObj(m, objOffset, sThreads[i]); 2200e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 2210e54c0160c84894696c05af6cad9eae3690f9496Aart Bik }); 2220e54c0160c84894696c05af6cad9eae3690f9496Aart Bik join(); 223700ae4071cc297e2c567322661704d5eb5af76aeAart Bik expectEqualObj(sThreads[9], m.o); // one thread's last value wins 2240e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 2250e54c0160c84894696c05af6cad9eae3690f9496Aart Bik // Some sanity on adders within different threads. 2260e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 2270e54c0160c84894696c05af6cad9eae3690f9496Aart Bik fork(new Runnable() { 2280e54c0160c84894696c05af6cad9eae3690f9496Aart Bik public void run() { 2290e54c0160c84894696c05af6cad9eae3690f9496Aart Bik for (int i = 0; i < 10; i++) 2300e54c0160c84894696c05af6cad9eae3690f9496Aart Bik add32(m, intOffset, i + 1); 2310e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 2320e54c0160c84894696c05af6cad9eae3690f9496Aart Bik }); 2330e54c0160c84894696c05af6cad9eae3690f9496Aart Bik join(); 234700ae4071cc297e2c567322661704d5eb5af76aeAart Bik expectEqual32(559, m.i); // all values accounted for 2350e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 2360e54c0160c84894696c05af6cad9eae3690f9496Aart Bik fork(new Runnable() { 2370e54c0160c84894696c05af6cad9eae3690f9496Aart Bik public void run() { 2380e54c0160c84894696c05af6cad9eae3690f9496Aart Bik for (int i = 0; i < 10; i++) 2390e54c0160c84894696c05af6cad9eae3690f9496Aart Bik add64(m, longOffset, (long) (i + 1)); 2400e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 2410e54c0160c84894696c05af6cad9eae3690f9496Aart Bik }); 2420e54c0160c84894696c05af6cad9eae3690f9496Aart Bik join(); 243700ae4071cc297e2c567322661704d5eb5af76aeAart Bik expectEqual64(659L, m.l); // all values accounted for 244700ae4071cc297e2c567322661704d5eb5af76aeAart Bik 245700ae4071cc297e2c567322661704d5eb5af76aeAart Bik // Some sanity on fences within same thread. Note that memory fences within one 246700ae4071cc297e2c567322661704d5eb5af76aeAart Bik // thread make little sense, but the sanity check ensures nothing bad happens. 247700ae4071cc297e2c567322661704d5eb5af76aeAart Bik 248700ae4071cc297e2c567322661704d5eb5af76aeAart Bik m.i = -1; 249700ae4071cc297e2c567322661704d5eb5af76aeAart Bik m.l = -2L; 250700ae4071cc297e2c567322661704d5eb5af76aeAart Bik m.o = null; 251700ae4071cc297e2c567322661704d5eb5af76aeAart Bik 252700ae4071cc297e2c567322661704d5eb5af76aeAart Bik load(); 253700ae4071cc297e2c567322661704d5eb5af76aeAart Bik store(); 254700ae4071cc297e2c567322661704d5eb5af76aeAart Bik full(); 255700ae4071cc297e2c567322661704d5eb5af76aeAart Bik 256700ae4071cc297e2c567322661704d5eb5af76aeAart Bik expectEqual32(-1, m.i); 257700ae4071cc297e2c567322661704d5eb5af76aeAart Bik expectEqual64(-2L, m.l); 258700ae4071cc297e2c567322661704d5eb5af76aeAart Bik expectEqualObj(null, m.o); 259700ae4071cc297e2c567322661704d5eb5af76aeAart Bik 260700ae4071cc297e2c567322661704d5eb5af76aeAart Bik // Some sanity on full fence within different threads. We write the non-volatile m.l after 261700ae4071cc297e2c567322661704d5eb5af76aeAart Bik // the fork(), which means there is no happens-before relation in the Java memory model 262700ae4071cc297e2c567322661704d5eb5af76aeAart Bik // with respect to the read in the threads. This relation is enforced by the memory fences 263700ae4071cc297e2c567322661704d5eb5af76aeAart Bik // and the weak-set() -> get() guard. Note that the guard semantics used here are actually 264700ae4071cc297e2c567322661704d5eb5af76aeAart Bik // too strong and already enforce total memory visibility, but this test illustrates what 265700ae4071cc297e2c567322661704d5eb5af76aeAart Bik // should still happen if Java had a true relaxed memory guard. 266700ae4071cc297e2c567322661704d5eb5af76aeAart Bik 267700ae4071cc297e2c567322661704d5eb5af76aeAart Bik final AtomicBoolean guard1 = new AtomicBoolean(); 268700ae4071cc297e2c567322661704d5eb5af76aeAart Bik m.l = 0L; 269700ae4071cc297e2c567322661704d5eb5af76aeAart Bik 270700ae4071cc297e2c567322661704d5eb5af76aeAart Bik fork(new Runnable() { 271700ae4071cc297e2c567322661704d5eb5af76aeAart Bik public void run() { 272700ae4071cc297e2c567322661704d5eb5af76aeAart Bik while (!guard1.get()); // busy-waiting 273700ae4071cc297e2c567322661704d5eb5af76aeAart Bik full(); 274700ae4071cc297e2c567322661704d5eb5af76aeAart Bik expectEqual64(-123456789L, m.l); 275700ae4071cc297e2c567322661704d5eb5af76aeAart Bik } 276700ae4071cc297e2c567322661704d5eb5af76aeAart Bik }); 277700ae4071cc297e2c567322661704d5eb5af76aeAart Bik 278700ae4071cc297e2c567322661704d5eb5af76aeAart Bik m.l = -123456789L; 279700ae4071cc297e2c567322661704d5eb5af76aeAart Bik full(); 280700ae4071cc297e2c567322661704d5eb5af76aeAart Bik while (!guard1.weakCompareAndSet(false, true)); // relaxed memory order 281700ae4071cc297e2c567322661704d5eb5af76aeAart Bik join(); 282700ae4071cc297e2c567322661704d5eb5af76aeAart Bik 283700ae4071cc297e2c567322661704d5eb5af76aeAart Bik // Some sanity on release/acquire fences within different threads. We write the non-volatile 284700ae4071cc297e2c567322661704d5eb5af76aeAart Bik // m.l after the fork(), which means there is no happens-before relation in the Java memory 285700ae4071cc297e2c567322661704d5eb5af76aeAart Bik // model with respect to the read in the threads. This relation is enforced by the memory fences 286700ae4071cc297e2c567322661704d5eb5af76aeAart Bik // and the weak-set() -> get() guard. Note that the guard semantics used here are actually 287700ae4071cc297e2c567322661704d5eb5af76aeAart Bik // too strong and already enforce total memory visibility, but this test illustrates what 288700ae4071cc297e2c567322661704d5eb5af76aeAart Bik // should still happen if Java had a true relaxed memory guard. 289700ae4071cc297e2c567322661704d5eb5af76aeAart Bik 290700ae4071cc297e2c567322661704d5eb5af76aeAart Bik final AtomicBoolean guard2 = new AtomicBoolean(); 291700ae4071cc297e2c567322661704d5eb5af76aeAart Bik m.l = 0L; 292700ae4071cc297e2c567322661704d5eb5af76aeAart Bik 293700ae4071cc297e2c567322661704d5eb5af76aeAart Bik fork(new Runnable() { 294700ae4071cc297e2c567322661704d5eb5af76aeAart Bik public void run() { 295700ae4071cc297e2c567322661704d5eb5af76aeAart Bik while (!guard2.get()); // busy-waiting 296700ae4071cc297e2c567322661704d5eb5af76aeAart Bik load(); 297700ae4071cc297e2c567322661704d5eb5af76aeAart Bik expectEqual64(-987654321L, m.l); 298700ae4071cc297e2c567322661704d5eb5af76aeAart Bik } 299700ae4071cc297e2c567322661704d5eb5af76aeAart Bik }); 300700ae4071cc297e2c567322661704d5eb5af76aeAart Bik 301700ae4071cc297e2c567322661704d5eb5af76aeAart Bik m.l = -987654321L; 302700ae4071cc297e2c567322661704d5eb5af76aeAart Bik store(); 303700ae4071cc297e2c567322661704d5eb5af76aeAart Bik while (!guard2.weakCompareAndSet(false, true)); // relaxed memory order 304700ae4071cc297e2c567322661704d5eb5af76aeAart Bik join(); 305700ae4071cc297e2c567322661704d5eb5af76aeAart Bik 306700ae4071cc297e2c567322661704d5eb5af76aeAart Bik // Some sanity on release/acquire fences within different threads using a test suggested by 307700ae4071cc297e2c567322661704d5eb5af76aeAart Bik // Hans Boehm. Even this test remains with the realm of sanity only, since having the threads 308700ae4071cc297e2c567322661704d5eb5af76aeAart Bik // read the same value consistently would be a valid outcome. 309700ae4071cc297e2c567322661704d5eb5af76aeAart Bik 310700ae4071cc297e2c567322661704d5eb5af76aeAart Bik m.x_value = -1; 311700ae4071cc297e2c567322661704d5eb5af76aeAart Bik m.y_value = -1; 312700ae4071cc297e2c567322661704d5eb5af76aeAart Bik m.running = true; 313700ae4071cc297e2c567322661704d5eb5af76aeAart Bik 314700ae4071cc297e2c567322661704d5eb5af76aeAart Bik fork(new Runnable() { 315700ae4071cc297e2c567322661704d5eb5af76aeAart Bik public void run() { 316700ae4071cc297e2c567322661704d5eb5af76aeAart Bik while (m.running) { 317700ae4071cc297e2c567322661704d5eb5af76aeAart Bik for (int few_times = 0; few_times < 1000; few_times++) { 318700ae4071cc297e2c567322661704d5eb5af76aeAart Bik // Read y first, then load fence, then read x. 319700ae4071cc297e2c567322661704d5eb5af76aeAart Bik // They should appear in order, if seen at all. 320700ae4071cc297e2c567322661704d5eb5af76aeAart Bik int local_y = m.y_value; 321700ae4071cc297e2c567322661704d5eb5af76aeAart Bik load(); 322700ae4071cc297e2c567322661704d5eb5af76aeAart Bik int local_x = m.x_value; 323700ae4071cc297e2c567322661704d5eb5af76aeAart Bik expectLessThanOrEqual32(local_y, local_x); 324700ae4071cc297e2c567322661704d5eb5af76aeAart Bik } 325700ae4071cc297e2c567322661704d5eb5af76aeAart Bik } 326700ae4071cc297e2c567322661704d5eb5af76aeAart Bik } 327700ae4071cc297e2c567322661704d5eb5af76aeAart Bik }); 328700ae4071cc297e2c567322661704d5eb5af76aeAart Bik 329700ae4071cc297e2c567322661704d5eb5af76aeAart Bik for (int many_times = 0; many_times < 100000; many_times++) { 330700ae4071cc297e2c567322661704d5eb5af76aeAart Bik m.x_value = many_times; 331700ae4071cc297e2c567322661704d5eb5af76aeAart Bik store(); 332700ae4071cc297e2c567322661704d5eb5af76aeAart Bik m.y_value = many_times; 333700ae4071cc297e2c567322661704d5eb5af76aeAart Bik } 334700ae4071cc297e2c567322661704d5eb5af76aeAart Bik m.running = false; 335700ae4071cc297e2c567322661704d5eb5af76aeAart Bik join(); 3360e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 337700ae4071cc297e2c567322661704d5eb5af76aeAart Bik // All done! 3380e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 3390e54c0160c84894696c05af6cad9eae3690f9496Aart Bik System.out.println("passed"); 3400e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 3410e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 3420e54c0160c84894696c05af6cad9eae3690f9496Aart Bik // Use reflection to implement "Unsafe.getUnsafe()"; 3430e54c0160c84894696c05af6cad9eae3690f9496Aart Bik private static Unsafe getUnsafe() { 3440e54c0160c84894696c05af6cad9eae3690f9496Aart Bik try { 3450e54c0160c84894696c05af6cad9eae3690f9496Aart Bik Class<?> unsafeClass = Unsafe.class; 3460e54c0160c84894696c05af6cad9eae3690f9496Aart Bik Field f = unsafeClass.getDeclaredField("theUnsafe"); 3470e54c0160c84894696c05af6cad9eae3690f9496Aart Bik f.setAccessible(true); 3480e54c0160c84894696c05af6cad9eae3690f9496Aart Bik return (Unsafe) f.get(null); 3490e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } catch (Exception e) { 3500e54c0160c84894696c05af6cad9eae3690f9496Aart Bik throw new Error("Cannot get Unsafe instance"); 3510e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 3520e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 3530e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 354700ae4071cc297e2c567322661704d5eb5af76aeAart Bik private static void expectEqual32(int expected, int result) { 3550e54c0160c84894696c05af6cad9eae3690f9496Aart Bik if (expected != result) { 3560e54c0160c84894696c05af6cad9eae3690f9496Aart Bik throw new Error("Expected: " + expected + ", found: " + result); 3570e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 3580e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 3590e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 360700ae4071cc297e2c567322661704d5eb5af76aeAart Bik private static void expectLessThanOrEqual32(int val1, int val2) { 361700ae4071cc297e2c567322661704d5eb5af76aeAart Bik if (val1 > val2) { 362700ae4071cc297e2c567322661704d5eb5af76aeAart Bik throw new Error("Expected: " + val1 + " <= " + val2); 363700ae4071cc297e2c567322661704d5eb5af76aeAart Bik } 364700ae4071cc297e2c567322661704d5eb5af76aeAart Bik } 365700ae4071cc297e2c567322661704d5eb5af76aeAart Bik 366700ae4071cc297e2c567322661704d5eb5af76aeAart Bik private static void expectEqual64(long expected, long result) { 3670e54c0160c84894696c05af6cad9eae3690f9496Aart Bik if (expected != result) { 3680e54c0160c84894696c05af6cad9eae3690f9496Aart Bik throw new Error("Expected: " + expected + ", found: " + result); 3690e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 3700e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 3710e54c0160c84894696c05af6cad9eae3690f9496Aart Bik 372700ae4071cc297e2c567322661704d5eb5af76aeAart Bik private static void expectEqualObj(Object expected, Object result) { 3730e54c0160c84894696c05af6cad9eae3690f9496Aart Bik if (expected != result) { 3740e54c0160c84894696c05af6cad9eae3690f9496Aart Bik throw new Error("Expected: " + expected + ", found: " + result); 3750e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 3760e54c0160c84894696c05af6cad9eae3690f9496Aart Bik } 3770e54c0160c84894696c05af6cad9eae3690f9496Aart Bik} 378