/*
 * Copyright (c) 2001, 2023, 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_G1CONCURRENTREFINE_HPP
#define SHARE_GC_G1_G1CONCURRENTREFINE_HPP

#include "gc/g1/g1ConcurrentRefineStats.hpp"
#include "gc/g1/g1ConcurrentRefineThreadsNeeded.hpp"
#include "memory/allocation.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"

// Forward decl
class G1ConcurrentRefine;
class G1ConcurrentRefineThread;
class G1DirtyCardQueueSet;
class G1Policy;
class ThreadClosure;

// Helper class for refinement thread management. Used to start, stop and
// iterate over them.
class G1ConcurrentRefineThreadControl {
  G1ConcurrentRefine* _cr;
  G1ConcurrentRefineThread** _threads;
  uint _max_num_threads;

  // Create the refinement thread for the given worker id.
  // If initializing is true, ignore InjectGCWorkerCreationFailure.
  G1ConcurrentRefineThread* create_refinement_thread(uint worker_id, bool initializing);

  NONCOPYABLE(G1ConcurrentRefineThreadControl);

public:
  G1ConcurrentRefineThreadControl();
  ~G1ConcurrentRefineThreadControl();

  jint initialize(G1ConcurrentRefine* cr, uint max_num_threads);

  void assert_current_thread_is_primary_refinement_thread() const NOT_DEBUG_RETURN;

  uint max_num_threads() const { return _max_num_threads; }

  // Activate the indicated thread.  If the thread has not yet been allocated,
  // allocate and then activate.  If allocation is needed and fails, return
  // false.  Otherwise return true.
  // precondition: worker_id < max_num_threads().
  // precondition: current thread is not the designated worker.
  bool activate(uint worker_id);

  void worker_threads_do(ThreadClosure* tc);
  void stop();
};

// Controls concurrent refinement.
//
// Mutator threads produce dirty cards, which need to be examined for updates
// to the remembered sets (refinement).  There is a pause-time budget for
// processing these dirty cards (see -XX:G1RSetUpdatingPauseTimePercent).  The
// purpose of concurrent refinement is to (attempt to) ensure the number of
// pending dirty cards at the start of a GC can be processed within that time
// budget.
//
// Concurrent refinement is performed by a combination of dedicated threads
// and by mutator threads as they produce dirty cards.  If configured to not
// have any dedicated threads (-XX:G1ConcRefinementThreads=0) then all
// concurrent refinement work is performed by mutator threads.  When there are
// dedicated threads, they generally do most of the concurrent refinement
// work, to minimize throughput impact of refinement work on mutator threads.
//
// This class determines the target number of dirty cards pending for the next
// GC.  It also owns the dedicated refinement threads and controls their
// activation in order to achieve that target.
//
// There are two kinds of dedicated refinement threads, a single primary
// thread and some number of secondary threads.  When active, all refinement
// threads take buffers of dirty cards from the dirty card queue and process
// them.  Between buffers they query this owning object to find out whether
// they should continue running, deactivating themselves if not.
//
// The primary thread drives the control system that determines how many
// refinement threads should be active.  If inactive, it wakes up periodically
// to recalculate the number of active threads needed, and activates
// additional threads as necessary.  While active it also periodically
// recalculates the number wanted and activates more threads if needed.  It
// also reduces the number of wanted threads when the target has been reached,
// triggering deactivations.
class G1ConcurrentRefine : public CHeapObj<mtGC> {
  G1Policy* _policy;
  volatile uint _threads_wanted;
  size_t _pending_cards_target;
  Ticks _last_adjust;
  Ticks _last_deactivate;
  bool _needs_adjust;
  G1ConcurrentRefineThreadsNeeded _threads_needed;
  G1ConcurrentRefineThreadControl _thread_control;
  G1DirtyCardQueueSet& _dcqs;

  G1ConcurrentRefine(G1Policy* policy);

  static uint worker_id_offset();

  jint initialize();

  void assert_current_thread_is_primary_refinement_thread() const {
    _thread_control.assert_current_thread_is_primary_refinement_thread();
  }

  // For the first few collection cycles we don't have a target (and so don't
  // do any concurrent refinement), because there hasn't been enough pause
  // time refinement work to be done to make useful predictions.  We use
  // SIZE_MAX as a special marker value to indicate we're in this state.
  static const size_t PendingCardsTargetUninitialized = SIZE_MAX;
  bool is_pending_cards_target_initialized() const {
    return _pending_cards_target != PendingCardsTargetUninitialized;
  }

  void update_pending_cards_target(double logged_cards_scan_time_ms,
                                   size_t processed_logged_cards,
                                   size_t predicted_thread_buffer_cards,
                                   double goal_ms);

  uint64_t adjust_threads_period_ms() const;
  bool is_in_last_adjustment_period() const;

  class RemSetSamplingClosure;  // Helper class for adjusting young length.
  void adjust_young_list_target_length();

  void adjust_threads_wanted(size_t available_bytes);

  NONCOPYABLE(G1ConcurrentRefine);

public:
  ~G1ConcurrentRefine();

  // Returns a G1ConcurrentRefine instance if succeeded to create/initialize the
  // G1ConcurrentRefine instance. Otherwise, returns null with error code.
  static G1ConcurrentRefine* create(G1Policy* policy, jint* ecode);

  // Stop all the refinement threads.
  void stop();

  // Called at the end of a GC to prepare for refinement during the next
  // concurrent phase.  Updates the target for the number of pending dirty
  // cards.  Updates the mutator refinement threshold.  Ensures the primary
  // refinement thread (if it exists) is active, so it will adjust the number
  // of running threads.
  void adjust_after_gc(double logged_cards_scan_time_ms,
                       size_t processed_logged_cards,
                       size_t predicted_thread_buffer_cards,
                       double goal_ms);

  // Target number of pending dirty cards at the start of the next GC.
  size_t pending_cards_target() const { return _pending_cards_target; }

  // May recalculate the number of refinement threads that should be active in
  // order to meet the pending cards target.  Returns true if adjustment was
  // performed, and clears any pending request.  Returns false if the
  // adjustment period has not expired, or because a timed or requested
  // adjustment could not be performed immediately and so was deferred.
  // precondition: current thread is the primary refinement thread.
  bool adjust_threads_periodically();

  // The amount of time (in ms) the primary refinement thread should sleep
  // when it is inactive.  It requests adjustment whenever it is reactivated.
  // precondition: current thread is the primary refinement thread.
  uint64_t adjust_threads_wait_ms() const;

  // Record a request for thread adjustment as soon as possible.
  // precondition: current thread is the primary refinement thread.
  void record_thread_adjustment_needed();

  // Test whether there is a pending request for thread adjustment.
  // precondition: current thread is the primary refinement thread.
  bool is_thread_adjustment_needed() const;

  // Reduce the number of active threads wanted.
  // precondition: current thread is the primary refinement thread.
  void reduce_threads_wanted();

  // Test whether the thread designated by worker_id should be active.
  bool is_thread_wanted(uint worker_id) const;

  // Return total of concurrent refinement stats for the
  // ConcurrentRefineThreads.  Also reset the stats for the threads.
  G1ConcurrentRefineStats get_and_reset_refinement_stats();

  // Perform a single refinement step; called by the refinement
  // threads.  Returns true if there was refinement work available.
  // Updates stats.
  bool try_refinement_step(uint worker_id,
                           size_t stop_at,
                           G1ConcurrentRefineStats* stats);

  // Iterate over all concurrent refinement threads applying the given closure.
  void threads_do(ThreadClosure *tc);

  // Maximum number of refinement threads.
  static uint max_num_threads();
};

#endif // SHARE_GC_G1_G1CONCURRENTREFINE_HPP
