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
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