mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 12:24:24 +00:00
174 lines
4.8 KiB
C++
174 lines
4.8 KiB
C++
// 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,
|
|
bool 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
|