blob: bff8d7678c77bcd56623fa9decfac71da0db7d26 [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
Elena Sayapina1af6a1f2014-06-20 16:58:37 +070017#include "monitor.h"
18
19#include <string>
20
David Sehr8f4b0562018-03-02 12:01:51 -080021#include "base/atomic.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070022#include "barrier.h"
Vladimir Marko80afd022015-05-19 18:08:00 +010023#include "base/time_utils.h"
Vladimir Marko3481ba22015-04-13 12:22:36 +010024#include "class_linker-inl.h"
Elena Sayapina1af6a1f2014-06-20 16:58:37 +070025#include "common_runtime_test.h"
26#include "handle_scope-inl.h"
27#include "mirror/class-inl.h"
28#include "mirror/string-inl.h" // Strings are easiest to allocate
Mathieu Chartier4b0ef1c2016-07-29 16:26:01 -070029#include "object_lock.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070030#include "scoped_thread_state_change-inl.h"
Elena Sayapina1af6a1f2014-06-20 16:58:37 +070031#include "thread_pool.h"
Elena Sayapina1af6a1f2014-06-20 16:58:37 +070032
33namespace art {
34
35class MonitorTest : public CommonRuntimeTest {
36 protected:
Ian Rogerse63db272014-07-15 15:36:11 -070037 void SetUpRuntimeOptions(RuntimeOptions *options) OVERRIDE {
Elena Sayapina1af6a1f2014-06-20 16:58:37 +070038 // Use a smaller heap
Andreas Gampe26761f72017-07-20 18:00:39 -070039 SetUpRuntimeOptionsForFillHeap(options);
40
Elena Sayapina1af6a1f2014-06-20 16:58:37 +070041 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
Elena Sayapina1af6a1f2014-06-20 16:58:37 +070056// Check that an exception can be thrown correctly.
57// This test is potentially racy, but the timeout is long enough that it should work.
58
59class CreateTask : public Task {
60 public:
Roland Levillain3887c462015-08-12 18:15:42 +010061 CreateTask(MonitorTest* monitor_test, uint64_t initial_sleep, int64_t millis, bool expected) :
Elena Sayapina1af6a1f2014-06-20 16:58:37 +070062 monitor_test_(monitor_test), initial_sleep_(initial_sleep), millis_(millis),
63 expected_(expected) {}
64
65 void Run(Thread* self) {
66 {
67 ScopedObjectAccess soa(self);
68
69 monitor_test_->thread_ = self; // Pass the Thread.
Mathieu Chartier2cebb242015-04-21 16:50:40 -070070 monitor_test_->object_.Get()->MonitorEnter(self); // Lock the object. This should transition
71 LockWord lock_after = monitor_test_->object_.Get()->GetLockWord(false); // it to thinLocked.
Elena Sayapina1af6a1f2014-06-20 16:58:37 +070072 LockWord::LockState new_state = lock_after.GetState();
73
74 // Cannot use ASSERT only, as analysis thinks we'll keep holding the mutex.
75 if (LockWord::LockState::kThinLocked != new_state) {
76 monitor_test_->object_.Get()->MonitorExit(self); // To appease analysis.
77 ASSERT_EQ(LockWord::LockState::kThinLocked, new_state); // To fail the test.
78 return;
79 }
80
81 // Force a fat lock by running identity hashcode to fill up lock word.
82 monitor_test_->object_.Get()->IdentityHashCode();
83 LockWord lock_after2 = monitor_test_->object_.Get()->GetLockWord(false);
84 LockWord::LockState new_state2 = lock_after2.GetState();
85
86 // Cannot use ASSERT only, as analysis thinks we'll keep holding the mutex.
87 if (LockWord::LockState::kFatLocked != new_state2) {
88 monitor_test_->object_.Get()->MonitorExit(self); // To appease analysis.
89 ASSERT_EQ(LockWord::LockState::kFatLocked, new_state2); // To fail the test.
90 return;
91 }
92 } // Need to drop the mutator lock to use the barrier.
93
94 monitor_test_->barrier_->Wait(self); // Let the other thread know we're done.
95
96 {
97 ScopedObjectAccess soa(self);
98
99 // Give the other task a chance to do its thing.
100 NanoSleep(initial_sleep_ * 1000 * 1000);
101
102 // Now try to Wait on the Monitor.
103 Monitor::Wait(self, monitor_test_->object_.Get(), millis_, 0, true,
104 ThreadState::kTimedWaiting);
105
106 // Check the exception status against what we expect.
107 EXPECT_EQ(expected_, self->IsExceptionPending());
108 if (expected_) {
109 self->ClearException();
110 }
111 }
112
113 monitor_test_->complete_barrier_->Wait(self); // Wait for test completion.
114
115 {
116 ScopedObjectAccess soa(self);
117 monitor_test_->object_.Get()->MonitorExit(self); // Release the object. Appeases analysis.
118 }
119 }
120
121 void Finalize() {
122 delete this;
123 }
124
125 private:
126 MonitorTest* monitor_test_;
127 uint64_t initial_sleep_;
128 int64_t millis_;
129 bool expected_;
130};
131
132
133class UseTask : public Task {
134 public:
135 UseTask(MonitorTest* monitor_test, uint64_t initial_sleep, int64_t millis, bool expected) :
136 monitor_test_(monitor_test), initial_sleep_(initial_sleep), millis_(millis),
137 expected_(expected) {}
138
139 void Run(Thread* self) {
140 monitor_test_->barrier_->Wait(self); // Wait for the other thread to set up the monitor.
141
142 {
143 ScopedObjectAccess soa(self);
144
145 // Give the other task a chance to do its thing.
146 NanoSleep(initial_sleep_ * 1000 * 1000);
147
148 Monitor::Wait(self, monitor_test_->object_.Get(), millis_, 0, true,
149 ThreadState::kTimedWaiting);
150
151 // Check the exception status against what we expect.
152 EXPECT_EQ(expected_, self->IsExceptionPending());
153 if (expected_) {
154 self->ClearException();
155 }
156 }
157
158 monitor_test_->complete_barrier_->Wait(self); // Wait for test completion.
159 }
160
161 void Finalize() {
162 delete this;
163 }
164
165 private:
166 MonitorTest* monitor_test_;
167 uint64_t initial_sleep_;
168 int64_t millis_;
169 bool expected_;
170};
171
172class InterruptTask : public Task {
173 public:
174 InterruptTask(MonitorTest* monitor_test, uint64_t initial_sleep, uint64_t millis) :
175 monitor_test_(monitor_test), initial_sleep_(initial_sleep), millis_(millis) {}
176
177 void Run(Thread* self) {
178 monitor_test_->barrier_->Wait(self); // Wait for the other thread to set up the monitor.
179
180 {
181 ScopedObjectAccess soa(self);
182
183 // Give the other task a chance to do its thing.
184 NanoSleep(initial_sleep_ * 1000 * 1000);
185
186 // Interrupt the other thread.
187 monitor_test_->thread_->Interrupt(self);
188
189 // Give it some more time to get to the exception code.
190 NanoSleep(millis_ * 1000 * 1000);
191
192 // Now try to Wait.
193 Monitor::Wait(self, monitor_test_->object_.Get(), 10, 0, true,
194 ThreadState::kTimedWaiting);
195
196 // No check here, as depending on scheduling we may or may not fail.
197 if (self->IsExceptionPending()) {
198 self->ClearException();
199 }
200 }
201
202 monitor_test_->complete_barrier_->Wait(self); // Wait for test completion.
203 }
204
205 void Finalize() {
206 delete this;
207 }
208
209 private:
210 MonitorTest* monitor_test_;
211 uint64_t initial_sleep_;
212 uint64_t millis_;
213};
214
215class WatchdogTask : public Task {
216 public:
217 explicit WatchdogTask(MonitorTest* monitor_test) : monitor_test_(monitor_test) {}
218
219 void Run(Thread* self) {
220 ScopedObjectAccess soa(self);
221
222 monitor_test_->watchdog_object_.Get()->MonitorEnter(self); // Lock the object.
223
224 monitor_test_->watchdog_object_.Get()->Wait(self, 30 * 1000, 0); // Wait for 30s, or being
225 // woken up.
226
227 monitor_test_->watchdog_object_.Get()->MonitorExit(self); // Release the lock.
228
229 if (!monitor_test_->completed_) {
230 LOG(FATAL) << "Watchdog timeout!";
231 }
232 }
233
234 void Finalize() {
235 delete this;
236 }
237
238 private:
239 MonitorTest* monitor_test_;
240};
241
242static void CommonWaitSetup(MonitorTest* test, ClassLinker* class_linker, uint64_t create_sleep,
243 int64_t c_millis, bool c_expected, bool interrupt, uint64_t use_sleep,
244 int64_t u_millis, bool u_expected, const char* pool_name) {
Mathieu Chartiered150002015-08-28 11:16:54 -0700245 Thread* const self = Thread::Current();
246 ScopedObjectAccess soa(self);
Elena Sayapina1af6a1f2014-06-20 16:58:37 +0700247 // First create the object we lock. String is easiest.
Mathieu Chartiered150002015-08-28 11:16:54 -0700248 StackHandleScope<3> hs(soa.Self());
249 test->object_ = hs.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "hello, world!"));
250 test->watchdog_object_ = hs.NewHandle(mirror::String::AllocFromModifiedUtf8(self,
251 "hello, world!"));
Elena Sayapina1af6a1f2014-06-20 16:58:37 +0700252
253 // Create the barrier used to synchronize.
254 test->barrier_ = std::unique_ptr<Barrier>(new Barrier(2));
255 test->complete_barrier_ = std::unique_ptr<Barrier>(new Barrier(3));
256 test->completed_ = false;
257
Mathieu Chartiered150002015-08-28 11:16:54 -0700258 // Our job: Fill the heap, then try Wait.
Andreas Gampe26761f72017-07-20 18:00:39 -0700259 {
260 VariableSizedHandleScope vhs(soa.Self());
261 test->FillHeap(soa.Self(), class_linker, &vhs);
Elena Sayapina1af6a1f2014-06-20 16:58:37 +0700262
Andreas Gampe26761f72017-07-20 18:00:39 -0700263 // Now release everything.
Mathieu Chartiered150002015-08-28 11:16:54 -0700264 }
Elena Sayapina1af6a1f2014-06-20 16:58:37 +0700265
Mathieu Chartiered150002015-08-28 11:16:54 -0700266 // Need to drop the mutator lock to allow barriers.
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700267 ScopedThreadSuspension sts(soa.Self(), kNative);
Elena Sayapina1af6a1f2014-06-20 16:58:37 +0700268 ThreadPool thread_pool(pool_name, 3);
269 thread_pool.AddTask(self, new CreateTask(test, create_sleep, c_millis, c_expected));
270 if (interrupt) {
271 thread_pool.AddTask(self, new InterruptTask(test, use_sleep, static_cast<uint64_t>(u_millis)));
272 } else {
273 thread_pool.AddTask(self, new UseTask(test, use_sleep, u_millis, u_expected));
274 }
275 thread_pool.AddTask(self, new WatchdogTask(test));
276 thread_pool.StartWorkers(self);
277
278 // Wait on completion barrier.
Mathieu Chartiered150002015-08-28 11:16:54 -0700279 test->complete_barrier_->Wait(self);
Elena Sayapina1af6a1f2014-06-20 16:58:37 +0700280 test->completed_ = true;
281
282 // Wake the watchdog.
283 {
Mathieu Chartiered150002015-08-28 11:16:54 -0700284 ScopedObjectAccess soa2(self);
Elena Sayapina1af6a1f2014-06-20 16:58:37 +0700285 test->watchdog_object_.Get()->MonitorEnter(self); // Lock the object.
286 test->watchdog_object_.Get()->NotifyAll(self); // Wake up waiting parties.
287 test->watchdog_object_.Get()->MonitorExit(self); // Release the lock.
288 }
289
290 thread_pool.StopWorkers(self);
291}
292
293
294// First test: throwing an exception when trying to wait in Monitor with another thread.
295TEST_F(MonitorTest, CheckExceptionsWait1) {
296 // Make the CreateTask wait 10ms, the UseTask wait 10ms.
297 // => The use task will get the lock first and get to self == owner check.
Andreas Gampe369810a2015-01-14 19:53:31 -0800298 // This will lead to OOM and monitor error messages in the log.
299 ScopedLogSeverity sls(LogSeverity::FATAL);
Elena Sayapina1af6a1f2014-06-20 16:58:37 +0700300 CommonWaitSetup(this, class_linker_, 10, 50, false, false, 2, 50, true,
301 "Monitor test thread pool 1");
302}
303
304// Second test: throwing an exception for invalid wait time.
305TEST_F(MonitorTest, CheckExceptionsWait2) {
306 // Make the CreateTask wait 0ms, the UseTask wait 10ms.
307 // => The create task will get the lock first and get to ms >= 0
Andreas Gampe369810a2015-01-14 19:53:31 -0800308 // This will lead to OOM and monitor error messages in the log.
309 ScopedLogSeverity sls(LogSeverity::FATAL);
Elena Sayapina1af6a1f2014-06-20 16:58:37 +0700310 CommonWaitSetup(this, class_linker_, 0, -1, true, false, 10, 50, true,
311 "Monitor test thread pool 2");
312}
313
314// Third test: throwing an interrupted-exception.
315TEST_F(MonitorTest, CheckExceptionsWait3) {
316 // Make the CreateTask wait 0ms, then Wait for a long time. Make the InterruptTask wait 10ms,
317 // after which it will interrupt the create task and then wait another 10ms.
318 // => The create task will get to the interrupted-exception throw.
Andreas Gampe369810a2015-01-14 19:53:31 -0800319 // This will lead to OOM and monitor error messages in the log.
320 ScopedLogSeverity sls(LogSeverity::FATAL);
Elena Sayapina1af6a1f2014-06-20 16:58:37 +0700321 CommonWaitSetup(this, class_linker_, 0, 500, true, true, 10, 50, true,
322 "Monitor test thread pool 3");
323}
324
Mathieu Chartier4b0ef1c2016-07-29 16:26:01 -0700325class TryLockTask : public Task {
326 public:
327 explicit TryLockTask(Handle<mirror::Object> obj) : obj_(obj) {}
328
329 void Run(Thread* self) {
330 ScopedObjectAccess soa(self);
331 // Lock is held by other thread, try lock should fail.
332 ObjectTryLock<mirror::Object> lock(self, obj_);
333 EXPECT_FALSE(lock.Acquired());
334 }
335
336 void Finalize() {
337 delete this;
338 }
339
340 private:
341 Handle<mirror::Object> obj_;
342};
343
344// Test trylock in deadlock scenarios.
345TEST_F(MonitorTest, TestTryLock) {
346 ScopedLogSeverity sls(LogSeverity::FATAL);
347
348 Thread* const self = Thread::Current();
349 ThreadPool thread_pool("the pool", 2);
350 ScopedObjectAccess soa(self);
Andreas Gampe38cea842016-11-03 13:06:25 -0700351 StackHandleScope<1> hs(self);
Mathieu Chartier4b0ef1c2016-07-29 16:26:01 -0700352 Handle<mirror::Object> obj1(
353 hs.NewHandle<mirror::Object>(mirror::String::AllocFromModifiedUtf8(self, "hello, world!")));
Mathieu Chartier4b0ef1c2016-07-29 16:26:01 -0700354 {
355 ObjectLock<mirror::Object> lock1(self, obj1);
Mathieu Chartier4b0ef1c2016-07-29 16:26:01 -0700356 {
357 ObjectTryLock<mirror::Object> trylock(self, obj1);
358 EXPECT_TRUE(trylock.Acquired());
359 }
360 // Test failure case.
361 thread_pool.AddTask(self, new TryLockTask(obj1));
362 thread_pool.StartWorkers(self);
363 ScopedThreadSuspension sts(self, kSuspended);
364 thread_pool.Wait(Thread::Current(), /*do_work*/false, /*may_hold_locks*/false);
365 }
366 // Test that the trylock actually locks the object.
367 {
368 ObjectTryLock<mirror::Object> trylock(self, obj1);
369 EXPECT_TRUE(trylock.Acquired());
370 obj1->Notify(self);
371 // Since we hold the lock there should be no monitor state exeception.
372 self->AssertNoPendingException();
373 }
374 thread_pool.StopWorkers(self);
375}
376
377
Elena Sayapina1af6a1f2014-06-20 16:58:37 +0700378} // namespace art