1// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/lockers.h"
6#include "platform/assert.h"
7#include "vm/heap/safepoint.h"
8#include "vm/isolate.h"
9
10namespace dart {
11
12Monitor::WaitResult MonitorLocker::WaitWithSafepointCheck(Thread* thread,
13 int64_t millis) {
14 ASSERT(thread == Thread::Current());
15 ASSERT(thread->execution_state() == Thread::kThreadInVM);
16#if defined(DEBUG)
17 if (no_safepoint_scope_) {
18 thread->DecrementNoSafepointScopeDepth();
19 }
20#endif
21 thread->set_execution_state(Thread::kThreadInBlockedState);
22 thread->EnterSafepoint();
23 Monitor::WaitResult result = monitor_->Wait(millis);
24 // First try a fast update of the thread state to indicate it is not at a
25 // safepoint anymore.
26 if (!thread->TryExitSafepoint()) {
27 // Fast update failed which means we could potentially be in the middle
28 // of a safepoint operation and need to block for it.
29 monitor_->Exit();
30 SafepointHandler* handler = thread->isolate_group()->safepoint_handler();
31 handler->ExitSafepointUsingLock(thread);
32 monitor_->Enter();
33 }
34 thread->set_execution_state(Thread::kThreadInVM);
35#if defined(DEBUG)
36 if (no_safepoint_scope_) {
37 thread->IncrementNoSafepointScopeDepth();
38 }
39#endif
40 return result;
41}
42
43SafepointMutexLocker::SafepointMutexLocker(Mutex* mutex) : mutex_(mutex) {
44 ASSERT(mutex != NULL);
45 if (!mutex_->TryLock()) {
46 // We did not get the lock and could potentially block, so transition
47 // accordingly.
48 Thread* thread = Thread::Current();
49 if (thread != NULL) {
50 TransitionVMToBlocked transition(thread);
51 mutex->Lock();
52 } else {
53 mutex->Lock();
54 }
55 }
56}
57
58SafepointMonitorLocker::SafepointMonitorLocker(Monitor* monitor)
59 : monitor_(monitor) {
60 ASSERT(monitor_ != NULL);
61 if (!monitor_->TryEnter()) {
62 // We did not get the lock and could potentially block, so transition
63 // accordingly.
64 Thread* thread = Thread::Current();
65 if (thread != NULL) {
66 TransitionVMToBlocked transition(thread);
67 monitor_->Enter();
68 } else {
69 monitor_->Enter();
70 }
71 }
72}
73
74Monitor::WaitResult SafepointMonitorLocker::Wait(int64_t millis) {
75 Thread* thread = Thread::Current();
76 if (thread != NULL) {
77 Monitor::WaitResult result;
78 {
79 TransitionVMToBlocked transition(thread);
80 result = monitor_->Wait(millis);
81 }
82 return result;
83 } else {
84 return monitor_->Wait(millis);
85 }
86}
87
88} // namespace dart
89