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 | |
10 | namespace dart { |
11 | |
12 | Monitor::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 | |
43 | SafepointMutexLocker::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 | |
58 | SafepointMonitorLocker::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 | |
74 | Monitor::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 |