Files
sdk/runtime/vm/thread_registry.cc
T
Siva Annamalai e72c1fb47d Implement safepointing of threads :
- uses thread execution status transition to track when a thread is in a safepoint or needs to block for a safepoint
 - introduces a monitor per Thread object
 - uses a per thread safepoint handshake between the thread requesting a safepoint and the requested thread.

The ThreadRegistry class now contains only the thread list for an isolate and the functionality of scheduling a thread onto an Isolate and unscheduling it from teh isolate. We could fold this functionality into the Isolate class in a different CL.

R=rmacnak@google.com, zra@google.com

Review URL: https://codereview.chromium.org/1541073002 .
2016-02-01 10:57:34 -08:00

150 lines
4.1 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/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) {
ASSERT(thread->api_top_scope() == NULL);
ReturnToFreelistLocked(thread);
}
}
void ThreadRegistry::VisitObjectPointers(ObjectPointerVisitor* visitor,
bool validate_frames) {
MonitorLocker ml(threads_lock());
Thread* thread = active_list_;
while (thread != NULL) {
if (thread->zone() != NULL) {
thread->zone()->VisitObjectPointers(visitor);
}
thread->VisitObjectPointers(visitor);
// Iterate over all the stack frames and visit objects on the stack.
StackFrameIterator frames_iterator(thread->top_exit_frame_info(),
validate_frames);
StackFrame* frame = frames_iterator.NextFrame();
while (frame != NULL) {
frame->VisitObjectPointers(visitor);
frame = frames_iterator.NextFrame();
}
thread = thread->next_;
}
}
void ThreadRegistry::PrepareForGC() {
MonitorLocker ml(threads_lock());
Thread* thread = active_list_;
while (thread != NULL) {
thread->PrepareForGC();
thread = thread->next_;
}
}
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