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

Side by Side Diff: runtime/vm/thread_registry.h

Issue 1259223005: Safepoint interface and unit tests. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Ready for review. Created 5 years, 4 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #ifndef VM_THREAD_REGISTRY_H_ 5 #ifndef VM_THREAD_REGISTRY_H_
6 #define VM_THREAD_REGISTRY_H_ 6 #define VM_THREAD_REGISTRY_H_
7 7
8 #include "vm/globals.h" 8 #include "vm/globals.h"
9 #include "vm/growable_array.h" 9 #include "vm/growable_array.h"
10 #include "vm/isolate.h" 10 #include "vm/isolate.h"
11 #include "vm/lockers.h" 11 #include "vm/lockers.h"
12 #include "vm/thread.h" 12 #include "vm/thread.h"
13 13
14 namespace dart { 14 namespace dart {
15 15
16 // Unordered collection of threads relating to a particular isolate. 16 // Unordered collection of threads relating to a particular isolate.
17 class ThreadRegistry { 17 class ThreadRegistry {
18 public: 18 public:
19 ThreadRegistry() : mutex_(new Mutex()), entries_() {} 19 ThreadRegistry()
20 : monitor_(new Monitor()),
21 entries_(),
22 in_rendezvous_(false),
23 remaining_(0),
24 round_(0) {}
25
26 // Bring all threads in this isolate, except the caller, to a safepoint. The
Ivan Posva 2015/07/31 20:28:09 Please add a comment that the caller is expected t
koda 2015/07/31 22:40:44 Done.
27 // threads will wait until ResumeAllThreads is called. Must be called at a
28 // safepoint, since it first waits for any already pending requests. Any
29 // thread that tries to enter/exit this isolate during rendezvous will wait
30 // in RestoreStateTo/SaveStateFrom, respectively.
31 void SafepointAllThreads();
Ivan Posva 2015/07/31 20:28:09 Isn't the All redundant here?
koda 2015/07/31 22:40:44 Done.
32
33 // Unblocks all threads participating in the rendezvous that was organized
34 // by a prior call to SafepointAllThreads.
35 // TODO(koda): Consider adding a scope helper to avoid omitting this call.
36 void ResumeAllThreads();
37
38 // Indicate that the current thread is at a safepoint, and offer to wait for
39 // any pending rendezvous request (if none, returns immediately).
40 void CheckSafepoint() {
41 MonitorLocker ml(monitor_);
42 CheckSafepointLocked();
43 }
20 44
21 bool RestoreStateTo(Thread* thread, Thread::State* state) { 45 bool RestoreStateTo(Thread* thread, Thread::State* state) {
22 MutexLocker ml(mutex_); 46 MonitorLocker ml(monitor_);
47 // Wait for any rendezvous in progress.
48 while (in_rendezvous_) {
49 ml.Wait(Monitor::kNoTimeout);
50 }
23 Entry* entry = FindEntry(thread); 51 Entry* entry = FindEntry(thread);
24 if (entry != NULL) { 52 if (entry != NULL) {
25 Thread::State st = entry->state; 53 Thread::State st = entry->state;
26 // TODO(koda): Support same thread re-entering same isolate with 54 // TODO(koda): Support same thread re-entering same isolate with
27 // Dart frames in between. For now, just assert it doesn't happen. 55 // Dart frames in between. For now, just assert it doesn't happen.
28 if (st.top_exit_frame_info != thread->top_exit_frame_info()) { 56 if (st.top_exit_frame_info != thread->top_exit_frame_info()) {
29 ASSERT(thread->top_exit_frame_info() == 0 || 57 ASSERT(thread->top_exit_frame_info() == 0 ||
30 thread->top_exit_frame_info() > st.top_exit_frame_info); 58 thread->top_exit_frame_info() > st.top_exit_frame_info);
31 } 59 }
32 ASSERT(!entry->scheduled); 60 ASSERT(!entry->scheduled);
(...skipping 10 matching lines...) Expand all
43 new_entry.scheduled = true; 71 new_entry.scheduled = true;
44 #if defined(DEBUG) 72 #if defined(DEBUG)
45 // State field is not in use, so zap it. 73 // State field is not in use, so zap it.
46 memset(&new_entry.state, 0xda, sizeof(new_entry.state)); 74 memset(&new_entry.state, 0xda, sizeof(new_entry.state));
47 #endif 75 #endif
48 entries_.Add(new_entry); 76 entries_.Add(new_entry);
49 return false; 77 return false;
50 } 78 }
51 79
52 void SaveStateFrom(Thread* thread, const Thread::State& state) { 80 void SaveStateFrom(Thread* thread, const Thread::State& state) {
53 MutexLocker ml(mutex_); 81 MonitorLocker ml(monitor_);
82 // Exiting an isolate must always be a safepoint.
Ivan Posva 2015/07/31 20:28:09 As already discussed I strongly disagree with this
koda 2015/07/31 22:40:44 You convinced me that this should change in a futu
83 CheckSafepointLocked();
54 Entry* entry = FindEntry(thread); 84 Entry* entry = FindEntry(thread);
55 ASSERT(entry != NULL); 85 ASSERT(entry != NULL);
56 ASSERT(entry->scheduled); 86 ASSERT(entry->scheduled);
57 entry->scheduled = false; 87 entry->scheduled = false;
58 entry->state = state; 88 entry->state = state;
59 } 89 }
60 90
61 bool Contains(Thread* thread) { 91 bool Contains(Thread* thread) {
62 MutexLocker ml(mutex_); 92 MonitorLocker ml(monitor_);
63 return (FindEntry(thread) != NULL); 93 return (FindEntry(thread) != NULL);
64 } 94 }
65 95
66 void CheckNotScheduled(Isolate* isolate) { 96 void CheckNotScheduled(Isolate* isolate) {
67 MutexLocker ml(mutex_); 97 MonitorLocker ml(monitor_);
68 for (int i = 0; i < entries_.length(); ++i) { 98 for (int i = 0; i < entries_.length(); ++i) {
69 const Entry& entry = entries_[i]; 99 const Entry& entry = entries_[i];
70 if (entry.scheduled) { 100 if (entry.scheduled) {
71 FATAL3("Isolate %p still scheduled on %p (whose isolate_ is %p)\n", 101 FATAL3("Isolate %p still scheduled on %p (whose isolate_ is %p)\n",
72 isolate, 102 isolate,
73 entry.thread, 103 entry.thread,
74 entry.thread->isolate()); 104 entry.thread->isolate());
75 } 105 }
76 } 106 }
77 } 107 }
78 108
79 void VisitObjectPointers(ObjectPointerVisitor* visitor) { 109 void VisitObjectPointers(ObjectPointerVisitor* visitor) {
80 MutexLocker ml(mutex_); 110 MonitorLocker ml(monitor_);
81 for (int i = 0; i < entries_.length(); ++i) { 111 for (int i = 0; i < entries_.length(); ++i) {
82 const Entry& entry = entries_[i]; 112 const Entry& entry = entries_[i];
83 Zone* zone = entry.scheduled ? entry.thread->zone() : entry.state.zone; 113 Zone* zone = entry.scheduled ? entry.thread->zone() : entry.state.zone;
84 if (zone != NULL) { 114 if (zone != NULL) {
85 zone->VisitObjectPointers(visitor); 115 zone->VisitObjectPointers(visitor);
86 } 116 }
87 } 117 }
88 } 118 }
89 119
90 private: 120 private:
91 struct Entry { 121 struct Entry {
92 Thread* thread; 122 Thread* thread;
93 bool scheduled; 123 bool scheduled;
94 Thread::State state; 124 Thread::State state;
95 }; 125 };
96 126
97 // Returns Entry corresponding to thread in registry or NULL. 127 // Returns Entry corresponding to thread in registry or NULL.
98 // Note: Lock should be taken before this function is called. 128 // Note: Lock should be taken before this function is called.
129 // TODO(koda): Add method Monitor::IsOwnedByCurrentThread.
99 Entry* FindEntry(Thread* thread) { 130 Entry* FindEntry(Thread* thread) {
100 DEBUG_ASSERT(mutex_->IsOwnedByCurrentThread());
101 for (int i = 0; i < entries_.length(); ++i) { 131 for (int i = 0; i < entries_.length(); ++i) {
102 if (entries_[i].thread == thread) { 132 if (entries_[i].thread == thread) {
103 return &entries_[i]; 133 return &entries_[i];
104 } 134 }
105 } 135 }
106 return NULL; 136 return NULL;
107 } 137 }
108 138
109 Mutex* mutex_; 139 // Note: Lock should be taken before this function is called.
140 void CheckSafepointLocked();
141
142 // Returns the number threads that are scheduled on this isolate.
143 // Note: Lock should be taken before this function is called.
144 intptr_t CountScheduledLocked();
145
146 Monitor* monitor_; // All access is synchronized through this monitor.
110 MallocGrowableArray<Entry> entries_; 147 MallocGrowableArray<Entry> entries_;
111 148
149 // Safepoint rendezvous state.
150 bool in_rendezvous_; // A safepoint rendezvous request is in progress.
151 intptr_t remaining_; // Number of threads yet to reach their safepoint.
152 int64_t round_; // Counter, to prevent missing updates to remaining_
153 // (see comments in CheckSafepointLocked).
112 154
113 DISALLOW_COPY_AND_ASSIGN(ThreadRegistry); 155 DISALLOW_COPY_AND_ASSIGN(ThreadRegistry);
114 }; 156 };
115 157
116 } // namespace dart 158 } // namespace dart
117 159
118 #endif // VM_THREAD_REGISTRY_H_ 160 #endif // VM_THREAD_REGISTRY_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698