// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/trace_event/memory_dump_manager.h"

#include <algorithm>

#include "base/atomic_sequence_num.h"
#include "base/compiler_specific.h"
#include "base/trace_event/memory_dump_provider.h"
#include "base/trace_event/memory_dump_session_state.h"
#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/trace_event_argument.h"
#include "build/build_config.h"

#if !defined(OS_NACL)
#include "base/trace_event/process_memory_totals_dump_provider.h"
#endif

#if defined(OS_LINUX) || defined(OS_ANDROID)
#include "base/trace_event/malloc_dump_provider.h"
#include "base/trace_event/process_memory_maps_dump_provider.h"
#endif

#if defined(OS_ANDROID)
#include "base/trace_event/java_heap_dump_provider_android.h"
#endif

#if defined(OS_WIN)
#include "base/trace_event/winheap_dump_provider_win.h"
#endif

namespace base {
namespace trace_event {

namespace {

// TODO(primiano): this should be smarter and should do something similar to
// trace event synthetic delays.
const char kTraceCategory[] = TRACE_DISABLED_BY_DEFAULT("memory-infra");

MemoryDumpManager* g_instance_for_testing = nullptr;
const int kDumpIntervalSeconds = 2;
const int kTraceEventNumArgs = 1;
const char* kTraceEventArgNames[] = {"dumps"};
const unsigned char kTraceEventArgTypes[] = {TRACE_VALUE_TYPE_CONVERTABLE};
StaticAtomicSequenceNumber g_next_guid;

const char* MemoryDumpTypeToString(const MemoryDumpType& dump_type) {
  switch (dump_type) {
    case MemoryDumpType::TASK_BEGIN:
      return "TASK_BEGIN";
    case MemoryDumpType::TASK_END:
      return "TASK_END";
    case MemoryDumpType::PERIODIC_INTERVAL:
      return "PERIODIC_INTERVAL";
    case MemoryDumpType::EXPLICITLY_TRIGGERED:
      return "EXPLICITLY_TRIGGERED";
  }
  NOTREACHED();
  return "UNKNOWN";
}

// Internal class used to hold details about ProcessMemoryDump requests for the
// current process.
// TODO(primiano): In the upcoming CLs, ProcessMemoryDump will become async.
// and this class will be used to convey more details across PostTask()s.
class ProcessMemoryDumpHolder
    : public RefCountedThreadSafe<ProcessMemoryDumpHolder> {
 public:
  ProcessMemoryDumpHolder(
      MemoryDumpRequestArgs req_args,
      const scoped_refptr<MemoryDumpSessionState>& session_state,
      MemoryDumpCallback callback)
      : process_memory_dump(session_state),
        req_args(req_args),
        callback(callback),
        task_runner(MessageLoop::current()->task_runner()),
        num_pending_async_requests(0) {}

  ProcessMemoryDump process_memory_dump;
  const MemoryDumpRequestArgs req_args;

  // Callback passed to the initial call to CreateProcessDump().
  MemoryDumpCallback callback;

  // Thread on which FinalizeDumpAndAddToTrace() should be called, which is the
  // same that invoked the initial CreateProcessDump().
  const scoped_refptr<SingleThreadTaskRunner> task_runner;

  // Number of pending ContinueAsyncProcessDump() calls.
  int num_pending_async_requests;

 private:
  friend class RefCountedThreadSafe<ProcessMemoryDumpHolder>;
  virtual ~ProcessMemoryDumpHolder() {}
  DISALLOW_COPY_AND_ASSIGN(ProcessMemoryDumpHolder);
};

void FinalizeDumpAndAddToTrace(
    const scoped_refptr<ProcessMemoryDumpHolder>& pmd_holder) {
  DCHECK_EQ(0, pmd_holder->num_pending_async_requests);

  if (!pmd_holder->task_runner->BelongsToCurrentThread()) {
    pmd_holder->task_runner->PostTask(
        FROM_HERE, Bind(&FinalizeDumpAndAddToTrace, pmd_holder));
    return;
  }

  scoped_refptr<ConvertableToTraceFormat> event_value(new TracedValue());
  pmd_holder->process_memory_dump.AsValueInto(
      static_cast<TracedValue*>(event_value.get()));
  const char* const event_name =
      MemoryDumpTypeToString(pmd_holder->req_args.dump_type);

  TRACE_EVENT_API_ADD_TRACE_EVENT(
      TRACE_EVENT_PHASE_MEMORY_DUMP,
      TraceLog::GetCategoryGroupEnabled(kTraceCategory), event_name,
      pmd_holder->req_args.dump_guid, kTraceEventNumArgs, kTraceEventArgNames,
      kTraceEventArgTypes, nullptr /* arg_values */, &event_value,
      TRACE_EVENT_FLAG_HAS_ID);

  if (!pmd_holder->callback.is_null()) {
    pmd_holder->callback.Run(pmd_holder->req_args.dump_guid, true);
    pmd_holder->callback.Reset();
  }
}

void RequestPeriodicGlobalDump() {
  MemoryDumpManager::GetInstance()->RequestGlobalDump(
      MemoryDumpType::PERIODIC_INTERVAL);
}

}  // namespace

// static
const char* const MemoryDumpManager::kTraceCategoryForTesting = kTraceCategory;

// static
MemoryDumpManager* MemoryDumpManager::GetInstance() {
  if (g_instance_for_testing)
    return g_instance_for_testing;

  return Singleton<MemoryDumpManager,
                   LeakySingletonTraits<MemoryDumpManager>>::get();
}

// static
void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) {
  if (instance)
    instance->skip_core_dumpers_auto_registration_for_testing_ = true;
  g_instance_for_testing = instance;
}

MemoryDumpManager::MemoryDumpManager()
    : delegate_(nullptr),
      memory_tracing_enabled_(0),
      skip_core_dumpers_auto_registration_for_testing_(false) {
  g_next_guid.GetNext();  // Make sure that first guid is not zero.
}

MemoryDumpManager::~MemoryDumpManager() {
  base::trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(this);
}

void MemoryDumpManager::Initialize() {
  TRACE_EVENT0(kTraceCategory, "init");  // Add to trace-viewer category list.
  trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this);

  if (skip_core_dumpers_auto_registration_for_testing_)
    return;

  // Enable the core dump providers.
#if !defined(OS_NACL)
  RegisterDumpProvider(ProcessMemoryTotalsDumpProvider::GetInstance());
#endif

#if (defined(OS_LINUX) && !defined(FNL_MUSL)) || defined(OS_ANDROID)
  RegisterDumpProvider(ProcessMemoryMapsDumpProvider::GetInstance());
  RegisterDumpProvider(MallocDumpProvider::GetInstance());
#endif

#if defined(OS_ANDROID)
  RegisterDumpProvider(JavaHeapDumpProvider::GetInstance());
#endif

#if defined(OS_WIN)
  RegisterDumpProvider(WinHeapDumpProvider::GetInstance());
#endif
}

void MemoryDumpManager::SetDelegate(MemoryDumpManagerDelegate* delegate) {
  AutoLock lock(lock_);
  DCHECK_EQ(static_cast<MemoryDumpManagerDelegate*>(nullptr), delegate_);
  delegate_ = delegate;
}

void MemoryDumpManager::RegisterDumpProvider(
    MemoryDumpProvider* mdp,
    const scoped_refptr<SingleThreadTaskRunner>& task_runner) {
  MemoryDumpProviderInfo mdp_info(task_runner);
  AutoLock lock(lock_);
  dump_providers_.insert(std::make_pair(mdp, mdp_info));
}

void MemoryDumpManager::RegisterDumpProvider(MemoryDumpProvider* mdp) {
  RegisterDumpProvider(mdp, nullptr);
}

void MemoryDumpManager::UnregisterDumpProvider(MemoryDumpProvider* mdp) {
  AutoLock lock(lock_);

  auto it = dump_providers_.find(mdp);
  if (it == dump_providers_.end())
    return;

  const MemoryDumpProviderInfo& mdp_info = it->second;
  // Unregistration of a MemoryDumpProvider while tracing is ongoing is safe
  // only if the MDP has specified a thread affinity (via task_runner()) AND
  // the unregistration happens on the same thread (so the MDP cannot unregister
  // and OnMemoryDump() at the same time).
  // Otherwise, it is not possible to guarantee that its unregistration is
  // race-free. If you hit this DCHECK, your MDP has a bug.
  DCHECK_IMPLIES(
      subtle::NoBarrier_Load(&memory_tracing_enabled_),
      mdp_info.task_runner && mdp_info.task_runner->BelongsToCurrentThread())
      << "The MemoryDumpProvider attempted to unregister itself in a racy way. "
      << " Please file a crbug.";

  // Remove from the enabled providers list. This is to deal with the case that
  // UnregisterDumpProvider is called while the trace is enabled.
  dump_providers_.erase(it);
}

void MemoryDumpManager::RequestGlobalDump(
    MemoryDumpType dump_type,
    const MemoryDumpCallback& callback) {
  // Bail out immediately if tracing is not enabled at all.
  if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_)))
    return;

  const uint64 guid =
      TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext());

  // The delegate_ is supposed to be thread safe, immutable and long lived.
  // No need to keep the lock after we ensure that a delegate has been set.
  MemoryDumpManagerDelegate* delegate;
  {
    AutoLock lock(lock_);
    delegate = delegate_;
  }

  if (delegate) {
    // The delegate is in charge to coordinate the request among all the
    // processes and call the CreateLocalDumpPoint on the local process.
    MemoryDumpRequestArgs args = {guid, dump_type};
    delegate->RequestGlobalMemoryDump(args, callback);
  } else if (!callback.is_null()) {
    callback.Run(guid, false /* success */);
  }
}

void MemoryDumpManager::RequestGlobalDump(MemoryDumpType dump_type) {
  RequestGlobalDump(dump_type, MemoryDumpCallback());
}

// Creates a memory dump for the current process and appends it to the trace.
void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args,
                                          const MemoryDumpCallback& callback) {
  scoped_refptr<ProcessMemoryDumpHolder> pmd_holder(
      new ProcessMemoryDumpHolder(args, session_state_, callback));
  ProcessMemoryDump* pmd = &pmd_holder->process_memory_dump;
  bool did_any_provider_dump = false;

  // Iterate over the active dump providers and invoke OnMemoryDump(pmd).
  // The MDM guarantees linearity (at most one MDP is active within one
  // process) and thread-safety (MDM enforces the right locking when entering /
  // leaving the MDP.OnMemoryDump() call). This is to simplify the clients'
  // design
  // and not let the MDPs worry about locking.
  // As regards thread affinity, depending on the MDP configuration (see
  // memory_dump_provider.h), the OnMemoryDump() invocation can happen:
  //  - Synchronousy on the MDM thread, when MDP.task_runner() is not set.
  //  - Posted on MDP.task_runner(), when MDP.task_runner() is set.
  {
    AutoLock lock(lock_);
    for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it) {
      MemoryDumpProvider* mdp = it->first;
      MemoryDumpProviderInfo* mdp_info = &it->second;
      if (mdp_info->disabled)
        continue;
      if (mdp_info->task_runner) {
        // The OnMemoryDump() call must be posted.
        bool did_post_async_task = mdp_info->task_runner->PostTask(
            FROM_HERE, Bind(&MemoryDumpManager::ContinueAsyncProcessDump,
                            Unretained(this), Unretained(mdp), pmd_holder));
        // The thread underlying the TaskRunner might have gone away.
        if (did_post_async_task)
          ++pmd_holder->num_pending_async_requests;
      } else {
        // Invoke the dump provider synchronously.
        did_any_provider_dump |= InvokeDumpProviderLocked(mdp, pmd);
      }
    }
  }  // AutoLock

  // If at least one synchronous provider did dump and there are no pending
  // asynchronous requests, add the dump to the trace and invoke the callback
  // straight away (FinalizeDumpAndAddToTrace() takes care of the callback).
  if (did_any_provider_dump && pmd_holder->num_pending_async_requests == 0)
    FinalizeDumpAndAddToTrace(pmd_holder);
}

// Invokes the MemoryDumpProvider.OnMemoryDump(), taking care of the fail-safe
// logic which disables the dumper when failing (crbug.com/461788).
bool MemoryDumpManager::InvokeDumpProviderLocked(MemoryDumpProvider* mdp,
                                                 ProcessMemoryDump* pmd) {
  lock_.AssertAcquired();
  bool dump_successful = mdp->OnMemoryDump(pmd);
  if (!dump_successful) {
    LOG(ERROR) << "The memory dumper failed, possibly due to sandboxing "
                  "(crbug.com/461788), disabling it for current process. Try "
                  "restarting chrome with the --no-sandbox switch.";
    dump_providers_.find(mdp)->second.disabled = true;
  }
  return dump_successful;
}

// This is posted to arbitrary threads as a continuation of CreateProcessDump(),
// when one or more MemoryDumpProvider(s) require the OnMemoryDump() call to
// happen on a different thread.
void MemoryDumpManager::ContinueAsyncProcessDump(
    MemoryDumpProvider* mdp,
    scoped_refptr<ProcessMemoryDumpHolder> pmd_holder) {
  bool should_finalize_dump = false;
  {
    // The lock here is to guarantee that different asynchronous dumps on
    // different threads are still serialized, so that the MemoryDumpProvider
    // has a consistent view of the |pmd| argument passed.
    AutoLock lock(lock_);
    ProcessMemoryDump* pmd = &pmd_holder->process_memory_dump;

    // Check if the MemoryDumpProvider is still there. It might have been
    // destroyed and unregistered while hopping threads.
    if (dump_providers_.count(mdp))
      InvokeDumpProviderLocked(mdp, pmd);

    // Finalize the dump appending it to the trace if this was the last
    // asynchronous request pending.
    --pmd_holder->num_pending_async_requests;
    if (pmd_holder->num_pending_async_requests == 0)
      should_finalize_dump = true;
  }  // AutoLock(lock_)

  if (should_finalize_dump)
    FinalizeDumpAndAddToTrace(pmd_holder);
}

void MemoryDumpManager::OnTraceLogEnabled() {
  // TODO(primiano): at this point we query  TraceLog::GetCurrentCategoryFilter
  // to figure out (and cache) which dumpers should be enabled or not.
  // For the moment piggy back everything on the generic "memory" category.
  bool enabled;
  TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &enabled);

  AutoLock lock(lock_);

  // There is no point starting the tracing without a delegate.
  if (!enabled || !delegate_) {
    // Disable all the providers.
    for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it)
      it->second.disabled = true;
    return;
  }

  session_state_ = new MemoryDumpSessionState();
  for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it)
    it->second.disabled = false;

  subtle::NoBarrier_Store(&memory_tracing_enabled_, 1);

  if (delegate_->IsCoordinatorProcess()) {
    periodic_dump_timer_.Start(FROM_HERE,
                               TimeDelta::FromSeconds(kDumpIntervalSeconds),
                               base::Bind(&RequestPeriodicGlobalDump));
  }
}

void MemoryDumpManager::OnTraceLogDisabled() {
  AutoLock lock(lock_);
  periodic_dump_timer_.Stop();
  subtle::NoBarrier_Store(&memory_tracing_enabled_, 0);
  session_state_ = nullptr;
}

MemoryDumpManager::MemoryDumpProviderInfo::MemoryDumpProviderInfo(
    const scoped_refptr<SingleThreadTaskRunner>& task_runner)
    : task_runner(task_runner), disabled(false) {
}
MemoryDumpManager::MemoryDumpProviderInfo::~MemoryDumpProviderInfo() {
}

}  // namespace trace_event
}  // namespace base
