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:
RandGen(uint32_t seed)29   explicit RandGen(uint32_t seed) : val_(seed) {}
30 
next()31   uint32_t next() {
32     val_ = val_ * 48271 % 2147483647 + 13;
33     return val_;
34   }
35 
36   uint32_t val_;
37 };
38 
VerifyMonitor(Monitor * mon,Thread * self)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 
TEST_F(MonitorPoolTest,MonitorPoolTest)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