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