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

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

Issue 1439483003: - Add an OSThread structure which is the generic TLS structure for all C++ (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: code-review Created 5 years, 1 month 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
« no previous file with comments | « runtime/vm/thread_pool.cc ('k') | runtime/vm/thread_registry.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/stack_frame.h" 12 #include "vm/stack_frame.h"
13 #include "vm/thread.h" 13 #include "vm/thread.h"
14 14
15 namespace dart { 15 namespace dart {
16 16
17 // Unordered collection of threads relating to a particular isolate. 17 // Unordered collection of threads relating to a particular isolate.
18 class ThreadRegistry { 18 class ThreadRegistry {
19 public: 19 public:
20 ThreadRegistry() 20 ThreadRegistry()
21 : monitor_(new Monitor()), 21 : monitor_(new Monitor()),
22 entries_(), 22 active_list_(NULL),
23 free_list_(NULL),
24 mutator_thread_(NULL),
23 in_rendezvous_(false), 25 in_rendezvous_(false),
24 remaining_(0), 26 remaining_(0),
25 round_(0) {} 27 round_(0) {}
26 28
27 ~ThreadRegistry(); 29 ~ThreadRegistry();
28 30
31 Thread* active_list() const { return active_list_; }
32
29 // Bring all threads in this isolate to a safepoint. The caller is 33 // Bring all threads in this isolate to a safepoint. The caller is
30 // expected to be implicitly at a safepoint. The threads will wait 34 // expected to be implicitly at a safepoint. The threads will wait
31 // until ResumeAllThreads is called. First participates in any 35 // until ResumeAllThreads is called. First participates in any
32 // already pending rendezvous requested by another thread. Any 36 // already pending rendezvous requested by another thread. Any
33 // thread that tries to enter this isolate during rendezvous will 37 // thread that tries to enter this isolate during rendezvous will
34 // wait in RestoreStateTo. Nesting is not supported: the caller must 38 // wait in RestoreStateTo. Nesting is not supported: the caller must
35 // call ResumeAllThreads before making further calls to 39 // call ResumeAllThreads before making further calls to
36 // SafepointThreads. 40 // SafepointThreads.
37 void SafepointThreads(); 41 void SafepointThreads();
38 42
39 // Unblocks all threads participating in the rendezvous that was organized 43 // Unblocks all threads participating in the rendezvous that was organized
40 // by a prior call to SafepointThreads. 44 // by a prior call to SafepointThreads.
41 // TODO(koda): Consider adding a scope helper to avoid omitting this call. 45 // TODO(koda): Consider adding a scope helper to avoid omitting this call.
42 void ResumeAllThreads(); 46 void ResumeAllThreads();
43 47
44 // Indicate that the current thread is at a safepoint, and offer to wait for 48 // Indicate that the current thread is at a safepoint, and offer to wait for
45 // any pending rendezvous request (if none, returns immediately). 49 // any pending rendezvous request (if none, returns immediately).
46 void CheckSafepoint() { 50 void CheckSafepoint() {
47 MonitorLocker ml(monitor_); 51 MonitorLocker ml(monitor_);
48 CheckSafepointLocked(); 52 CheckSafepointLocked();
49 } 53 }
50 54
51 bool RestoreStateTo(Thread* thread, Thread::State* state, 55 Thread* Schedule(Isolate* isolate, bool is_mutator, bool bypass_safepoint);
52 bool bypass_safepoint) { 56 void Unschedule(Thread* thread, bool is_mutator, bool bypass_safepoint);
53 MonitorLocker ml(monitor_); 57 void VisitObjectPointers(ObjectPointerVisitor* visitor, bool validate_frames);
54 // Wait for any rendezvous in progress.
55 while (!bypass_safepoint && in_rendezvous_) {
56 ml.Wait(Monitor::kNoTimeout);
57 }
58 Entry* entry = FindEntry(thread);
59 if (entry != NULL) {
60 Thread::State st = entry->state;
61 // TODO(koda): Support same thread re-entering same isolate with
62 // Dart frames in between. For now, just assert it doesn't happen.
63 if (st.top_exit_frame_info != thread->top_exit_frame_info()) {
64 ASSERT(thread->top_exit_frame_info() == 0 ||
65 thread->top_exit_frame_info() > st.top_exit_frame_info);
66 }
67 ASSERT(!entry->scheduled);
68 entry->scheduled = true;
69 #if defined(DEBUG)
70 // State field is not in use, so zap it.
71 memset(&entry->state, 0xda, sizeof(entry->state));
72 #endif
73 *state = st;
74 return true;
75 }
76 Entry new_entry;
77 new_entry.thread = thread;
78 new_entry.scheduled = true;
79 #if defined(DEBUG)
80 // State field is not in use, so zap it.
81 memset(&new_entry.state, 0xda, sizeof(new_entry.state));
82 #endif
83 entries_.Add(new_entry);
84 return false;
85 }
86
87 void SaveStateFrom(Thread* thread, const Thread::State& state,
88 bool bypass_safepoint) {
89 MonitorLocker ml(monitor_);
90 Entry* entry = FindEntry(thread);
91 ASSERT(entry != NULL);
92 ASSERT(entry->scheduled);
93 entry->scheduled = false;
94 entry->state = state;
95 if (!bypass_safepoint && in_rendezvous_) {
96 // Don't wait for this thread.
97 ASSERT(remaining_ > 0);
98 if (--remaining_ == 0) {
99 ml.NotifyAll();
100 }
101 }
102 }
103
104 bool Contains(Thread* thread) {
105 MonitorLocker ml(monitor_);
106 return (FindEntry(thread) != NULL);
107 }
108
109 void CheckNotScheduled(Isolate* isolate) {
110 MonitorLocker ml(monitor_);
111 for (int i = 0; i < entries_.length(); ++i) {
112 const Entry& entry = entries_[i];
113 if (entry.scheduled) {
114 FATAL3("Isolate %p still scheduled on %p (whose isolate_ is %p)\n",
115 isolate,
116 entry.thread,
117 entry.thread->isolate());
118 }
119 }
120 }
121
122 void VisitObjectPointers(ObjectPointerVisitor* visitor,
123 bool validate_frames) {
124 MonitorLocker ml(monitor_);
125 for (int i = 0; i < entries_.length(); ++i) {
126 const Entry& entry = entries_[i];
127 const Thread::State& state =
128 entry.scheduled ? entry.thread->state_ : entry.state;
129 if (state.zone != NULL) {
130 state.zone->VisitObjectPointers(visitor);
131 }
132 if (entry.scheduled) {
133 ASSERT(entry.thread != NULL);
134 entry.thread->VisitObjectPointers(visitor);
135 }
136 // Iterate over all the stack frames and visit objects on the stack.
137 StackFrameIterator frames_iterator(state.top_exit_frame_info,
138 validate_frames);
139 StackFrame* frame = frames_iterator.NextFrame();
140 while (frame != NULL) {
141 frame->VisitObjectPointers(visitor);
142 frame = frames_iterator.NextFrame();
143 }
144 }
145 }
146
147 void PruneThread(Thread* thread);
148
149 void ReclaimTimelineBlocks();
150
151 struct Entry {
152 // NOTE: |thread| is deleted automatically when the thread exits.
153 // In other words, it is not safe to dereference |thread| unless you are on
154 // the thread itself.
155 Thread* thread;
156 bool scheduled;
157 Thread::State state;
158 };
159
160 class EntryIterator {
161 public:
162 explicit EntryIterator(ThreadRegistry* registry);
163 ~EntryIterator();
164
165 // Returns false when there are no more entries.
166 bool HasNext() const;
167
168 // Returns the next entry and moves forward.
169 const Entry& Next();
170
171 private:
172 void Reset(ThreadRegistry* registry);
173
174 intptr_t index_;
175 ThreadRegistry* registry_;
176 };
177 58
178 private: 59 private:
179 // Returns Entry corresponding to thread in registry or NULL. 60 Thread* GetThreadFromFreelist(Isolate* isolate);
180 // Note: Lock should be taken before this function is called. 61 void ReturnThreadToFreelist(Thread* thread);
181 // TODO(koda): Add method Monitor::IsOwnedByCurrentThread.
182 Entry* FindEntry(Thread* thread) {
183 for (int i = 0; i < entries_.length(); ++i) {
184 if (entries_[i].thread == thread) {
185 return &entries_[i];
186 }
187 }
188 return NULL;
189 }
190 62
191 // Note: Lock should be taken before this function is called. 63 // Note: Lock should be taken before this function is called.
192 void CheckSafepointLocked(); 64 void CheckSafepointLocked();
193 65
194 // Returns the number threads that are scheduled on this isolate. 66 // Returns the number threads that are scheduled on this isolate.
195 // Note: Lock should be taken before this function is called. 67 // Note: Lock should be taken before this function is called.
196 intptr_t CountScheduledLocked(); 68 intptr_t CountScheduledLocked();
197 69
198 Monitor* monitor_; // All access is synchronized through this monitor. 70 Monitor* monitor_; // All access is synchronized through this monitor.
199 MallocGrowableArray<Entry> entries_; 71 Thread* active_list_; // List of active threads in the isolate.
72 Thread* free_list_; // Free list of Thread objects that can be reused.
73 // TODO(asiva): Currently we treat a mutator thread as a special thread
74 // and always schedule execution of Dart code on the same mutator thread
75 // object. This is because ApiState is still an object associated with
76 // the isolate and switching execution to another thread causes problems.
77 // Once ApiState is made a per Thread object it should be possible to
78 // free a mutator thread like all other threads and continue running on
79 // a different thread.
80 Thread* mutator_thread_;
200 81
201 // Safepoint rendezvous state. 82 // Safepoint rendezvous state.
202 bool in_rendezvous_; // A safepoint rendezvous request is in progress. 83 bool in_rendezvous_; // A safepoint rendezvous request is in progress.
203 intptr_t remaining_; // Number of threads yet to reach their safepoint. 84 intptr_t remaining_; // Number of threads yet to reach their safepoint.
204 int64_t round_; // Counter, to prevent missing updates to remaining_ 85 int64_t round_; // Counter, to prevent missing updates to remaining_
205 // (see comments in CheckSafepointLocked). 86 // (see comments in CheckSafepointLocked).
206 87
207 DISALLOW_COPY_AND_ASSIGN(ThreadRegistry); 88 DISALLOW_COPY_AND_ASSIGN(ThreadRegistry);
208 }; 89 };
209 90
210 } // namespace dart 91 } // namespace dart
211 92
212 #endif // VM_THREAD_REGISTRY_H_ 93 #endif // VM_THREAD_REGISTRY_H_
OLDNEW
« no previous file with comments | « runtime/vm/thread_pool.cc ('k') | runtime/vm/thread_registry.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698