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.io.PrintWriter; 20 import java.io.StringWriter; 21 import java.lang.reflect.Executable; 22 import java.lang.reflect.Method; 23 import java.lang.reflect.Field; 24 import java.util.ArrayList; 25 import java.util.Arrays; 26 import java.util.Collection; 27 import java.util.HashSet; 28 import java.util.List; 29 import java.util.concurrent.Semaphore; 30 import java.util.Vector; 31 import java.util.function.Function; 32 import java.util.function.Predicate; 33 import java.util.function.Supplier; 34 import java.util.function.Consumer; 35 36 public class Test1917 { 37 public final static boolean TEST_PRINT_ALL = false; 38 39 public static class ThreadPauser implements Runnable { 40 public Semaphore sem_wakeup_main = new Semaphore(0); 41 public Semaphore sem_wait = new Semaphore(0); 42 run()43 public void run() { 44 try { 45 sem_wakeup_main.release(); 46 sem_wait.acquire(); 47 } catch (Exception e) { 48 throw new Error("Error with semaphores!", e); 49 } 50 } 51 waitForOtherThreadToPause()52 public void waitForOtherThreadToPause() throws Exception { 53 sem_wakeup_main.acquire(); 54 while (!sem_wait.hasQueuedThreads()) {} 55 } 56 wakeupOtherThread()57 public void wakeupOtherThread() throws Exception { 58 sem_wait.release(); 59 } 60 } 61 62 public static class StackTraceGenerator implements Runnable { 63 private final Thread thr; 64 private final Consumer<StackTrace.StackFrameData> con; StackTraceGenerator(Thread thr, Consumer<StackTrace.StackFrameData> con)65 public StackTraceGenerator(Thread thr, Consumer<StackTrace.StackFrameData> con) { 66 this.thr = thr; 67 this.con = con; 68 } 69 StackTraceGenerator(Consumer<StackTrace.StackFrameData> con)70 public StackTraceGenerator(Consumer<StackTrace.StackFrameData> con) { 71 this(null, con); 72 } 73 getThread()74 public Thread getThread() { 75 if (thr == null) { 76 return Thread.currentThread(); 77 } else { 78 return thr; 79 } 80 } run()81 public void run() { 82 for (StackTrace.StackFrameData s : StackTrace.GetStackTrace(getThread())) { 83 con.accept(s); 84 } 85 } 86 } 87 88 public static class RecurCount implements Runnable { 89 private final int cnt; 90 private final Runnable then; RecurCount(int cnt, Runnable then)91 public RecurCount(int cnt, Runnable then) { 92 this.cnt = cnt; 93 this.then = then; 94 } 95 run()96 public void run() { 97 doRecur(0); 98 } 99 doRecur(int n)100 public void doRecur(int n) { 101 if (n < cnt) { 102 doRecur(n + 1); 103 } else { 104 then.run(); 105 } 106 } 107 } 108 makePrintStackFramesConsumer()109 public static Consumer<StackTrace.StackFrameData> makePrintStackFramesConsumer() 110 throws Exception { 111 final Method end_method = Test1917.class.getDeclaredMethod("run"); 112 return new Consumer<StackTrace.StackFrameData>() { 113 public void accept(StackTrace.StackFrameData data) { 114 if (TEST_PRINT_ALL) { 115 System.out.println(data); 116 } else { 117 Package p = data.method.getDeclaringClass().getPackage(); 118 // Filter out anything to do with the testing harness. 119 if (p != null && p.equals(Test1917.class.getPackage())) { 120 System.out.printf("'%s' line: %d\n", 121 data.method, 122 Breakpoint.locationToLine(data.method, data.current_location)); 123 } else if (data.method.getDeclaringClass().equals(Semaphore.class)) { 124 System.out.printf("'%s' line: <NOT-DETERMINISTIC>\n", data.method); 125 } 126 } 127 } 128 }; 129 } 130 131 public static void run() throws Exception { 132 System.out.println("Recurring 5 times"); 133 new RecurCount(5, new StackTraceGenerator(makePrintStackFramesConsumer())).run(); 134 135 System.out.println("Recurring 5 times on another thread"); 136 Thread thr = new Thread( 137 Thread.currentThread().getThreadGroup(), 138 new RecurCount(5, new StackTraceGenerator(makePrintStackFramesConsumer())), 139 "Recurring Thread 1", 140 10*1000000 /* 10 mb*/); 141 thr.start(); 142 thr.join(); 143 144 System.out.println("Recurring 5 times on another thread. Stack trace from main thread!"); 145 ThreadPauser pause = new ThreadPauser(); 146 Thread thr2 = new Thread( 147 Thread.currentThread().getThreadGroup(), 148 new RecurCount(5, pause), 149 "Recurring Thread 2", 150 10*1000000 /* 10 mb*/); 151 thr2.start(); 152 pause.waitForOtherThreadToPause(); 153 new StackTraceGenerator(thr2, makePrintStackFramesConsumer()).run(); 154 pause.wakeupOtherThread(); 155 thr2.join(); 156 } 157 } 158