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.util.concurrent.Semaphore; 20 import java.util.Arrays; 21 22 public class Test1930 { 23 public static final int NUM_RETRY = 100; testSingleThread()24 private static void testSingleThread() { 25 Monitors.NamedLock lk = new Monitors.NamedLock("Test1930 - testSingleThread"); 26 executeLocked(() -> { printMonitorUsage(lk); }, lk); 27 } testSingleThreadNative()28 private static void testSingleThreadNative() { 29 Monitors.NamedLock lk = new Monitors.NamedLock("Test1930 - testSingleThread"); 30 executeLockedNative(() -> { printMonitorUsage(lk); }, lk); 31 } 32 testLockedTwice()33 private static void testLockedTwice() { 34 final Monitors.NamedLock lk = new Monitors.NamedLock("Test1930 - testLockedTwice"); 35 executeLocked(() -> { executeLocked(() -> { printMonitorUsage(lk); }, lk); }, lk); 36 } 37 testLockedTwiceNJ()38 private static void testLockedTwiceNJ() { 39 final Monitors.NamedLock lk = new Monitors.NamedLock("Test1930 - testLockedTwiceNJ"); 40 executeLockedNative(() -> { executeLockedNative(() -> { printMonitorUsage(lk); }, lk); }, lk); 41 } 42 testLockedTwiceJN()43 private static void testLockedTwiceJN() { 44 final Monitors.NamedLock lk = new Monitors.NamedLock("Test1930 - testLockedTwiceJN"); 45 executeLockedNative(() -> { executeLockedNative(() -> { printMonitorUsage(lk); }, lk); }, lk); 46 } 47 testLockedTwiceNative()48 private static void testLockedTwiceNative() { 49 final Monitors.NamedLock lk = new Monitors.NamedLock("Test1930 - testLockedTwiceNative"); 50 executeLockedNative(() -> { executeLockedNative(() -> { printMonitorUsage(lk); }, lk); }, lk); 51 } 52 53 public final static class ThreadSignaler { 54 public volatile boolean signal = false; 55 } 56 testLockWait()57 private static void testLockWait() throws Exception { 58 final Monitors.NamedLock lk = new Monitors.NamedLock("Test1930 - testLockWait"); 59 final Semaphore sem = new Semaphore(0); 60 final Thread t = new Thread(() -> { 61 sem.release(); 62 synchronized (lk) { 63 printMonitorUsage(lk); 64 } 65 }, "Test1930 Thread - testLockWait"); 66 synchronized (lk) { 67 t.start(); 68 // Wait for the other thread to actually start. 69 sem.acquire(); 70 // Wait for the other thread to go to sleep trying to get the mutex. This might take a (short) 71 // time since we try spinning first for better performance. 72 boolean found_wait = false; 73 for (long i = 0; i < NUM_RETRY; i++) { 74 if (Arrays.asList(Monitors.getObjectMonitorUsage(lk).waiters).contains(t)) { 75 found_wait = true; 76 break; 77 } else { 78 Thread.sleep(500); 79 Thread.yield(); 80 } 81 } 82 if (!found_wait) { 83 System.out.println("other thread doesn't seem to be waiting."); 84 } 85 printMonitorUsage(lk); 86 } 87 t.join(); 88 printMonitorUsage(lk); 89 } 90 testNotifyWait()91 private static void testNotifyWait() throws Exception { 92 final Monitors.NamedLock lk = new Monitors.NamedLock("Test1930 - testNotifyWait"); 93 final Semaphore sem = new Semaphore(0); 94 Thread t = new Thread(() -> { 95 synchronized (lk) { 96 printMonitorUsage(lk); 97 sem.release(); 98 try { 99 lk.DoWait(); 100 } catch (Exception e) { 101 throw new Error("Error waiting!", e); 102 } 103 printMonitorUsage(lk); 104 } 105 }, "Test1930 Thread - testLockWait"); 106 t.start(); 107 sem.acquire(); 108 synchronized (lk) { 109 printMonitorUsage(lk); 110 lk.DoNotifyAll(); 111 } 112 t.join(); 113 printMonitorUsage(lk); 114 } 115 run()116 public static void run() throws Exception { 117 // Single threaded tests. 118 System.out.println("Running with single thread."); 119 testSingleThread(); 120 System.out.println("Running with single thread in native."); 121 testSingleThreadNative(); 122 System.out.println("Lock twice"); 123 testLockedTwice(); 124 System.out.println("Lock twice native"); 125 testLockedTwiceNative(); 126 System.out.println("Lock twice Java then native"); 127 testLockedTwiceJN(); 128 System.out.println("Lock twice native then Java"); 129 testLockedTwiceNJ(); 130 131 // Mutli threaded tests. 132 System.out.println("lock with wait"); 133 testLockWait(); 134 System.out.println("Wait for notify."); 135 testNotifyWait(); 136 } 137 printPreLock(Object lock)138 public static void printPreLock(Object lock) { 139 System.out.println(String.format("Pre-lock[%s]: %s", 140 Thread.currentThread().getName(), Monitors.getObjectMonitorUsage(lock))); 141 } 142 executeLocked(Runnable r, Object lock)143 public static void executeLocked(Runnable r, Object lock) { 144 printPreLock(lock); 145 synchronized (lock) { 146 r.run(); 147 } 148 } 149 executeLockedNative(Runnable r, Object m)150 public native static void executeLockedNative(Runnable r, Object m); printMonitorUsage(Object m)151 public static void printMonitorUsage(Object m) { 152 System.out.println(String.format("Thread[%s]: %s", 153 Thread.currentThread().getName(), Monitors.getObjectMonitorUsage(m))); 154 } 155 } 156