| // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| #include "vm/lockers.h" |
| #include "platform/assert.h" |
| #include "vm/heap/safepoint.h" |
| |
| namespace dart { |
| |
| Monitor::WaitResult MonitorLocker::WaitWithSafepointCheck(Thread* thread, |
| int64_t millis) { |
| ASSERT(thread == Thread::Current()); |
| ASSERT(thread->execution_state() == Thread::kThreadInVM); |
| thread->set_execution_state(Thread::kThreadInBlockedState); |
| thread->EnterSafepoint(); |
| Monitor::WaitResult result = monitor_->Wait(millis); |
| // First try a fast update of the thread state to indicate it is not at a |
| // safepoint anymore. |
| if (!thread->TryExitSafepoint()) { |
| // Fast update failed which means we could potentially be in the middle |
| // of a safepoint operation and need to block for it. |
| monitor_->Exit(); |
| SafepointHandler* handler = thread->isolate()->safepoint_handler(); |
| handler->ExitSafepointUsingLock(thread); |
| monitor_->Enter(); |
| } |
| thread->set_execution_state(Thread::kThreadInVM); |
| return result; |
| } |
| |
| SafepointMutexLocker::SafepointMutexLocker(Mutex* mutex) : mutex_(mutex) { |
| ASSERT(mutex != NULL); |
| if (!mutex_->TryLock()) { |
| // We did not get the lock and could potentially block, so transition |
| // accordingly. |
| Thread* thread = Thread::Current(); |
| if (thread != NULL) { |
| thread->set_execution_state(Thread::kThreadInBlockedState); |
| thread->EnterSafepoint(); |
| mutex->Lock(); |
| // Update thread state and block if a safepoint operation is in progress. |
| thread->ExitSafepoint(); |
| thread->set_execution_state(Thread::kThreadInVM); |
| } else { |
| mutex->Lock(); |
| } |
| } |
| } |
| |
| SafepointMonitorLocker::SafepointMonitorLocker(Monitor* monitor) |
| : monitor_(monitor) { |
| ASSERT(monitor_ != NULL); |
| if (!monitor_->TryEnter()) { |
| // We did not get the lock and could potentially block, so transition |
| // accordingly. |
| Thread* thread = Thread::Current(); |
| if (thread != NULL) { |
| thread->set_execution_state(Thread::kThreadInBlockedState); |
| thread->EnterSafepoint(); |
| monitor_->Enter(); |
| // Update thread state and block if a safepoint operation is in progress. |
| thread->ExitSafepoint(); |
| thread->set_execution_state(Thread::kThreadInVM); |
| } else { |
| monitor_->Enter(); |
| } |
| } |
| } |
| |
| Monitor::WaitResult SafepointMonitorLocker::Wait(int64_t millis) { |
| Thread* thread = Thread::Current(); |
| if (thread != NULL) { |
| thread->set_execution_state(Thread::kThreadInBlockedState); |
| thread->EnterSafepoint(); |
| Monitor::WaitResult result = monitor_->Wait(millis); |
| // First try a fast update of the thread state to indicate it is not at a |
| // safepoint anymore. |
| if (!thread->TryExitSafepoint()) { |
| // Fast update failed which means we could potentially be in the middle |
| // of a safepoint operation and need to block for it. |
| monitor_->Exit(); |
| SafepointHandler* handler = thread->isolate()->safepoint_handler(); |
| handler->ExitSafepointUsingLock(thread); |
| monitor_->Enter(); |
| } |
| thread->set_execution_state(Thread::kThreadInVM); |
| return result; |
| } else { |
| return monitor_->Wait(millis); |
| } |
| } |
| |
| } // namespace dart |