/*
 * Copyright (c) 2021, 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.
 *
 */

#ifndef SHARE_GC_G1_G1MONOTONICARENAFREEPOOL_HPP
#define SHARE_GC_G1_G1MONOTONICARENAFREEPOOL_HPP

#include "gc/g1/g1CardSet.hpp"
#include "gc/g1/g1MonotonicArena.hpp"
#include "utilities/growableArray.hpp"

// Statistics for a monotonic arena. Contains the number of segments and memory
// used for each. Note that statistics are typically not taken atomically so there
// can be inconsistencies. The user must be prepared for them.
class G1MonotonicArenaMemoryStats {
public:

  size_t _num_mem_sizes[G1CardSetConfiguration::num_mem_object_types()];
  size_t _num_segments[G1CardSetConfiguration::num_mem_object_types()];

  // Returns all-zero statistics.
  G1MonotonicArenaMemoryStats();

  void add(G1MonotonicArenaMemoryStats const other) {
    STATIC_ASSERT(ARRAY_SIZE(_num_segments) == ARRAY_SIZE(_num_mem_sizes));
    for (uint i = 0; i < ARRAY_SIZE(_num_mem_sizes); i++) {
      _num_mem_sizes[i] += other._num_mem_sizes[i];
      _num_segments[i] += other._num_segments[i];
    }
  }

  void clear();

  uint num_pools() const { return G1CardSetConfiguration::num_mem_object_types(); }
};

// A set of free lists holding freed segments for use by G1MonotonicArena,
// e.g. G1CardSetAllocators::_arena
class G1MonotonicArenaFreePool {
  using SegmentFreeList = G1MonotonicArena::SegmentFreeList;

  const uint _num_free_lists;
  SegmentFreeList* _free_lists;

public:
  class G1ReturnMemoryProcessor;
  typedef GrowableArrayCHeap<G1ReturnMemoryProcessor*, mtGC> G1ReturnMemoryProcessorSet;

  void update_unlink_processors(G1ReturnMemoryProcessorSet* unlink_processors);

  explicit G1MonotonicArenaFreePool(uint num_free_lists);
  ~G1MonotonicArenaFreePool();

  SegmentFreeList* free_list(uint i) {
    assert(i < _num_free_lists, "must be");
    return &_free_lists[i];
  }

  uint num_free_lists() const { return _num_free_lists; }

  G1MonotonicArenaMemoryStats memory_sizes() const;
  size_t mem_size() const;

  void print_on(outputStream* out) const;
};

// Data structure containing current in-progress state for returning memory to the
// operating system for a single G1SegmentFreeList.
class G1MonotonicArenaFreePool::G1ReturnMemoryProcessor : public CHeapObj<mtGC> {
  using SegmentFreeList = G1MonotonicArena::SegmentFreeList;
  using Segment = G1MonotonicArena::Segment;
  SegmentFreeList* _source;
  size_t _return_to_vm_size;

  Segment* _first;
  size_t _unlinked_bytes;
  size_t _num_unlinked;

public:
  explicit G1ReturnMemoryProcessor(size_t return_to_vm) :
    _source(nullptr), _return_to_vm_size(return_to_vm), _first(nullptr), _unlinked_bytes(0), _num_unlinked(0) {
  }

  // Updates the instance members about the given free list for
  // the purpose of giving back memory. Only necessary members are updated,
  // e.g. if there is nothing to return to the VM, do not set the source list.
  void visit_free_list(SegmentFreeList* source);

  bool finished_return_to_vm() const { return _return_to_vm_size == 0; }
  bool finished_return_to_os() const { return _first == nullptr; }

  // Returns memory to the VM until the given deadline expires. Returns true if
  // there is no more work. Guarantees forward progress, i.e. at least one segment
  // has been processed after returning.
  // return_to_vm() re-adds segments to the respective free list.
  bool return_to_vm(jlong deadline);
  // Returns memory to the VM until the given deadline expires. Returns true if
  // there is no more work. Guarantees forward progress, i.e. at least one segment
  // has been processed after returning.
  // return_to_os() gives back segments to the OS.
  bool return_to_os(jlong deadline);
};

#endif //SHARE_GC_G1_G1MONOTONICARENAFREEPOOL_HPP
