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