1 /*
2  * Copyright (C) 2016 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.ref.WeakReference;
20 import java.util.ArrayList;
21 import java.util.Arrays;
22 import java.util.concurrent.CountDownLatch;
23 import java.util.concurrent.Semaphore;
24 
25 public class Test1909 {
26 
27   public static class ThreadHolder {
28     public Thread thr;
ThreadHolder(Thread thr)29     public ThreadHolder(Thread thr) {
30       this.thr = thr;
31     }
32 
getTLS(long jvmtienv)33     public long getTLS(long jvmtienv) {
34       return Test1909.getTLS(jvmtienv, this.thr);
35     }
setTLS(long jvmtienv, long ptr)36     public void setTLS(long jvmtienv, long ptr) {
37       Test1909.setTLS(jvmtienv, this.thr, ptr);
38     }
39   }
40 
41   public static class ThreadWaiter {
42     public boolean exit;
43     public Thread thr;
44     public final Object lock;
45 
ThreadWaiter()46     public ThreadWaiter() {
47       this.exit = false;
48       this.lock = new Object();
49       this.thr = new Thread(() -> {
50         try {
51           synchronized (lock) {
52             while (!this.exit) {
53               this.lock.wait();
54             }
55           }
56         } catch (Exception e) {
57           e.printStackTrace();
58         }
59       });
60       // Kill threads if we exit.
61       thr.setDaemon(true);
62       thr.start();
63     }
64 
cleanup()65     public void cleanup() throws Exception {
66       synchronized (lock) {
67         exit = true;
68         lock.notifyAll();
69       }
70       thr.join();
71     }
getTLS(long jvmtienv)72     public long getTLS(long jvmtienv) {
73       return Test1909.getTLS(jvmtienv, this.thr);
74     }
setTLS(long jvmtienv, long ptr)75     public void setTLS(long jvmtienv, long ptr) {
76       Test1909.setTLS(jvmtienv, this.thr, ptr);
77     }
78   }
79 
checkEq(long a, long b)80   public static void checkEq(long a, long b) {
81     if (a != b) {
82       throw new Error("Expected: " + a + " got: " + b);
83     }
84   }
85 
run()86   public static void run() throws Exception {
87     ThreadHolder tc = new ThreadHolder(Thread.currentThread());
88     ThreadWaiter t1 = new ThreadWaiter();
89     long e1 = newJvmtiEnv();
90     long e2 = newJvmtiEnv();
91 
92     // Everything should be 0
93     checkEq(0, tc.getTLS(e1));
94     checkEq(0, t1.getTLS(e1));
95     checkEq(0, tc.getTLS(e2));
96     checkEq(0, t1.getTLS(e2));
97 
98     // Set in one pair.
99     tc.setTLS(e1, 1);
100     checkEq(1, tc.getTLS(e1));
101     checkEq(0, t1.getTLS(e1));
102     checkEq(0, tc.getTLS(e2));
103     checkEq(0, t1.getTLS(e2));
104 
105     // Set in another pair.
106     t1.setTLS(e1, 2);
107     checkEq(1, tc.getTLS(e1));
108     checkEq(2, t1.getTLS(e1));
109     checkEq(0, tc.getTLS(e2));
110     checkEq(0, t1.getTLS(e2));
111 
112     // Set in third pair.
113     tc.setTLS(e2, 3);
114     checkEq(1, tc.getTLS(e1));
115     checkEq(2, t1.getTLS(e1));
116     checkEq(3, tc.getTLS(e2));
117     checkEq(0, t1.getTLS(e2));
118 
119     // Set in fourth pair.
120     t1.setTLS(e2, 4);
121     checkEq(1, tc.getTLS(e1));
122     checkEq(2, t1.getTLS(e1));
123     checkEq(3, tc.getTLS(e2));
124     checkEq(4, t1.getTLS(e2));
125 
126     // Create a new thread and make sure everything is 0.
127     ThreadWaiter t2 = new ThreadWaiter();
128     checkEq(1, tc.getTLS(e1));
129     checkEq(2, t1.getTLS(e1));
130     checkEq(0, t2.getTLS(e1));
131     checkEq(3, tc.getTLS(e2));
132     checkEq(4, t1.getTLS(e2));
133     checkEq(0, t2.getTLS(e2));
134 
135     // Create a new jvmtienv and make sure everything is 0.
136     long e3 = newJvmtiEnv();
137     checkEq(1, tc.getTLS(e1));
138     checkEq(2, t1.getTLS(e1));
139     checkEq(0, t2.getTLS(e1));
140     checkEq(3, tc.getTLS(e2));
141     checkEq(4, t1.getTLS(e2));
142     checkEq(0, t2.getTLS(e2));
143     checkEq(0, tc.getTLS(e3));
144     checkEq(0, t1.getTLS(e3));
145     checkEq(0, t2.getTLS(e3));
146 
147     // Delete an env without data and make sure everything is still there.
148     destroyJvmtiEnv(e3);
149     checkEq(1, tc.getTLS(e1));
150     checkEq(2, t1.getTLS(e1));
151     checkEq(0, t2.getTLS(e1));
152     checkEq(3, tc.getTLS(e2));
153     checkEq(4, t1.getTLS(e2));
154     checkEq(0, t2.getTLS(e2));
155 
156     // Delete an env with data and make sure everything is still there.
157     destroyJvmtiEnv(e2);
158     checkEq(1, tc.getTLS(e1));
159     checkEq(2, t1.getTLS(e1));
160     checkEq(0, t2.getTLS(e1));
161 
162     // Delete a thread. Make sure other thread still has data.
163     t1.cleanup();
164     checkEq(1, tc.getTLS(e1));
165     checkEq(0, t2.getTLS(e1));
166 
167     t2.cleanup();
168 
169     System.out.println("Test passed");
170   }
171 
getTLS(long jvmtienv, Thread thr)172   public static native long getTLS(long jvmtienv, Thread thr);
setTLS(long jvmtienv, Thread thr, long ptr)173   public static native void setTLS(long jvmtienv, Thread thr, long ptr);
newJvmtiEnv()174   public static native long newJvmtiEnv();
destroyJvmtiEnv(long jvmtienv)175   public static native void destroyJvmtiEnv(long jvmtienv);
176 }
177