blob: 94408ba18695176bd75e9a1904fdd73bc0886b62 [file] [log] [blame]
Andreas Gampe319dbe82017-01-09 16:42:21 -08001/* Copyright (C) 2017 The Android Open Source Project
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This file implements interfaces from the file jvmti.h. This implementation
5 * is licensed under the same terms as the file jvmti.h. The
6 * copyright and license information for the file jvmti.h follows.
7 *
8 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
9 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10 *
11 * This code is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License version 2 only, as
13 * published by the Free Software Foundation. Oracle designates this
14 * particular file as subject to the "Classpath" exception as provided
15 * by Oracle in the LICENSE file that accompanied this code.
16 *
17 * This code is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * version 2 for more details (a copy is included in the LICENSE file that
21 * accompanied this code).
22 *
23 * You should have received a copy of the GNU General Public License version
24 * 2 along with this work; if not, write to the Free Software Foundation,
25 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26 *
27 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
28 * or visit www.oracle.com if you need additional information or have any
29 * questions.
30 */
31
32#include "ti_monitor.h"
33
34#include <atomic>
Igor Murashkin5573c372017-11-16 13:34:30 -080035#include <chrono>
36#include <condition_variable>
37#include <mutex>
Andreas Gampe319dbe82017-01-09 16:42:21 -080038
39#include "art_jvmti.h"
Alex Light41006c62017-09-14 09:51:14 -070040#include "monitor.h"
Andreas Gampe319dbe82017-01-09 16:42:21 -080041#include "runtime.h"
42#include "scoped_thread_state_change-inl.h"
Andreas Gampeb486a982017-06-01 13:45:54 -070043#include "thread-current-inl.h"
Alex Light23aa7482017-08-16 10:01:13 -070044#include "ti_thread.h"
Alex Light41006c62017-09-14 09:51:14 -070045#include "thread.h"
46#include "thread_pool.h"
Andreas Gampe319dbe82017-01-09 16:42:21 -080047
48namespace openjdkjvmti {
49
50// We cannot use ART monitors, as they require the mutator lock for contention locking. We
51// also cannot use pthread mutexes and condition variables (or C++11 abstractions) directly,
52// as the do not have the right semantics for recursive mutexes and waiting (wait only unlocks
53// the mutex once).
54// So go ahead and use a wrapper that does the counting explicitly.
55
56class JvmtiMonitor {
57 public:
Alex Light23aa7482017-08-16 10:01:13 -070058 JvmtiMonitor() : owner_(nullptr), count_(0) { }
Andreas Gampe319dbe82017-01-09 16:42:21 -080059
David Sehrae3bcac2017-02-03 15:19:00 -080060 static bool Destroy(art::Thread* self, JvmtiMonitor* monitor) NO_THREAD_SAFETY_ANALYSIS {
Andreas Gampe319dbe82017-01-09 16:42:21 -080061 // Check whether this thread holds the monitor, or nobody does.
62 art::Thread* owner_thread = monitor->owner_.load(std::memory_order_relaxed);
63 if (owner_thread != nullptr && self != owner_thread) {
64 return false;
65 }
66
67 if (monitor->count_ > 0) {
68 monitor->count_ = 0;
69 monitor->owner_.store(nullptr, std::memory_order_relaxed);
70 monitor->mutex_.unlock();
71 }
72
73 delete monitor;
74 return true;
75 }
76
David Sehrae3bcac2017-02-03 15:19:00 -080077 void MonitorEnter(art::Thread* self) NO_THREAD_SAFETY_ANALYSIS {
Alex Light23aa7482017-08-16 10:01:13 -070078 // Perform a suspend-check. The spec doesn't require this but real-world agents depend on this
79 // behavior. We do this by performing a suspend-check then retrying if the thread is suspended
80 // before or after locking the internal mutex.
81 do {
82 ThreadUtil::SuspendCheck(self);
83 if (ThreadUtil::WouldSuspendForUserCode(self)) {
84 continue;
85 }
Andreas Gampe319dbe82017-01-09 16:42:21 -080086
Alex Light23aa7482017-08-16 10:01:13 -070087 // Check for recursive enter.
88 if (IsOwner(self)) {
89 count_++;
90 return;
91 }
92
93 // Checking for user-code suspension takes acquiring 2 art::Mutexes so we want to avoid doing
94 // that if possible. To avoid it we try to get the internal mutex without sleeping. If we do
95 // this we don't bother doing another suspend check since it can linearize after the lock.
96 if (mutex_.try_lock()) {
97 break;
98 } else {
99 // Lock with sleep. We will need to check for suspension after this to make sure that agents
100 // won't deadlock.
101 mutex_.lock();
102 if (!ThreadUtil::WouldSuspendForUserCode(self)) {
103 break;
104 } else {
105 // We got suspended in the middle of waiting for the mutex. We should release the mutex
106 // and try again so we can get it while not suspended. This lets some other
107 // (non-suspended) thread acquire the mutex in case it's waiting to wake us up.
108 mutex_.unlock();
109 continue;
110 }
111 }
112 } while (true);
Andreas Gampe319dbe82017-01-09 16:42:21 -0800113
114 DCHECK(owner_.load(std::memory_order_relaxed) == nullptr);
115 owner_.store(self, std::memory_order_relaxed);
116 DCHECK_EQ(0u, count_);
117 count_ = 1;
118 }
119
David Sehrae3bcac2017-02-03 15:19:00 -0800120 bool MonitorExit(art::Thread* self) NO_THREAD_SAFETY_ANALYSIS {
Andreas Gampe319dbe82017-01-09 16:42:21 -0800121 if (!IsOwner(self)) {
122 return false;
123 }
124
125 --count_;
126 if (count_ == 0u) {
127 owner_.store(nullptr, std::memory_order_relaxed);
128 mutex_.unlock();
129 }
130
131 return true;
132 }
133
134 bool Wait(art::Thread* self) {
135 auto wait_without_timeout = [&](std::unique_lock<std::mutex>& lk) {
136 cond_.wait(lk);
137 };
138 return Wait(self, wait_without_timeout);
139 }
140
141 bool Wait(art::Thread* self, uint64_t timeout_in_ms) {
142 auto wait_with_timeout = [&](std::unique_lock<std::mutex>& lk) {
143 cond_.wait_for(lk, std::chrono::milliseconds(timeout_in_ms));
144 };
145 return Wait(self, wait_with_timeout);
146 }
147
148 bool Notify(art::Thread* self) {
149 return Notify(self, [&]() { cond_.notify_one(); });
150 }
151
152 bool NotifyAll(art::Thread* self) {
153 return Notify(self, [&]() { cond_.notify_all(); });
154 }
155
156 private:
Alex Light23aa7482017-08-16 10:01:13 -0700157 bool IsOwner(art::Thread* self) const {
Andreas Gampe319dbe82017-01-09 16:42:21 -0800158 // There's a subtle correctness argument here for a relaxed load outside the critical section.
159 // A thread is guaranteed to see either its own latest store or another thread's store. If a
160 // thread sees another thread's store than it cannot be holding the lock.
161 art::Thread* owner_thread = owner_.load(std::memory_order_relaxed);
162 return self == owner_thread;
163 }
164
165 template <typename T>
166 bool Wait(art::Thread* self, T how_to_wait) {
167 if (!IsOwner(self)) {
168 return false;
169 }
170
171 size_t old_count = count_;
Alex Light4d77daf2018-01-04 11:51:14 -0800172 DCHECK_GT(old_count, 0u);
Andreas Gampe319dbe82017-01-09 16:42:21 -0800173
174 count_ = 0;
175 owner_.store(nullptr, std::memory_order_relaxed);
176
177 {
178 std::unique_lock<std::mutex> lk(mutex_, std::adopt_lock);
179 how_to_wait(lk);
Alex Light4d77daf2018-01-04 11:51:14 -0800180 // Here we release the mutex. We will get it back below. We first need to do a suspend-check
181 // without holding it however. This is done in the MonitorEnter function.
182 // TODO We could do this more efficiently.
183 // We hold the mutex_ but the overall monitor is not owned at this point.
184 CHECK(owner_.load(std::memory_order_relaxed) == nullptr);
185 DCHECK_EQ(0u, count_);
Andreas Gampe319dbe82017-01-09 16:42:21 -0800186 }
187
Alex Light4d77daf2018-01-04 11:51:14 -0800188 // Reaquire the mutex/monitor, also go to sleep if we were suspended.
189 MonitorEnter(self);
190 CHECK(owner_.load(std::memory_order_relaxed) == self);
191 DCHECK_EQ(1u, count_);
192 // Reset the count.
Andreas Gampe319dbe82017-01-09 16:42:21 -0800193 count_ = old_count;
194
195 return true;
196 }
197
198 template <typename T>
199 bool Notify(art::Thread* self, T how_to_notify) {
200 if (!IsOwner(self)) {
201 return false;
202 }
203
204 how_to_notify();
205
206 return true;
207 }
208
209 std::mutex mutex_;
210 std::condition_variable cond_;
211 std::atomic<art::Thread*> owner_;
212 size_t count_;
213};
214
215static jrawMonitorID EncodeMonitor(JvmtiMonitor* monitor) {
216 return reinterpret_cast<jrawMonitorID>(monitor);
217}
218
219static JvmtiMonitor* DecodeMonitor(jrawMonitorID id) {
220 return reinterpret_cast<JvmtiMonitor*>(id);
221}
222
223jvmtiError MonitorUtil::CreateRawMonitor(jvmtiEnv* env ATTRIBUTE_UNUSED,
224 const char* name,
225 jrawMonitorID* monitor_ptr) {
226 if (name == nullptr || monitor_ptr == nullptr) {
227 return ERR(NULL_POINTER);
228 }
229
230 JvmtiMonitor* monitor = new JvmtiMonitor();
231 *monitor_ptr = EncodeMonitor(monitor);
232
233 return ERR(NONE);
234}
235
236jvmtiError MonitorUtil::DestroyRawMonitor(jvmtiEnv* env ATTRIBUTE_UNUSED, jrawMonitorID id) {
237 if (id == nullptr) {
238 return ERR(INVALID_MONITOR);
239 }
240
241 JvmtiMonitor* monitor = DecodeMonitor(id);
242 art::Thread* self = art::Thread::Current();
243
244 if (!JvmtiMonitor::Destroy(self, monitor)) {
245 return ERR(NOT_MONITOR_OWNER);
246 }
247
248 return ERR(NONE);
249}
250
251jvmtiError MonitorUtil::RawMonitorEnter(jvmtiEnv* env ATTRIBUTE_UNUSED, jrawMonitorID id) {
252 if (id == nullptr) {
253 return ERR(INVALID_MONITOR);
254 }
255
256 JvmtiMonitor* monitor = DecodeMonitor(id);
257 art::Thread* self = art::Thread::Current();
258
259 monitor->MonitorEnter(self);
260
261 return ERR(NONE);
262}
263
264jvmtiError MonitorUtil::RawMonitorExit(jvmtiEnv* env ATTRIBUTE_UNUSED, jrawMonitorID id) {
265 if (id == nullptr) {
266 return ERR(INVALID_MONITOR);
267 }
268
269 JvmtiMonitor* monitor = DecodeMonitor(id);
270 art::Thread* self = art::Thread::Current();
271
272 if (!monitor->MonitorExit(self)) {
273 return ERR(NOT_MONITOR_OWNER);
274 }
275
276 return ERR(NONE);
277}
278
279jvmtiError MonitorUtil::RawMonitorWait(jvmtiEnv* env ATTRIBUTE_UNUSED,
280 jrawMonitorID id,
281 jlong millis) {
282 if (id == nullptr) {
283 return ERR(INVALID_MONITOR);
284 }
285
286 JvmtiMonitor* monitor = DecodeMonitor(id);
287 art::Thread* self = art::Thread::Current();
288
Alex Light6ced0912017-08-16 15:16:13 -0700289 // What millis < 0 means is not defined in the spec. Real world agents seem to assume that it is a
290 // valid call though. We treat it as though it was 0 and wait indefinitely.
Andreas Gampe319dbe82017-01-09 16:42:21 -0800291 bool result = (millis > 0)
292 ? monitor->Wait(self, static_cast<uint64_t>(millis))
293 : monitor->Wait(self);
294
295 if (!result) {
296 return ERR(NOT_MONITOR_OWNER);
297 }
298
299 // TODO: Make sure that is really what we should be checking here.
300 if (self->IsInterrupted()) {
301 return ERR(INTERRUPT);
302 }
303
304 return ERR(NONE);
305}
306
307jvmtiError MonitorUtil::RawMonitorNotify(jvmtiEnv* env ATTRIBUTE_UNUSED, jrawMonitorID id) {
308 if (id == nullptr) {
309 return ERR(INVALID_MONITOR);
310 }
311
312 JvmtiMonitor* monitor = DecodeMonitor(id);
313 art::Thread* self = art::Thread::Current();
314
315 if (!monitor->Notify(self)) {
316 return ERR(NOT_MONITOR_OWNER);
317 }
318
319 return ERR(NONE);
320}
321
322jvmtiError MonitorUtil::RawMonitorNotifyAll(jvmtiEnv* env ATTRIBUTE_UNUSED, jrawMonitorID id) {
323 if (id == nullptr) {
324 return ERR(INVALID_MONITOR);
325 }
326
327 JvmtiMonitor* monitor = DecodeMonitor(id);
328 art::Thread* self = art::Thread::Current();
329
330 if (!monitor->NotifyAll(self)) {
331 return ERR(NOT_MONITOR_OWNER);
332 }
333
334 return ERR(NONE);
335}
336
Alex Light41006c62017-09-14 09:51:14 -0700337jvmtiError MonitorUtil::GetCurrentContendedMonitor(jvmtiEnv* env ATTRIBUTE_UNUSED,
338 jthread thread,
339 jobject* monitor) {
340 if (monitor == nullptr) {
341 return ERR(NULL_POINTER);
342 }
343 art::Thread* self = art::Thread::Current();
344 art::ScopedObjectAccess soa(self);
Alex Lightb1e31a82017-10-04 16:57:36 -0700345 art::Locks::thread_list_lock_->ExclusiveLock(self);
Alex Light7ddc23d2017-09-22 15:33:41 -0700346 art::Thread* target = nullptr;
347 jvmtiError err = ERR(INTERNAL);
348 if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) {
Alex Lightb1e31a82017-10-04 16:57:36 -0700349 art::Locks::thread_list_lock_->ExclusiveUnlock(self);
Alex Light7ddc23d2017-09-22 15:33:41 -0700350 return err;
Alex Light41006c62017-09-14 09:51:14 -0700351 }
352 struct GetContendedMonitorClosure : public art::Closure {
353 public:
354 explicit GetContendedMonitorClosure(art::Thread* current, jobject* out)
355 : result_thread_(current), out_(out) {}
356
357 void Run(art::Thread* target_thread) REQUIRES_SHARED(art::Locks::mutator_lock_) {
358 switch (target_thread->GetState()) {
359 // These three we are actually currently waiting on a monitor and have sent the appropriate
360 // events (if anyone is listening).
361 case art::kBlocked:
362 case art::kTimedWaiting:
363 case art::kWaiting: {
364 art::mirror::Object* mon = art::Monitor::GetContendedMonitor(target_thread);
365 *out_ = (mon == nullptr) ? nullptr
366 : result_thread_->GetJniEnv()->AddLocalReference<jobject>(mon);
367 return;
368 }
369 case art::kTerminated:
370 case art::kRunnable:
371 case art::kSleeping:
372 case art::kWaitingForLockInflation:
373 case art::kWaitingForTaskProcessor:
374 case art::kWaitingForGcToComplete:
375 case art::kWaitingForCheckPointsToRun:
376 case art::kWaitingPerformingGc:
377 case art::kWaitingForDebuggerSend:
378 case art::kWaitingForDebuggerToAttach:
379 case art::kWaitingInMainDebuggerLoop:
380 case art::kWaitingForDebuggerSuspension:
381 case art::kWaitingForJniOnLoad:
382 case art::kWaitingForSignalCatcherOutput:
383 case art::kWaitingInMainSignalCatcherLoop:
384 case art::kWaitingForDeoptimization:
385 case art::kWaitingForMethodTracingStart:
386 case art::kWaitingForVisitObjects:
387 case art::kWaitingForGetObjectsAllocated:
388 case art::kWaitingWeakGcRootRead:
389 case art::kWaitingForGcThreadFlip:
390 case art::kStarting:
391 case art::kNative:
392 case art::kSuspended: {
393 // We aren't currently (explicitly) waiting for a monitor anything so just return null.
394 *out_ = nullptr;
395 return;
396 }
397 }
398 }
399
400 private:
401 art::Thread* result_thread_;
402 jobject* out_;
403 };
404 GetContendedMonitorClosure closure(self, monitor);
Alex Lightb1e31a82017-10-04 16:57:36 -0700405 // RequestSynchronousCheckpoint releases the thread_list_lock_ as a part of its execution.
Alex Lightd9aff132017-10-31 22:30:05 +0000406 if (!ThreadUtil::RequestGCSafeSynchronousCheckpoint(target, &closure)) {
Alex Light7ddc23d2017-09-22 15:33:41 -0700407 return ERR(THREAD_NOT_ALIVE);
408 }
Alex Light41006c62017-09-14 09:51:14 -0700409 return OK;
410}
411
Andreas Gampe319dbe82017-01-09 16:42:21 -0800412} // namespace openjdkjvmti