// 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);

    // The [mutator_thread_] is kept alive until the destruction of the isolate.
    mutator_thread_->isolate_ = nullptr;

    // 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;
    }
  }
}

// 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::ReleaseStoreBuffers() {
  MonitorLocker ml(threads_lock());
  Thread* thread = active_list_;
  while (thread != NULL) {
    if (!thread->BypassSafepoints()) {
      thread->ReleaseStoreBuffer();
    }
    thread = thread->next_;
  }
}

void ThreadRegistry::AcquireMarkingStacks() {
  MonitorLocker ml(threads_lock());
  Thread* thread = active_list_;
  while (thread != NULL) {
    if (!thread->BypassSafepoints()) {
      thread->MarkingStackAcquire();
      thread->DeferredMarkingStackAcquire();
    }
    thread = thread->next_;
  }
}

void ThreadRegistry::ReleaseMarkingStacks() {
  MonitorLocker ml(threads_lock());
  Thread* thread = active_list_;
  while (thread != NULL) {
    if (!thread->BypassSafepoints()) {
      thread->MarkingStackRelease();
      thread->DeferredMarkingStackRelease();
    }
    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
