147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light/* 247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light * Copyright (C) 2017 The Android Open Source Project 347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light * 447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light * Licensed under the Apache License, Version 2.0 (the "License"); 547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light * you may not use this file except in compliance with the License. 647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light * You may obtain a copy of the License at 747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light * 847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light * http://www.apache.org/licenses/LICENSE-2.0 947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light * 1047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light * Unless required by applicable law or agreed to in writing, software 1147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light * distributed under the License is distributed on an "AS IS" BASIS, 1247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light * See the License for the specific language governing permissions and 1447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light * limitations under the License. 1547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light */ 1647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light 1747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightpackage art; 1847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light 1947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.io.PrintWriter; 2047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.io.StringWriter; 2147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.lang.reflect.Executable; 2247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.lang.reflect.Method; 2347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.lang.reflect.Field; 2447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.util.ArrayList; 2547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.util.Arrays; 2647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.util.Collection; 2747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.util.HashSet; 2847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.util.List; 2947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.util.concurrent.Semaphore; 3047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.util.Vector; 3147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.util.function.Function; 3247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.util.function.Predicate; 3347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.util.function.Supplier; 3447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightimport java.util.function.Consumer; 3547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light 3647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Lightpublic class Test1917 { 3747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light public final static boolean TEST_PRINT_ALL = false; 3847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light 3947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light public static class ThreadPauser implements Runnable { 4047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light public Semaphore sem_wakeup_main = new Semaphore(0); 4147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light public Semaphore sem_wait = new Semaphore(0); 4247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light 4347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light public void run() { 4447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light try { 4547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light sem_wakeup_main.release(); 4647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light sem_wait.acquire(); 4747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } catch (Exception e) { 4847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light throw new Error("Error with semaphores!", e); 4947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } 5047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } 5147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light 5247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light public void waitForOtherThreadToPause() throws Exception { 5347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light sem_wakeup_main.acquire(); 544013595d91898c5a18fbc480cbd4023c4307ec62Alex Light while (!sem_wait.hasQueuedThreads()) {} 5547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } 5647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light 5747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light public void wakeupOtherThread() throws Exception { 5847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light sem_wait.release(); 5947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } 6047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } 6147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light 6247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light public static class StackTraceGenerator implements Runnable { 6347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light private final Thread thr; 6447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light private final Consumer<StackTrace.StackFrameData> con; 6547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light public StackTraceGenerator(Thread thr, Consumer<StackTrace.StackFrameData> con) { 6647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light this.thr = thr; 6747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light this.con = con; 6847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } 6947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light 7047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light public StackTraceGenerator(Consumer<StackTrace.StackFrameData> con) { 7147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light this(null, con); 7247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } 7347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light 7447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light public Thread getThread() { 7547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light if (thr == null) { 7647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light return Thread.currentThread(); 7747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } else { 7847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light return thr; 7947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } 8047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } 8147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light public void run() { 8247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light for (StackTrace.StackFrameData s : StackTrace.GetStackTrace(getThread())) { 8347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light con.accept(s); 8447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } 8547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } 8647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } 8747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light 8847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light public static class RecurCount implements Runnable { 8947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light private final int cnt; 9047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light private final Runnable then; 9147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light public RecurCount(int cnt, Runnable then) { 9247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light this.cnt = cnt; 9347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light this.then = then; 9447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } 9547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light 9647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light public void run() { 9747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light doRecur(0); 9847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } 9947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light 10047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light public void doRecur(int n) { 10147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light if (n < cnt) { 10247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light doRecur(n + 1); 10347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } else { 10447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light then.run(); 10547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } 10647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } 10747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } 10847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light 10947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light public static Consumer<StackTrace.StackFrameData> makePrintStackFramesConsumer() 11047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light throws Exception { 11147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light final Method end_method = Test1917.class.getDeclaredMethod("run"); 11247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light return new Consumer<StackTrace.StackFrameData>() { 11347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light public void accept(StackTrace.StackFrameData data) { 11447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light if (TEST_PRINT_ALL) { 11547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light System.out.println(data); 11647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } else { 11747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light Package p = data.method.getDeclaringClass().getPackage(); 11847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light // Filter out anything to do with the testing harness. 11947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light if (p != null && p.equals(Test1917.class.getPackage())) { 12047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light System.out.printf("'%s' line: %d\n", 12147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light data.method, 12247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light Breakpoint.locationToLine(data.method, data.current_location)); 12347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } else if (data.method.getDeclaringClass().equals(Semaphore.class)) { 12447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light System.out.printf("'%s' line: <NOT-DETERMINISTIC>\n", data.method); 12547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } 12647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } 12747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } 12847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light }; 12947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } 13047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light 13147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light public static void run() throws Exception { 13247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light System.out.println("Recurring 5 times"); 13347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light new RecurCount(5, new StackTraceGenerator(makePrintStackFramesConsumer())).run(); 13447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light 13547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light System.out.println("Recurring 5 times on another thread"); 13647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light Thread thr = new Thread( 13747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light new RecurCount(5, new StackTraceGenerator(makePrintStackFramesConsumer()))); 13847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light thr.start(); 13947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light thr.join(); 14047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light 14147d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light System.out.println("Recurring 5 times on another thread. Stack trace from main thread!"); 14247d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light ThreadPauser pause = new ThreadPauser(); 14347d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light Thread thr2 = new Thread(new RecurCount(5, pause)); 14447d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light thr2.start(); 14547d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light pause.waitForOtherThreadToPause(); 14647d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light new StackTraceGenerator(thr2, makePrintStackFramesConsumer()).run(); 14747d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light pause.wakeupOtherThread(); 14847d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light thr2.join(); 14947d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light } 15047d49b842a87823df6ffda30bb21bd6d8e4d8641Alex Light} 151