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.h" 21#include "thread-inl.h" 22 23namespace art { 24 25class MonitorPoolTest : public CommonRuntimeTest {}; 26 27class 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 39static 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 48TEST_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