blob: 424e9f1a9618413e879fe67a6163330b97fb083c [file] [log] [blame]
Alex Lightdf00a1e2017-11-01 09:29:53 -07001/*
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
23namespace art {
24
25struct TestClosure : public Closure {
26 bool first_run_start;
27 bool first_run_end;
28 bool second_run;
29 bool second_run_interleaved;
30
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010031 void Run(Thread* self) override {
Alex Lightdf00a1e2017-11-01 09:29:53 -070032 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
50 void Check() {
51 CHECK(first_run_start);
52 CHECK(first_run_end);
53 CHECK(second_run);
54 CHECK(second_run_interleaved);
55 }
56};
57
58static TestClosure gTestClosure = {};
59
60extern "C" JNIEXPORT void JNICALL Java_Main_checkCheckpointsRun(JNIEnv*, jclass) {
61 gTestClosure.Check();
62}
63
64struct SetupClosure : public Closure {
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010065 void Run(Thread* self) override {
Alex Lightdf00a1e2017-11-01 09:29:53 -070066 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
75static SetupClosure gSetupClosure = {};
76
77extern "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