Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(502)

Unified Diff: runtime/vm/safepoint.cc

Issue 1541073002: Implement safepointing of threads (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: fix-typo Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/safepoint.h ('k') | runtime/vm/scavenger.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « runtime/vm/safepoint.h ('k') | runtime/vm/scavenger.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698