xref: /aosp_15_r20/art/test/004-checker-UnsafeTest18/src/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Field;
18*795d594fSAndroid Build Coastguard Worker import java.util.concurrent.atomic.AtomicBoolean;
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker import sun.misc.Unsafe;
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker /**
23*795d594fSAndroid Build Coastguard Worker  * Checker test on the 1.8 unsafe operations. Note, this is by no means an
24*795d594fSAndroid Build Coastguard Worker  * exhaustive unit test for these CAS (compare-and-swap) and fence operations.
25*795d594fSAndroid Build Coastguard Worker  * Instead, this test ensures the methods are recognized as intrinsic and behave
26*795d594fSAndroid Build Coastguard Worker  * as expected.
27*795d594fSAndroid Build Coastguard Worker  */
28*795d594fSAndroid Build Coastguard Worker public class Main {
29*795d594fSAndroid Build Coastguard Worker 
30*795d594fSAndroid Build Coastguard Worker   private static final Unsafe unsafe = getUnsafe();
31*795d594fSAndroid Build Coastguard Worker 
32*795d594fSAndroid Build Coastguard Worker   private static Thread[] sThreads = new Thread[10];
33*795d594fSAndroid Build Coastguard Worker 
34*795d594fSAndroid Build Coastguard Worker   //
35*795d594fSAndroid Build Coastguard Worker   // Fields accessed by setters and adders, and by memory fence tests.
36*795d594fSAndroid Build Coastguard Worker   //
37*795d594fSAndroid Build Coastguard Worker 
38*795d594fSAndroid Build Coastguard Worker   public int i = 0;
39*795d594fSAndroid Build Coastguard Worker   public long l = 0;
40*795d594fSAndroid Build Coastguard Worker   public Object o = null;
41*795d594fSAndroid Build Coastguard Worker 
42*795d594fSAndroid Build Coastguard Worker   public int x_value;
43*795d594fSAndroid Build Coastguard Worker   public int y_value;
44*795d594fSAndroid Build Coastguard Worker   public volatile boolean running;
45*795d594fSAndroid Build Coastguard Worker 
46*795d594fSAndroid Build Coastguard Worker   //
47*795d594fSAndroid Build Coastguard Worker   // Setters.
48*795d594fSAndroid Build Coastguard Worker   //
49*795d594fSAndroid Build Coastguard Worker 
50*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.set32(java.lang.Object, long, int) builder (after)
51*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Result:i\d+>> InvokeVirtual intrinsic:UnsafeGetAndSetInt
52*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                 Return [<<Result>>]
set32(Object o, long offset, int newValue)53*795d594fSAndroid Build Coastguard Worker   private static int set32(Object o, long offset, int newValue) {
54*795d594fSAndroid Build Coastguard Worker     return unsafe.getAndSetInt(o, offset, newValue);
55*795d594fSAndroid Build Coastguard Worker   }
56*795d594fSAndroid Build Coastguard Worker 
57*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: long Main.set64(java.lang.Object, long, long) builder (after)
58*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Result:j\d+>> InvokeVirtual intrinsic:UnsafeGetAndSetLong
59*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                 Return [<<Result>>]
set64(Object o, long offset, long newValue)60*795d594fSAndroid Build Coastguard Worker   private static long set64(Object o, long offset, long newValue) {
61*795d594fSAndroid Build Coastguard Worker     return unsafe.getAndSetLong(o, offset, newValue);
62*795d594fSAndroid Build Coastguard Worker   }
63*795d594fSAndroid Build Coastguard Worker 
64*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: java.lang.Object Main.setObj(java.lang.Object, long, java.lang.Object) builder (after)
65*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Result:l\d+>> InvokeVirtual intrinsic:UnsafeGetAndSetObject
66*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                 Return [<<Result>>]
setObj(Object o, long offset, Object newValue)67*795d594fSAndroid Build Coastguard Worker   private static Object setObj(Object o, long offset, Object newValue) {
68*795d594fSAndroid Build Coastguard Worker     return unsafe.getAndSetObject(o, offset, newValue);
69*795d594fSAndroid Build Coastguard Worker   }
70*795d594fSAndroid Build Coastguard Worker 
71*795d594fSAndroid Build Coastguard Worker   //
72*795d594fSAndroid Build Coastguard Worker   // Adders.
73*795d594fSAndroid Build Coastguard Worker   //
74*795d594fSAndroid Build Coastguard Worker 
75*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.add32(java.lang.Object, long, int) builder (after)
76*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Result:i\d+>> InvokeVirtual intrinsic:UnsafeGetAndAddInt
77*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                 Return [<<Result>>]
add32(Object o, long offset, int delta)78*795d594fSAndroid Build Coastguard Worker   private static int add32(Object o, long offset, int delta) {
79*795d594fSAndroid Build Coastguard Worker     return unsafe.getAndAddInt(o, offset, delta);
80*795d594fSAndroid Build Coastguard Worker   }
81*795d594fSAndroid Build Coastguard Worker 
82*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: long Main.add64(java.lang.Object, long, long) builder (after)
83*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Result:j\d+>> InvokeVirtual intrinsic:UnsafeGetAndAddLong
84*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                 Return [<<Result>>]
add64(Object o, long offset, long delta)85*795d594fSAndroid Build Coastguard Worker   private static long add64(Object o, long offset, long delta) {
86*795d594fSAndroid Build Coastguard Worker     return unsafe.getAndAddLong(o, offset, delta);
87*795d594fSAndroid Build Coastguard Worker   }
88*795d594fSAndroid Build Coastguard Worker 
89*795d594fSAndroid Build Coastguard Worker   //
90*795d594fSAndroid Build Coastguard Worker   // Fences (native).
91*795d594fSAndroid Build Coastguard Worker   //
92*795d594fSAndroid Build Coastguard Worker 
93*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void Main.load() builder (after)
94*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT: InvokeVirtual
95*795d594fSAndroid Build Coastguard Worker   //
96*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void Main.load() builder (after)
97*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: MemoryBarrier kind:LoadAny
load()98*795d594fSAndroid Build Coastguard Worker   private static void load() {
99*795d594fSAndroid Build Coastguard Worker     unsafe.loadFence();
100*795d594fSAndroid Build Coastguard Worker   }
101*795d594fSAndroid Build Coastguard Worker 
102*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void Main.store() builder (after)
103*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT: InvokeVirtual
104*795d594fSAndroid Build Coastguard Worker   //
105*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void Main.store() builder (after)
106*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: MemoryBarrier kind:AnyStore
store()107*795d594fSAndroid Build Coastguard Worker   private static void store() {
108*795d594fSAndroid Build Coastguard Worker     unsafe.storeFence();
109*795d594fSAndroid Build Coastguard Worker   }
110*795d594fSAndroid Build Coastguard Worker 
111*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void Main.full() builder (after)
112*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT: InvokeVirtual
113*795d594fSAndroid Build Coastguard Worker   //
114*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void Main.full() builder (after)
115*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: MemoryBarrier kind:AnyAny
full()116*795d594fSAndroid Build Coastguard Worker   private static void full() {
117*795d594fSAndroid Build Coastguard Worker     unsafe.fullFence();
118*795d594fSAndroid Build Coastguard Worker   }
119*795d594fSAndroid Build Coastguard Worker 
120*795d594fSAndroid Build Coastguard Worker   //
121*795d594fSAndroid Build Coastguard Worker   // Thread fork/join.
122*795d594fSAndroid Build Coastguard Worker   //
123*795d594fSAndroid Build Coastguard Worker 
fork(Runnable r)124*795d594fSAndroid Build Coastguard Worker   private static void fork(Runnable r) {
125*795d594fSAndroid Build Coastguard Worker     for (int i = 0; i < 10; i++) {
126*795d594fSAndroid Build Coastguard Worker       sThreads[i] = new Thread(r);
127*795d594fSAndroid Build Coastguard Worker     }
128*795d594fSAndroid Build Coastguard Worker     // Start the threads only after the full array has been written with new threads,
129*795d594fSAndroid Build Coastguard Worker     // because one test relies on the contents of this array to be consistent.
130*795d594fSAndroid Build Coastguard Worker     for (int i = 0; i < 10; i++) {
131*795d594fSAndroid Build Coastguard Worker       sThreads[i].start();
132*795d594fSAndroid Build Coastguard Worker     }
133*795d594fSAndroid Build Coastguard Worker   }
134*795d594fSAndroid Build Coastguard Worker 
join()135*795d594fSAndroid Build Coastguard Worker   private static void join() {
136*795d594fSAndroid Build Coastguard Worker     try {
137*795d594fSAndroid Build Coastguard Worker       for (int i = 0; i < 10; i++) {
138*795d594fSAndroid Build Coastguard Worker         sThreads[i].join();
139*795d594fSAndroid Build Coastguard Worker       }
140*795d594fSAndroid Build Coastguard Worker     } catch (InterruptedException e) {
141*795d594fSAndroid Build Coastguard Worker       throw new Error("Failed join: " + e);
142*795d594fSAndroid Build Coastguard Worker     }
143*795d594fSAndroid Build Coastguard Worker   }
144*795d594fSAndroid Build Coastguard Worker 
145*795d594fSAndroid Build Coastguard Worker   //
146*795d594fSAndroid Build Coastguard Worker   // Driver.
147*795d594fSAndroid Build Coastguard Worker   //
148*795d594fSAndroid Build Coastguard Worker 
main(String[] args)149*795d594fSAndroid Build Coastguard Worker   public static void main(String[] args) {
150*795d594fSAndroid Build Coastguard Worker     System.out.println("starting");
151*795d594fSAndroid Build Coastguard Worker 
152*795d594fSAndroid Build Coastguard Worker     final Main m = new Main();
153*795d594fSAndroid Build Coastguard Worker 
154*795d594fSAndroid Build Coastguard Worker     // Get the offsets.
155*795d594fSAndroid Build Coastguard Worker 
156*795d594fSAndroid Build Coastguard Worker     final long intOffset, longOffset, objOffset;
157*795d594fSAndroid Build Coastguard Worker     try {
158*795d594fSAndroid Build Coastguard Worker       Field intField = Main.class.getDeclaredField("i");
159*795d594fSAndroid Build Coastguard Worker       Field longField = Main.class.getDeclaredField("l");
160*795d594fSAndroid Build Coastguard Worker       Field objField = Main.class.getDeclaredField("o");
161*795d594fSAndroid Build Coastguard Worker 
162*795d594fSAndroid Build Coastguard Worker       intOffset = unsafe.objectFieldOffset(intField);
163*795d594fSAndroid Build Coastguard Worker       longOffset = unsafe.objectFieldOffset(longField);
164*795d594fSAndroid Build Coastguard Worker       objOffset = unsafe.objectFieldOffset(objField);
165*795d594fSAndroid Build Coastguard Worker 
166*795d594fSAndroid Build Coastguard Worker     } catch (NoSuchFieldException e) {
167*795d594fSAndroid Build Coastguard Worker       throw new Error("No offset: " + e);
168*795d594fSAndroid Build Coastguard Worker     }
169*795d594fSAndroid Build Coastguard Worker 
170*795d594fSAndroid Build Coastguard Worker     // Some checks on setters and adders within same thread.
171*795d594fSAndroid Build Coastguard Worker 
172*795d594fSAndroid Build Coastguard Worker     set32(m, intOffset, 3);
173*795d594fSAndroid Build Coastguard Worker     expectEqual32(3, m.i);
174*795d594fSAndroid Build Coastguard Worker 
175*795d594fSAndroid Build Coastguard Worker     set64(m, longOffset, 7L);
176*795d594fSAndroid Build Coastguard Worker     expectEqual64(7L, m.l);
177*795d594fSAndroid Build Coastguard Worker 
178*795d594fSAndroid Build Coastguard Worker     setObj(m, objOffset, m);
179*795d594fSAndroid Build Coastguard Worker     expectEqualObj(m, m.o);
180*795d594fSAndroid Build Coastguard Worker 
181*795d594fSAndroid Build Coastguard Worker     add32(m, intOffset, 11);
182*795d594fSAndroid Build Coastguard Worker     expectEqual32(14, m.i);
183*795d594fSAndroid Build Coastguard Worker 
184*795d594fSAndroid Build Coastguard Worker     add64(m, longOffset, 13L);
185*795d594fSAndroid Build Coastguard Worker     expectEqual64(20L, m.l);
186*795d594fSAndroid Build Coastguard Worker 
187*795d594fSAndroid Build Coastguard Worker     // Some checks on setters within different threads.
188*795d594fSAndroid Build Coastguard Worker 
189*795d594fSAndroid Build Coastguard Worker     fork(new Runnable() {
190*795d594fSAndroid Build Coastguard Worker       public void run() {
191*795d594fSAndroid Build Coastguard Worker         for (int i = 0; i < 10; i++)
192*795d594fSAndroid Build Coastguard Worker           set32(m, intOffset, i);
193*795d594fSAndroid Build Coastguard Worker       }
194*795d594fSAndroid Build Coastguard Worker     });
195*795d594fSAndroid Build Coastguard Worker     join();
196*795d594fSAndroid Build Coastguard Worker     expectEqual32(9, m.i);  // one thread's last value wins
197*795d594fSAndroid Build Coastguard Worker 
198*795d594fSAndroid Build Coastguard Worker     fork(new Runnable() {
199*795d594fSAndroid Build Coastguard Worker       public void run() {
200*795d594fSAndroid Build Coastguard Worker         for (int i = 0; i < 10; i++)
201*795d594fSAndroid Build Coastguard Worker           set64(m, longOffset, (long) (100 + i));
202*795d594fSAndroid Build Coastguard Worker       }
203*795d594fSAndroid Build Coastguard Worker     });
204*795d594fSAndroid Build Coastguard Worker     join();
205*795d594fSAndroid Build Coastguard Worker     expectEqual64(109L, m.l);  // one thread's last value wins
206*795d594fSAndroid Build Coastguard Worker 
207*795d594fSAndroid Build Coastguard Worker     fork(new Runnable() {
208*795d594fSAndroid Build Coastguard Worker       public void run() {
209*795d594fSAndroid Build Coastguard Worker         for (int i = 0; i < 10; i++)
210*795d594fSAndroid Build Coastguard Worker           setObj(m, objOffset, sThreads[i]);
211*795d594fSAndroid Build Coastguard Worker       }
212*795d594fSAndroid Build Coastguard Worker     });
213*795d594fSAndroid Build Coastguard Worker     join();
214*795d594fSAndroid Build Coastguard Worker     expectEqualObj(sThreads[9], m.o);  // one thread's last value wins
215*795d594fSAndroid Build Coastguard Worker 
216*795d594fSAndroid Build Coastguard Worker     // Some checks on adders within different threads.
217*795d594fSAndroid Build Coastguard Worker 
218*795d594fSAndroid Build Coastguard Worker     fork(new Runnable() {
219*795d594fSAndroid Build Coastguard Worker       public void run() {
220*795d594fSAndroid Build Coastguard Worker         for (int i = 0; i < 10; i++)
221*795d594fSAndroid Build Coastguard Worker           add32(m, intOffset, i + 1);
222*795d594fSAndroid Build Coastguard Worker       }
223*795d594fSAndroid Build Coastguard Worker     });
224*795d594fSAndroid Build Coastguard Worker     join();
225*795d594fSAndroid Build Coastguard Worker     expectEqual32(559, m.i);  // all values accounted for
226*795d594fSAndroid Build Coastguard Worker 
227*795d594fSAndroid Build Coastguard Worker     fork(new Runnable() {
228*795d594fSAndroid Build Coastguard Worker       public void run() {
229*795d594fSAndroid Build Coastguard Worker         for (int i = 0; i < 10; i++)
230*795d594fSAndroid Build Coastguard Worker           add64(m, longOffset, (long) (i + 1));
231*795d594fSAndroid Build Coastguard Worker       }
232*795d594fSAndroid Build Coastguard Worker     });
233*795d594fSAndroid Build Coastguard Worker     join();
234*795d594fSAndroid Build Coastguard Worker     expectEqual64(659L, m.l);  // all values accounted for
235*795d594fSAndroid Build Coastguard Worker 
236*795d594fSAndroid Build Coastguard Worker     // Some checks on fences within same thread. Note that memory fences within one
237*795d594fSAndroid Build Coastguard Worker     // thread make little sense, but the assertion ensures nothing bad happens.
238*795d594fSAndroid Build Coastguard Worker 
239*795d594fSAndroid Build Coastguard Worker     m.i = -1;
240*795d594fSAndroid Build Coastguard Worker     m.l = -2L;
241*795d594fSAndroid Build Coastguard Worker     m.o = null;
242*795d594fSAndroid Build Coastguard Worker 
243*795d594fSAndroid Build Coastguard Worker     load();
244*795d594fSAndroid Build Coastguard Worker     store();
245*795d594fSAndroid Build Coastguard Worker     full();
246*795d594fSAndroid Build Coastguard Worker 
247*795d594fSAndroid Build Coastguard Worker     expectEqual32(-1, m.i);
248*795d594fSAndroid Build Coastguard Worker     expectEqual64(-2L, m.l);
249*795d594fSAndroid Build Coastguard Worker     expectEqualObj(null, m.o);
250*795d594fSAndroid Build Coastguard Worker 
251*795d594fSAndroid Build Coastguard Worker     // Some checks on full fence within different threads. We write the non-volatile m.l after
252*795d594fSAndroid Build Coastguard Worker     // the fork(), which means there is no happens-before relation in the Java memory model
253*795d594fSAndroid Build Coastguard Worker     // with respect to the read in the threads. This relation is enforced by the memory fences
254*795d594fSAndroid Build Coastguard Worker     // and the weak-set() -> get() guard. Note that the guard semantics used here are actually
255*795d594fSAndroid Build Coastguard Worker     // too strong and already enforce total memory visibility, but this test illustrates what
256*795d594fSAndroid Build Coastguard Worker     // should still happen if Java had a true relaxed memory guard.
257*795d594fSAndroid Build Coastguard Worker 
258*795d594fSAndroid Build Coastguard Worker     final AtomicBoolean guard1 = new AtomicBoolean();
259*795d594fSAndroid Build Coastguard Worker     m.l = 0L;
260*795d594fSAndroid Build Coastguard Worker 
261*795d594fSAndroid Build Coastguard Worker     fork(new Runnable() {
262*795d594fSAndroid Build Coastguard Worker       public void run() {
263*795d594fSAndroid Build Coastguard Worker         while (!guard1.get());  // busy-waiting
264*795d594fSAndroid Build Coastguard Worker         full();
265*795d594fSAndroid Build Coastguard Worker         expectEqual64(-123456789L, m.l);
266*795d594fSAndroid Build Coastguard Worker       }
267*795d594fSAndroid Build Coastguard Worker     });
268*795d594fSAndroid Build Coastguard Worker 
269*795d594fSAndroid Build Coastguard Worker     m.l = -123456789L;
270*795d594fSAndroid Build Coastguard Worker     full();
271*795d594fSAndroid Build Coastguard Worker     while (!guard1.weakCompareAndSet(false, true));  // relaxed memory order
272*795d594fSAndroid Build Coastguard Worker     join();
273*795d594fSAndroid Build Coastguard Worker 
274*795d594fSAndroid Build Coastguard Worker     // Some checks on release/acquire fences within different threads. We write the non-volatile
275*795d594fSAndroid Build Coastguard Worker     // m.l after the fork(), which means there is no happens-before relation in the Java memory
276*795d594fSAndroid Build Coastguard Worker     // model with respect to the read in the threads. This relation is enforced by the memory fences
277*795d594fSAndroid Build Coastguard Worker     // and the weak-set() -> get() guard. Note that the guard semantics used here are actually
278*795d594fSAndroid Build Coastguard Worker     // too strong and already enforce total memory visibility, but this test illustrates what
279*795d594fSAndroid Build Coastguard Worker     // should still happen if Java had a true relaxed memory guard.
280*795d594fSAndroid Build Coastguard Worker 
281*795d594fSAndroid Build Coastguard Worker     final AtomicBoolean guard2 = new AtomicBoolean();
282*795d594fSAndroid Build Coastguard Worker     m.l = 0L;
283*795d594fSAndroid Build Coastguard Worker 
284*795d594fSAndroid Build Coastguard Worker     fork(new Runnable() {
285*795d594fSAndroid Build Coastguard Worker       public void run() {
286*795d594fSAndroid Build Coastguard Worker         while (!guard2.get());  // busy-waiting
287*795d594fSAndroid Build Coastguard Worker         load();
288*795d594fSAndroid Build Coastguard Worker         expectEqual64(-987654321L, m.l);
289*795d594fSAndroid Build Coastguard Worker       }
290*795d594fSAndroid Build Coastguard Worker     });
291*795d594fSAndroid Build Coastguard Worker 
292*795d594fSAndroid Build Coastguard Worker     m.l = -987654321L;
293*795d594fSAndroid Build Coastguard Worker     store();
294*795d594fSAndroid Build Coastguard Worker     while (!guard2.weakCompareAndSet(false, true));  // relaxed memory order
295*795d594fSAndroid Build Coastguard Worker     join();
296*795d594fSAndroid Build Coastguard Worker 
297*795d594fSAndroid Build Coastguard Worker     // Some checks on release/acquire fences within different threads using a test suggested by
298*795d594fSAndroid Build Coastguard Worker     // Hans Boehm. Even this test remains with the realm of soundness checking only, since having
299*795d594fSAndroid Build Coastguard Worker     // the threads read the same value consistently would be a valid outcome.
300*795d594fSAndroid Build Coastguard Worker 
301*795d594fSAndroid Build Coastguard Worker     m.x_value = -1;
302*795d594fSAndroid Build Coastguard Worker     m.y_value = -1;
303*795d594fSAndroid Build Coastguard Worker     m.running = true;
304*795d594fSAndroid Build Coastguard Worker 
305*795d594fSAndroid Build Coastguard Worker     fork(new Runnable() {
306*795d594fSAndroid Build Coastguard Worker       public void run() {
307*795d594fSAndroid Build Coastguard Worker         while (m.running) {
308*795d594fSAndroid Build Coastguard Worker           for (int few_times = 0; few_times < 1000; few_times++) {
309*795d594fSAndroid Build Coastguard Worker             // Read y first, then load fence, then read x.
310*795d594fSAndroid Build Coastguard Worker             // They should appear in order, if seen at all.
311*795d594fSAndroid Build Coastguard Worker             int local_y = m.y_value;
312*795d594fSAndroid Build Coastguard Worker             load();
313*795d594fSAndroid Build Coastguard Worker             int local_x = m.x_value;
314*795d594fSAndroid Build Coastguard Worker             expectLessThanOrEqual32(local_y, local_x);
315*795d594fSAndroid Build Coastguard Worker           }
316*795d594fSAndroid Build Coastguard Worker         }
317*795d594fSAndroid Build Coastguard Worker       }
318*795d594fSAndroid Build Coastguard Worker     });
319*795d594fSAndroid Build Coastguard Worker 
320*795d594fSAndroid Build Coastguard Worker     for (int many_times = 0; many_times < 100000; many_times++) {
321*795d594fSAndroid Build Coastguard Worker       m.x_value = many_times;
322*795d594fSAndroid Build Coastguard Worker       store();
323*795d594fSAndroid Build Coastguard Worker       m.y_value = many_times;
324*795d594fSAndroid Build Coastguard Worker     }
325*795d594fSAndroid Build Coastguard Worker     m.running = false;
326*795d594fSAndroid Build Coastguard Worker     join();
327*795d594fSAndroid Build Coastguard Worker 
328*795d594fSAndroid Build Coastguard Worker     // All done!
329*795d594fSAndroid Build Coastguard Worker 
330*795d594fSAndroid Build Coastguard Worker     System.out.println("passed");
331*795d594fSAndroid Build Coastguard Worker   }
332*795d594fSAndroid Build Coastguard Worker 
333*795d594fSAndroid Build Coastguard Worker   // Use reflection to implement "Unsafe.getUnsafe()";
getUnsafe()334*795d594fSAndroid Build Coastguard Worker   private static Unsafe getUnsafe() {
335*795d594fSAndroid Build Coastguard Worker     try {
336*795d594fSAndroid Build Coastguard Worker       Class<?> unsafeClass = Unsafe.class;
337*795d594fSAndroid Build Coastguard Worker       Field f = unsafeClass.getDeclaredField("theUnsafe");
338*795d594fSAndroid Build Coastguard Worker       f.setAccessible(true);
339*795d594fSAndroid Build Coastguard Worker       return (Unsafe) f.get(null);
340*795d594fSAndroid Build Coastguard Worker     } catch (Exception e) {
341*795d594fSAndroid Build Coastguard Worker       throw new Error("Cannot get Unsafe instance");
342*795d594fSAndroid Build Coastguard Worker     }
343*795d594fSAndroid Build Coastguard Worker   }
344*795d594fSAndroid Build Coastguard Worker 
expectEqual32(int expected, int result)345*795d594fSAndroid Build Coastguard Worker   private static void expectEqual32(int expected, int result) {
346*795d594fSAndroid Build Coastguard Worker     if (expected != result) {
347*795d594fSAndroid Build Coastguard Worker       throw new Error("Expected: " + expected + ", found: " + result);
348*795d594fSAndroid Build Coastguard Worker     }
349*795d594fSAndroid Build Coastguard Worker   }
350*795d594fSAndroid Build Coastguard Worker 
expectLessThanOrEqual32(int val1, int val2)351*795d594fSAndroid Build Coastguard Worker   private static void expectLessThanOrEqual32(int val1, int val2) {
352*795d594fSAndroid Build Coastguard Worker     if (val1 > val2) {
353*795d594fSAndroid Build Coastguard Worker       throw new Error("Expected: " + val1 + " <= " + val2);
354*795d594fSAndroid Build Coastguard Worker     }
355*795d594fSAndroid Build Coastguard Worker   }
356*795d594fSAndroid Build Coastguard Worker 
expectEqual64(long expected, long result)357*795d594fSAndroid Build Coastguard Worker   private static void expectEqual64(long expected, long result) {
358*795d594fSAndroid Build Coastguard Worker     if (expected != result) {
359*795d594fSAndroid Build Coastguard Worker       throw new Error("Expected: " + expected + ", found: " + result);
360*795d594fSAndroid Build Coastguard Worker     }
361*795d594fSAndroid Build Coastguard Worker   }
362*795d594fSAndroid Build Coastguard Worker 
expectEqualObj(Object expected, Object result)363*795d594fSAndroid Build Coastguard Worker   private static void expectEqualObj(Object expected, Object result) {
364*795d594fSAndroid Build Coastguard Worker     if (expected != result) {
365*795d594fSAndroid Build Coastguard Worker       throw new Error("Expected: " + expected + ", found: " + result);
366*795d594fSAndroid Build Coastguard Worker     }
367*795d594fSAndroid Build Coastguard Worker   }
368*795d594fSAndroid Build Coastguard Worker }
369