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

Side by Side Diff: runtime/vm/thread.cc

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-comments 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
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 #include "vm/thread.h" 5 #include "vm/thread.h"
6 6
7 #include "vm/growable_array.h" 7 #include "vm/growable_array.h"
8 #include "vm/isolate.h" 8 #include "vm/isolate.h"
9 #include "vm/lockers.h" 9 #include "vm/lockers.h"
10 #include "vm/log.h" 10 #include "vm/log.h"
11 #include "vm/native_entry.h" 11 #include "vm/native_entry.h"
12 #include "vm/object.h" 12 #include "vm/object.h"
13 #include "vm/os_thread.h" 13 #include "vm/os_thread.h"
14 #include "vm/profiler.h" 14 #include "vm/profiler.h"
15 #include "vm/runtime_entry.h" 15 #include "vm/runtime_entry.h"
16 #include "vm/stub_code.h" 16 #include "vm/stub_code.h"
17 #include "vm/symbols.h" 17 #include "vm/symbols.h"
18 #include "vm/thread_interrupter.h" 18 #include "vm/thread_interrupter.h"
19 #include "vm/thread_registry.h" 19 #include "vm/thread_registry.h"
20 20
21 namespace dart { 21 namespace dart {
22 22
23 // The single thread local key which stores all the thread local data
24 // for a thread.
25 ThreadLocalKey Thread::thread_key_ = OSThread::kUnsetThreadLocalKey;
26 Thread* Thread::thread_list_head_ = NULL;
27 Mutex* Thread::thread_list_lock_ = NULL;
28
29 // Remove |thread| from each isolate's thread registry.
30 class ThreadPruner : public IsolateVisitor {
31 public:
32 explicit ThreadPruner(Thread* thread)
33 : thread_(thread) {
34 ASSERT(thread_ != NULL);
35 }
36
37 void VisitIsolate(Isolate* isolate) {
38 ThreadRegistry* registry = isolate->thread_registry();
39 ASSERT(registry != NULL);
40 registry->PruneThread(thread_);
41 }
42 private:
43 Thread* thread_;
44 };
45
46
47 void Thread::AddThreadToList(Thread* thread) {
48 ASSERT(thread != NULL);
49 ASSERT(thread->isolate() == NULL);
50 ASSERT(thread_list_lock_ != NULL);
51 MutexLocker ml(thread_list_lock_);
52
53 ASSERT(thread->thread_list_next_ == NULL);
54
55 #if defined(DEBUG)
56 {
57 // Ensure that we aren't already in the list.
58 Thread* current = thread_list_head_;
59 while (current != NULL) {
60 ASSERT(current != thread);
61 current = current->thread_list_next_;
62 }
63 }
64 #endif
65
66 // Insert at head of list.
67 thread->thread_list_next_ = thread_list_head_;
68 thread_list_head_ = thread;
69 }
70
71
72 void Thread::RemoveThreadFromList(Thread* thread) {
73 ASSERT(thread != NULL);
74 ASSERT(thread->isolate() == NULL);
75 ASSERT(thread_list_lock_ != NULL);
76 MutexLocker ml(thread_list_lock_);
77
78 // Handle case where |thread| is head of list.
79 if (thread_list_head_ == thread) {
80 thread_list_head_ = thread->thread_list_next_;
81 thread->thread_list_next_ = NULL;
82 return;
83 }
84
85 Thread* current = thread_list_head_;
86 Thread* previous = NULL;
87
88 // Scan across list and remove |thread|.
89 while (current != NULL) {
90 previous = current;
91 current = current->thread_list_next_;
92 if (current == thread) {
93 // We found |thread|, remove from list.
94 previous->thread_list_next_ = current->thread_list_next_;
95 thread->thread_list_next_ = NULL;
96 return;
97 }
98 }
99
100 UNREACHABLE();
101 }
102
103
104 bool Thread::IsThreadInList(ThreadId join_id) {
105 if (join_id == OSThread::kInvalidThreadJoinId) {
106 return false;
107 }
108 ThreadIterator it;
109 while (it.HasNext()) {
110 Thread* t = it.Next();
111 // An address test is not sufficient because the allocator may recycle
112 // the address for another Thread. Test against the thread's join id.
113 if (t->join_id() == join_id) {
114 return true;
115 }
116 }
117 return false;
118 }
119
120
121 static void DeleteThread(void* thread) {
122 delete reinterpret_cast<Thread*>(thread);
123 }
124
125
126 void Thread::Shutdown() {
127 if (thread_list_lock_ != NULL) {
128 // Delete the current thread.
129 Thread* thread = Current();
130 ASSERT(thread != NULL);
131 delete thread;
132 thread = NULL;
133 SetCurrent(NULL);
134
135 // Check that there are no more threads, then delete the lock.
136 {
137 MutexLocker ml(thread_list_lock_);
138 ASSERT(thread_list_head_ == NULL);
139 }
140
141 // Clean up TLS.
142 OSThread::DeleteThreadLocal(thread_key_);
143 thread_key_ = OSThread::kUnsetThreadLocalKey;
144
145 // Delete the thread list lock.
146 delete thread_list_lock_;
147 thread_list_lock_ = NULL;
148 }
149 }
150
151
152 Thread::~Thread() { 23 Thread::~Thread() {
153 // We should cleanly exit any isolate before destruction. 24 // We should cleanly exit any isolate before destruction.
154 ASSERT(isolate_ == NULL); 25 ASSERT(isolate_ == NULL);
155 // Clear |this| from all isolate's thread registry.
156 ThreadPruner pruner(this);
zra 2015/11/16 20:12:28 What prunes threads from the registry now?
siva 2015/11/17 20:52:25 The thread registry destructor deletes any remaini
157 Isolate::VisitIsolates(&pruner);
158 delete log_;
159 log_ = NULL;
160 RemoveThreadFromList(this);
161 }
162
163
164 void Thread::InitOnceBeforeIsolate() {
165 ASSERT(thread_list_lock_ == NULL);
166 thread_list_lock_ = new Mutex();
167 ASSERT(thread_list_lock_ != NULL);
168 ASSERT(thread_key_ == OSThread::kUnsetThreadLocalKey);
169 thread_key_ = OSThread::CreateThreadLocal(DeleteThread);
170 ASSERT(thread_key_ != OSThread::kUnsetThreadLocalKey);
171 ASSERT(Thread::Current() == NULL);
172 // Allocate a new Thread and postpone initialization of VM constants for
173 // this first thread.
174 Thread* thread = new Thread(false);
175 // Verify that current thread was set.
176 ASSERT(Thread::Current() == thread);
177 }
178
179
180 void Thread::InitOnceAfterObjectAndStubCode() {
181 Thread* thread = Thread::Current();
182 ASSERT(thread != NULL);
183 ASSERT(thread->isolate() == Dart::vm_isolate());
184 thread->InitVMConstants();
185 } 26 }
186 27
187 28
188 void Thread::SetCurrent(Thread* current) { 29 void Thread::SetCurrent(Thread* current) {
189 OSThread::SetThreadLocal(thread_key_, reinterpret_cast<uword>(current)); 30 OSThread::SetThreadLocal(OSThread::thread_key_,
31 reinterpret_cast<uword>(current));
190 } 32 }
191 33
192 34
193 void Thread::EnsureInit() {
194 if (Thread::Current() == NULL) {
195 // Allocate a new Thread.
196 Thread* thread = new Thread();
197 // Verify that current thread was set.
198 ASSERT(Thread::Current() == thread);
199 }
200 }
201
202
203 #if defined(DEBUG) 35 #if defined(DEBUG)
204 #define REUSABLE_HANDLE_SCOPE_INIT(object) \ 36 #define REUSABLE_HANDLE_SCOPE_INIT(object) \
205 reusable_##object##_handle_scope_active_(false), 37 reusable_##object##_handle_scope_active_(false),
206 #else 38 #else
207 #define REUSABLE_HANDLE_SCOPE_INIT(object) 39 #define REUSABLE_HANDLE_SCOPE_INIT(object)
208 #endif // defined(DEBUG) 40 #endif // defined(DEBUG)
209 41
210 #define REUSABLE_HANDLE_INITIALIZERS(object) \ 42 #define REUSABLE_HANDLE_INITIALIZERS(object) \
211 object##_handle_(NULL), 43 object##_handle_(NULL),
212 44
213 45
214 Thread::Thread(bool init_vm_constants) 46 Thread::Thread(Isolate* isolate)
215 : id_(OSThread::GetCurrentThreadId()), 47 : BaseThread(false),
216 join_id_(OSThread::GetCurrentThreadJoinId()), 48 os_thread_(NULL),
217 trace_id_(OSThread::GetCurrentThreadTraceId()),
218 thread_interrupt_disabled_(1), // Thread interrupts disabled by default.
219 isolate_(NULL), 49 isolate_(NULL),
220 heap_(NULL), 50 heap_(NULL),
221 timeline_block_(NULL), 51 zone_(NULL),
52 top_exit_frame_info_(0),
53 top_resource_(NULL),
54 long_jump_base_(NULL),
222 store_buffer_block_(NULL), 55 store_buffer_block_(NULL),
223 log_(new class Log()), 56 no_callback_scope_depth_(0),
224 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS) 57 #if defined(DEBUG)
225 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT) 58 top_handle_scope_(NULL),
59 no_handle_scope_depth_(0),
60 no_safepoint_scope_depth_(0),
61 #endif
226 reusable_handles_(), 62 reusable_handles_(),
227 cha_(NULL), 63 cha_(NULL),
228 deopt_id_(0), 64 deopt_id_(0),
229 vm_tag_(0), 65 vm_tag_(0),
230 pending_functions_(GrowableObjectArray::null()), 66 pending_functions_(GrowableObjectArray::null()),
231 no_callback_scope_depth_(0), 67 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS)
232 thread_list_next_(NULL), 68 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT)
233 name_(NULL) { 69 next_(NULL) {
234 ClearState();
235
236 #define DEFAULT_INIT(type_name, member_name, init_expr, default_init_value) \ 70 #define DEFAULT_INIT(type_name, member_name, init_expr, default_init_value) \
237 member_name = default_init_value; 71 member_name = default_init_value;
238 CACHED_CONSTANTS_LIST(DEFAULT_INIT) 72 CACHED_CONSTANTS_LIST(DEFAULT_INIT)
239 #undef DEFAULT_INIT 73 #undef DEFAULT_INIT
240 74
241 #define DEFAULT_INIT(name) \ 75 #define DEFAULT_INIT(name) \
242 name##_entry_point_ = 0; 76 name##_entry_point_ = 0;
243 RUNTIME_ENTRY_LIST(DEFAULT_INIT) 77 RUNTIME_ENTRY_LIST(DEFAULT_INIT)
244 #undef DEFAULT_INIT 78 #undef DEFAULT_INIT
245 79
246 #define DEFAULT_INIT(returntype, name, ...) \ 80 #define DEFAULT_INIT(returntype, name, ...) \
247 name##_entry_point_ = 0; 81 name##_entry_point_ = 0;
248 LEAF_RUNTIME_ENTRY_LIST(DEFAULT_INIT) 82 LEAF_RUNTIME_ENTRY_LIST(DEFAULT_INIT)
249 #undef DEFAULT_INIT 83 #undef DEFAULT_INIT
250 84
251 if (init_vm_constants) { 85 // We cannot initialize the VM constants here for the vm isolate thread
86 // due to boot strapping issues.
87 if ((Dart::vm_isolate() != NULL) && (isolate != Dart::vm_isolate())) {
252 InitVMConstants(); 88 InitVMConstants();
253 } 89 }
254 SetCurrent(this);
255 AddThreadToList(this);
256 } 90 }
257 91
258 92
259 void Thread::InitVMConstants() { 93 void Thread::InitVMConstants() {
260 #define ASSERT_VM_HEAP(type_name, member_name, init_expr, default_init_value) \ 94 #define ASSERT_VM_HEAP(type_name, member_name, init_expr, default_init_value) \
261 ASSERT((init_expr)->IsOldObject()); 95 ASSERT((init_expr)->IsOldObject());
262 CACHED_VM_OBJECTS_LIST(ASSERT_VM_HEAP) 96 CACHED_VM_OBJECTS_LIST(ASSERT_VM_HEAP)
263 #undef ASSERT_VM_HEAP 97 #undef ASSERT_VM_HEAP
264 98
265 #define INIT_VALUE(type_name, member_name, init_expr, default_init_value) \ 99 #define INIT_VALUE(type_name, member_name, init_expr, default_init_value) \
(...skipping 15 matching lines...) Expand all
281 #undef INIT_VALUE 115 #undef INIT_VALUE
282 116
283 // Setup the thread specific reusable handles. 117 // Setup the thread specific reusable handles.
284 #define REUSABLE_HANDLE_ALLOCATION(object) \ 118 #define REUSABLE_HANDLE_ALLOCATION(object) \
285 this->object##_handle_ = this->AllocateReusableHandle<object>(); 119 this->object##_handle_ = this->AllocateReusableHandle<object>();
286 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_ALLOCATION) 120 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_ALLOCATION)
287 #undef REUSABLE_HANDLE_ALLOCATION 121 #undef REUSABLE_HANDLE_ALLOCATION
288 } 122 }
289 123
290 124
291 void Thread::ClearState() {
292 memset(&state_, 0, sizeof(state_));
293 pending_functions_ = GrowableObjectArray::null();
294 }
295
296
297 RawGrowableObjectArray* Thread::pending_functions() { 125 RawGrowableObjectArray* Thread::pending_functions() {
298 if (pending_functions_ == GrowableObjectArray::null()) { 126 if (pending_functions_ == GrowableObjectArray::null()) {
299 pending_functions_ = GrowableObjectArray::New(Heap::kOld); 127 pending_functions_ = GrowableObjectArray::New(Heap::kOld);
300 } 128 }
301 return pending_functions_; 129 return pending_functions_;
302 } 130 }
303 131
304 132
305 void Thread::Schedule(Isolate* isolate, bool bypass_safepoint) {
306 State st;
307 if (isolate->thread_registry()->RestoreStateTo(this, &st, bypass_safepoint)) {
308 ASSERT(isolate->thread_registry()->Contains(this));
309 state_ = st;
310 }
311 }
312
313
314 void Thread::Unschedule(bool bypass_safepoint) {
315 ThreadRegistry* reg = isolate_->thread_registry();
316 ASSERT(reg->Contains(this));
317 reg->SaveStateFrom(this, state_, bypass_safepoint);
318 ClearState();
319 }
320
321
322 void Thread::EnterIsolate(Isolate* isolate) { 133 void Thread::EnterIsolate(Isolate* isolate) {
323 Thread* thread = Thread::Current(); 134 const bool kIsMutatorThread = true;
324 ASSERT(thread != NULL); 135 const bool kDontBypassSafepoints = false;
325 ASSERT(thread->isolate() == NULL); 136 ThreadRegistry* tr = isolate->thread_registry();
326 ASSERT(!isolate->HasMutatorThread()); 137 Thread* thread = tr->Schedule(
327 thread->isolate_ = isolate; 138 isolate, kIsMutatorThread, kDontBypassSafepoints);
328 isolate->MakeCurrentThreadMutator(thread); 139 isolate->MakeCurrentThreadMutator(thread);
329 thread->set_vm_tag(VMTag::kVMTagId); 140 thread->set_vm_tag(VMTag::kVMTagId);
330 ASSERT(thread->store_buffer_block_ == NULL); 141 ASSERT(thread->store_buffer_block_ == NULL);
331 thread->StoreBufferAcquire(); 142 thread->StoreBufferAcquire();
332 ASSERT(isolate->heap() != NULL);
333 thread->heap_ = isolate->heap();
334 thread->Schedule(isolate);
335 thread->EnableThreadInterrupts();
336 } 143 }
337 144
338 145
339 void Thread::ExitIsolate() { 146 void Thread::ExitIsolate() {
340 Thread* thread = Thread::Current(); 147 Thread* thread = Thread::Current();
341 // TODO(koda): Audit callers; they should know whether they're in an isolate. 148 ASSERT(thread != NULL);
342 if (thread == NULL || thread->isolate() == NULL) return; 149 ASSERT(thread->IsMutatorThread());
343 #if defined(DEBUG) 150 #if defined(DEBUG)
344 ASSERT(!thread->IsAnyReusableHandleScopeActive()); 151 ASSERT(!thread->IsAnyReusableHandleScopeActive());
345 #endif // DEBUG 152 #endif // DEBUG
346 thread->DisableThreadInterrupts();
347 // Clear since GC will not visit the thread once it is unscheduled. 153 // Clear since GC will not visit the thread once it is unscheduled.
348 thread->ClearReusableHandles(); 154 thread->ClearReusableHandles();
155 thread->StoreBufferRelease();
349 Isolate* isolate = thread->isolate(); 156 Isolate* isolate = thread->isolate();
350 thread->Unschedule(); 157 ASSERT(isolate != NULL);
351 // TODO(koda): Move store_buffer_block_ into State.
352 thread->StoreBufferRelease();
353 if (isolate->is_runnable()) { 158 if (isolate->is_runnable()) {
354 thread->set_vm_tag(VMTag::kIdleTagId); 159 thread->set_vm_tag(VMTag::kIdleTagId);
355 } else { 160 } else {
356 thread->set_vm_tag(VMTag::kLoadWaitTagId); 161 thread->set_vm_tag(VMTag::kLoadWaitTagId);
357 } 162 }
163 const bool kIsMutatorThread = true;
164 const bool kDontBypassSafepoints = false;
165 ThreadRegistry* tr = isolate->thread_registry();
166 tr->Unschedule(thread, kIsMutatorThread, kDontBypassSafepoints);
358 isolate->ClearMutatorThread(); 167 isolate->ClearMutatorThread();
359 thread->isolate_ = NULL;
360 ASSERT(Isolate::Current() == NULL);
361 thread->heap_ = NULL;
362 } 168 }
363 169
364 170
365 void Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) { 171 void Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) {
366 Thread* thread = Thread::Current(); 172 const bool kIsNotMutatorThread = false;
367 ASSERT(thread != NULL); 173 ThreadRegistry* tr = isolate->thread_registry();
368 ASSERT(thread->isolate() == NULL); 174 Thread* thread = tr->Schedule(isolate, kIsNotMutatorThread, bypass_safepoint);
369 thread->isolate_ = isolate;
370 ASSERT(thread->store_buffer_block_ == NULL); 175 ASSERT(thread->store_buffer_block_ == NULL);
371 // TODO(koda): Use StoreBufferAcquire once we properly flush before Scavenge. 176 // TODO(koda): Use StoreBufferAcquire once we properly flush before Scavenge.
372 thread->store_buffer_block_ = 177 thread->store_buffer_block_ =
373 thread->isolate()->store_buffer()->PopEmptyBlock(); 178 thread->isolate()->store_buffer()->PopEmptyBlock();
374 ASSERT(isolate->heap() != NULL); 179 // This thread should not be the main mutator.
375 thread->heap_ = isolate->heap();
376 // Do not update isolate->mutator_thread, but perform sanity check:
377 // this thread should not be both the main mutator and helper.
378 ASSERT(!thread->IsMutatorThread()); 180 ASSERT(!thread->IsMutatorThread());
379 thread->Schedule(isolate, bypass_safepoint);
380 thread->EnableThreadInterrupts();
381 } 181 }
382 182
383 183
384 void Thread::ExitIsolateAsHelper(bool bypass_safepoint) { 184 void Thread::ExitIsolateAsHelper(bool bypass_safepoint) {
385 Thread* thread = Thread::Current(); 185 Thread* thread = Thread::Current();
386 thread->DisableThreadInterrupts(); 186 ASSERT(thread != NULL);
187 ASSERT(!thread->IsMutatorThread());
188 thread->StoreBufferRelease();
387 Isolate* isolate = thread->isolate(); 189 Isolate* isolate = thread->isolate();
388 ASSERT(isolate != NULL); 190 ASSERT(isolate != NULL);
389 thread->Unschedule(bypass_safepoint); 191 const bool kIsNotMutatorThread = false;
390 // TODO(koda): Move store_buffer_block_ into State. 192 ThreadRegistry* tr = isolate->thread_registry();
391 thread->StoreBufferRelease(); 193 tr->Unschedule(thread, kIsNotMutatorThread, bypass_safepoint);
392 thread->isolate_ = NULL;
393 thread->heap_ = NULL;
394 ASSERT(!thread->IsMutatorThread());
395 } 194 }
396 195
397 196
398 // TODO(koda): Make non-static and invoke in SafepointThreads. 197 // TODO(koda): Make non-static and invoke in SafepointThreads.
399 void Thread::PrepareForGC() { 198 void Thread::PrepareForGC() {
400 Thread* thread = Thread::Current(); 199 Thread* thread = Thread::Current();
401 // Prevent scheduling another GC. 200 // Prevent scheduling another GC.
402 thread->StoreBufferRelease(StoreBuffer::kIgnoreThreshold); 201 thread->StoreBufferRelease(StoreBuffer::kIgnoreThreshold);
403 // Make sure to get an *empty* block; the isolate needs all entries 202 // Make sure to get an *empty* block; the isolate needs all entries
404 // at GC time. 203 // at GC time.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 (vm_tag() == VMTag::kDartTagId); 251 (vm_tag() == VMTag::kDartTagId);
453 } 252 }
454 253
455 254
456 bool Thread::HasExitedDartCode() const { 255 bool Thread::HasExitedDartCode() const {
457 return (top_exit_frame_info() != 0) && 256 return (top_exit_frame_info() != 0) &&
458 (vm_tag() != VMTag::kDartTagId); 257 (vm_tag() != VMTag::kDartTagId);
459 } 258 }
460 259
461 260
462 CHA* Thread::cha() const {
463 ASSERT(isolate_ != NULL);
464 return cha_;
465 }
466
467
468 void Thread::set_cha(CHA* value) {
469 ASSERT(isolate_ != NULL);
470 cha_ = value;
471 }
472
473
474 Log* Thread::log() const {
475 return log_;
476 }
477
478
479 template<class C> 261 template<class C>
480 C* Thread::AllocateReusableHandle() { 262 C* Thread::AllocateReusableHandle() {
481 C* handle = reinterpret_cast<C*>(reusable_handles_.AllocateScopedHandle()); 263 C* handle = reinterpret_cast<C*>(reusable_handles_.AllocateScopedHandle());
482 C::initializeHandle(handle, C::null()); 264 C::initializeHandle(handle, C::null());
483 return handle; 265 return handle;
484 } 266 }
485 267
486 268
487 void Thread::ClearReusableHandles() { 269 void Thread::ClearReusableHandles() {
488 #define CLEAR_REUSABLE_HANDLE(object) \ 270 #define CLEAR_REUSABLE_HANDLE(object) \
489 *object##_handle_ = object::null(); 271 *object##_handle_ = object::null();
490 REUSABLE_HANDLE_LIST(CLEAR_REUSABLE_HANDLE) 272 REUSABLE_HANDLE_LIST(CLEAR_REUSABLE_HANDLE)
491 #undef CLEAR_REUSABLE_HANDLE 273 #undef CLEAR_REUSABLE_HANDLE
492 } 274 }
493 275
494 276
495 void Thread::VisitObjectPointers(ObjectPointerVisitor* visitor) { 277 void Thread::VisitObjectPointers(ObjectPointerVisitor* visitor) {
496 ASSERT(visitor != NULL); 278 ASSERT(visitor != NULL);
497 279
498 // Visit objects in thread specific handles area. 280 // Visit objects in thread specific handles area.
499 reusable_handles_.VisitObjectPointers(visitor); 281 reusable_handles_.VisitObjectPointers(visitor);
500 282
501 if (pending_functions_ != GrowableObjectArray::null()) { 283 if (pending_functions_ != GrowableObjectArray::null()) {
502 visitor->VisitPointer( 284 visitor->VisitPointer(
503 reinterpret_cast<RawObject**>(&pending_functions_)); 285 reinterpret_cast<RawObject**>(&pending_functions_));
504 } 286 }
505 } 287 }
506 288
507 289
508 void Thread::DisableThreadInterrupts() {
509 ASSERT(Thread::Current() == this);
510 AtomicOperations::FetchAndIncrement(&thread_interrupt_disabled_);
511 }
512
513
514 void Thread::EnableThreadInterrupts() {
515 ASSERT(Thread::Current() == this);
516 uintptr_t old =
517 AtomicOperations::FetchAndDecrement(&thread_interrupt_disabled_);
518 if (old == 1) {
519 // We just decremented from 1 to 0.
520 // Make sure the thread interrupter is awake.
521 ThreadInterrupter::WakeUp();
522 }
523 if (old == 0) {
524 // We just decremented from 0, this means we've got a mismatched pair
525 // of calls to EnableThreadInterrupts and DisableThreadInterrupts.
526 FATAL("Invalid call to Thread::EnableThreadInterrupts()");
527 }
528 }
529
530
531 bool Thread::ThreadInterruptsEnabled() {
532 return AtomicOperations::LoadRelaxed(&thread_interrupt_disabled_) == 0;
533 }
534
535
536 bool Thread::CanLoadFromThread(const Object& object) { 290 bool Thread::CanLoadFromThread(const Object& object) {
537 #define CHECK_OBJECT(type_name, member_name, expr, default_init_value) \ 291 #define CHECK_OBJECT(type_name, member_name, expr, default_init_value) \
538 if (object.raw() == expr) return true; 292 if (object.raw() == expr) return true;
539 CACHED_VM_OBJECTS_LIST(CHECK_OBJECT) 293 CACHED_VM_OBJECTS_LIST(CHECK_OBJECT)
540 #undef CHECK_OBJECT 294 #undef CHECK_OBJECT
541 return false; 295 return false;
542 } 296 }
543 297
544 298
545 intptr_t Thread::OffsetFromThread(const Object& object) { 299 intptr_t Thread::OffsetFromThread(const Object& object) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
578 return Thread::name##_entry_point_offset(); \ 332 return Thread::name##_entry_point_offset(); \
579 } 333 }
580 LEAF_RUNTIME_ENTRY_LIST(COMPUTE_OFFSET) 334 LEAF_RUNTIME_ENTRY_LIST(COMPUTE_OFFSET)
581 #undef COMPUTE_OFFSET 335 #undef COMPUTE_OFFSET
582 336
583 UNREACHABLE(); 337 UNREACHABLE();
584 return -1; 338 return -1;
585 } 339 }
586 340
587 341
588 ThreadIterator::ThreadIterator() {
589 ASSERT(Thread::thread_list_lock_ != NULL);
590 // Lock the thread list while iterating.
591 Thread::thread_list_lock_->Lock();
592 next_ = Thread::thread_list_head_;
593 }
594
595
596 ThreadIterator::~ThreadIterator() {
597 ASSERT(Thread::thread_list_lock_ != NULL);
598 // Unlock the thread list when done.
599 Thread::thread_list_lock_->Unlock();
600 }
601
602
603 bool ThreadIterator::HasNext() const {
604 ASSERT(Thread::thread_list_lock_ != NULL);
605 ASSERT(Thread::thread_list_lock_->IsOwnedByCurrentThread());
606 return next_ != NULL;
607 }
608
609
610 Thread* ThreadIterator::Next() {
611 ASSERT(Thread::thread_list_lock_ != NULL);
612 ASSERT(Thread::thread_list_lock_->IsOwnedByCurrentThread());
613 Thread* current = next_;
614 next_ = next_->thread_list_next_;
615 return current;
616 }
617
618
619 DisableThreadInterruptsScope::DisableThreadInterruptsScope(Thread* thread) 342 DisableThreadInterruptsScope::DisableThreadInterruptsScope(Thread* thread)
620 : StackResource(thread) { 343 : StackResource(thread) {
621 if (thread != NULL) { 344 if (thread != NULL) {
622 thread->DisableThreadInterrupts(); 345 OSThread* os_thread = thread->os_thread();
346 ASSERT(os_thread != NULL);
347 os_thread->DisableThreadInterrupts();
623 } 348 }
624 } 349 }
625 350
626 351
627 DisableThreadInterruptsScope::~DisableThreadInterruptsScope() { 352 DisableThreadInterruptsScope::~DisableThreadInterruptsScope() {
628 if (thread() != NULL) { 353 if (thread() != NULL) {
629 thread()->EnableThreadInterrupts(); 354 OSThread* os_thread = thread()->os_thread();
355 ASSERT(os_thread != NULL);
356 os_thread->EnableThreadInterrupts();
630 } 357 }
631 } 358 }
632 359
633 } // namespace dart 360 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698