Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2014 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 "barrier.h"
     18 #include "monitor.h"
     19 
     20 #include <string>
     21 
     22 #include "atomic.h"
     23 #include "common_runtime_test.h"
     24 #include "handle_scope-inl.h"
     25 #include "mirror/class-inl.h"
     26 #include "mirror/string-inl.h"  // Strings are easiest to allocate
     27 #include "scoped_thread_state_change.h"
     28 #include "thread_pool.h"
     29 #include "utils.h"
     30 
     31 namespace art {
     32 
     33 class MonitorTest : public CommonRuntimeTest {
     34  protected:
     35   void SetUpRuntimeOptions(RuntimeOptions *options) OVERRIDE {
     36     // Use a smaller heap
     37     for (std::pair<std::string, const void*>& pair : *options) {
     38       if (pair.first.find("-Xmx") == 0) {
     39         pair.first = "-Xmx4M";  // Smallest we can go.
     40       }
     41     }
     42     options->push_back(std::make_pair("-Xint", nullptr));
     43   }
     44  public:
     45   std::unique_ptr<Monitor> monitor_;
     46   Handle<mirror::String> object_;
     47   Handle<mirror::String> second_object_;
     48   Handle<mirror::String> watchdog_object_;
     49   // One exception test is for waiting on another Thread's lock. This is used to race-free &
     50   // loop-free pass
     51   Thread* thread_;
     52   std::unique_ptr<Barrier> barrier_;
     53   std::unique_ptr<Barrier> complete_barrier_;
     54   bool completed_;
     55 };
     56 
     57 // Fill the heap.
     58 static const size_t kMaxHandles = 1000000;  // Use arbitrary large amount for now.
     59 static void FillHeap(Thread* self, ClassLinker* class_linker,
     60                      std::unique_ptr<StackHandleScope<kMaxHandles>>* hsp,
     61                      std::vector<Handle<mirror::Object>>* handles)
     62     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     63   Runtime::Current()->GetHeap()->SetIdealFootprint(1 * GB);
     64 
     65   hsp->reset(new StackHandleScope<kMaxHandles>(self));
     66   // Class java.lang.Object.
     67   Handle<mirror::Class> c((*hsp)->NewHandle(class_linker->FindSystemClass(self,
     68                                                                        "Ljava/lang/Object;")));
     69   // Array helps to fill memory faster.
     70   Handle<mirror::Class> ca((*hsp)->NewHandle(class_linker->FindSystemClass(self,
     71                                                                         "[Ljava/lang/Object;")));
     72 
     73   // Start allocating with 128K
     74   size_t length = 128 * KB / 4;
     75   while (length > 10) {
     76     Handle<mirror::Object> h((*hsp)->NewHandle<mirror::Object>(
     77         mirror::ObjectArray<mirror::Object>::Alloc(self, ca.Get(), length / 4)));
     78     if (self->IsExceptionPending() || h.Get() == nullptr) {
     79       self->ClearException();
     80 
     81       // Try a smaller length
     82       length = length / 8;
     83       // Use at most half the reported free space.
     84       size_t mem = Runtime::Current()->GetHeap()->GetFreeMemory();
     85       if (length * 8 > mem) {
     86         length = mem / 8;
     87       }
     88     } else {
     89       handles->push_back(h);
     90     }
     91   }
     92 
     93   // Allocate simple objects till it fails.
     94   while (!self->IsExceptionPending()) {
     95     Handle<mirror::Object> h = (*hsp)->NewHandle<mirror::Object>(c->AllocObject(self));
     96     if (!self->IsExceptionPending() && h.Get() != nullptr) {
     97       handles->push_back(h);
     98     }
     99   }
    100   self->ClearException();
    101 }
    102 
    103 // Check that an exception can be thrown correctly.
    104 // This test is potentially racy, but the timeout is long enough that it should work.
    105 
    106 class CreateTask : public Task {
    107  public:
    108   explicit CreateTask(MonitorTest* monitor_test, uint64_t initial_sleep, int64_t millis,
    109                       bool expected) :
    110       monitor_test_(monitor_test), initial_sleep_(initial_sleep), millis_(millis),
    111       expected_(expected) {}
    112 
    113   void Run(Thread* self) {
    114     {
    115       ScopedObjectAccess soa(self);
    116 
    117       monitor_test_->thread_ = self;        // Pass the Thread.
    118       monitor_test_->object_.Get()->MonitorEnter(self);     // Lock the object. This should transition
    119       LockWord lock_after = monitor_test_->object_.Get()->GetLockWord(false);     // it to thinLocked.
    120       LockWord::LockState new_state = lock_after.GetState();
    121 
    122       // Cannot use ASSERT only, as analysis thinks we'll keep holding the mutex.
    123       if (LockWord::LockState::kThinLocked != new_state) {
    124         monitor_test_->object_.Get()->MonitorExit(self);         // To appease analysis.
    125         ASSERT_EQ(LockWord::LockState::kThinLocked, new_state);  // To fail the test.
    126         return;
    127       }
    128 
    129       // Force a fat lock by running identity hashcode to fill up lock word.
    130       monitor_test_->object_.Get()->IdentityHashCode();
    131       LockWord lock_after2 = monitor_test_->object_.Get()->GetLockWord(false);
    132       LockWord::LockState new_state2 = lock_after2.GetState();
    133 
    134       // Cannot use ASSERT only, as analysis thinks we'll keep holding the mutex.
    135       if (LockWord::LockState::kFatLocked != new_state2) {
    136         monitor_test_->object_.Get()->MonitorExit(self);         // To appease analysis.
    137         ASSERT_EQ(LockWord::LockState::kFatLocked, new_state2);  // To fail the test.
    138         return;
    139       }
    140     }  // Need to drop the mutator lock to use the barrier.
    141 
    142     monitor_test_->barrier_->Wait(self);           // Let the other thread know we're done.
    143 
    144     {
    145       ScopedObjectAccess soa(self);
    146 
    147       // Give the other task a chance to do its thing.
    148       NanoSleep(initial_sleep_ * 1000 * 1000);
    149 
    150       // Now try to Wait on the Monitor.
    151       Monitor::Wait(self, monitor_test_->object_.Get(), millis_, 0, true,
    152                     ThreadState::kTimedWaiting);
    153 
    154       // Check the exception status against what we expect.
    155       EXPECT_EQ(expected_, self->IsExceptionPending());
    156       if (expected_) {
    157         self->ClearException();
    158       }
    159     }
    160 
    161     monitor_test_->complete_barrier_->Wait(self);  // Wait for test completion.
    162 
    163     {
    164       ScopedObjectAccess soa(self);
    165       monitor_test_->object_.Get()->MonitorExit(self);  // Release the object. Appeases analysis.
    166     }
    167   }
    168 
    169   void Finalize() {
    170     delete this;
    171   }
    172 
    173  private:
    174   MonitorTest* monitor_test_;
    175   uint64_t initial_sleep_;
    176   int64_t millis_;
    177   bool expected_;
    178 };
    179 
    180 
    181 class UseTask : public Task {
    182  public:
    183   UseTask(MonitorTest* monitor_test, uint64_t initial_sleep, int64_t millis, bool expected) :
    184       monitor_test_(monitor_test), initial_sleep_(initial_sleep), millis_(millis),
    185       expected_(expected) {}
    186 
    187   void Run(Thread* self) {
    188     monitor_test_->barrier_->Wait(self);  // Wait for the other thread to set up the monitor.
    189 
    190     {
    191       ScopedObjectAccess soa(self);
    192 
    193       // Give the other task a chance to do its thing.
    194       NanoSleep(initial_sleep_ * 1000 * 1000);
    195 
    196       Monitor::Wait(self, monitor_test_->object_.Get(), millis_, 0, true,
    197                     ThreadState::kTimedWaiting);
    198 
    199       // Check the exception status against what we expect.
    200       EXPECT_EQ(expected_, self->IsExceptionPending());
    201       if (expected_) {
    202         self->ClearException();
    203       }
    204     }
    205 
    206     monitor_test_->complete_barrier_->Wait(self);  // Wait for test completion.
    207   }
    208 
    209   void Finalize() {
    210     delete this;
    211   }
    212 
    213  private:
    214   MonitorTest* monitor_test_;
    215   uint64_t initial_sleep_;
    216   int64_t millis_;
    217   bool expected_;
    218 };
    219 
    220 class InterruptTask : public Task {
    221  public:
    222   InterruptTask(MonitorTest* monitor_test, uint64_t initial_sleep, uint64_t millis) :
    223       monitor_test_(monitor_test), initial_sleep_(initial_sleep), millis_(millis) {}
    224 
    225   void Run(Thread* self) {
    226     monitor_test_->barrier_->Wait(self);  // Wait for the other thread to set up the monitor.
    227 
    228     {
    229       ScopedObjectAccess soa(self);
    230 
    231       // Give the other task a chance to do its thing.
    232       NanoSleep(initial_sleep_ * 1000 * 1000);
    233 
    234       // Interrupt the other thread.
    235       monitor_test_->thread_->Interrupt(self);
    236 
    237       // Give it some more time to get to the exception code.
    238       NanoSleep(millis_ * 1000 * 1000);
    239 
    240       // Now try to Wait.
    241       Monitor::Wait(self, monitor_test_->object_.Get(), 10, 0, true,
    242                     ThreadState::kTimedWaiting);
    243 
    244       // No check here, as depending on scheduling we may or may not fail.
    245       if (self->IsExceptionPending()) {
    246         self->ClearException();
    247       }
    248     }
    249 
    250     monitor_test_->complete_barrier_->Wait(self);  // Wait for test completion.
    251   }
    252 
    253   void Finalize() {
    254     delete this;
    255   }
    256 
    257  private:
    258   MonitorTest* monitor_test_;
    259   uint64_t initial_sleep_;
    260   uint64_t millis_;
    261 };
    262 
    263 class WatchdogTask : public Task {
    264  public:
    265   explicit WatchdogTask(MonitorTest* monitor_test) : monitor_test_(monitor_test) {}
    266 
    267   void Run(Thread* self) {
    268     ScopedObjectAccess soa(self);
    269 
    270     monitor_test_->watchdog_object_.Get()->MonitorEnter(self);        // Lock the object.
    271 
    272     monitor_test_->watchdog_object_.Get()->Wait(self, 30 * 1000, 0);  // Wait for 30s, or being
    273                                                                       // woken up.
    274 
    275     monitor_test_->watchdog_object_.Get()->MonitorExit(self);         // Release the lock.
    276 
    277     if (!monitor_test_->completed_) {
    278       LOG(FATAL) << "Watchdog timeout!";
    279     }
    280   }
    281 
    282   void Finalize() {
    283     delete this;
    284   }
    285 
    286  private:
    287   MonitorTest* monitor_test_;
    288 };
    289 
    290 static void CommonWaitSetup(MonitorTest* test, ClassLinker* class_linker, uint64_t create_sleep,
    291                             int64_t c_millis, bool c_expected, bool interrupt, uint64_t use_sleep,
    292                             int64_t u_millis, bool u_expected, const char* pool_name) {
    293   // First create the object we lock. String is easiest.
    294   StackHandleScope<3> hs(Thread::Current());
    295   {
    296     ScopedObjectAccess soa(Thread::Current());
    297     test->object_ = hs.NewHandle(mirror::String::AllocFromModifiedUtf8(Thread::Current(),
    298                                                                        "hello, world!"));
    299     test->watchdog_object_ = hs.NewHandle(mirror::String::AllocFromModifiedUtf8(Thread::Current(),
    300                                                                                 "hello, world!"));
    301   }
    302 
    303   // Create the barrier used to synchronize.
    304   test->barrier_ = std::unique_ptr<Barrier>(new Barrier(2));
    305   test->complete_barrier_ = std::unique_ptr<Barrier>(new Barrier(3));
    306   test->completed_ = false;
    307 
    308   // Fill the heap.
    309   std::unique_ptr<StackHandleScope<kMaxHandles>> hsp;
    310   std::vector<Handle<mirror::Object>> handles;
    311   {
    312     Thread* self = Thread::Current();
    313     ScopedObjectAccess soa(self);
    314 
    315     // Our job: Fill the heap, then try Wait.
    316     FillHeap(self, class_linker, &hsp, &handles);
    317 
    318     // Now release everything.
    319     auto it = handles.begin();
    320     auto end = handles.end();
    321 
    322     for ( ; it != end; ++it) {
    323       it->Assign(nullptr);
    324     }
    325   }  // Need to drop the mutator lock to allow barriers.
    326 
    327   Thread* self = Thread::Current();
    328   ThreadPool thread_pool(pool_name, 3);
    329   thread_pool.AddTask(self, new CreateTask(test, create_sleep, c_millis, c_expected));
    330   if (interrupt) {
    331     thread_pool.AddTask(self, new InterruptTask(test, use_sleep, static_cast<uint64_t>(u_millis)));
    332   } else {
    333     thread_pool.AddTask(self, new UseTask(test, use_sleep, u_millis, u_expected));
    334   }
    335   thread_pool.AddTask(self, new WatchdogTask(test));
    336   thread_pool.StartWorkers(self);
    337 
    338   // Wait on completion barrier.
    339   test->complete_barrier_->Wait(Thread::Current());
    340   test->completed_ = true;
    341 
    342   // Wake the watchdog.
    343   {
    344     Thread* self = Thread::Current();
    345     ScopedObjectAccess soa(self);
    346 
    347     test->watchdog_object_.Get()->MonitorEnter(self);     // Lock the object.
    348     test->watchdog_object_.Get()->NotifyAll(self);        // Wake up waiting parties.
    349     test->watchdog_object_.Get()->MonitorExit(self);      // Release the lock.
    350   }
    351 
    352   thread_pool.StopWorkers(self);
    353 }
    354 
    355 
    356 // First test: throwing an exception when trying to wait in Monitor with another thread.
    357 TEST_F(MonitorTest, CheckExceptionsWait1) {
    358   // Make the CreateTask wait 10ms, the UseTask wait 10ms.
    359   // => The use task will get the lock first and get to self == owner check.
    360   CommonWaitSetup(this, class_linker_, 10, 50, false, false, 2, 50, true,
    361                   "Monitor test thread pool 1");
    362 }
    363 
    364 // Second test: throwing an exception for invalid wait time.
    365 TEST_F(MonitorTest, CheckExceptionsWait2) {
    366   // Make the CreateTask wait 0ms, the UseTask wait 10ms.
    367   // => The create task will get the lock first and get to ms >= 0
    368   CommonWaitSetup(this, class_linker_, 0, -1, true, false, 10, 50, true,
    369                   "Monitor test thread pool 2");
    370 }
    371 
    372 // Third test: throwing an interrupted-exception.
    373 TEST_F(MonitorTest, CheckExceptionsWait3) {
    374   // Make the CreateTask wait 0ms, then Wait for a long time. Make the InterruptTask wait 10ms,
    375   // after which it will interrupt the create task and then wait another 10ms.
    376   // => The create task will get to the interrupted-exception throw.
    377   CommonWaitSetup(this, class_linker_, 0, 500, true, true, 10, 50, true,
    378                   "Monitor test thread pool 3");
    379 }
    380 
    381 }  // namespace art
    382