blob: bdba494e148f0fcc3790bc9fd8234bb83f660333 [file] [log] [blame]
Elena Sayapina1af6a1f2014-06-20 16:58:37 +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 "barrier.h"
18#include "monitor.h"
19
20#include <string>
21
22#include "atomic.h"
23#include "common_runtime_test.h"
24#include "handle_scope-inl.h"
25#include "mirror/class-inl.h"
26#include "mirror/string-inl.h" // Strings are easiest to allocate
27#include "thread_pool.h"
28#include "utils.h"
29
30namespace art {
31
32class MonitorTest : public CommonRuntimeTest {
33 protected:
34 void SetUpRuntimeOptions(Runtime::Options *options) OVERRIDE {
35 // Use a smaller heap
36 for (std::pair<std::string, const void*>& pair : *options) {
37 if (pair.first.find("-Xmx") == 0) {
38 pair.first = "-Xmx4M"; // Smallest we can go.
39 }
40 }
41 options->push_back(std::make_pair("-Xint", nullptr));
42 }
43 public:
44 std::unique_ptr<Monitor> monitor_;
45 Handle<mirror::String> object_;
46 Handle<mirror::String> second_object_;
47 Handle<mirror::String> watchdog_object_;
48 // One exception test is for waiting on another Thread's lock. This is used to race-free &
49 // loop-free pass
50 Thread* thread_;
51 std::unique_ptr<Barrier> barrier_;
52 std::unique_ptr<Barrier> complete_barrier_;
53 bool completed_;
54};
55
56// Fill the heap.
57static const size_t kMaxHandles = 1000000; // Use arbitrary large amount for now.
58static void FillHeap(Thread* self, ClassLinker* class_linker,
59 std::unique_ptr<StackHandleScope<kMaxHandles>>* hsp,
60 std::vector<Handle<mirror::Object>>* handles)
61 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
62 Runtime::Current()->GetHeap()->SetIdealFootprint(1 * GB);
63
64 hsp->reset(new StackHandleScope<kMaxHandles>(self));
65 // Class java.lang.Object.
66 Handle<mirror::Class> c((*hsp)->NewHandle(class_linker->FindSystemClass(self,
67 "Ljava/lang/Object;")));
68 // Array helps to fill memory faster.
69 Handle<mirror::Class> ca((*hsp)->NewHandle(class_linker->FindSystemClass(self,
70 "[Ljava/lang/Object;")));
71
72 // Start allocating with 128K
73 size_t length = 128 * KB / 4;
74 while (length > 10) {
75 Handle<mirror::Object> h((*hsp)->NewHandle<mirror::Object>(
76 mirror::ObjectArray<mirror::Object>::Alloc(self, ca.Get(), length / 4)));
77 if (self->IsExceptionPending() || h.Get() == nullptr) {
78 self->ClearException();
79
80 // Try a smaller length
81 length = length / 8;
82 // Use at most half the reported free space.
83 size_t mem = Runtime::Current()->GetHeap()->GetFreeMemory();
84 if (length * 8 > mem) {
85 length = mem / 8;
86 }
87 } else {
88 handles->push_back(h);
89 }
90 }
91
92 // Allocate simple objects till it fails.
93 while (!self->IsExceptionPending()) {
94 Handle<mirror::Object> h = (*hsp)->NewHandle<mirror::Object>(c->AllocObject(self));
95 if (!self->IsExceptionPending() && h.Get() != nullptr) {
96 handles->push_back(h);
97 }
98 }
99 self->ClearException();
100}
101
102// Check that an exception can be thrown correctly.
103// This test is potentially racy, but the timeout is long enough that it should work.
104
105class CreateTask : public Task {
106 public:
107 explicit CreateTask(MonitorTest* monitor_test, uint64_t initial_sleep, int64_t millis,
108 bool expected) :
109 monitor_test_(monitor_test), initial_sleep_(initial_sleep), millis_(millis),
110 expected_(expected) {}
111
112 void Run(Thread* self) {
113 {
114 ScopedObjectAccess soa(self);
115
116 monitor_test_->thread_ = self; // Pass the Thread.
117 monitor_test_->object_.Get()->MonitorEnter(self); // Lock the object. This should transition
118 LockWord lock_after = monitor_test_->object_.Get()->GetLockWord(false); // it to thinLocked.
119 LockWord::LockState new_state = lock_after.GetState();
120
121 // Cannot use ASSERT only, as analysis thinks we'll keep holding the mutex.
122 if (LockWord::LockState::kThinLocked != new_state) {
123 monitor_test_->object_.Get()->MonitorExit(self); // To appease analysis.
124 ASSERT_EQ(LockWord::LockState::kThinLocked, new_state); // To fail the test.
125 return;
126 }
127
128 // Force a fat lock by running identity hashcode to fill up lock word.
129 monitor_test_->object_.Get()->IdentityHashCode();
130 LockWord lock_after2 = monitor_test_->object_.Get()->GetLockWord(false);
131 LockWord::LockState new_state2 = lock_after2.GetState();
132
133 // Cannot use ASSERT only, as analysis thinks we'll keep holding the mutex.
134 if (LockWord::LockState::kFatLocked != new_state2) {
135 monitor_test_->object_.Get()->MonitorExit(self); // To appease analysis.
136 ASSERT_EQ(LockWord::LockState::kFatLocked, new_state2); // To fail the test.
137 return;
138 }
139 } // Need to drop the mutator lock to use the barrier.
140
141 monitor_test_->barrier_->Wait(self); // Let the other thread know we're done.
142
143 {
144 ScopedObjectAccess soa(self);
145
146 // Give the other task a chance to do its thing.
147 NanoSleep(initial_sleep_ * 1000 * 1000);
148
149 // Now try to Wait on the Monitor.
150 Monitor::Wait(self, monitor_test_->object_.Get(), millis_, 0, true,
151 ThreadState::kTimedWaiting);
152
153 // Check the exception status against what we expect.
154 EXPECT_EQ(expected_, self->IsExceptionPending());
155 if (expected_) {
156 self->ClearException();
157 }
158 }
159
160 monitor_test_->complete_barrier_->Wait(self); // Wait for test completion.
161
162 {
163 ScopedObjectAccess soa(self);
164 monitor_test_->object_.Get()->MonitorExit(self); // Release the object. Appeases analysis.
165 }
166 }
167
168 void Finalize() {
169 delete this;
170 }
171
172 private:
173 MonitorTest* monitor_test_;
174 uint64_t initial_sleep_;
175 int64_t millis_;
176 bool expected_;
177};
178
179
180class UseTask : public Task {
181 public:
182 UseTask(MonitorTest* monitor_test, uint64_t initial_sleep, int64_t millis, bool expected) :
183 monitor_test_(monitor_test), initial_sleep_(initial_sleep), millis_(millis),
184 expected_(expected) {}
185
186 void Run(Thread* self) {
187 monitor_test_->barrier_->Wait(self); // Wait for the other thread to set up the monitor.
188
189 {
190 ScopedObjectAccess soa(self);
191
192 // Give the other task a chance to do its thing.
193 NanoSleep(initial_sleep_ * 1000 * 1000);
194
195 Monitor::Wait(self, monitor_test_->object_.Get(), millis_, 0, true,
196 ThreadState::kTimedWaiting);
197
198 // Check the exception status against what we expect.
199 EXPECT_EQ(expected_, self->IsExceptionPending());
200 if (expected_) {
201 self->ClearException();
202 }
203 }
204
205 monitor_test_->complete_barrier_->Wait(self); // Wait for test completion.
206 }
207
208 void Finalize() {
209 delete this;
210 }
211
212 private:
213 MonitorTest* monitor_test_;
214 uint64_t initial_sleep_;
215 int64_t millis_;
216 bool expected_;
217};
218
219class InterruptTask : public Task {
220 public:
221 InterruptTask(MonitorTest* monitor_test, uint64_t initial_sleep, uint64_t millis) :
222 monitor_test_(monitor_test), initial_sleep_(initial_sleep), millis_(millis) {}
223
224 void Run(Thread* self) {
225 monitor_test_->barrier_->Wait(self); // Wait for the other thread to set up the monitor.
226
227 {
228 ScopedObjectAccess soa(self);
229
230 // Give the other task a chance to do its thing.
231 NanoSleep(initial_sleep_ * 1000 * 1000);
232
233 // Interrupt the other thread.
234 monitor_test_->thread_->Interrupt(self);
235
236 // Give it some more time to get to the exception code.
237 NanoSleep(millis_ * 1000 * 1000);
238
239 // Now try to Wait.
240 Monitor::Wait(self, monitor_test_->object_.Get(), 10, 0, true,
241 ThreadState::kTimedWaiting);
242
243 // No check here, as depending on scheduling we may or may not fail.
244 if (self->IsExceptionPending()) {
245 self->ClearException();
246 }
247 }
248
249 monitor_test_->complete_barrier_->Wait(self); // Wait for test completion.
250 }
251
252 void Finalize() {
253 delete this;
254 }
255
256 private:
257 MonitorTest* monitor_test_;
258 uint64_t initial_sleep_;
259 uint64_t millis_;
260};
261
262class WatchdogTask : public Task {
263 public:
264 explicit WatchdogTask(MonitorTest* monitor_test) : monitor_test_(monitor_test) {}
265
266 void Run(Thread* self) {
267 ScopedObjectAccess soa(self);
268
269 monitor_test_->watchdog_object_.Get()->MonitorEnter(self); // Lock the object.
270
271 monitor_test_->watchdog_object_.Get()->Wait(self, 30 * 1000, 0); // Wait for 30s, or being
272 // woken up.
273
274 monitor_test_->watchdog_object_.Get()->MonitorExit(self); // Release the lock.
275
276 if (!monitor_test_->completed_) {
277 LOG(FATAL) << "Watchdog timeout!";
278 }
279 }
280
281 void Finalize() {
282 delete this;
283 }
284
285 private:
286 MonitorTest* monitor_test_;
287};
288
289static void CommonWaitSetup(MonitorTest* test, ClassLinker* class_linker, uint64_t create_sleep,
290 int64_t c_millis, bool c_expected, bool interrupt, uint64_t use_sleep,
291 int64_t u_millis, bool u_expected, const char* pool_name) {
292 // First create the object we lock. String is easiest.
293 StackHandleScope<3> hs(Thread::Current());
294 {
295 ScopedObjectAccess soa(Thread::Current());
296 test->object_ = hs.NewHandle(mirror::String::AllocFromModifiedUtf8(Thread::Current(),
297 "hello, world!"));
298 test->watchdog_object_ = hs.NewHandle(mirror::String::AllocFromModifiedUtf8(Thread::Current(),
299 "hello, world!"));
300 }
301
302 // Create the barrier used to synchronize.
303 test->barrier_ = std::unique_ptr<Barrier>(new Barrier(2));
304 test->complete_barrier_ = std::unique_ptr<Barrier>(new Barrier(3));
305 test->completed_ = false;
306
307 // Fill the heap.
308 std::unique_ptr<StackHandleScope<kMaxHandles>> hsp;
309 std::vector<Handle<mirror::Object>> handles;
310 {
311 Thread* self = Thread::Current();
312 ScopedObjectAccess soa(self);
313
314 // Our job: Fill the heap, then try Wait.
315 FillHeap(self, class_linker, &hsp, &handles);
316
317 // Now release everything.
318 auto it = handles.begin();
319 auto end = handles.end();
320
321 for ( ; it != end; ++it) {
322 it->Assign(nullptr);
323 }
324 } // Need to drop the mutator lock to allow barriers.
325
326 Thread* self = Thread::Current();
327 ThreadPool thread_pool(pool_name, 3);
328 thread_pool.AddTask(self, new CreateTask(test, create_sleep, c_millis, c_expected));
329 if (interrupt) {
330 thread_pool.AddTask(self, new InterruptTask(test, use_sleep, static_cast<uint64_t>(u_millis)));
331 } else {
332 thread_pool.AddTask(self, new UseTask(test, use_sleep, u_millis, u_expected));
333 }
334 thread_pool.AddTask(self, new WatchdogTask(test));
335 thread_pool.StartWorkers(self);
336
337 // Wait on completion barrier.
338 test->complete_barrier_->Wait(Thread::Current());
339 test->completed_ = true;
340
341 // Wake the watchdog.
342 {
343 Thread* self = Thread::Current();
344 ScopedObjectAccess soa(self);
345
346 test->watchdog_object_.Get()->MonitorEnter(self); // Lock the object.
347 test->watchdog_object_.Get()->NotifyAll(self); // Wake up waiting parties.
348 test->watchdog_object_.Get()->MonitorExit(self); // Release the lock.
349 }
350
351 thread_pool.StopWorkers(self);
352}
353
354
355// First test: throwing an exception when trying to wait in Monitor with another thread.
356TEST_F(MonitorTest, CheckExceptionsWait1) {
357 // Make the CreateTask wait 10ms, the UseTask wait 10ms.
358 // => The use task will get the lock first and get to self == owner check.
359 CommonWaitSetup(this, class_linker_, 10, 50, false, false, 2, 50, true,
360 "Monitor test thread pool 1");
361}
362
363// Second test: throwing an exception for invalid wait time.
364TEST_F(MonitorTest, CheckExceptionsWait2) {
365 // Make the CreateTask wait 0ms, the UseTask wait 10ms.
366 // => The create task will get the lock first and get to ms >= 0
367 CommonWaitSetup(this, class_linker_, 0, -1, true, false, 10, 50, true,
368 "Monitor test thread pool 2");
369}
370
371// Third test: throwing an interrupted-exception.
372TEST_F(MonitorTest, CheckExceptionsWait3) {
373 // Make the CreateTask wait 0ms, then Wait for a long time. Make the InterruptTask wait 10ms,
374 // after which it will interrupt the create task and then wait another 10ms.
375 // => The create task will get to the interrupted-exception throw.
376 CommonWaitSetup(this, class_linker_, 0, 500, true, true, 10, 50, true,
377 "Monitor test thread pool 3");
378}
379
380} // namespace art