17c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom/* 27c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom * Copyright (C) 2011 The Android Open Source Project 37c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom * 47c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License"); 57c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom * you may not use this file except in compliance with the License. 67c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom * You may obtain a copy of the License at 77c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom * 87c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom * http://www.apache.org/licenses/LICENSE-2.0 97c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom * 107c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom * Unless required by applicable law or agreed to in writing, software 117c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS, 127c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom * See the License for the specific language governing permissions and 147c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom * limitations under the License. 157c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom */ 167c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 171c83cbc4a817acbd7f9abb5b29a2d418a958e6a1Andreas Gampeimport java.lang.reflect.*; 187c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstromimport java.util.ArrayList; 197c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstromimport java.util.Arrays; 207c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstromimport java.util.Collections; 217c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstromimport java.util.HashMap; 22f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampeimport java.util.HashSet; 237c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstromimport java.util.List; 247c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstromimport java.util.Map; 25f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampeimport java.util.Set; 267c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 277c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom// Run on host with: 287c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom// javac ThreadTest.java && java ThreadStress && rm *.class 29f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe// Through run-test: 30f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe// test/run-test {run-test-args} 004-ThreadStress [Main {ThreadStress-args}] 31f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe// (It is important to pass Main if you want to give parameters...) 32f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe// 33f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe// ThreadStress command line parameters: 34f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe// -n X ............ number of threads 35def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao// -d X ............ number of daemon threads 36f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe// -o X ............ number of overall operations 37f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe// -t X ............ number of operations per thread 38f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe// --dumpmap ....... print the frequency map 39f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe// -oom:X .......... frequency of OOM (double) 40f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe// -alloc:X ........ frequency of Alloc 41f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe// -stacktrace:X ... frequency of StackTrace 42f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe// -exit:X ......... frequency of Exit 43f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe// -sleep:X ........ frequency of Sleep 44f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe// -wait:X ......... frequency of Wait 45f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe// -timedwait:X .... frequency of TimedWait 46f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 471c83cbc4a817acbd7f9abb5b29a2d418a958e6a1Andreas Gampepublic class Main implements Runnable { 487c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 494514d3c0e69a49f5dbe19138330a2bb2aee36d63Brian Carlstrom public static final boolean DEBUG = false; 507c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 51f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private static abstract class Operation { 52f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe /** 53f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe * Perform the action represented by this operation. Returns true if the thread should 54f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe * continue. 55f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe */ 56f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public abstract boolean perform(); 57f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 58f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 59f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static class OOM extends Operation { 60059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe private final static int ALLOC_SIZE = 1024; 61059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe 62f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe @Override 63f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public boolean perform() { 64f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe try { 65f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe List<byte[]> l = new ArrayList<byte[]>(); 66f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe while (true) { 67059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe l.add(new byte[ALLOC_SIZE]); 68f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 69f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } catch (OutOfMemoryError e) { 70f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 71f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return true; 72f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 73f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 74f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 75f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static class SigQuit extends Operation { 76f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static int sigquit; 77f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static Method kill; 78f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static int pid; 79f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 80f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe static { 81f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe int pidTemp = -1; 82f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe int sigquitTemp = -1; 83f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Method killTemp = null; 84f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 85f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe try { 86f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Class<?> osClass = Class.forName("android.system.Os"); 87f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Method getpid = osClass.getDeclaredMethod("getpid"); 88f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe pidTemp = (Integer)getpid.invoke(null); 89f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 90f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Class<?> osConstants = Class.forName("android.system.OsConstants"); 91f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Field sigquitField = osConstants.getDeclaredField("SIGQUIT"); 92f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe sigquitTemp = (Integer)sigquitField.get(null); 93f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 94f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe killTemp = osClass.getDeclaredMethod("kill", int.class, int.class); 95f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } catch (Exception e) { 96f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (!e.getClass().getName().equals("ErrnoException")) { 97f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe e.printStackTrace(System.out); 98f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 99f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 100f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 101f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe pid = pidTemp; 102f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe sigquit = sigquitTemp; 103f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe kill = killTemp; 104f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 105f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 106f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe @Override 107f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public boolean perform() { 108f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe try { 109f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe kill.invoke(null, pid, sigquit); 110f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } catch (Exception e) { 111f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (!e.getClass().getName().equals("ErrnoException")) { 112f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe e.printStackTrace(System.out); 113f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 114f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 115f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return true; 116f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 117f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 118f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 119f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static class Alloc extends Operation { 120059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe private final static int ALLOC_SIZE = 1024; // Needs to be small enough to not be in LOS. 121059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe private final static int ALLOC_COUNT = 1024; 122059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe 123059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe @Override 124059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe public boolean perform() { 125059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe try { 126059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe List<byte[]> l = new ArrayList<byte[]>(); 127059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe for (int i = 0; i < ALLOC_COUNT; i++) { 128059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe l.add(new byte[ALLOC_SIZE]); 129059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe } 130059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe } catch (OutOfMemoryError e) { 131059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe } 132059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe return true; 133059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe } 134059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe } 135059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe 136059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe private final static class LargeAlloc extends Operation { 137059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe private final static int PAGE_SIZE = 4096; 138059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe private final static int PAGE_SIZE_MODIFIER = 10; // Needs to be large enough for LOS. 139059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe private final static int ALLOC_COUNT = 100; 140059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe 141f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe @Override 142f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public boolean perform() { 143f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe try { 144f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe List<byte[]> l = new ArrayList<byte[]>(); 145059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe for (int i = 0; i < ALLOC_COUNT; i++) { 146059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe l.add(new byte[PAGE_SIZE_MODIFIER * PAGE_SIZE]); 147f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 148f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } catch (OutOfMemoryError e) { 149f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 150f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return true; 151f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 152f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 153f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 154f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static class StackTrace extends Operation { 155f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe @Override 156f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public boolean perform() { 157f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Thread.currentThread().getStackTrace(); 158f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return true; 159f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 160f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 161f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 162f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static class Exit extends Operation { 163f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe @Override 164f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public boolean perform() { 165f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return false; 166f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 167f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 168f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 169f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static class Sleep extends Operation { 170059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe private final static int SLEEP_TIME = 100; 171059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe 172f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe @Override 173f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public boolean perform() { 174f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe try { 175059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe Thread.sleep(SLEEP_TIME); 176f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } catch (InterruptedException ignored) { 177f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 178f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return true; 179f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 180f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 1814cd121ef0cb35fced70c7d9de378277be7a727d9Elliott Hughes 182f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static class TimedWait extends Operation { 183059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe private final static int SLEEP_TIME = 100; 184059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe 185f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final Object lock; 1867c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 187f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public TimedWait(Object lock) { 188f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe this.lock = lock; 189f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 190f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 191f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe @Override 192f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public boolean perform() { 193f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe synchronized (lock) { 194f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe try { 195059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe lock.wait(SLEEP_TIME, 0); 196f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } catch (InterruptedException ignored) { 197f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 198f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 199f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return true; 2007c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 2017c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 2027c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 203f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static class Wait extends Operation { 204f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final Object lock; 205f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 206f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public Wait(Object lock) { 207f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe this.lock = lock; 208f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 209f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 210f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe @Override 211f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public boolean perform() { 212f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe synchronized (lock) { 213f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe try { 214f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe lock.wait(); 215f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } catch (InterruptedException ignored) { 216f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 217f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 218f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return true; 219f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 220f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 221f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 222f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static class SyncAndWork extends Operation { 223f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final Object lock; 224f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 225f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public SyncAndWork(Object lock) { 226f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe this.lock = lock; 227f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 228f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 229f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe @Override 230f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public boolean perform() { 231f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe synchronized (lock) { 232f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe try { 233f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Thread.sleep((int)(Math.random()*10)); 234f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } catch (InterruptedException ignored) { 235f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 236f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 237f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return true; 238f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 239f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 240f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 241f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static Map<Operation, Double> createDefaultFrequencyMap(Object lock) { 242f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Map<Operation, Double> frequencyMap = new HashMap<Operation, Double>(); 243f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap.put(new OOM(), 0.005); // 1/200 244f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap.put(new SigQuit(), 0.095); // 19/200 245059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe frequencyMap.put(new Alloc(), 0.25); // 50/200 246059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe frequencyMap.put(new LargeAlloc(), 0.05); // 10/200 247f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap.put(new StackTrace(), 0.1); // 20/200 248f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap.put(new Exit(), 0.25); // 50/200 249f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap.put(new Sleep(), 0.125); // 25/200 250f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap.put(new TimedWait(lock), 0.05); // 10/200 251f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap.put(new Wait(lock), 0.075); // 15/200 252f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 253f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return frequencyMap; 254f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 255f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 256f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static Map<Operation, Double> createLockFrequencyMap(Object lock) { 257f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Map<Operation, Double> frequencyMap = new HashMap<Operation, Double>(); 258f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap.put(new Sleep(), 0.2); 259f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap.put(new TimedWait(lock), 0.2); 260f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap.put(new Wait(lock), 0.2); 261f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap.put(new SyncAndWork(lock), 0.4); 262f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 263f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return frequencyMap; 264f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 265f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 2667c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom public static void main(String[] args) throws Exception { 267f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe parseAndRun(args); 268f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 2697c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 270f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private static Map<Operation, Double> updateFrequencyMap(Map<Operation, Double> in, 271f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Object lock, String arg) { 272f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe String split[] = arg.split(":"); 273f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (split.length != 2) { 274f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe throw new IllegalArgumentException("Can't split argument " + arg); 275f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 276f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe double d; 277f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe try { 278f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe d = Double.parseDouble(split[1]); 279f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } catch (Exception e) { 280f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe throw new IllegalArgumentException(e); 281f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 282f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (d < 0) { 283f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe throw new IllegalArgumentException(arg + ": value must be >= 0."); 284f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 285f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Operation op = null; 286f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (split[0].equals("-oom")) { 287f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe op = new OOM(); 288f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else if (split[0].equals("-sigquit")) { 289f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe op = new SigQuit(); 290f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else if (split[0].equals("-alloc")) { 291f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe op = new Alloc(); 292059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe } else if (split[0].equals("-largealloc")) { 293059e62711093bbc115e1d6ca56573e2df3ebdff8Andreas Gampe op = new LargeAlloc(); 294f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else if (split[0].equals("-stacktrace")) { 295f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe op = new StackTrace(); 296f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else if (split[0].equals("-exit")) { 297f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe op = new Exit(); 298f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else if (split[0].equals("-sleep")) { 299f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe op = new Sleep(); 300f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else if (split[0].equals("-wait")) { 301f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe op = new Wait(lock); 302f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else if (split[0].equals("-timedwait")) { 303f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe op = new TimedWait(lock); 304f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else { 305f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe throw new IllegalArgumentException("Unknown arg " + arg); 306f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 307f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 308f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (in == null) { 309f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe in = new HashMap<Operation, Double>(); 310f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 311f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe in.put(op, d); 3127c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 313f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return in; 314f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 315f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 316f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private static void normalize(Map<Operation, Double> map) { 317f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe double sum = 0; 318f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe for (Double d : map.values()) { 319f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe sum += d; 320f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 321f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (sum == 0) { 322f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe throw new RuntimeException("No elements!"); 323f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 324f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (sum != 1.0) { 325f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe // Avoid ConcurrentModificationException. 326f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Set<Operation> tmp = new HashSet<>(map.keySet()); 327f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe for (Operation op : tmp) { 328f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe map.put(op, map.get(op) / sum); 329f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 330f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 331f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 332f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 333f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public static void parseAndRun(String[] args) throws Exception { 334f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe int numberOfThreads = -1; 335def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao int numberOfDaemons = -1; 336f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe int totalOperations = -1; 337f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe int operationsPerThread = -1; 338f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Object lock = new Object(); 339f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Map<Operation, Double> frequencyMap = null; 340f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe boolean dumpMap = false; 341f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 342f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (args != null) { 343031768a340634e2dbdec1aebb2bb3fe509b2f1f6Mathieu Chartier // args[0] is libarttest 344031768a340634e2dbdec1aebb2bb3fe509b2f1f6Mathieu Chartier for (int i = 1; i < args.length; i++) { 345f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (args[i].equals("-n")) { 346f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe i++; 347f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe numberOfThreads = Integer.parseInt(args[i]); 348def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao } else if (args[i].equals("-d")) { 349def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao i++; 350def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao numberOfDaemons = Integer.parseInt(args[i]); 351f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else if (args[i].equals("-o")) { 352f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe i++; 353f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe totalOperations = Integer.parseInt(args[i]); 354f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else if (args[i].equals("-t")) { 355f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe i++; 356f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe operationsPerThread = Integer.parseInt(args[i]); 357f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else if (args[i].equals("--locks-only")) { 358f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe lock = new Object(); 359f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap = createLockFrequencyMap(lock); 360f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else if (args[i].equals("--dumpmap")) { 361f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe dumpMap = true; 362f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else { 363f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap = updateFrequencyMap(frequencyMap, lock, args[i]); 364f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 365f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 366f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 3677c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 368f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (totalOperations != -1 && operationsPerThread != -1) { 369f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe throw new IllegalArgumentException( 370f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe "Specified both totalOperations and operationsPerThread"); 371f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 372f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 373f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (numberOfThreads == -1) { 374f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe numberOfThreads = 5; 375f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 376f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 377def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao if (numberOfDaemons == -1) { 378def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao numberOfDaemons = 3; 379def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao } 380def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao 381f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (totalOperations == -1) { 382f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe totalOperations = 1000; 383f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 384f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 385f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (operationsPerThread == -1) { 386f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe operationsPerThread = totalOperations/numberOfThreads; 387f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 388f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 389f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (frequencyMap == null) { 390f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap = createDefaultFrequencyMap(lock); 391f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 392f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe normalize(frequencyMap); 393f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 394f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (dumpMap) { 395f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe System.out.println(frequencyMap); 396f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 397f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 398def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao runTest(numberOfThreads, numberOfDaemons, operationsPerThread, lock, frequencyMap); 399f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 400f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 401def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao public static void runTest(final int numberOfThreads, final int numberOfDaemons, 402def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao final int operationsPerThread, final Object lock, 403def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao Map<Operation, Double> frequencyMap) throws Exception { 404def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao // Each normal thread is going to do operationsPerThread 405def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao // operations. Each daemon thread will loop over all 406def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao // the operations and will not stop. 407def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao // The distribution of operations is determined by 4087c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // the Operation.frequency values. We fill out an Operation[] 4097c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // for each thread with the operations it is to perform. The 4107c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // Operation[] is shuffled so that there is more random 4117c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // interactions between the threads. 4127c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 4137c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // Fill in the Operation[] array for each thread by laying 4147c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // down references to operation according to their desired 4157c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // frequency. 416def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao // The first numberOfThreads elements are normal threads, the last 417def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao // numberOfDaemons elements are daemon threads. 418def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao final Main[] threadStresses = new Main[numberOfThreads + numberOfDaemons]; 4197c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom for (int t = 0; t < threadStresses.length; t++) { 4207c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom Operation[] operations = new Operation[operationsPerThread]; 4217c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom int o = 0; 4227c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom LOOP: 4237c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom while (true) { 424f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe for (Operation op : frequencyMap.keySet()) { 425f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe int freq = (int)(frequencyMap.get(op) * operationsPerThread); 426f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe for (int f = 0; f < freq; f++) { 4277c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom if (o == operations.length) { 4287c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom break LOOP; 4297c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 4307c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom operations[o] = op; 4317c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom o++; 4327c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 4337c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 4347c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 435def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao // Randomize the operation order 4367c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom Collections.shuffle(Arrays.asList(operations)); 437def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao threadStresses[t] = t < numberOfThreads ? new Main(lock, t, operations) : 438def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao new Daemon(lock, t, operations); 4397c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 4407c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 441f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe // Enable to dump operation counts per thread to make sure its 4427c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // sane compared to Operation.frequency 4437c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom if (DEBUG) { 4447c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom for (int t = 0; t < threadStresses.length; t++) { 445f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Operation[] operations = threadStresses[t].operations; 4467c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom Map<Operation, Integer> distribution = new HashMap<Operation, Integer>(); 4477c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom for (Operation operation : operations) { 4487c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom Integer ops = distribution.get(operation); 4497c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom if (ops == null) { 4507c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom ops = 1; 4517c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } else { 4527c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom ops++; 4537c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 4547c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom distribution.put(operation, ops); 4557c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 4567c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom System.out.println("Distribution for " + t); 457f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe for (Operation op : frequencyMap.keySet()) { 4587c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom System.out.println(op + " = " + distribution.get(op)); 4597c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 4607c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 4617c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 4627c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 4637c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // Create the runners for each thread. The runner Thread 4647c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // ensures that thread that exit due to Operation.EXIT will be 4657c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // restarted until they reach their desired 4667c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // operationsPerThread. 4677c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom Thread[] runners = new Thread[numberOfThreads]; 4687c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom for (int r = 0; r < runners.length; r++) { 4691c83cbc4a817acbd7f9abb5b29a2d418a958e6a1Andreas Gampe final Main ts = threadStresses[r]; 4705f51d4b80058236759fea1d932470a57f348c199Mathieu Chartier runners[r] = new Thread("Runner thread " + r) { 4711c83cbc4a817acbd7f9abb5b29a2d418a958e6a1Andreas Gampe final Main threadStress = ts; 4727c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom public void run() { 4737c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom int id = threadStress.id; 4745f51d4b80058236759fea1d932470a57f348c199Mathieu Chartier System.out.println("Starting worker for " + id); 4757c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom while (threadStress.nextOperation < operationsPerThread) { 4769d3c3fc49dc904ddd393f8d24ed062a42c68939aMathieu Chartier try { 47772e36d84d8c6eb4a0396ce7e4de8f696ad3d2a7fMathieu Chartier Thread thread = new Thread(ts, "Worker thread " + id); 47872e36d84d8c6eb4a0396ce7e4de8f696ad3d2a7fMathieu Chartier thread.start(); 47972e36d84d8c6eb4a0396ce7e4de8f696ad3d2a7fMathieu Chartier try { 48072e36d84d8c6eb4a0396ce7e4de8f696ad3d2a7fMathieu Chartier thread.join(); 48172e36d84d8c6eb4a0396ce7e4de8f696ad3d2a7fMathieu Chartier } catch (InterruptedException e) { 48272e36d84d8c6eb4a0396ce7e4de8f696ad3d2a7fMathieu Chartier } 48372e36d84d8c6eb4a0396ce7e4de8f696ad3d2a7fMathieu Chartier 4849d3c3fc49dc904ddd393f8d24ed062a42c68939aMathieu Chartier System.out.println("Thread exited for " + id + " with " 4859d3c3fc49dc904ddd393f8d24ed062a42c68939aMathieu Chartier + (operationsPerThread - threadStress.nextOperation) 4869d3c3fc49dc904ddd393f8d24ed062a42c68939aMathieu Chartier + " operations remaining."); 4879d3c3fc49dc904ddd393f8d24ed062a42c68939aMathieu Chartier } catch (OutOfMemoryError e) { 4889d3c3fc49dc904ddd393f8d24ed062a42c68939aMathieu Chartier // Ignore OOME since we need to print "Finishing worker" for the test 4899d3c3fc49dc904ddd393f8d24ed062a42c68939aMathieu Chartier // to pass. 4909d3c3fc49dc904ddd393f8d24ed062a42c68939aMathieu Chartier } 4917c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 49272e36d84d8c6eb4a0396ce7e4de8f696ad3d2a7fMathieu Chartier // Keep trying to print "Finishing worker" until it succeeds. 49372e36d84d8c6eb4a0396ce7e4de8f696ad3d2a7fMathieu Chartier while (true) { 49472e36d84d8c6eb4a0396ce7e4de8f696ad3d2a7fMathieu Chartier try { 49572e36d84d8c6eb4a0396ce7e4de8f696ad3d2a7fMathieu Chartier System.out.println("Finishing worker"); 49672e36d84d8c6eb4a0396ce7e4de8f696ad3d2a7fMathieu Chartier break; 49772e36d84d8c6eb4a0396ce7e4de8f696ad3d2a7fMathieu Chartier } catch (OutOfMemoryError e) { 49872e36d84d8c6eb4a0396ce7e4de8f696ad3d2a7fMathieu Chartier } 49972e36d84d8c6eb4a0396ce7e4de8f696ad3d2a7fMathieu Chartier } 5007c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 5017c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom }; 5027c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 5037c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 5047c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // The notifier thread is a daemon just loops forever to wake 5057c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // up threads in Operation.WAIT 506f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (lock != null) { 507f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Thread notifier = new Thread("Notifier") { 508f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public void run() { 509f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe while (true) { 510f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe synchronized (lock) { 511f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe lock.notifyAll(); 512f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 5137c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 5147c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 515f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe }; 516f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe notifier.setDaemon(true); 517f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe notifier.start(); 518f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 5197c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 520def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao // Create and start the daemon threads. 521def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao for (int r = 0; r < numberOfDaemons; r++) { 522def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao Main daemon = threadStresses[numberOfThreads + r]; 523def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao Thread t = new Thread(daemon, "Daemon thread " + daemon.id); 524def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao t.setDaemon(true); 525def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao t.start(); 526def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao } 527def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao 5287c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom for (int r = 0; r < runners.length; r++) { 5297c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom runners[r].start(); 5307c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 5317c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom for (int r = 0; r < runners.length; r++) { 5327c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom runners[r].join(); 5337c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 5347c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 5357c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 536def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao protected final Operation[] operations; 5377c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom private final Object lock; 538def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao protected final int id; 5397c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 5407c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom private int nextOperation; 5417c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 5421c83cbc4a817acbd7f9abb5b29a2d418a958e6a1Andreas Gampe private Main(Object lock, int id, Operation[] operations) { 5437c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom this.lock = lock; 5447c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom this.id = id; 5457c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom this.operations = operations; 5467c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 5477c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 5487c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom public void run() { 5497c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom try { 5507c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom if (DEBUG) { 5517c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom System.out.println("Starting ThreadStress " + id); 5527c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 5537c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom while (nextOperation < operations.length) { 5547c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom Operation operation = operations[nextOperation]; 5557c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom if (DEBUG) { 5567c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom System.out.println("ThreadStress " + id 5577c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom + " operation " + nextOperation 5587c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom + " is " + operation); 5597c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 5607c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom nextOperation++; 561f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (!operation.perform()) { 562f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return; 5637c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 5647c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 5654514d3c0e69a49f5dbe19138330a2bb2aee36d63Brian Carlstrom } finally { 5667c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom if (DEBUG) { 5677c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom System.out.println("Finishing ThreadStress for " + id); 5687c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 5697c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 5707c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 5711c83cbc4a817acbd7f9abb5b29a2d418a958e6a1Andreas Gampe 572def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao private static class Daemon extends Main { 573def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao private Daemon(Object lock, int id, Operation[] operations) { 574def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao super(lock, id, operations); 575def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao } 576def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao 577def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao public void run() { 578def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao try { 579def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao if (DEBUG) { 580def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao System.out.println("Starting ThreadStress Daemon " + id); 581def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao } 582def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao int i = 0; 583def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao while (true) { 584def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao Operation operation = operations[i]; 585def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao if (DEBUG) { 586def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao System.out.println("ThreadStress Daemon " + id 587def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao + " operation " + i 588def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao + " is " + operation); 589def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao } 590def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao operation.perform(); 591def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao i = (i + 1) % operations.length; 592def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao } 593bf81547a47c46a8853092432635bfec6167a2388Mathieu Chartier } catch (OutOfMemoryError e) { 594bf81547a47c46a8853092432635bfec6167a2388Mathieu Chartier // Catch OutOfMemoryErrors since these can cause the test to fail it they print 595bf81547a47c46a8853092432635bfec6167a2388Mathieu Chartier // the stack trace after "Finishing worker". 596def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao } finally { 597def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao if (DEBUG) { 598def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao System.out.println("Finishing ThreadStress Daemon for " + id); 599def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao } 600def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao } 601def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao } 602def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao } 603def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao 6047c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom} 605