blob: 48f9bd363fb5b9d724044d9b248b529d1649dda7 [file] [log] [blame]
Brian Carlstrom55621742011-10-17 00:41:56 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17import java.util.ArrayList;
18import java.util.List;
Andreas Gampe93f3da12014-07-26 01:13:13 -070019import java.util.concurrent.BrokenBarrierException;
20import java.util.concurrent.CyclicBarrier;
21import java.util.concurrent.SynchronousQueue;
22import java.util.concurrent.TimeUnit;
23import java.util.concurrent.TimeoutException;
Brian Carlstrom55621742011-10-17 00:41:56 -070024
Andreas Gampe1c83cbc2014-07-22 18:52:29 -070025public class Main implements Runnable {
Andreas Gampe93f3da12014-07-26 01:13:13 -070026
Andreas Gampeee576fa2015-01-15 08:02:22 -080027 // Timeout in minutes. Make it larger than the run-test timeout to get a native thread dump by
28 // ART on timeout when running on the host.
Mathieu Chartier8dcde232015-01-15 17:23:16 -080029 public final static long TIMEOUT_VALUE = 12;
Andreas Gampeee576fa2015-01-15 08:02:22 -080030
Andreas Gampe93f3da12014-07-26 01:13:13 -070031 public final static long MAX_SIZE = 1000; // Maximum size of array-list to allocate.
32
Brian Carlstrom55621742011-10-17 00:41:56 -070033 public static void main(String[] args) throws Exception {
34 Thread[] threads = new Thread[16];
Andreas Gampe93f3da12014-07-26 01:13:13 -070035
36 // Use a cyclic system of synchronous queues to pass a boolean token around.
37 //
38 // The combinations are:
39 //
40 // Worker receives: true false false true
41 // Worker has OOM: false false true true
42 // |
43 // v
44 // Value to pass: true false false false
45 // Exit out of loop: false true true true
46 // Wait on in queue: true false false true
47 //
48 // Finally, the workers are supposed to wait on the barrier to synchronize the GC run.
49
50 CyclicBarrier barrier = new CyclicBarrier(threads.length);
51 List<SynchronousQueue<Boolean>> queues = new ArrayList<SynchronousQueue<Boolean>>(
52 threads.length);
Brian Carlstrom55621742011-10-17 00:41:56 -070053 for (int i = 0; i < threads.length; i++) {
Andreas Gampe93f3da12014-07-26 01:13:13 -070054 queues.add(new SynchronousQueue<Boolean>());
55 }
56
57 for (int i = 0; i < threads.length; i++) {
58 threads[i] = new Thread(new Main(i, queues.get(i), queues.get((i + 1) % threads.length),
59 barrier));
Brian Carlstrom55621742011-10-17 00:41:56 -070060 }
61 for (Thread thread : threads) {
62 thread.start();
63 }
Andreas Gampe93f3da12014-07-26 01:13:13 -070064
65 // Push off the cycle.
66 checkTimeout(queues.get(0).offer(Boolean.TRUE, TIMEOUT_VALUE, TimeUnit.MINUTES));
67
68 // Wait for the threads to finish.
Brian Carlstrom55621742011-10-17 00:41:56 -070069 for (Thread thread : threads) {
70 thread.join();
71 }
Andreas Gampe93f3da12014-07-26 01:13:13 -070072
73 // Allocate objects to definitely run GC before quitting.
74 try {
75 for (int i = 0; i < 1000; i++) {
76 new ArrayList<Object>(i);
77 }
78 } catch (OutOfMemoryError oom) {
79 }
80 }
81
82 private static void checkTimeout(Object o) {
83 checkTimeout(o != null);
84 }
85
86 private static void checkTimeout(boolean b) {
87 if (!b) {
88 // Something went wrong.
89 System.out.println("Bad things happened, timeout.");
90 System.exit(1);
91 }
Brian Carlstrom55621742011-10-17 00:41:56 -070092 }
93
94 private final int id;
Andreas Gampe93f3da12014-07-26 01:13:13 -070095 private final SynchronousQueue<Boolean> waitOn;
96 private final SynchronousQueue<Boolean> pushTo;
97 private final CyclicBarrier finalBarrier;
Brian Carlstrom55621742011-10-17 00:41:56 -070098
Andreas Gampe93f3da12014-07-26 01:13:13 -070099 private Main(int id, SynchronousQueue<Boolean> waitOn, SynchronousQueue<Boolean> pushTo,
100 CyclicBarrier finalBarrier) {
Brian Carlstrom55621742011-10-17 00:41:56 -0700101 this.id = id;
Andreas Gampe93f3da12014-07-26 01:13:13 -0700102 this.waitOn = waitOn;
103 this.pushTo = pushTo;
104 this.finalBarrier = finalBarrier;
Brian Carlstrom55621742011-10-17 00:41:56 -0700105 }
106
107 public void run() {
Andreas Gampe93f3da12014-07-26 01:13:13 -0700108 try {
109 work();
110 } catch (Exception exc) {
111 // Any exception is bad.
112 exc.printStackTrace(System.err);
113 System.exit(1);
Brian Carlstrom55621742011-10-17 00:41:56 -0700114 }
115 }
Andreas Gampe21b4bf82014-07-25 16:37:09 -0700116
Andreas Gampe93f3da12014-07-26 01:13:13 -0700117 public void work() throws BrokenBarrierException, InterruptedException, TimeoutException {
118 ArrayList<Object> l = new ArrayList<Object>();
119
120 // Main loop.
121 for (int i = 0; ; i++) {
122 Boolean receivedB = waitOn.poll(TIMEOUT_VALUE, TimeUnit.MINUTES);
123 checkTimeout(receivedB);
124 boolean received = receivedB;
125
126 // This is the first stage, try to allocate up till MAX_SIZE.
127 boolean oom = i >= MAX_SIZE;
128 try {
129 l.add(new ArrayList<Object>(i));
130 } catch (OutOfMemoryError oome) {
131 oom = true;
132 }
133
134 if (!received || oom) {
135 // First stage, always push false.
136 checkTimeout(pushTo.offer(Boolean.FALSE, TIMEOUT_VALUE, TimeUnit.MINUTES));
137
138 // If we received true, wait for the false to come around.
139 if (received) {
140 checkTimeout(waitOn.poll(TIMEOUT_VALUE, TimeUnit.MINUTES));
141 }
142
143 // Break out of the loop.
144 break;
145 } else {
146 // Pass on true.
147 checkTimeout(pushTo.offer(Boolean.TRUE, TIMEOUT_VALUE, TimeUnit.MINUTES));
148 }
149 }
150
151 // We have reached the final point. Wait on the barrier, but at most a minute.
152 finalBarrier.await(TIMEOUT_VALUE, TimeUnit.MINUTES);
153
154 // Done.
155 }
Brian Carlstrom55621742011-10-17 00:41:56 -0700156}