blob: 5463877b837cc56e6375ef68b968e924b7e2b257 [file] [log] [blame]
Andreas Gampe74240812014-04-17 10:35:09 -07001/*
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"
Mathieu Chartier0795f232016-09-27 18:43:30 -070020#include "scoped_thread_state_change-inl.h"
Andreas Gampeb486a982017-06-01 13:45:54 -070021#include "thread-current-inl.h"
Andreas Gampe74240812014-04-17 10:35:09 -070022
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