xref: /aosp_15_r20/art/test/129-ThreadGetId/src/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2014 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Field;
18*795d594fSAndroid Build Coastguard Worker import java.util.Map;
19*795d594fSAndroid Build Coastguard Worker import java.util.concurrent.atomic.AtomicInteger;
20*795d594fSAndroid Build Coastguard Worker 
21*795d594fSAndroid Build Coastguard Worker public class Main implements Runnable {
22*795d594fSAndroid Build Coastguard Worker     static final int NUMBER_OF_THREADS = 5;
23*795d594fSAndroid Build Coastguard Worker     static volatile int ops_per_thread = 1000;
24*795d594fSAndroid Build Coastguard Worker     static AtomicInteger operations_completed = new AtomicInteger(0);
25*795d594fSAndroid Build Coastguard Worker     static int[] progress = new int[NUMBER_OF_THREADS];
26*795d594fSAndroid Build Coastguard Worker     static AtomicInteger totalStackFrames = new AtomicInteger(0);
27*795d594fSAndroid Build Coastguard Worker     static final boolean printStats = false;  // True causes test to fail.
28*795d594fSAndroid Build Coastguard Worker     int index;
29*795d594fSAndroid Build Coastguard Worker 
Main(int i)30*795d594fSAndroid Build Coastguard Worker     Main(int i) {
31*795d594fSAndroid Build Coastguard Worker         index = i;
32*795d594fSAndroid Build Coastguard Worker     }
33*795d594fSAndroid Build Coastguard Worker 
main(String[] args)34*795d594fSAndroid Build Coastguard Worker     public static void main(String[] args) throws Exception {
35*795d594fSAndroid Build Coastguard Worker         final Thread[] threads = new Thread[NUMBER_OF_THREADS];
36*795d594fSAndroid Build Coastguard Worker         Thread watchdog = new Thread() {
37*795d594fSAndroid Build Coastguard Worker             public void run() {
38*795d594fSAndroid Build Coastguard Worker                 try {
39*795d594fSAndroid Build Coastguard Worker                     if (printStats) {
40*795d594fSAndroid Build Coastguard Worker                         System.out.println("ops_per_thread = " + ops_per_thread);
41*795d594fSAndroid Build Coastguard Worker                     }
42*795d594fSAndroid Build Coastguard Worker                     Thread.sleep(10_000);
43*795d594fSAndroid Build Coastguard Worker                     if (printStats) {
44*795d594fSAndroid Build Coastguard Worker                         System.out.println("Ops completed after 10 seconds: " +
45*795d594fSAndroid Build Coastguard Worker                                 operations_completed.get());
46*795d594fSAndroid Build Coastguard Worker                     }
47*795d594fSAndroid Build Coastguard Worker                     if (operations_completed.get() < NUMBER_OF_THREADS * ops_per_thread / 2) {
48*795d594fSAndroid Build Coastguard Worker                         // We're in some sort of "go slow" mode, probably gcstress. Finish early.
49*795d594fSAndroid Build Coastguard Worker                         ops_per_thread /= 10;
50*795d594fSAndroid Build Coastguard Worker                     }
51*795d594fSAndroid Build Coastguard Worker                     if (printStats) {
52*795d594fSAndroid Build Coastguard Worker                         System.out.println("ops_per_thread = " + ops_per_thread);
53*795d594fSAndroid Build Coastguard Worker                     }
54*795d594fSAndroid Build Coastguard Worker                     Thread.sleep(200_000);
55*795d594fSAndroid Build Coastguard Worker                     System.out.print("Watchdog timed out: ");
56*795d594fSAndroid Build Coastguard Worker                     for (int i = 0; i < NUMBER_OF_THREADS; ++i) {
57*795d594fSAndroid Build Coastguard Worker                         System.out.print(progress[i] + ", ");
58*795d594fSAndroid Build Coastguard Worker                     }
59*795d594fSAndroid Build Coastguard Worker                     System.out.println("");
60*795d594fSAndroid Build Coastguard Worker                     System.err.println("Watchdog thread timed out");
61*795d594fSAndroid Build Coastguard Worker                     System.exit(1);
62*795d594fSAndroid Build Coastguard Worker                 } catch (InterruptedException e) {}
63*795d594fSAndroid Build Coastguard Worker             }
64*795d594fSAndroid Build Coastguard Worker         };
65*795d594fSAndroid Build Coastguard Worker         watchdog.start();
66*795d594fSAndroid Build Coastguard Worker         long start_millis = System.currentTimeMillis();
67*795d594fSAndroid Build Coastguard Worker         for (int t = 0; t < threads.length; t++) {
68*795d594fSAndroid Build Coastguard Worker             threads[t] = new Thread(new Main(t));
69*795d594fSAndroid Build Coastguard Worker             threads[t].start();
70*795d594fSAndroid Build Coastguard Worker         }
71*795d594fSAndroid Build Coastguard Worker         for (Thread t : threads) {
72*795d594fSAndroid Build Coastguard Worker             t.join();
73*795d594fSAndroid Build Coastguard Worker         }
74*795d594fSAndroid Build Coastguard Worker         if (printStats) {
75*795d594fSAndroid Build Coastguard Worker             long elapsed_millis = System.currentTimeMillis() - start_millis;
76*795d594fSAndroid Build Coastguard Worker             System.out.println("Captured " + totalStackFrames + " stack frames in " +
77*795d594fSAndroid Build Coastguard Worker                     elapsed_millis + "msecs");
78*795d594fSAndroid Build Coastguard Worker         }
79*795d594fSAndroid Build Coastguard Worker         System.out.println("All joined");
80*795d594fSAndroid Build Coastguard Worker         // Do this test after the other part to leave some time for the heap task daemon to start
81*795d594fSAndroid Build Coastguard Worker         // up.
82*795d594fSAndroid Build Coastguard Worker         test_getStackTraces();
83*795d594fSAndroid Build Coastguard Worker         watchdog.interrupt();
84*795d594fSAndroid Build Coastguard Worker         System.out.println("Finishing");
85*795d594fSAndroid Build Coastguard Worker     }
86*795d594fSAndroid Build Coastguard Worker 
getHeapTaskDaemon()87*795d594fSAndroid Build Coastguard Worker     static Thread getHeapTaskDaemon() throws Exception {
88*795d594fSAndroid Build Coastguard Worker         Field f = ThreadGroup.class.getDeclaredField("systemThreadGroup");
89*795d594fSAndroid Build Coastguard Worker         f.setAccessible(true);
90*795d594fSAndroid Build Coastguard Worker         ThreadGroup systemThreadGroup = (ThreadGroup) f.get(null);
91*795d594fSAndroid Build Coastguard Worker 
92*795d594fSAndroid Build Coastguard Worker         while (true) {
93*795d594fSAndroid Build Coastguard Worker             int activeCount = systemThreadGroup.activeCount();
94*795d594fSAndroid Build Coastguard Worker             Thread[] array = new Thread[activeCount];
95*795d594fSAndroid Build Coastguard Worker             systemThreadGroup.enumerate(array);
96*795d594fSAndroid Build Coastguard Worker             for (Thread thread : array) {
97*795d594fSAndroid Build Coastguard Worker                 if (thread.getName().equals("HeapTaskDaemon") &&
98*795d594fSAndroid Build Coastguard Worker                     thread.getState() != Thread.State.NEW) {
99*795d594fSAndroid Build Coastguard Worker                     return thread;
100*795d594fSAndroid Build Coastguard Worker                 }
101*795d594fSAndroid Build Coastguard Worker             }
102*795d594fSAndroid Build Coastguard Worker             // Yield to eventually get the daemon started.
103*795d594fSAndroid Build Coastguard Worker             Thread.sleep(10);
104*795d594fSAndroid Build Coastguard Worker         }
105*795d594fSAndroid Build Coastguard Worker     }
106*795d594fSAndroid Build Coastguard Worker 
test_getStackTraces()107*795d594fSAndroid Build Coastguard Worker     static void test_getStackTraces() throws Exception {
108*795d594fSAndroid Build Coastguard Worker         Thread heapDaemon = getHeapTaskDaemon();
109*795d594fSAndroid Build Coastguard Worker 
110*795d594fSAndroid Build Coastguard Worker         // Force a GC to ensure the daemon truly started.
111*795d594fSAndroid Build Coastguard Worker         Runtime.getRuntime().gc();
112*795d594fSAndroid Build Coastguard Worker         // Check all the current threads for positive IDs.
113*795d594fSAndroid Build Coastguard Worker         Map<Thread, StackTraceElement[]> map = Thread.getAllStackTraces();
114*795d594fSAndroid Build Coastguard Worker         for (Map.Entry<Thread, StackTraceElement[]> pair : map.entrySet()) {
115*795d594fSAndroid Build Coastguard Worker             Thread thread = pair.getKey();
116*795d594fSAndroid Build Coastguard Worker             // Expect empty stack trace since we do not support suspending the GC thread for
117*795d594fSAndroid Build Coastguard Worker             // obtaining stack traces. See b/28261069.
118*795d594fSAndroid Build Coastguard Worker             if (thread == heapDaemon) {
119*795d594fSAndroid Build Coastguard Worker                 System.out.println(thread.getName() + " depth " + pair.getValue().length);
120*795d594fSAndroid Build Coastguard Worker             }
121*795d594fSAndroid Build Coastguard Worker         }
122*795d594fSAndroid Build Coastguard Worker     }
123*795d594fSAndroid Build Coastguard Worker 
test_getId()124*795d594fSAndroid Build Coastguard Worker     public void test_getId() {
125*795d594fSAndroid Build Coastguard Worker         if (Thread.currentThread().getId() <= 0) {
126*795d594fSAndroid Build Coastguard Worker             System.out.println("current thread's ID is not positive");
127*795d594fSAndroid Build Coastguard Worker         }
128*795d594fSAndroid Build Coastguard Worker         // Check all the current threads for positive IDs.
129*795d594fSAndroid Build Coastguard Worker         Map<Thread, StackTraceElement[]> stMap = Thread.getAllStackTraces();
130*795d594fSAndroid Build Coastguard Worker         for (Thread thread : stMap.keySet()) {
131*795d594fSAndroid Build Coastguard Worker             if (thread.getId() <= 0) {
132*795d594fSAndroid Build Coastguard Worker                 System.out.println("thread's ID is not positive: " + thread.getName());
133*795d594fSAndroid Build Coastguard Worker             }
134*795d594fSAndroid Build Coastguard Worker             totalStackFrames.addAndGet(stMap.get(thread).length);
135*795d594fSAndroid Build Coastguard Worker         }
136*795d594fSAndroid Build Coastguard Worker     }
137*795d594fSAndroid Build Coastguard Worker 
run()138*795d594fSAndroid Build Coastguard Worker     public void run() {
139*795d594fSAndroid Build Coastguard Worker         for (int i = 1; i <= ops_per_thread; ++i) {
140*795d594fSAndroid Build Coastguard Worker             test_getId();
141*795d594fSAndroid Build Coastguard Worker             operations_completed.addAndGet(1);
142*795d594fSAndroid Build Coastguard Worker             progress[index] = i;
143*795d594fSAndroid Build Coastguard Worker         }
144*795d594fSAndroid Build Coastguard Worker         System.out.println("Thread finished");
145*795d594fSAndroid Build Coastguard Worker     }
146*795d594fSAndroid Build Coastguard Worker }
147