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

Unified Diff: runtime/vm/safepoint.h

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/runtime_entry.h ('k') | runtime/vm/safepoint.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/safepoint.h
diff --git a/runtime/vm/safepoint.h b/runtime/vm/safepoint.h
new file mode 100644
index 0000000000000000000000000000000000000000..1c13a872f379371d8ea07cf0f64274b3df16b917
--- /dev/null
+++ b/runtime/vm/safepoint.h
@@ -0,0 +1,328 @@
+// 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.
+
+#ifndef VM_SAFEPOINT_H_
+#define VM_SAFEPOINT_H_
+
+#include "vm/globals.h"
+#include "vm/lockers.h"
+#include "vm/thread.h"
+
+namespace dart {
+
+// A stack based scope that can be used to perform an operation after getting
+// all threads to a safepoint. At the end of the operation all the threads are
+// resumed.
+class SafepointOperationScope : public StackResource {
+ public:
+ explicit SafepointOperationScope(Thread* T);
+ ~SafepointOperationScope();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SafepointOperationScope);
+};
+
+
+// Implements handling of safepoint operations for all threads in an Isolate.
+class SafepointHandler {
+ public:
+ explicit SafepointHandler(Isolate* I);
+ ~SafepointHandler();
+
+ void EnterSafepointUsingLock(Thread* T);
+ void ExitSafepointUsingLock(Thread* T);
+
+ void SafepointThreads(Thread* T);
+ void ResumeThreads(Thread* T);
+
+ void BlockForSafepoint(Thread* T);
+
+ private:
+ Isolate* isolate() const { return isolate_; }
+ Monitor* threads_lock() const { return isolate_->threads_lock(); }
+ bool safepoint_in_progress() const {
+ ASSERT(threads_lock()->IsOwnedByCurrentThread());
+ return safepoint_in_progress_;
+ }
+ void set_safepoint_in_progress(bool value) {
+ ASSERT(threads_lock()->IsOwnedByCurrentThread());
+ safepoint_in_progress_ = value;
+ }
+
+ Isolate* isolate_;
+
+ // Monitor used by thread initiating a safepoint operation to track threads
+ // not at a safepoint and wait for these threads to reach a safepoint.
+ Monitor* safepoint_lock_;
+ int32_t number_threads_not_at_safepoint_;
+
+ // Flag to indicate if a safepoint operation is currently in progress.
+ bool safepoint_in_progress_;
+
+ friend class Isolate;
+ friend class SafepointOperationScope;
+};
+
+
+/*
+ * Set of StackResource classes to track thread execution state transitions:
+ *
+ * kThreadInGenerated transitioning to
+ * ==> kThreadInVM:
+ * - set_execution_state(kThreadInVM).
+ * - block if safepoint is requested.
+ * ==> kThreadInNative:
+ * - set_execution_state(kThreadInNative).
+ * - EnterSafepoint().
+ * ==> kThreadInBlockedState:
+ * - Invalid transition
+ *
+ * kThreadInVM transitioning to
+ * ==> kThreadInGenerated
+ * - set_execution_state(kThreadInGenerated).
+ * ==> kThreadInNative
+ * - set_execution_state(kThreadInNative).
+ * - EnterSafepoint.
+ * ==> kThreadInBlockedState
+ * - set_execution_state(kThreadInBlockedState).
+ * - EnterSafepoint.
+ *
+ * kThreadInNative transitioning to
+ * ==> kThreadInGenerated
+ * - ExitSafepoint.
+ * - set_execution_state(kThreadInGenerated).
+ * ==> kThreadInVM
+ * - ExitSafepoint.
+ * - set_execution_state(kThreadInVM).
+ * ==> kThreadInBlocked
+ * - Invalid transition.
+ *
+ * kThreadInBlocked transitioning to
+ * ==> kThreadInVM
+ * - ExitSafepoint.
+ * - set_execution_state(kThreadInVM).
+ * ==> kThreadInNative
+ * - Invalid transition.
+ * ==> kThreadInGenerated
+ * - Invalid transition.
+ */
+class TransitionSafepointState : public StackResource {
+ public:
+ explicit TransitionSafepointState(Thread* T) : StackResource(T) {}
+ ~TransitionSafepointState() {}
+
+ SafepointHandler* handler() const {
+ ASSERT(thread()->isolate() != NULL);
+ ASSERT(thread()->isolate()->safepoint_handler() != NULL);
+ return thread()->isolate()->safepoint_handler();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TransitionSafepointState);
+};
+
+
+// TransitionGeneratedToVM is used to transition the safepoint state of a
+// thread from "running generated code" to "running vm code" and ensures
+// that the state is reverted back to "running generated code" when
+// exiting the scope/frame.
+class TransitionGeneratedToVM : public TransitionSafepointState {
+ public:
+ explicit TransitionGeneratedToVM(Thread* T) : TransitionSafepointState(T) {
+ ASSERT(T == Thread::Current());
+ ASSERT(T->execution_state() == Thread::kThreadInGenerated);
+ T->set_execution_state(Thread::kThreadInVM);
+ // Fast check to see if a safepoint is requested or not.
+ // We do the more expensive operation of blocking the thread
+ // only if a safepoint is requested.
+ if (T->IsSafepointRequested()) {
+ handler()->BlockForSafepoint(T);
+ }
+ }
+
+ ~TransitionGeneratedToVM() {
+ ASSERT(thread()->execution_state() == Thread::kThreadInVM);
+ thread()->set_execution_state(Thread::kThreadInGenerated);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TransitionGeneratedToVM);
+};
+
+
+// TransitionGeneratedToNative is used to transition the safepoint state of a
+// thread from "running generated code" to "running native code" and ensures
+// that the state is reverted back to "running generated code" when
+// exiting the scope/frame.
+class TransitionGeneratedToNative : public TransitionSafepointState {
+ public:
+ explicit TransitionGeneratedToNative(Thread* T)
+ : TransitionSafepointState(T) {
+ // Native code is considered to be at a safepoint and so we mark it
+ // accordingly.
+ ASSERT(T->execution_state() == Thread::kThreadInGenerated);
+ T->set_execution_state(Thread::kThreadInNative);
+ T->EnterSafepoint();
+ }
+
+ ~TransitionGeneratedToNative() {
+ // We are returning to generated code and so we are not at a safepoint
+ // anymore.
+ ASSERT(thread()->execution_state() == Thread::kThreadInNative);
+ thread()->ExitSafepoint();
+ thread()->set_execution_state(Thread::kThreadInGenerated);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TransitionGeneratedToNative);
+};
+
+
+// TransitionVMToBlocked is used to transition the safepoint state of a
+// thread from "running vm code" to "blocked on a monitor" and ensures
+// that the state is reverted back to "running vm code" when
+// exiting the scope/frame.
+class TransitionVMToBlocked : public TransitionSafepointState {
+ public:
+ explicit TransitionVMToBlocked(Thread* T) : TransitionSafepointState(T) {
+ // A thread blocked on a monitor is considered to be at a safepoint.
+ ASSERT(T->execution_state() == Thread::kThreadInVM);
+ T->set_execution_state(Thread::kThreadInBlockedState);
+ T->EnterSafepoint();
+ }
+
+ ~TransitionVMToBlocked() {
+ // We are returning to vm code and so we are not at a safepoint anymore.
+ ASSERT(thread()->execution_state() == Thread::kThreadInBlockedState);
+ thread()->ExitSafepoint();
+ thread()->set_execution_state(Thread::kThreadInVM);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TransitionVMToBlocked);
+};
+
+
+// TransitionVMToNative is used to transition the safepoint state of a
+// thread from "running vm code" to "running native code" and ensures
+// that the state is reverted back to "running vm code" when
+// exiting the scope/frame.
+class TransitionVMToNative : public TransitionSafepointState {
+ public:
+ explicit TransitionVMToNative(Thread* T) : TransitionSafepointState(T) {
+ // A thread running native code is considered to be at a safepoint.
+ ASSERT(T->execution_state() == Thread::kThreadInVM);
+ T->set_execution_state(Thread::kThreadInNative);
+ T->EnterSafepoint();
+ }
+
+ ~TransitionVMToNative() {
+ // We are returning to vm code and so we are not at a safepoint anymore.
+ ASSERT(thread()->execution_state() == Thread::kThreadInNative);
+ thread()->ExitSafepoint();
+ thread()->set_execution_state(Thread::kThreadInVM);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TransitionVMToNative);
+};
+
+
+// TransitionVMToGenerated is used to transition the safepoint state of a
+// thread from "running vm code" to "running generated code" and ensures
+// that the state is reverted back to "running vm code" when
+// exiting the scope/frame.
+class TransitionVMToGenerated : public TransitionSafepointState {
+ public:
+ explicit TransitionVMToGenerated(Thread* T) : TransitionSafepointState(T) {
+ ASSERT(T == Thread::Current());
+ ASSERT(T->execution_state() == Thread::kThreadInVM);
+ T->set_execution_state(Thread::kThreadInGenerated);
+ }
+
+ ~TransitionVMToGenerated() {
+ ASSERT(thread()->execution_state() == Thread::kThreadInGenerated);
+ thread()->set_execution_state(Thread::kThreadInVM);
+ // Fast check to see if a safepoint is requested or not.
+ // We do the more expensive operation of blocking the thread
+ // only if a safepoint is requested.
+ if (thread()->IsSafepointRequested()) {
+ handler()->BlockForSafepoint(thread());
+ }
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TransitionVMToGenerated);
+};
+
+
+// TransitionNativeToVM is used to transition the safepoint state of a
+// thread from "running native code" to "running vm code" and ensures
+// that the state is reverted back to "running native code" when
+// exiting the scope/frame.
+class TransitionNativeToVM : public TransitionSafepointState {
+ public:
+ explicit TransitionNativeToVM(Thread* T) : TransitionSafepointState(T) {
+ // We are about to execute vm code and so we are not at a safepoint anymore.
+ ASSERT(T->execution_state() == Thread::kThreadInNative);
+ T->ExitSafepoint();
+ T->set_execution_state(Thread::kThreadInVM);
+ }
+
+ ~TransitionNativeToVM() {
+ // We are returning to native code and so we are at a safepoint.
+ ASSERT(thread()->execution_state() == Thread::kThreadInVM);
+ thread()->set_execution_state(Thread::kThreadInNative);
+ thread()->EnterSafepoint();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TransitionNativeToVM);
+};
+
+
+// TransitionToGenerated is used to transition the safepoint state of a
+// thread from "running vm code" or "running native code" to
+// "running generated code" and ensures that the state is reverted back
+// to "running vm code" or "running native code" when exiting the
+// scope/frame.
+class TransitionToGenerated : public TransitionSafepointState {
+ public:
+ explicit TransitionToGenerated(Thread* T)
+ : TransitionSafepointState(T),
+ execution_state_(T->execution_state()) {
+ ASSERT(T == Thread::Current());
+ ASSERT((execution_state_ == Thread::kThreadInVM) ||
+ (execution_state_ == Thread::kThreadInNative));
+ if (execution_state_ == Thread::kThreadInNative) {
+ T->ExitSafepoint();
+ }
+ T->set_execution_state(Thread::kThreadInGenerated);
+ }
+
+ ~TransitionToGenerated() {
+ ASSERT(thread()->execution_state() == Thread::kThreadInGenerated);
+ if (execution_state_ == Thread::kThreadInNative) {
+ thread()->set_execution_state(Thread::kThreadInNative);
+ thread()->EnterSafepoint();
+ } else {
+ ASSERT(execution_state_ == Thread::kThreadInVM);
+ thread()->set_execution_state(Thread::kThreadInVM);
+ // Fast check to see if a safepoint is requested or not.
+ // We do the more expensive operation of blocking the thread
+ // only if a safepoint is requested.
+ if (thread()->IsSafepointRequested()) {
+ handler()->BlockForSafepoint(thread());
+ }
+ }
+ }
+
+ private:
+ int16_t execution_state_;
+ DISALLOW_COPY_AND_ASSIGN(TransitionToGenerated);
+};
+
+} // namespace dart
+
+#endif // VM_SAFEPOINT_H_
« no previous file with comments | « runtime/vm/runtime_entry.h ('k') | runtime/vm/safepoint.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698