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
17package art;
18
19import java.lang.ref.WeakReference;
20import java.util.ArrayList;
21import java.util.Arrays;
22import java.util.concurrent.CountDownLatch;
23import java.util.concurrent.Semaphore;
24
25public class Test1909 {
26
27  public static class ThreadHolder {
28    public Thread thr;
29    public ThreadHolder(Thread thr) {
30      this.thr = thr;
31    }
32
33    public long getTLS(long jvmtienv) {
34      return Test1909.getTLS(jvmtienv, this.thr);
35    }
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
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
65    public void cleanup() throws Exception {
66      synchronized (lock) {
67        exit = true;
68        lock.notifyAll();
69      }
70      thr.join();
71    }
72    public long getTLS(long jvmtienv) {
73      return Test1909.getTLS(jvmtienv, this.thr);
74    }
75    public void setTLS(long jvmtienv, long ptr) {
76      Test1909.setTLS(jvmtienv, this.thr, ptr);
77    }
78  }
79
80  public static void checkEq(long a, long b) {
81    if (a != b) {
82      throw new Error("Expected: " + a + " got: " + b);
83    }
84  }
85
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
172  public static native long getTLS(long jvmtienv, Thread thr);
173  public static native void setTLS(long jvmtienv, Thread thr, long ptr);
174  public static native long newJvmtiEnv();
175  public static native void destroyJvmtiEnv(long jvmtienv);
176}
177