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