1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package art; 18 19 import java.lang.reflect.Method; 20 import java.util.Arrays; 21 import java.util.Objects; 22 import java.util.HashMap; 23 import java.util.List; 24 import java.util.Map; 25 import java.util.concurrent.atomic.*; 26 import java.util.concurrent.locks.LockSupport; 27 import java.util.ListIterator; 28 import java.util.function.Consumer; 29 import java.util.function.Function; 30 31 public class Test1931 { printStackTrace(Throwable t)32 public static void printStackTrace(Throwable t) { 33 System.out.println("Caught exception: " + t); 34 for (Throwable c = t.getCause(); c != null; c = c.getCause()) { 35 System.out.println("\tCaused by: " + 36 (Test1931.class.getPackage().equals(c.getClass().getPackage()) 37 ? c.toString() : c.getClass().toString())); 38 } 39 } 40 handleMonitorEnter(Thread thd, Object lock)41 public static void handleMonitorEnter(Thread thd, Object lock) { 42 System.out.println(thd.getName() + " contended-LOCKING " + lock); 43 } 44 handleMonitorEntered(Thread thd, Object lock)45 public static void handleMonitorEntered(Thread thd, Object lock) { 46 System.out.println(thd.getName() + " LOCKED " + lock); 47 } handleMonitorWait(Thread thd, Object lock, long timeout)48 public static void handleMonitorWait(Thread thd, Object lock, long timeout) { 49 System.out.println(thd.getName() + " start-monitor-wait " + lock + " timeout: " + timeout); 50 } 51 handleMonitorWaited(Thread thd, Object lock, boolean timed_out)52 public static void handleMonitorWaited(Thread thd, Object lock, boolean timed_out) { 53 System.out.println(thd.getName() + " monitor-waited " + lock + " timed_out: " + timed_out); 54 } 55 run()56 public static void run() throws Exception { 57 Monitors.setupMonitorEvents( 58 Test1931.class, 59 Test1931.class.getDeclaredMethod("handleMonitorEnter", Thread.class, Object.class), 60 Test1931.class.getDeclaredMethod("handleMonitorEntered", Thread.class, Object.class), 61 Test1931.class.getDeclaredMethod("handleMonitorWait", 62 Thread.class, Object.class, Long.TYPE), 63 Test1931.class.getDeclaredMethod("handleMonitorWaited", 64 Thread.class, Object.class, Boolean.TYPE), 65 Monitors.NamedLock.class, 66 null); 67 68 System.out.println("Testing contended locking."); 69 testLock(new Monitors.NamedLock("Lock testLock")); 70 71 System.out.println("Testing park."); 72 testPark(new Monitors.NamedLock("Parking blocker object")); 73 74 System.out.println("Testing monitor wait."); 75 testWait(new Monitors.NamedLock("Lock testWait")); 76 77 System.out.println("Testing monitor timed wait."); 78 testTimedWait(new Monitors.NamedLock("Lock testTimedWait")); 79 80 System.out.println("Testing monitor timed with timeout."); 81 testTimedWaitTimeout(new Monitors.NamedLock("Lock testTimedWaitTimeout")); 82 83 // TODO It would be good (but annoying) to do this with jasmin/smali in order to test if it's 84 // different without the reflection. 85 System.out.println("Waiting on an unlocked monitor."); 86 testUnlockedWait(new Monitors.NamedLock("Lock testUnlockedWait")); 87 88 System.out.println("Waiting with an illegal argument (negative timeout)"); 89 testIllegalWait(new Monitors.NamedLock("Lock testIllegalWait")); 90 91 System.out.println("Interrupt a monitor being waited on."); 92 testInteruptWait(new Monitors.NamedLock("Lock testInteruptWait")); 93 } 94 testPark(Object blocker)95 public static void testPark(Object blocker) throws Exception { 96 Thread holder = new Thread(() -> { 97 LockSupport.parkNanos(blocker, 10); // Should round up to one millisecond 98 }, "ParkThread"); 99 holder.start(); 100 holder.join(); 101 } 102 testInteruptWait(final Monitors.NamedLock lk)103 public static void testInteruptWait(final Monitors.NamedLock lk) throws Exception { 104 final Monitors.LockController controller1 = new Monitors.LockController(lk); 105 controller1.DoLock(); 106 controller1.waitForLockToBeHeld(); 107 controller1.DoWait(); 108 controller1.waitForNotifySleep(); 109 try { 110 controller1.interruptWorker(); 111 controller1.waitForLockToBeHeld(); 112 controller1.DoUnlock(); 113 System.out.println("No Exception thrown!"); 114 } catch (Monitors.TestException e) { 115 printStackTrace(e); 116 } 117 controller1.DoCleanup(); 118 } 119 testIllegalWait(final Monitors.NamedLock lk)120 public static void testIllegalWait(final Monitors.NamedLock lk) throws Exception { 121 Monitors.LockController controller1 = new Monitors.LockController(lk, /*timed_wait time*/-100); 122 controller1.DoLock(); 123 controller1.waitForLockToBeHeld(); 124 try { 125 controller1.DoTimedWait(); 126 controller1.waitForNotifySleep(); 127 controller1.waitForLockToBeHeld(); 128 controller1.DoUnlock(); 129 System.out.println("No Exception thrown!"); 130 } catch (Monitors.TestException e) { 131 printStackTrace(e); 132 } 133 controller1.DoCleanup(); 134 } 135 testUnlockedWait(final Monitors.NamedLock lk)136 public static void testUnlockedWait(final Monitors.NamedLock lk) throws Exception { 137 synchronized (lk) { 138 Thread thd = new Thread(() -> { 139 try { 140 Method m = Object.class.getDeclaredMethod("wait"); 141 m.invoke(lk); 142 } catch (Exception e) { 143 printStackTrace(e); 144 } 145 }, "Unlocked wait thread:"); 146 thd.start(); 147 thd.join(); 148 } 149 } 150 testLock(Monitors.NamedLock lk)151 public static void testLock(Monitors.NamedLock lk) throws Exception { 152 Monitors.LockController controller1 = new Monitors.LockController(lk); 153 Monitors.LockController controller2 = new Monitors.LockController(lk); 154 controller1.DoLock(); 155 controller1.waitForLockToBeHeld(); 156 controller2.DoLock(); 157 if (controller2.IsLocked()) { 158 throw new Exception("c2 was able to gain lock while it was held by c1"); 159 } 160 controller2.waitForContendedSleep(); 161 controller1.DoUnlock(); 162 controller2.waitForLockToBeHeld(); 163 controller2.DoUnlock(); 164 } 165 testWait(Monitors.NamedLock lk)166 public static void testWait(Monitors.NamedLock lk) throws Exception { 167 Monitors.LockController controller1 = new Monitors.LockController(lk); 168 Monitors.LockController controller2 = new Monitors.LockController(lk); 169 controller1.DoLock(); 170 controller1.waitForLockToBeHeld(); 171 controller1.DoWait(); 172 controller1.waitForNotifySleep(); 173 controller2.DoLock(); 174 controller2.waitForLockToBeHeld(); 175 controller2.DoNotifyAll(); 176 controller2.DoUnlock(); 177 controller1.waitForLockToBeHeld(); 178 controller1.DoUnlock(); 179 } 180 testTimedWait(Monitors.NamedLock lk)181 public static void testTimedWait(Monitors.NamedLock lk) throws Exception { 182 // Time to wait (1 hour). We will wake it up before timeout. 183 final long millis = 60l * 60l * 1000l; 184 Monitors.LockController controller1 = new Monitors.LockController(lk, millis); 185 Monitors.LockController controller2 = new Monitors.LockController(lk); 186 controller1.DoLock(); 187 controller1.waitForLockToBeHeld(); 188 controller1.DoTimedWait(); 189 controller1.waitForNotifySleep(); 190 controller2.DoLock(); 191 controller2.waitForLockToBeHeld(); 192 controller2.DoNotifyAll(); 193 controller2.DoUnlock(); 194 controller1.waitForLockToBeHeld(); 195 controller1.DoUnlock(); 196 } 197 testTimedWaitTimeout(Monitors.NamedLock lk)198 public static void testTimedWaitTimeout(Monitors.NamedLock lk) throws Exception { 199 // Time to wait (10 seconds). We will wait for the timeout. 200 final long millis = 10l * 1000l; 201 Monitors.LockController controller1 = new Monitors.LockController(lk, millis); 202 controller1.DoLock(); 203 controller1.waitForLockToBeHeld(); 204 System.out.println("Waiting for 10 seconds."); 205 controller1.DoTimedWait(); 206 controller1.waitForNotifySleep(); 207 controller1.DoUnlock(); 208 System.out.println("Wait finished with timeout."); 209 } 210 } 211