1 /*
2 * Copyright 2020 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 #include <atomic>
18 #include <sstream>
19
20 #include "base/globals.h"
21 #include "jit/jit.h"
22 #include "jit/jit_code_cache.h"
23 #include "jni.h"
24 #include "runtime.h"
25 #include "thread_list.h"
26
27 namespace art {
28 namespace NativeWait {
29
30 std::atomic<bool> native_waiting = false;
31 std::atomic<bool> native_wait = false;
32
33 // Perform late debuggable switch in the same way the zygote would (clear-jit,
34 // unmark-zygote, set-debuggable, deopt boot, restart jit). NB This skips
35 // restarting the heap threads since that doesn't seem to be needed to trigger
36 // b/144947842.
Java_art_Test2031_simulateZygoteFork(JNIEnv *,jclass)37 extern "C" JNIEXPORT void JNICALL Java_art_Test2031_simulateZygoteFork(JNIEnv*, jclass) {
38 Runtime* runtime = Runtime::Current();
39 bool has_jit = runtime->GetJit() != nullptr;
40 if (has_jit) {
41 runtime->GetJit()->PreZygoteFork();
42 }
43 runtime->SetAsZygoteChild(/*is_system_server=*/false, /*is_zygote=*/false);
44 runtime->AddCompilerOption("--debuggable");
45 runtime->SetJavaDebuggable(true);
46 {
47 // Deoptimize the boot image as it may be non-debuggable.
48 ScopedSuspendAll ssa(__FUNCTION__);
49 runtime->DeoptimizeBootImage();
50 }
51
52 if (has_jit) {
53 runtime->GetJitCodeCache()->PostForkChildAction(false, false);
54 runtime->GetJit()->PostForkChildAction(false, false);
55 // We have "zygote" code that isn't really part of the BCP. just don't collect it.
56 runtime->GetJitCodeCache()->SetGarbageCollectCode(false);
57 }
58 }
59
Java_art_Test2031_setupJvmti(JNIEnv * env,jclass,jstring testdir)60 extern "C" JNIEXPORT void JNICALL Java_art_Test2031_setupJvmti(JNIEnv* env,
61 jclass,
62 jstring testdir) {
63 const char* td = env->GetStringUTFChars(testdir, nullptr);
64 std::string testdir_str;
65 testdir_str.resize(env->GetStringUTFLength(testdir));
66 memcpy(testdir_str.data(), td, testdir_str.size());
67 env->ReleaseStringUTFChars(testdir, td);
68 std::ostringstream oss;
69 Runtime* runtime = Runtime::Current();
70 oss << testdir_str << (kIsDebugBuild ? "libtiagentd.so" : "libtiagent.so")
71 << "=2031-zygote-compiled-frame-deopt,art";
72 LOG(INFO) << "agent " << oss.str();
73 runtime->AttachAgent(env, oss.str(), nullptr);
74 }
Java_art_Test2031_waitForNativeSleep(JNIEnv *,jclass)75 extern "C" JNIEXPORT void JNICALL Java_art_Test2031_waitForNativeSleep(JNIEnv*, jclass) {
76 while (!native_waiting) {
77 }
78 }
Java_art_Test2031_wakeupNativeSleep(JNIEnv *,jclass)79 extern "C" JNIEXPORT void JNICALL Java_art_Test2031_wakeupNativeSleep(JNIEnv*, jclass) {
80 native_wait = false;
81 }
Java_art_Test2031_nativeSleep(JNIEnv *,jclass)82 extern "C" JNIEXPORT void JNICALL Java_art_Test2031_nativeSleep(JNIEnv*, jclass) {
83 native_wait = true;
84 do {
85 native_waiting = true;
86 } while (native_wait);
87 native_waiting = false;
88 }
89
90 } // namespace NativeWait
91 } // namespace art
92