// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. #include "vm/thread_registry.h" #include "vm/isolate.h" #include "vm/json_stream.h" #include "vm/lockers.h" namespace dart { ThreadRegistry::~ThreadRegistry() { // Go over the free thread list and delete the thread objects. { MonitorLocker ml(threads_lock()); // At this point the active list should be empty. ASSERT(active_list_ == NULL); // We have cached the mutator thread, delete it. delete mutator_thread_; mutator_thread_ = NULL; // Now delete all the threads in the free list. while (free_list_ != NULL) { Thread* thread = free_list_; free_list_ = thread->next_; delete thread; } } // Delete monitor. delete threads_lock_; } // Gets a free Thread structure, we special case the mutator thread // by reusing the cached structure, see comment in 'thread_registry.h'. Thread* ThreadRegistry::GetFreeThreadLocked(Isolate* isolate, bool is_mutator) { ASSERT(threads_lock()->IsOwnedByCurrentThread()); Thread* thread; if (is_mutator) { if (mutator_thread_ == NULL) { mutator_thread_ = GetFromFreelistLocked(isolate); } thread = mutator_thread_; } else { thread = GetFromFreelistLocked(isolate); ASSERT(thread->api_top_scope() == NULL); } // Now add this Thread to the active list for the isolate. AddToActiveListLocked(thread); return thread; } void ThreadRegistry::ReturnThreadLocked(bool is_mutator, Thread* thread) { ASSERT(threads_lock()->IsOwnedByCurrentThread()); // Remove thread from the active list for the isolate. RemoveFromActiveListLocked(thread); if (!is_mutator) { ReturnToFreelistLocked(thread); } } void ThreadRegistry::VisitObjectPointers(ObjectPointerVisitor* visitor, ValidationPolicy validate_frames) { MonitorLocker ml(threads_lock()); bool mutator_thread_visited = false; Thread* thread = active_list_; while (thread != NULL) { thread->VisitObjectPointers(visitor, validate_frames); if (mutator_thread_ == thread) { mutator_thread_visited = true; } thread = thread->next_; } // Visit mutator thread even if it is not in the active list because of // api handles. if (!mutator_thread_visited && (mutator_thread_ != NULL)) { mutator_thread_->VisitObjectPointers(visitor, validate_frames); } } void ThreadRegistry::PrepareForGC() { MonitorLocker ml(threads_lock()); Thread* thread = active_list_; while (thread != NULL) { thread->PrepareForGC(); thread = thread->next_; } } #ifndef PRODUCT void ThreadRegistry::PrintJSON(JSONStream* stream) const { MonitorLocker ml(threads_lock()); JSONArray threads(stream); Thread* current = active_list_; while (current != NULL) { threads.AddValue(current); current = current->next_; } } #endif intptr_t ThreadRegistry::CountZoneHandles() const { MonitorLocker ml(threads_lock()); intptr_t count = 0; Thread* current = active_list_; while (current != NULL) { count += current->CountZoneHandles(); current = current->next_; } return count; } intptr_t ThreadRegistry::CountScopedHandles() const { MonitorLocker ml(threads_lock()); intptr_t count = 0; Thread* current = active_list_; while (current != NULL) { count += current->CountScopedHandles(); current = current->next_; } return count; } void ThreadRegistry::AddToActiveListLocked(Thread* thread) { ASSERT(thread != NULL); ASSERT(threads_lock()->IsOwnedByCurrentThread()); thread->next_ = active_list_; active_list_ = thread; } void ThreadRegistry::RemoveFromActiveListLocked(Thread* thread) { ASSERT(thread != NULL); ASSERT(threads_lock()->IsOwnedByCurrentThread()); Thread* prev = NULL; Thread* current = active_list_; while (current != NULL) { if (current == thread) { if (prev == NULL) { active_list_ = current->next_; } else { prev->next_ = current->next_; } break; } prev = current; current = current->next_; } } Thread* ThreadRegistry::GetFromFreelistLocked(Isolate* isolate) { ASSERT(threads_lock()->IsOwnedByCurrentThread()); Thread* thread = NULL; // Get thread structure from free list or create a new one. if (free_list_ == NULL) { thread = new Thread(isolate); } else { thread = free_list_; free_list_ = thread->next_; } return thread; } void ThreadRegistry::ReturnToFreelistLocked(Thread* thread) { ASSERT(thread != NULL); ASSERT(thread->os_thread_ == NULL); ASSERT(thread->isolate_ == NULL); ASSERT(thread->heap_ == NULL); ASSERT(threads_lock()->IsOwnedByCurrentThread()); // Add thread to the free list. thread->next_ = free_list_; free_list_ = thread; } } // namespace dart