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

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 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.h ('k') | runtime/vm/thread_interrupter.h » ('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 #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);
157 Isolate::VisitIsolates(&pruner);
158 delete log_;
159 log_ = NULL;
160 RemoveThreadFromList(this);
161 } 26 }
162 27
163 28
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 }
186
187
188 void Thread::SetCurrent(Thread* current) {
189 OSThread::SetThreadLocal(thread_key_, reinterpret_cast<uword>(current));
190 }
191
192
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) 29 #if defined(DEBUG)
204 #define REUSABLE_HANDLE_SCOPE_INIT(object) \ 30 #define REUSABLE_HANDLE_SCOPE_INIT(object) \
205 reusable_##object##_handle_scope_active_(false), 31 reusable_##object##_handle_scope_active_(false),
206 #else 32 #else
207 #define REUSABLE_HANDLE_SCOPE_INIT(object) 33 #define REUSABLE_HANDLE_SCOPE_INIT(object)
208 #endif // defined(DEBUG) 34 #endif // defined(DEBUG)
209 35
210 #define REUSABLE_HANDLE_INITIALIZERS(object) \ 36 #define REUSABLE_HANDLE_INITIALIZERS(object) \
211 object##_handle_(NULL), 37 object##_handle_(NULL),
212 38
213 39
214 Thread::Thread(bool init_vm_constants) 40 Thread::Thread(Isolate* isolate)
215 : id_(OSThread::GetCurrentThreadId()), 41 : BaseThread(false),
216 join_id_(OSThread::GetCurrentThreadJoinId()), 42 os_thread_(NULL),
217 trace_id_(OSThread::GetCurrentThreadTraceId()),
218 thread_interrupt_disabled_(1), // Thread interrupts disabled by default.
219 isolate_(NULL), 43 isolate_(NULL),
220 heap_(NULL), 44 heap_(NULL),
221 timeline_block_(NULL), 45 zone_(NULL),
46 top_exit_frame_info_(0),
47 top_resource_(NULL),
48 long_jump_base_(NULL),
222 store_buffer_block_(NULL), 49 store_buffer_block_(NULL),
223 log_(new class Log()), 50 no_callback_scope_depth_(0),
224 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS) 51 #if defined(DEBUG)
225 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT) 52 top_handle_scope_(NULL),
53 no_handle_scope_depth_(0),
54 no_safepoint_scope_depth_(0),
55 #endif
226 reusable_handles_(), 56 reusable_handles_(),
227 cha_(NULL), 57 cha_(NULL),
228 deopt_id_(0), 58 deopt_id_(0),
229 vm_tag_(0), 59 vm_tag_(0),
230 pending_functions_(GrowableObjectArray::null()), 60 pending_functions_(GrowableObjectArray::null()),
231 no_callback_scope_depth_(0), 61 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS)
232 thread_list_next_(NULL), 62 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT)
233 name_(NULL) { 63 next_(NULL) {
234 ClearState();
235
236 #define DEFAULT_INIT(type_name, member_name, init_expr, default_init_value) \ 64 #define DEFAULT_INIT(type_name, member_name, init_expr, default_init_value) \
237 member_name = default_init_value; 65 member_name = default_init_value;
238 CACHED_CONSTANTS_LIST(DEFAULT_INIT) 66 CACHED_CONSTANTS_LIST(DEFAULT_INIT)
239 #undef DEFAULT_INIT 67 #undef DEFAULT_INIT
240 68
241 #define DEFAULT_INIT(name) \ 69 #define DEFAULT_INIT(name) \
242 name##_entry_point_ = 0; 70 name##_entry_point_ = 0;
243 RUNTIME_ENTRY_LIST(DEFAULT_INIT) 71 RUNTIME_ENTRY_LIST(DEFAULT_INIT)
244 #undef DEFAULT_INIT 72 #undef DEFAULT_INIT
245 73
246 #define DEFAULT_INIT(returntype, name, ...) \ 74 #define DEFAULT_INIT(returntype, name, ...) \
247 name##_entry_point_ = 0; 75 name##_entry_point_ = 0;
248 LEAF_RUNTIME_ENTRY_LIST(DEFAULT_INIT) 76 LEAF_RUNTIME_ENTRY_LIST(DEFAULT_INIT)
249 #undef DEFAULT_INIT 77 #undef DEFAULT_INIT
250 78
251 if (init_vm_constants) { 79 // We cannot initialize the VM constants here for the vm isolate thread
80 // due to boot strapping issues.
81 if ((Dart::vm_isolate() != NULL) && (isolate != Dart::vm_isolate())) {
252 InitVMConstants(); 82 InitVMConstants();
253 } 83 }
254 SetCurrent(this);
255 AddThreadToList(this);
256 } 84 }
257 85
258 86
259 void Thread::InitVMConstants() { 87 void Thread::InitVMConstants() {
260 #define ASSERT_VM_HEAP(type_name, member_name, init_expr, default_init_value) \ 88 #define ASSERT_VM_HEAP(type_name, member_name, init_expr, default_init_value) \
261 ASSERT((init_expr)->IsOldObject()); 89 ASSERT((init_expr)->IsOldObject());
262 CACHED_VM_OBJECTS_LIST(ASSERT_VM_HEAP) 90 CACHED_VM_OBJECTS_LIST(ASSERT_VM_HEAP)
263 #undef ASSERT_VM_HEAP 91 #undef ASSERT_VM_HEAP
264 92
265 #define INIT_VALUE(type_name, member_name, init_expr, default_init_value) \ 93 #define INIT_VALUE(type_name, member_name, init_expr, default_init_value) \
(...skipping 15 matching lines...) Expand all
281 #undef INIT_VALUE 109 #undef INIT_VALUE
282 110
283 // Setup the thread specific reusable handles. 111 // Setup the thread specific reusable handles.
284 #define REUSABLE_HANDLE_ALLOCATION(object) \ 112 #define REUSABLE_HANDLE_ALLOCATION(object) \
285 this->object##_handle_ = this->AllocateReusableHandle<object>(); 113 this->object##_handle_ = this->AllocateReusableHandle<object>();
286 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_ALLOCATION) 114 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_ALLOCATION)
287 #undef REUSABLE_HANDLE_ALLOCATION 115 #undef REUSABLE_HANDLE_ALLOCATION
288 } 116 }
289 117
290 118
291 void Thread::ClearState() {
292 memset(&state_, 0, sizeof(state_));
293 pending_functions_ = GrowableObjectArray::null();
294 }
295
296
297 RawGrowableObjectArray* Thread::pending_functions() { 119 RawGrowableObjectArray* Thread::pending_functions() {
298 if (pending_functions_ == GrowableObjectArray::null()) { 120 if (pending_functions_ == GrowableObjectArray::null()) {
299 pending_functions_ = GrowableObjectArray::New(Heap::kOld); 121 pending_functions_ = GrowableObjectArray::New(Heap::kOld);
300 } 122 }
301 return pending_functions_; 123 return pending_functions_;
302 } 124 }
303 125
304 126
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) { 127 void Thread::EnterIsolate(Isolate* isolate) {
323 Thread* thread = Thread::Current(); 128 const bool kIsMutatorThread = true;
324 ASSERT(thread != NULL); 129 const bool kDontBypassSafepoints = false;
325 ASSERT(thread->isolate() == NULL); 130 ThreadRegistry* tr = isolate->thread_registry();
326 ASSERT(!isolate->HasMutatorThread()); 131 Thread* thread = tr->Schedule(
327 thread->isolate_ = isolate; 132 isolate, kIsMutatorThread, kDontBypassSafepoints);
328 isolate->MakeCurrentThreadMutator(thread); 133 isolate->MakeCurrentThreadMutator(thread);
329 thread->set_vm_tag(VMTag::kVMTagId); 134 thread->set_vm_tag(VMTag::kVMTagId);
330 ASSERT(thread->store_buffer_block_ == NULL); 135 ASSERT(thread->store_buffer_block_ == NULL);
331 thread->StoreBufferAcquire(); 136 thread->StoreBufferAcquire();
332 ASSERT(isolate->heap() != NULL);
333 thread->heap_ = isolate->heap();
334 thread->Schedule(isolate);
335 thread->EnableThreadInterrupts();
336 } 137 }
337 138
338 139
339 void Thread::ExitIsolate() { 140 void Thread::ExitIsolate() {
340 Thread* thread = Thread::Current(); 141 Thread* thread = Thread::Current();
341 // TODO(koda): Audit callers; they should know whether they're in an isolate. 142 ASSERT(thread != NULL);
342 if (thread == NULL || thread->isolate() == NULL) return; 143 ASSERT(thread->IsMutatorThread());
343 #if defined(DEBUG) 144 #if defined(DEBUG)
344 ASSERT(!thread->IsAnyReusableHandleScopeActive()); 145 ASSERT(!thread->IsAnyReusableHandleScopeActive());
345 #endif // DEBUG 146 #endif // DEBUG
346 thread->DisableThreadInterrupts();
347 // Clear since GC will not visit the thread once it is unscheduled. 147 // Clear since GC will not visit the thread once it is unscheduled.
348 thread->ClearReusableHandles(); 148 thread->ClearReusableHandles();
149 thread->StoreBufferRelease();
349 Isolate* isolate = thread->isolate(); 150 Isolate* isolate = thread->isolate();
350 thread->Unschedule(); 151 ASSERT(isolate != NULL);
351 // TODO(koda): Move store_buffer_block_ into State.
352 thread->StoreBufferRelease();
353 if (isolate->is_runnable()) { 152 if (isolate->is_runnable()) {
354 thread->set_vm_tag(VMTag::kIdleTagId); 153 thread->set_vm_tag(VMTag::kIdleTagId);
355 } else { 154 } else {
356 thread->set_vm_tag(VMTag::kLoadWaitTagId); 155 thread->set_vm_tag(VMTag::kLoadWaitTagId);
357 } 156 }
157 const bool kIsMutatorThread = true;
158 const bool kDontBypassSafepoints = false;
159 ThreadRegistry* tr = isolate->thread_registry();
160 tr->Unschedule(thread, kIsMutatorThread, kDontBypassSafepoints);
358 isolate->ClearMutatorThread(); 161 isolate->ClearMutatorThread();
359 thread->isolate_ = NULL;
360 ASSERT(Isolate::Current() == NULL);
361 thread->heap_ = NULL;
362 } 162 }
363 163
364 164
365 void Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) { 165 void Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) {
366 Thread* thread = Thread::Current(); 166 const bool kIsNotMutatorThread = false;
367 ASSERT(thread != NULL); 167 ThreadRegistry* tr = isolate->thread_registry();
368 ASSERT(thread->isolate() == NULL); 168 Thread* thread = tr->Schedule(isolate, kIsNotMutatorThread, bypass_safepoint);
369 thread->isolate_ = isolate;
370 ASSERT(thread->store_buffer_block_ == NULL); 169 ASSERT(thread->store_buffer_block_ == NULL);
371 // TODO(koda): Use StoreBufferAcquire once we properly flush before Scavenge. 170 // TODO(koda): Use StoreBufferAcquire once we properly flush before Scavenge.
372 thread->store_buffer_block_ = 171 thread->store_buffer_block_ =
373 thread->isolate()->store_buffer()->PopEmptyBlock(); 172 thread->isolate()->store_buffer()->PopEmptyBlock();
374 ASSERT(isolate->heap() != NULL); 173 // 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()); 174 ASSERT(!thread->IsMutatorThread());
379 thread->Schedule(isolate, bypass_safepoint);
380 thread->EnableThreadInterrupts();
381 } 175 }
382 176
383 177
384 void Thread::ExitIsolateAsHelper(bool bypass_safepoint) { 178 void Thread::ExitIsolateAsHelper(bool bypass_safepoint) {
385 Thread* thread = Thread::Current(); 179 Thread* thread = Thread::Current();
386 thread->DisableThreadInterrupts(); 180 ASSERT(thread != NULL);
181 ASSERT(!thread->IsMutatorThread());
182 thread->StoreBufferRelease();
387 Isolate* isolate = thread->isolate(); 183 Isolate* isolate = thread->isolate();
388 ASSERT(isolate != NULL); 184 ASSERT(isolate != NULL);
389 thread->Unschedule(bypass_safepoint); 185 const bool kIsNotMutatorThread = false;
390 // TODO(koda): Move store_buffer_block_ into State. 186 ThreadRegistry* tr = isolate->thread_registry();
391 thread->StoreBufferRelease(); 187 tr->Unschedule(thread, kIsNotMutatorThread, bypass_safepoint);
392 thread->isolate_ = NULL;
393 thread->heap_ = NULL;
394 ASSERT(!thread->IsMutatorThread());
395 } 188 }
396 189
397 190
398 // TODO(koda): Make non-static and invoke in SafepointThreads. 191 // TODO(koda): Make non-static and invoke in SafepointThreads.
399 void Thread::PrepareForGC() { 192 void Thread::PrepareForGC() {
400 Thread* thread = Thread::Current(); 193 Thread* thread = Thread::Current();
401 // Prevent scheduling another GC. 194 // Prevent scheduling another GC.
402 thread->StoreBufferRelease(StoreBuffer::kIgnoreThreshold); 195 thread->StoreBufferRelease(StoreBuffer::kIgnoreThreshold);
403 // Make sure to get an *empty* block; the isolate needs all entries 196 // Make sure to get an *empty* block; the isolate needs all entries
404 // at GC time. 197 // at GC time.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 (vm_tag() == VMTag::kDartTagId); 245 (vm_tag() == VMTag::kDartTagId);
453 } 246 }
454 247
455 248
456 bool Thread::HasExitedDartCode() const { 249 bool Thread::HasExitedDartCode() const {
457 return (top_exit_frame_info() != 0) && 250 return (top_exit_frame_info() != 0) &&
458 (vm_tag() != VMTag::kDartTagId); 251 (vm_tag() != VMTag::kDartTagId);
459 } 252 }
460 253
461 254
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> 255 template<class C>
480 C* Thread::AllocateReusableHandle() { 256 C* Thread::AllocateReusableHandle() {
481 C* handle = reinterpret_cast<C*>(reusable_handles_.AllocateScopedHandle()); 257 C* handle = reinterpret_cast<C*>(reusable_handles_.AllocateScopedHandle());
482 C::initializeHandle(handle, C::null()); 258 C::initializeHandle(handle, C::null());
483 return handle; 259 return handle;
484 } 260 }
485 261
486 262
487 void Thread::ClearReusableHandles() { 263 void Thread::ClearReusableHandles() {
488 #define CLEAR_REUSABLE_HANDLE(object) \ 264 #define CLEAR_REUSABLE_HANDLE(object) \
489 *object##_handle_ = object::null(); 265 *object##_handle_ = object::null();
490 REUSABLE_HANDLE_LIST(CLEAR_REUSABLE_HANDLE) 266 REUSABLE_HANDLE_LIST(CLEAR_REUSABLE_HANDLE)
491 #undef CLEAR_REUSABLE_HANDLE 267 #undef CLEAR_REUSABLE_HANDLE
492 } 268 }
493 269
494 270
495 void Thread::VisitObjectPointers(ObjectPointerVisitor* visitor) { 271 void Thread::VisitObjectPointers(ObjectPointerVisitor* visitor) {
496 ASSERT(visitor != NULL); 272 ASSERT(visitor != NULL);
497 273
498 // Visit objects in thread specific handles area. 274 // Visit objects in thread specific handles area.
499 reusable_handles_.VisitObjectPointers(visitor); 275 reusable_handles_.VisitObjectPointers(visitor);
500 276
501 if (pending_functions_ != GrowableObjectArray::null()) { 277 if (pending_functions_ != GrowableObjectArray::null()) {
502 visitor->VisitPointer( 278 visitor->VisitPointer(
503 reinterpret_cast<RawObject**>(&pending_functions_)); 279 reinterpret_cast<RawObject**>(&pending_functions_));
504 } 280 }
505 } 281 }
506 282
507 283
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) { 284 bool Thread::CanLoadFromThread(const Object& object) {
537 #define CHECK_OBJECT(type_name, member_name, expr, default_init_value) \ 285 #define CHECK_OBJECT(type_name, member_name, expr, default_init_value) \
538 if (object.raw() == expr) return true; 286 if (object.raw() == expr) return true;
539 CACHED_VM_OBJECTS_LIST(CHECK_OBJECT) 287 CACHED_VM_OBJECTS_LIST(CHECK_OBJECT)
540 #undef CHECK_OBJECT 288 #undef CHECK_OBJECT
541 return false; 289 return false;
542 } 290 }
543 291
544 292
545 intptr_t Thread::OffsetFromThread(const Object& object) { 293 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(); \ 326 return Thread::name##_entry_point_offset(); \
579 } 327 }
580 LEAF_RUNTIME_ENTRY_LIST(COMPUTE_OFFSET) 328 LEAF_RUNTIME_ENTRY_LIST(COMPUTE_OFFSET)
581 #undef COMPUTE_OFFSET 329 #undef COMPUTE_OFFSET
582 330
583 UNREACHABLE(); 331 UNREACHABLE();
584 return -1; 332 return -1;
585 } 333 }
586 334
587 335
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) 336 DisableThreadInterruptsScope::DisableThreadInterruptsScope(Thread* thread)
620 : StackResource(thread) { 337 : StackResource(thread) {
621 if (thread != NULL) { 338 if (thread != NULL) {
622 thread->DisableThreadInterrupts(); 339 OSThread* os_thread = thread->os_thread();
340 ASSERT(os_thread != NULL);
341 os_thread->DisableThreadInterrupts();
623 } 342 }
624 } 343 }
625 344
626 345
627 DisableThreadInterruptsScope::~DisableThreadInterruptsScope() { 346 DisableThreadInterruptsScope::~DisableThreadInterruptsScope() {
628 if (thread() != NULL) { 347 if (thread() != NULL) {
629 thread()->EnableThreadInterrupts(); 348 OSThread* os_thread = thread()->os_thread();
349 ASSERT(os_thread != NULL);
350 os_thread->EnableThreadInterrupts();
630 } 351 }
631 } 352 }
632 353
633 } // namespace dart 354 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/thread.h ('k') | runtime/vm/thread_interrupter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698