Main.java revision bf81547a47c46a8853092432635bfec6167a2388
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 { 60f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe @Override 61f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public boolean perform() { 62f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe try { 63f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe List<byte[]> l = new ArrayList<byte[]>(); 64f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe while (true) { 65f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe l.add(new byte[1024]); 66f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 67f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } catch (OutOfMemoryError e) { 68f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 69f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return true; 70f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 71f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 72f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 73f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static class SigQuit extends Operation { 74f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static int sigquit; 75f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static Method kill; 76f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static int pid; 77f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 78f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe static { 79f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe int pidTemp = -1; 80f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe int sigquitTemp = -1; 81f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Method killTemp = null; 82f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 83f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe try { 84f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Class<?> osClass = Class.forName("android.system.Os"); 85f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Method getpid = osClass.getDeclaredMethod("getpid"); 86f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe pidTemp = (Integer)getpid.invoke(null); 87f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 88f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Class<?> osConstants = Class.forName("android.system.OsConstants"); 89f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Field sigquitField = osConstants.getDeclaredField("SIGQUIT"); 90f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe sigquitTemp = (Integer)sigquitField.get(null); 91f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 92f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe killTemp = osClass.getDeclaredMethod("kill", int.class, int.class); 93f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } catch (Exception e) { 94f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (!e.getClass().getName().equals("ErrnoException")) { 95f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe e.printStackTrace(System.out); 96f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 97f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 98f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 99f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe pid = pidTemp; 100f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe sigquit = sigquitTemp; 101f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe kill = killTemp; 102f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 103f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 104f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe @Override 105f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public boolean perform() { 106f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe try { 107f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe kill.invoke(null, pid, sigquit); 108f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } catch (Exception e) { 109f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (!e.getClass().getName().equals("ErrnoException")) { 110f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe e.printStackTrace(System.out); 111f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 112f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 113f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return true; 114f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 115f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 116f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 117f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static class Alloc extends Operation { 118f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe @Override 119f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public boolean perform() { 120f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe try { 121f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe List<byte[]> l = new ArrayList<byte[]>(); 122f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe for (int i = 0; i < 1024; i++) { 123f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe l.add(new byte[1024]); 124f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 125f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } catch (OutOfMemoryError e) { 126f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 127f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return true; 128f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 129f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 130f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 131f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static class StackTrace extends Operation { 132f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe @Override 133f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public boolean perform() { 134f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Thread.currentThread().getStackTrace(); 135f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return true; 136f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 137f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 138f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 139f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static class Exit extends Operation { 140f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe @Override 141f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public boolean perform() { 142f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return false; 143f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 144f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 145f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 146f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static class Sleep extends Operation { 147f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe @Override 148f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public boolean perform() { 149f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe try { 150f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Thread.sleep(100); 151f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } catch (InterruptedException ignored) { 152f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 153f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return true; 154f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 155f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 1564cd121ef0cb35fced70c7d9de378277be7a727d9Elliott Hughes 157f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static class TimedWait extends Operation { 158f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final Object lock; 1597c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 160f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public TimedWait(Object lock) { 161f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe this.lock = lock; 162f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 163f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 164f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe @Override 165f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public boolean perform() { 166f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe synchronized (lock) { 167f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe try { 168f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe lock.wait(100, 0); 169f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } catch (InterruptedException ignored) { 170f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 171f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 172f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return true; 1737c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 1747c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 1757c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 176f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static class Wait extends Operation { 177f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final Object lock; 178f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 179f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public Wait(Object lock) { 180f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe this.lock = lock; 181f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 182f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 183f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe @Override 184f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public boolean perform() { 185f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe synchronized (lock) { 186f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe try { 187f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe lock.wait(); 188f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } catch (InterruptedException ignored) { 189f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 190f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 191f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return true; 192f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 193f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 194f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 195f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static class SyncAndWork extends Operation { 196f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final Object lock; 197f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 198f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public SyncAndWork(Object lock) { 199f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe this.lock = lock; 200f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 201f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 202f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe @Override 203f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public boolean perform() { 204f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe synchronized (lock) { 205f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe try { 206f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Thread.sleep((int)(Math.random()*10)); 207f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } catch (InterruptedException ignored) { 208f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 209f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 210f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return true; 211f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 212f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 213f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 214f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static Map<Operation, Double> createDefaultFrequencyMap(Object lock) { 215f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Map<Operation, Double> frequencyMap = new HashMap<Operation, Double>(); 216f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap.put(new OOM(), 0.005); // 1/200 217f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap.put(new SigQuit(), 0.095); // 19/200 218f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap.put(new Alloc(), 0.3); // 60/200 219f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap.put(new StackTrace(), 0.1); // 20/200 220f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap.put(new Exit(), 0.25); // 50/200 221f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap.put(new Sleep(), 0.125); // 25/200 222f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap.put(new TimedWait(lock), 0.05); // 10/200 223f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap.put(new Wait(lock), 0.075); // 15/200 224f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 225f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return frequencyMap; 226f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 227f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 228f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private final static Map<Operation, Double> createLockFrequencyMap(Object lock) { 229f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Map<Operation, Double> frequencyMap = new HashMap<Operation, Double>(); 230f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap.put(new Sleep(), 0.2); 231f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap.put(new TimedWait(lock), 0.2); 232f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap.put(new Wait(lock), 0.2); 233f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap.put(new SyncAndWork(lock), 0.4); 234f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 235f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return frequencyMap; 236f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 237f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 2387c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom public static void main(String[] args) throws Exception { 239f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe parseAndRun(args); 240f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 2417c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 242f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private static Map<Operation, Double> updateFrequencyMap(Map<Operation, Double> in, 243f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Object lock, String arg) { 244f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe String split[] = arg.split(":"); 245f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (split.length != 2) { 246f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe throw new IllegalArgumentException("Can't split argument " + arg); 247f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 248f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe double d; 249f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe try { 250f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe d = Double.parseDouble(split[1]); 251f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } catch (Exception e) { 252f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe throw new IllegalArgumentException(e); 253f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 254f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (d < 0) { 255f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe throw new IllegalArgumentException(arg + ": value must be >= 0."); 256f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 257f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Operation op = null; 258f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (split[0].equals("-oom")) { 259f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe op = new OOM(); 260f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else if (split[0].equals("-sigquit")) { 261f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe op = new SigQuit(); 262f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else if (split[0].equals("-alloc")) { 263f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe op = new Alloc(); 264f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else if (split[0].equals("-stacktrace")) { 265f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe op = new StackTrace(); 266f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else if (split[0].equals("-exit")) { 267f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe op = new Exit(); 268f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else if (split[0].equals("-sleep")) { 269f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe op = new Sleep(); 270f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else if (split[0].equals("-wait")) { 271f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe op = new Wait(lock); 272f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else if (split[0].equals("-timedwait")) { 273f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe op = new TimedWait(lock); 274f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else { 275f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe throw new IllegalArgumentException("Unknown arg " + arg); 276f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 277f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 278f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (in == null) { 279f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe in = new HashMap<Operation, Double>(); 280f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 281f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe in.put(op, d); 2827c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 283f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return in; 284f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 285f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 286f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe private static void normalize(Map<Operation, Double> map) { 287f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe double sum = 0; 288f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe for (Double d : map.values()) { 289f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe sum += d; 290f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 291f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (sum == 0) { 292f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe throw new RuntimeException("No elements!"); 293f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 294f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (sum != 1.0) { 295f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe // Avoid ConcurrentModificationException. 296f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Set<Operation> tmp = new HashSet<>(map.keySet()); 297f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe for (Operation op : tmp) { 298f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe map.put(op, map.get(op) / sum); 299f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 300f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 301f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 302f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 303f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public static void parseAndRun(String[] args) throws Exception { 304f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe int numberOfThreads = -1; 305def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao int numberOfDaemons = -1; 306f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe int totalOperations = -1; 307f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe int operationsPerThread = -1; 308f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Object lock = new Object(); 309f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Map<Operation, Double> frequencyMap = null; 310f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe boolean dumpMap = false; 311f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 312f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (args != null) { 313f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe for (int i = 0; i < args.length; i++) { 314f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (args[i].equals("-n")) { 315f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe i++; 316f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe numberOfThreads = Integer.parseInt(args[i]); 317def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao } else if (args[i].equals("-d")) { 318def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao i++; 319def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao numberOfDaemons = Integer.parseInt(args[i]); 320f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else if (args[i].equals("-o")) { 321f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe i++; 322f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe totalOperations = Integer.parseInt(args[i]); 323f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else if (args[i].equals("-t")) { 324f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe i++; 325f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe operationsPerThread = Integer.parseInt(args[i]); 326f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else if (args[i].equals("--locks-only")) { 327f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe lock = new Object(); 328f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap = createLockFrequencyMap(lock); 329f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else if (args[i].equals("--dumpmap")) { 330f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe dumpMap = true; 331f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } else { 332f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap = updateFrequencyMap(frequencyMap, lock, args[i]); 333f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 334f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 335f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 3367c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 337f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (totalOperations != -1 && operationsPerThread != -1) { 338f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe throw new IllegalArgumentException( 339f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe "Specified both totalOperations and operationsPerThread"); 340f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 341f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 342f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (numberOfThreads == -1) { 343f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe numberOfThreads = 5; 344f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 345f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 346def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao if (numberOfDaemons == -1) { 347def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao numberOfDaemons = 3; 348def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao } 349def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao 350f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (totalOperations == -1) { 351f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe totalOperations = 1000; 352f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 353f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 354f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (operationsPerThread == -1) { 355f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe operationsPerThread = totalOperations/numberOfThreads; 356f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 357f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 358f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (frequencyMap == null) { 359f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe frequencyMap = createDefaultFrequencyMap(lock); 360f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 361f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe normalize(frequencyMap); 362f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 363f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (dumpMap) { 364f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe System.out.println(frequencyMap); 365f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 366f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 367def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao runTest(numberOfThreads, numberOfDaemons, operationsPerThread, lock, frequencyMap); 368f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 369f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe 370def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao public static void runTest(final int numberOfThreads, final int numberOfDaemons, 371def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao final int operationsPerThread, final Object lock, 372def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao Map<Operation, Double> frequencyMap) throws Exception { 373def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao // Each normal thread is going to do operationsPerThread 374def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao // operations. Each daemon thread will loop over all 375def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao // the operations and will not stop. 376def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao // The distribution of operations is determined by 3777c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // the Operation.frequency values. We fill out an Operation[] 3787c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // for each thread with the operations it is to perform. The 3797c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // Operation[] is shuffled so that there is more random 3807c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // interactions between the threads. 3817c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 3827c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // Fill in the Operation[] array for each thread by laying 3837c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // down references to operation according to their desired 3847c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // frequency. 385def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao // The first numberOfThreads elements are normal threads, the last 386def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao // numberOfDaemons elements are daemon threads. 387def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao final Main[] threadStresses = new Main[numberOfThreads + numberOfDaemons]; 3887c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom for (int t = 0; t < threadStresses.length; t++) { 3897c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom Operation[] operations = new Operation[operationsPerThread]; 3907c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom int o = 0; 3917c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom LOOP: 3927c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom while (true) { 393f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe for (Operation op : frequencyMap.keySet()) { 394f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe int freq = (int)(frequencyMap.get(op) * operationsPerThread); 395f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe for (int f = 0; f < freq; f++) { 3967c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom if (o == operations.length) { 3977c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom break LOOP; 3987c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 3997c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom operations[o] = op; 4007c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom o++; 4017c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 4027c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 4037c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 404def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao // Randomize the operation order 4057c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom Collections.shuffle(Arrays.asList(operations)); 406def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao threadStresses[t] = t < numberOfThreads ? new Main(lock, t, operations) : 407def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao new Daemon(lock, t, operations); 4087c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 4097c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 410f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe // Enable to dump operation counts per thread to make sure its 4117c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // sane compared to Operation.frequency 4127c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom if (DEBUG) { 4137c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom for (int t = 0; t < threadStresses.length; t++) { 414f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Operation[] operations = threadStresses[t].operations; 4157c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom Map<Operation, Integer> distribution = new HashMap<Operation, Integer>(); 4167c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom for (Operation operation : operations) { 4177c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom Integer ops = distribution.get(operation); 4187c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom if (ops == null) { 4197c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom ops = 1; 4207c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } else { 4217c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom ops++; 4227c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 4237c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom distribution.put(operation, ops); 4247c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 4257c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom System.out.println("Distribution for " + t); 426f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe for (Operation op : frequencyMap.keySet()) { 4277c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom System.out.println(op + " = " + distribution.get(op)); 4287c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 4297c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 4307c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 4317c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 4327c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // Create the runners for each thread. The runner Thread 4337c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // ensures that thread that exit due to Operation.EXIT will be 4347c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // restarted until they reach their desired 4357c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // operationsPerThread. 4367c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom Thread[] runners = new Thread[numberOfThreads]; 4377c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom for (int r = 0; r < runners.length; r++) { 4381c83cbc4a817acbd7f9abb5b29a2d418a958e6a1Andreas Gampe final Main ts = threadStresses[r]; 4395f51d4b80058236759fea1d932470a57f348c199Mathieu Chartier runners[r] = new Thread("Runner thread " + r) { 4401c83cbc4a817acbd7f9abb5b29a2d418a958e6a1Andreas Gampe final Main threadStress = ts; 4417c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom public void run() { 4427c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom int id = threadStress.id; 4435f51d4b80058236759fea1d932470a57f348c199Mathieu Chartier System.out.println("Starting worker for " + id); 4447c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom while (threadStress.nextOperation < operationsPerThread) { 4455f51d4b80058236759fea1d932470a57f348c199Mathieu Chartier Thread thread = new Thread(ts, "Worker thread " + id); 4467c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom thread.start(); 4477c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom try { 4487c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom thread.join(); 4497c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } catch (InterruptedException e) { 4507c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 4517c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom System.out.println("Thread exited for " + id + " with " 4527c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom + (operationsPerThread - threadStress.nextOperation) 4537c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom + " operations remaining."); 4547c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 4551c83cbc4a817acbd7f9abb5b29a2d418a958e6a1Andreas Gampe System.out.println("Finishing worker"); 4567c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 4577c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom }; 4587c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 4597c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 4607c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // The notifier thread is a daemon just loops forever to wake 4617c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom // up threads in Operation.WAIT 462f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (lock != null) { 463f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe Thread notifier = new Thread("Notifier") { 464f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe public void run() { 465f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe while (true) { 466f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe synchronized (lock) { 467f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe lock.notifyAll(); 468f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 4697c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 4707c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 471f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe }; 472f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe notifier.setDaemon(true); 473f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe notifier.start(); 474f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe } 4757c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 476def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao // Create and start the daemon threads. 477def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao for (int r = 0; r < numberOfDaemons; r++) { 478def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao Main daemon = threadStresses[numberOfThreads + r]; 479def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao Thread t = new Thread(daemon, "Daemon thread " + daemon.id); 480def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao t.setDaemon(true); 481def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao t.start(); 482def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao } 483def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao 4847c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom for (int r = 0; r < runners.length; r++) { 4857c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom runners[r].start(); 4867c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 4877c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom for (int r = 0; r < runners.length; r++) { 4887c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom runners[r].join(); 4897c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 4907c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 4917c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 492def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao protected final Operation[] operations; 4937c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom private final Object lock; 494def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao protected final int id; 4957c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 4967c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom private int nextOperation; 4977c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 4981c83cbc4a817acbd7f9abb5b29a2d418a958e6a1Andreas Gampe private Main(Object lock, int id, Operation[] operations) { 4997c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom this.lock = lock; 5007c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom this.id = id; 5017c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom this.operations = operations; 5027c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 5037c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom 5047c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom public void run() { 5057c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom try { 5067c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom if (DEBUG) { 5077c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom System.out.println("Starting ThreadStress " + id); 5087c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 5097c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom while (nextOperation < operations.length) { 5107c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom Operation operation = operations[nextOperation]; 5117c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom if (DEBUG) { 5127c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom System.out.println("ThreadStress " + id 5137c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom + " operation " + nextOperation 5147c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom + " is " + operation); 5157c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 5167c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom nextOperation++; 517f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe if (!operation.perform()) { 518f2fdc7368c5fd5d9cbb4bd1d962b887e87f0654cAndreas Gampe return; 5197c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 5207c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 5214514d3c0e69a49f5dbe19138330a2bb2aee36d63Brian Carlstrom } finally { 5227c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom if (DEBUG) { 5237c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom System.out.println("Finishing ThreadStress for " + id); 5247c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 5257c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 5267c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom } 5271c83cbc4a817acbd7f9abb5b29a2d418a958e6a1Andreas Gampe 528def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao private static class Daemon extends Main { 529def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao private Daemon(Object lock, int id, Operation[] operations) { 530def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao super(lock, id, operations); 531def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao } 532def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao 533def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao public void run() { 534def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao try { 535def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao if (DEBUG) { 536def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao System.out.println("Starting ThreadStress Daemon " + id); 537def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao } 538def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao int i = 0; 539def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao while (true) { 540def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao Operation operation = operations[i]; 541def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao if (DEBUG) { 542def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao System.out.println("ThreadStress Daemon " + id 543def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao + " operation " + i 544def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao + " is " + operation); 545def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao } 546def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao operation.perform(); 547def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao i = (i + 1) % operations.length; 548def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao } 549bf81547a47c46a8853092432635bfec6167a2388Mathieu Chartier } catch (OutOfMemoryError e) { 550bf81547a47c46a8853092432635bfec6167a2388Mathieu Chartier // Catch OutOfMemoryErrors since these can cause the test to fail it they print 551bf81547a47c46a8853092432635bfec6167a2388Mathieu Chartier // the stack trace after "Finishing worker". 552def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao } finally { 553def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao if (DEBUG) { 554def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao System.out.println("Finishing ThreadStress Daemon for " + id); 555def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao } 556def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao } 557def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao } 558def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao } 559def3fcdbc5e9ef21c16047caac53ab53fb02de0cMan Cao 5607c6deaa3382f1f4fb0f591af206f03045c6e9004Brian Carlstrom} 561