/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "art_method-inl.h" #include "base/mutex-inl.h" #include "scoped_thread_state_change-inl.h" #include "thread-inl.h" #include "thread_pool.h" namespace art { struct TestClosure : public Closure { bool first_run_start; bool first_run_end; bool second_run; bool second_run_interleaved; void Run(Thread* self) override { CHECK_EQ(self, Thread::Current()) << "Not running on target thread!"; if (!first_run_start) { CHECK(!second_run); first_run_start = true; // Suspend ourself so that we will perform the second run. { ScopedObjectAccess soa(self); self->FullSuspendCheck(); } first_run_end = true; } else { CHECK(!second_run); CHECK(first_run_start); second_run = true; second_run_interleaved = !first_run_end; } } void Check() { CHECK(first_run_start); CHECK(first_run_end); CHECK(second_run); CHECK(second_run_interleaved); } }; static TestClosure gTestClosure = {}; extern "C" JNIEXPORT void JNICALL Java_Main_checkCheckpointsRun(JNIEnv*, jclass) { gTestClosure.Check(); } struct SetupClosure : public Closure { void Run(Thread* self) override { CHECK_EQ(self, Thread::Current()) << "Not running on target thread!"; ScopedObjectAccess soa(self); MutexLock tscl_mu(self, *Locks::thread_suspend_count_lock_); // Both should succeed since we are in runnable and have the lock. CHECK(self->RequestCheckpoint(&gTestClosure)) << "Could not set first checkpoint."; CHECK(self->RequestCheckpoint(&gTestClosure)) << "Could not set second checkpoint."; } }; static SetupClosure gSetupClosure = {}; extern "C" JNIEXPORT void JNICALL Java_Main_pushCheckpoints(JNIEnv*, jclass, jobject thr) { Thread* self = Thread::Current(); ScopedObjectAccess soa(self); MutexLock tll_mu(self, *Locks::thread_list_lock_); Thread* target = Thread::FromManagedThread(soa, thr); while (true) { MutexLock tscl_mu(self, *Locks::thread_suspend_count_lock_); if (target->RequestCheckpoint(&gSetupClosure)) { break; } } } } // namespace art