/*
 * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#include "precompiled.hpp"
#include "runtime/threadCritical.hpp"
#include "services/nmtCommon.hpp"
#include "services/nmtUsage.hpp"
#include "services/mallocTracker.hpp"
#include "services/threadStackTracker.hpp"
#include "services/virtualMemoryTracker.hpp"

// Enabled all options for snapshot.
const NMTUsageOptions NMTUsage::OptionsAll = { true, true, true };
// Skip expensive thread stacks when refreshing usage.
const NMTUsageOptions NMTUsage::OptionsNoTS = { false, true, true };

NMTUsage::NMTUsage(NMTUsageOptions options) :
    _malloc_by_type(),
    _malloc_total(),
    _vm_by_type(),
    _vm_total(),
    _usage_options(options) { }

void NMTUsage::walk_thread_stacks() {
  // If backed by virtual memory, snapping the thread stacks involves walking
  // them to to figure out how much memory is committed if they are backed by
  // virtual memory. This needs ot happen before we take the snapshot of the
  // virtual memory since it will update this information.
  if (ThreadStackTracker::track_as_vm()) {
    VirtualMemoryTracker::snapshot_thread_stacks();
  }
}

void NMTUsage::update_malloc_usage() {
  // Thread critical needed keep values in sync, total area size
  // is deducted from mtChunk in the end to give correct values.
  ThreadCritical tc;
  const MallocMemorySnapshot* ms = MallocMemorySummary::as_snapshot();

  size_t total_arena_size = 0;
  for (int i = 0; i < mt_number_of_types; i++) {
    MEMFLAGS flag = NMTUtil::index_to_flag(i);
    const MallocMemory* mm = ms->by_type(flag);
    _malloc_by_type[i] = mm->malloc_size() + mm->arena_size();
    total_arena_size +=  mm->arena_size();
  }

  // Total malloc size.
  _malloc_total = ms->total();

  // Adjustment due to mtChunk double counting.
  _malloc_by_type[NMTUtil::flag_to_index(mtChunk)] -= total_arena_size;
  _malloc_total -= total_arena_size;

  // Adjust mtNMT to include malloc overhead.
  _malloc_by_type[NMTUtil::flag_to_index(mtNMT)] += ms->malloc_overhead();
}

void NMTUsage::update_vm_usage() {
  const VirtualMemorySnapshot* vms = VirtualMemorySummary::as_snapshot();

  // Reset total to allow recalculation.
  _vm_total.committed = 0;
  _vm_total.reserved = 0;
  for (int i = 0; i < mt_number_of_types; i++) {
    MEMFLAGS flag = NMTUtil::index_to_flag(i);
    const VirtualMemory* vm = vms->by_type(flag);

    _vm_by_type[i].reserved = vm->reserved();
    _vm_by_type[i].committed = vm->committed();
    _vm_total.reserved += vm->reserved();
    _vm_total.committed += vm->committed();
  }
}

void NMTUsage::refresh() {
  if (_usage_options.include_malloc) {
    update_malloc_usage();
  }

  if (_usage_options.include_vm) {
    // Thread stacks only makes sense if virtual memory
    // is also included. It must be executed before the
    // over all usage is calculated.
    if (_usage_options.update_thread_stacks) {
      walk_thread_stacks();
    }
    update_vm_usage();
  }
}

size_t NMTUsage::total_reserved() const {
  return _malloc_total + _vm_total.reserved;
}

size_t NMTUsage::total_committed() const {
  return _malloc_total + _vm_total.committed;
}

size_t NMTUsage::reserved(MEMFLAGS flag) const {
  int index = NMTUtil::flag_to_index(flag);
  return _malloc_by_type[index] + _vm_by_type[index].reserved;
}

size_t NMTUsage::committed(MEMFLAGS flag) const {
  int index = NMTUtil::flag_to_index(flag);
  return _malloc_by_type[index] + _vm_by_type[index].committed;
}
