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

Unified Diff: runtime/vm/thread.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/stack_frame_test.cc ('k') | runtime/vm/thread.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/thread.h
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index ad073afba47f266280bd45b41e6c2738ab110206..2f1b4dff014ca3495615400ff215f69fc1fe7084 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -6,6 +6,9 @@
#define VM_THREAD_H_
#include "include/dart_api.h"
+#include "platform/assert.h"
+#include "vm/atomic.h"
+#include "vm/bitfield.h"
#include "vm/globals.h"
#include "vm/handles.h"
#include "vm/os_thread.h"
@@ -143,6 +146,9 @@ class Thread : public BaseThread {
os_thread_ = os_thread;
}
+ // Monitor corresponding to this thread.
+ Monitor* thread_lock() const { return thread_lock_; }
+
// The topmost zone used for allocation in this thread.
Zone* zone() const { return zone_; }
@@ -209,7 +215,9 @@ class Thread : public BaseThread {
return OFFSET_OF(Thread, store_buffer_block_);
}
- uword top_exit_frame_info() const { return top_exit_frame_info_; }
+ uword top_exit_frame_info() const {
+ return top_exit_frame_info_;
+ }
static intptr_t top_exit_frame_info_offset() {
return OFFSET_OF(Thread, top_exit_frame_info_);
}
@@ -356,6 +364,8 @@ LEAF_RUNTIME_ENTRY_LIST(DEFINE_OFFSET_METHOD)
return OFFSET_OF(Thread, vm_tag_);
}
+ RawGrowableObjectArray* pending_functions();
+
#if defined(DEBUG)
#define REUSABLE_HANDLE_SCOPE_ACCESSORS(object) \
void set_reusable_##object##_handle_scope_active(bool value) { \
@@ -385,7 +395,120 @@ LEAF_RUNTIME_ENTRY_LIST(DEFINE_OFFSET_METHOD)
REUSABLE_HANDLE_LIST(REUSABLE_HANDLE)
#undef REUSABLE_HANDLE
- RawGrowableObjectArray* pending_functions();
+ /*
+ * Fields used to support safepointing a thread.
+ *
+ * - Bit 0 of the safepoint_state_ field is used to indicate if the thread is
+ * already at a safepoint,
+ * - Bit 1 of the safepoint_state_ field is used to indicate if a safepoint
+ * operation is requested for this thread.
+ * - Bit 2 of the safepoint_state_ field is used to indicate that the thread
+ * is blocked for the safepoint operation to complete.
+ *
+ * The safepoint execution state (described above) for a thread is stored in
+ * in the execution_state_ field.
+ * Potential execution states a thread could be in:
+ * kThreadInGenerated - The thread is running jitted dart/stub code.
+ * kThreadInVM - The thread is running VM code.
+ * kThreadInNative - The thread is running native code.
+ * kThreadInBlockedState - The thread is blocked waiting for a resource.
+ */
+ static intptr_t safepoint_state_offset() {
+ return OFFSET_OF(Thread, safepoint_state_);
+ }
+ static bool IsAtSafepoint(uint32_t state) {
+ return AtSafepointField::decode(state);
+ }
+ bool IsAtSafepoint() const {
+ return AtSafepointField::decode(safepoint_state_);
+ }
+ static uint32_t SetAtSafepoint(bool value, uint32_t state) {
+ return AtSafepointField::update(value, state);
+ }
+ void SetAtSafepoint(bool value) {
+ ASSERT(thread_lock()->IsOwnedByCurrentThread());
+ safepoint_state_ = AtSafepointField::update(value, safepoint_state_);
+ }
+ bool IsSafepointRequested() const {
+ return SafepointRequestedField::decode(safepoint_state_);
+ }
+ static uint32_t SetSafepointRequested(bool value, uint32_t state) {
+ return SafepointRequestedField::update(value, state);
+ }
+ uint32_t SetSafepointRequested(bool value) {
+ ASSERT(thread_lock()->IsOwnedByCurrentThread());
+ uint32_t old_state;
+ uint32_t new_state;
+ do {
+ old_state = safepoint_state_;
+ new_state = SafepointRequestedField::update(value, old_state);
+ } while (AtomicOperations::CompareAndSwapUint32(&safepoint_state_,
+ old_state,
+ new_state) != old_state);
+ return old_state;
+ }
+ static bool IsBlockedForSafepoint(uint32_t state) {
+ return BlockedForSafepointField::decode(state);
+ }
+ bool IsBlockedForSafepoint() const {
+ return BlockedForSafepointField::decode(safepoint_state_);
+ }
+ void SetBlockedForSafepoint(bool value) {
+ ASSERT(thread_lock()->IsOwnedByCurrentThread());
+ safepoint_state_ =
+ BlockedForSafepointField::update(value, safepoint_state_);
+ }
+
+ enum ExecutionState {
+ kThreadInVM = 0,
+ kThreadInGenerated,
+ kThreadInNative,
+ kThreadInBlockedState
+ };
+
+ ExecutionState execution_state() const {
+ return static_cast<ExecutionState>(execution_state_);
+ }
+ void set_execution_state(ExecutionState state) {
+ execution_state_ = static_cast<uint32_t>(state);
+ }
+ static intptr_t execution_state_offset() {
+ return OFFSET_OF(Thread, execution_state_);
+ }
+
+ void EnterSafepoint() {
+ // First try a fast update of the thread state to indicate it is at a
+ // safepoint.
+ uint32_t new_state = SetAtSafepoint(true, 0);
+ uword addr = reinterpret_cast<uword>(this) + safepoint_state_offset();
+ if (AtomicOperations::CompareAndSwapUint32(
+ reinterpret_cast<uint32_t*>(addr), 0, new_state) != 0) {
+ // Fast update failed which means we could potentially be in the middle
+ // of a safepoint operation.
+ EnterSafepointUsingLock();
+ }
+ }
+
+ void ExitSafepoint() {
+ // First try a fast update of the thread state to indicate it is not at a
+ // safepoint anymore.
+ uint32_t old_state = SetAtSafepoint(true, 0);
+ uword addr = reinterpret_cast<uword>(this) + safepoint_state_offset();
+ if (AtomicOperations::CompareAndSwapUint32(
+ reinterpret_cast<uint32_t*>(addr), old_state, 0) != old_state) {
+ // Fast update failed which means we could potentially be in the middle
+ // of a safepoint operation.
+ ExitSafepointUsingLock();
+ }
+ }
+
+ void CheckForSafepoint() {
+ if (IsSafepointRequested()) {
+ BlockForSafepoint();
+ }
+ }
+
+ Thread* next() const { return next_; }
// Visit all object pointers.
void VisitObjectPointers(ObjectPointerVisitor* visitor);
@@ -401,6 +524,7 @@ LEAF_RUNTIME_ENTRY_LIST(DEFINE_OFFSET_METHOD)
template<class T> T* AllocateReusableHandle();
OSThread* os_thread_;
+ Monitor* thread_lock_;
Isolate* isolate_;
Heap* heap_;
Zone* zone_;
@@ -453,6 +577,12 @@ LEAF_RUNTIME_ENTRY_LIST(DECLARE_MEMBERS)
#undef REUSABLE_HANDLE_SCOPE_VARIABLE
#endif // defined(DEBUG)
+ class AtSafepointField : public BitField<bool, 0, 1> {};
+ class SafepointRequestedField : public BitField<bool, 1, 1> {};
+ class BlockedForSafepointField : public BitField<bool, 2, 1> {};
+ uint32_t safepoint_state_;
+ uint32_t execution_state_;
+
Thread* next_; // Used to chain the thread structures in an isolate.
explicit Thread(Isolate* isolate);
@@ -469,6 +599,13 @@ LEAF_RUNTIME_ENTRY_LIST(DECLARE_MEMBERS)
top_exit_frame_info_ = top_exit_frame_info;
}
+ void set_safepoint_state(uint32_t value) {
+ safepoint_state_ = value;
+ }
+ void EnterSafepointUsingLock();
+ void ExitSafepointUsingLock();
+ void BlockForSafepoint();
+
static void SetCurrent(Thread* current) {
OSThread::SetCurrentTLS(reinterpret_cast<uword>(current));
}
« no previous file with comments | « runtime/vm/stack_frame_test.cc ('k') | runtime/vm/thread.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698