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 "monitor_pool.h"
     18 
     19 #include "common_runtime_test.h"
     20 #include "scoped_thread_state_change-inl.h"
     21 #include "thread-current-inl.h"
     22 
     23 namespace art {
     24 
     25 class MonitorPoolTest : public CommonRuntimeTest {};
     26 
     27 class RandGen {
     28  public:
     29   explicit RandGen(uint32_t seed) : val_(seed) {}
     30 
     31   uint32_t next() {
     32     val_ = val_ * 48271 % 2147483647 + 13;
     33     return val_;
     34   }
     35 
     36   uint32_t val_;
     37 };
     38 
     39 static void VerifyMonitor(Monitor* mon, Thread* self) {
     40   // Check whether the monitor id is correct.
     41   EXPECT_EQ(MonitorPool::MonitorIdFromMonitor(mon), mon->GetMonitorId());
     42   // Check whether the monitor id agrees with the compuation.
     43   EXPECT_EQ(MonitorPool::ComputeMonitorId(mon, self), mon->GetMonitorId());
     44   // Check whether we can use the monitor ID to get the monitor.
     45   EXPECT_EQ(mon, MonitorPool::MonitorFromMonitorId(mon->GetMonitorId()));
     46 }
     47 
     48 TEST_F(MonitorPoolTest, MonitorPoolTest) {
     49   std::vector<Monitor*> monitors;
     50   RandGen r(0x1234);
     51 
     52   // 1) Create and release monitors without increasing the storage.
     53 
     54   // Number of max alive monitors before resize.
     55   // Note: for correct testing, make sure this is corresponding to monitor-pool's initial size.
     56   const size_t kMaxUsage = 28;
     57 
     58   Thread* self = Thread::Current();
     59   ScopedObjectAccess soa(self);
     60 
     61   // Allocate and release monitors.
     62   for (size_t i = 0; i < 1000 ; i++) {
     63     bool alloc;
     64     if (monitors.size() == 0) {
     65       alloc = true;
     66     } else if (monitors.size() == kMaxUsage) {
     67       alloc = false;
     68     } else {
     69       // Random decision.
     70       alloc = r.next() % 2 == 0;
     71     }
     72 
     73     if (alloc) {
     74       Monitor* mon = MonitorPool::CreateMonitor(self, self, nullptr, static_cast<int32_t>(i));
     75       monitors.push_back(mon);
     76 
     77       VerifyMonitor(mon, self);
     78     } else {
     79       // Release a random monitor.
     80       size_t index = r.next() % monitors.size();
     81       Monitor* mon = monitors[index];
     82       monitors.erase(monitors.begin() + index);
     83 
     84       // Recheck the monitor.
     85       VerifyMonitor(mon, self);
     86 
     87       MonitorPool::ReleaseMonitor(self, mon);
     88     }
     89   }
     90 
     91   // Loop some time.
     92 
     93   for (size_t i = 0; i < 10; ++i) {
     94     // 2.1) Create enough monitors to require new chunks.
     95     size_t target_size = monitors.size() + 2*kMaxUsage;
     96     while (monitors.size() < target_size) {
     97       Monitor* mon = MonitorPool::CreateMonitor(self, self, nullptr,
     98                                                 static_cast<int32_t>(-monitors.size()));
     99       monitors.push_back(mon);
    100 
    101       VerifyMonitor(mon, self);
    102     }
    103 
    104     // 2.2) Verify all monitors.
    105     for (Monitor* mon : monitors) {
    106       VerifyMonitor(mon, self);
    107     }
    108 
    109     // 2.3) Release a number of monitors randomly.
    110     for (size_t j = 0; j < kMaxUsage; j++) {
    111       // Release a random monitor.
    112       size_t index = r.next() % monitors.size();
    113       Monitor* mon = monitors[index];
    114       monitors.erase(monitors.begin() + index);
    115 
    116       MonitorPool::ReleaseMonitor(self, mon);
    117     }
    118   }
    119 
    120   // Check and release all remaining monitors.
    121   for (Monitor* mon : monitors) {
    122     VerifyMonitor(mon, self);
    123     MonitorPool::ReleaseMonitor(self, mon);
    124   }
    125 }
    126 
    127 }  // namespace art
    128