| Index: runtime/vm/safepoint.cc | 
| diff --git a/runtime/vm/safepoint.cc b/runtime/vm/safepoint.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..47ef2576ef6b6b9ff277887e7f72d61f2d046363 | 
| --- /dev/null | 
| +++ b/runtime/vm/safepoint.cc | 
| @@ -0,0 +1,174 @@ | 
| +// 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/safepoint.h" | 
| + | 
| +#include "vm/thread.h" | 
| +#include "vm/thread_registry.h" | 
| + | 
| +namespace dart { | 
| + | 
| +SafepointOperationScope::SafepointOperationScope(Thread* T) : StackResource(T) { | 
| +  ASSERT(T != NULL); | 
| +  Isolate* I = T->isolate(); | 
| +  ASSERT(I != NULL); | 
| +  ASSERT(T->no_safepoint_scope_depth() == 0); | 
| + | 
| +  SafepointHandler* handler = I->safepoint_handler(); | 
| +  ASSERT(handler != NULL); | 
| + | 
| +  // Signal all threads to get to a safepoint and wait for them to | 
| +  // get to a safepoint. | 
| +  handler->SafepointThreads(T); | 
| +} | 
| + | 
| + | 
| +SafepointOperationScope::~SafepointOperationScope() { | 
| +  Thread* T = thread(); | 
| +  ASSERT(T != NULL); | 
| +  Isolate* I = T->isolate(); | 
| +  ASSERT(I != NULL); | 
| + | 
| +  // Resume all threads which are blocked for the safepoint operation. | 
| +  SafepointHandler* handler = I->safepoint_handler(); | 
| +  ASSERT(handler != NULL); | 
| +  handler->ResumeThreads(T); | 
| +} | 
| + | 
| + | 
| +SafepointHandler::SafepointHandler(Isolate* isolate) | 
| +    : isolate_(isolate), | 
| +      safepoint_lock_(new Monitor()), | 
| +      number_threads_not_at_safepoint_(0), | 
| +      safepoint_in_progress_(false) { | 
| +} | 
| + | 
| + | 
| +SafepointHandler::~SafepointHandler() { | 
| +  ASSERT(safepoint_in_progress_ == false); | 
| +  delete safepoint_lock_; | 
| +  safepoint_lock_ = NULL; | 
| +  isolate_ = NULL; | 
| +} | 
| + | 
| + | 
| +void SafepointHandler::SafepointThreads(Thread* T) { | 
| +  { | 
| +    // First grab the threads list lock for this isolate | 
| +    // and check if a safepoint is already in progress. This | 
| +    // ensures that two threads do not start a safepoint operation | 
| +    // at the same time. | 
| +    MonitorLocker sl(threads_lock()); | 
| + | 
| +    // Now check to see if a safepoint operation is already in progress | 
| +    // for this isolate, block if an operation is in progress. | 
| +    while (safepoint_in_progress()) { | 
| +      sl.WaitWithSafepointCheck(T); | 
| +    } | 
| + | 
| +    // Set safepoint in progress by this thread. | 
| +    set_safepoint_in_progress(true); | 
| + | 
| +    // Go over the active thread list and ensure that all threads active | 
| +    // in the isolate reach a safepoint. | 
| +    Thread* current = isolate()->thread_registry()->active_list(); | 
| +    while (current != NULL) { | 
| +      MonitorLocker tl(current->thread_lock()); | 
| +      if (current != T) { | 
| +        uint32_t state = current->SetSafepointRequested(true); | 
| +        if (!Thread::IsAtSafepoint(state)) { | 
| +          // Thread is not already at a safepoint so try to | 
| +          // get it to a safepoint and wait for it to check in. | 
| +          if (current->IsMutatorThread()) { | 
| +            ASSERT(T->isolate() != NULL); | 
| +            T->isolate()->ScheduleInterrupts(Isolate::kVMInterrupt); | 
| +          } | 
| +          MonitorLocker sl(safepoint_lock_); | 
| +          ++number_threads_not_at_safepoint_; | 
| +        } | 
| +      } else { | 
| +        current->SetAtSafepoint(true); | 
| +      } | 
| +      current = current->next(); | 
| +    } | 
| +  } | 
| +  // Now wait for all threads that are not already at a safepoint to check-in. | 
| +  { | 
| +    MonitorLocker sl(safepoint_lock_); | 
| +    while (number_threads_not_at_safepoint_ > 0) { | 
| +      sl.Wait(); | 
| +    } | 
| +  } | 
| +} | 
| + | 
| + | 
| +void SafepointHandler::ResumeThreads(Thread* T) { | 
| +  // First resume all the threads which are blocked for the safepoint | 
| +  // operation. | 
| +  MonitorLocker sl(threads_lock()); | 
| +  Thread* current = isolate()->thread_registry()->active_list(); | 
| +  while (current != NULL) { | 
| +    MonitorLocker tl(current->thread_lock()); | 
| +    if (current != T) { | 
| +      uint32_t state = current->SetSafepointRequested(false); | 
| +      if (Thread::IsBlockedForSafepoint(state)) { | 
| +        tl.Notify(); | 
| +      } | 
| +    } else { | 
| +      current->SetAtSafepoint(false); | 
| +    } | 
| +    current = current->next(); | 
| +  } | 
| +  // Now set the safepoint_in_progress_ flag to false and notify all threads | 
| +  // that are waiting to enter the isolate or waiting to start another | 
| +  // safepoint operation. | 
| +  set_safepoint_in_progress(false); | 
| +  sl.NotifyAll(); | 
| +} | 
| + | 
| + | 
| +void SafepointHandler::EnterSafepointUsingLock(Thread* T) { | 
| +  MonitorLocker tl(T->thread_lock()); | 
| +  T->SetAtSafepoint(true); | 
| +  if (T->IsSafepointRequested()) { | 
| +    MonitorLocker sl(safepoint_lock_); | 
| +    ASSERT(number_threads_not_at_safepoint_ > 0); | 
| +    number_threads_not_at_safepoint_ -= 1; | 
| +    sl.Notify(); | 
| +  } | 
| +} | 
| + | 
| + | 
| +void SafepointHandler::ExitSafepointUsingLock(Thread* T) { | 
| +  MonitorLocker tl(T->thread_lock()); | 
| +  ASSERT(T->IsAtSafepoint()); | 
| +  while (T->IsSafepointRequested()) { | 
| +    T->SetBlockedForSafepoint(true); | 
| +    tl.Wait(); | 
| +    T->SetBlockedForSafepoint(false); | 
| +  } | 
| +  T->SetAtSafepoint(false); | 
| +} | 
| + | 
| + | 
| +void SafepointHandler::BlockForSafepoint(Thread* T) { | 
| +  MonitorLocker tl(T->thread_lock()); | 
| +  if (T->IsSafepointRequested()) { | 
| +    T->SetAtSafepoint(true); | 
| +    { | 
| +      MonitorLocker sl(safepoint_lock_); | 
| +      ASSERT(number_threads_not_at_safepoint_ > 0); | 
| +      number_threads_not_at_safepoint_ -= 1; | 
| +      sl.Notify(); | 
| +    } | 
| +    while (T->IsSafepointRequested()) { | 
| +      T->SetBlockedForSafepoint(true); | 
| +      tl.Wait(); | 
| +      T->SetBlockedForSafepoint(false); | 
| +    } | 
| +    T->SetAtSafepoint(false); | 
| +  } | 
| +} | 
| + | 
| +}  // namespace dart | 
|  |