diff options
Diffstat (limited to 'runtime/thread.cc')
-rw-r--r-- | runtime/thread.cc | 48 |
1 files changed, 19 insertions, 29 deletions
diff --git a/runtime/thread.cc b/runtime/thread.cc index 47ffb4e13f..83ebe9931d 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -1346,36 +1346,26 @@ void Thread::ClearSuspendBarrier(AtomicInteger* target) { } void Thread::RunCheckpointFunction() { - bool done = false; - do { - // Grab the suspend_count lock and copy the checkpoints one by one. When the last checkpoint is - // copied, clear the list and the flag. The RequestCheckpoint function will also grab this lock - // to prevent a race between setting the kCheckpointRequest flag and clearing it. - Closure* checkpoint = nullptr; - { - MutexLock mu(this, *Locks::thread_suspend_count_lock_); - if (tlsPtr_.checkpoint_function != nullptr) { - checkpoint = tlsPtr_.checkpoint_function; - if (!checkpoint_overflow_.empty()) { - // Overflow list not empty, copy the first one out and continue. - tlsPtr_.checkpoint_function = checkpoint_overflow_.front(); - checkpoint_overflow_.pop_front(); - } else { - // No overflow checkpoints, this means that we are on the last pending checkpoint. - tlsPtr_.checkpoint_function = nullptr; - AtomicClearFlag(kCheckpointRequest); - done = true; - } - } else { - LOG(FATAL) << "Checkpoint flag set without pending checkpoint"; - } + // Grab the suspend_count lock, get the next checkpoint and update all the checkpoint fields. If + // there are no more checkpoints we will also clear the kCheckpointRequest flag. + Closure* checkpoint; + { + MutexLock mu(this, *Locks::thread_suspend_count_lock_); + checkpoint = tlsPtr_.checkpoint_function; + if (!checkpoint_overflow_.empty()) { + // Overflow list not empty, copy the first one out and continue. + tlsPtr_.checkpoint_function = checkpoint_overflow_.front(); + checkpoint_overflow_.pop_front(); + } else { + // No overflow checkpoints. Clear the kCheckpointRequest flag + tlsPtr_.checkpoint_function = nullptr; + AtomicClearFlag(kCheckpointRequest); } - - // Outside the lock, run the checkpoint functions that we collected. - ScopedTrace trace("Run checkpoint function"); - DCHECK(checkpoint != nullptr); - checkpoint->Run(this); - } while (!done); + } + // Outside the lock, run the checkpoint function. + ScopedTrace trace("Run checkpoint function"); + CHECK(checkpoint != nullptr) << "Checkpoint flag set without pending checkpoint"; + checkpoint->Run(this); } void Thread::RunEmptyCheckpoint() { |