Home | History | Annotate | Download | only in 203-multi-checkpoint
      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 
     31   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 
     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 
     58 static TestClosure gTestClosure = {};
     59 
     60 extern "C" JNIEXPORT void JNICALL Java_Main_checkCheckpointsRun(JNIEnv*, jclass) {
     61   gTestClosure.Check();
     62 }
     63 
     64 struct SetupClosure : public Closure {
     65   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 
     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