1 /*
2 * Copyright (C) 2017 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 "art_method-inl.h"
18 #include "base/mutex-inl.h"
19 #include "scoped_thread_state_change-inl.h"
20 #include "thread-inl.h"
21 #include "thread_pool.h"
22
23 namespace art {
24
25 struct TestClosure : public Closure {
26 bool first_run_start;
27 bool first_run_end;
28 bool second_run;
29 bool second_run_interleaved;
30
Runart::TestClosure31 void Run(Thread* self) override {
32 CHECK_EQ(self, Thread::Current()) << "Not running on target thread!";
33 if (!first_run_start) {
34 CHECK(!second_run);
35 first_run_start = true;
36 // Suspend ourself so that we will perform the second run.
37 {
38 ScopedObjectAccess soa(self);
39 self->FullSuspendCheck();
40 }
41 first_run_end = true;
42 } else {
43 CHECK(!second_run);
44 CHECK(first_run_start);
45 second_run = true;
46 second_run_interleaved = !first_run_end;
47 }
48 }
49
Checkart::TestClosure50 void Check() {
51 CHECK(first_run_start);
52 CHECK(first_run_end);
53 CHECK(second_run);
54 CHECK(second_run_interleaved);
55 }
56 };
57
58 static TestClosure gTestClosure = {};
59
Java_Main_checkCheckpointsRun(JNIEnv *,jclass)60 extern "C" JNIEXPORT void JNICALL Java_Main_checkCheckpointsRun(JNIEnv*, jclass) {
61 gTestClosure.Check();
62 }
63
64 struct SetupClosure : public Closure {
Runart::SetupClosure65 void Run(Thread* self) override {
66 CHECK_EQ(self, Thread::Current()) << "Not running on target thread!";
67 ScopedObjectAccess soa(self);
68 MutexLock tscl_mu(self, *Locks::thread_suspend_count_lock_);
69 // Both should succeed since we are in runnable and have the lock.
70 CHECK(self->RequestCheckpoint(&gTestClosure)) << "Could not set first checkpoint.";
71 CHECK(self->RequestCheckpoint(&gTestClosure)) << "Could not set second checkpoint.";
72 }
73 };
74
75 static SetupClosure gSetupClosure = {};
76
Java_Main_pushCheckpoints(JNIEnv *,jclass,jobject thr)77 extern "C" JNIEXPORT void JNICALL Java_Main_pushCheckpoints(JNIEnv*, jclass, jobject thr) {
78 Thread* self = Thread::Current();
79 ScopedObjectAccess soa(self);
80 MutexLock tll_mu(self, *Locks::thread_list_lock_);
81 Thread* target = Thread::FromManagedThread(soa, thr);
82 while (true) {
83 MutexLock tscl_mu(self, *Locks::thread_suspend_count_lock_);
84 if (target->RequestCheckpoint(&gSetupClosure)) {
85 break;
86 }
87 }
88 }
89
90 } // namespace art
91