/* Abstract base class inherited by all process_stratum targets

   Copyright (C) 2018-2026 Free Software Foundation, Inc.

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program 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 for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#include "process-stratum-target.h"
#include "inferior.h"
#include <algorithm>

process_stratum_target::~process_stratum_target ()
{
}

struct gdbarch *
process_stratum_target::thread_architecture (ptid_t ptid)
{
  inferior *inf = find_inferior_ptid (this, ptid);
  gdb_assert (inf != NULL);
  return inf->arch ();
}

bool
process_stratum_target::has_all_memory ()
{
  /* If no inferior selected, then we can't read memory here.  */
  return inferior_ptid != null_ptid;
}

bool
process_stratum_target::has_memory ()
{
  /* If no inferior selected, then we can't read memory here.  */
  return inferior_ptid != null_ptid;
}

bool
process_stratum_target::has_stack ()
{
  /* If no inferior selected, there's no stack.  */
  return inferior_ptid != null_ptid;
}

bool
process_stratum_target::has_registers ()
{
  /* Can't read registers from no inferior.  */
  return inferior_ptid != null_ptid;
}

bool
process_stratum_target::has_execution (inferior *inf)
{
  /* If there's a process running already, we can't make it run
     through hoops.  */
  return inf->pid != 0;
}

/* See process-stratum-target.h.  */

void
process_stratum_target::follow_exec (inferior *follow_inf, ptid_t ptid,
				     const char *execd_pathname)
{
  inferior *orig_inf = current_inferior ();

  if (orig_inf != follow_inf)
    {
      /* Execution continues in a new inferior, push the original inferior's
	 process target on the new inferior's target stack.  The process target
	 may decide to unpush itself from the original inferior's target stack
	 after that, at its discretion.  */
      follow_inf->push_target (orig_inf->process_target ());
      thread_info *t = add_thread (follow_inf->process_target (), ptid);

      /* Leave the new inferior / thread as the current inferior / thread.  */
      switch_to_thread (t);
    }
}

/* See process-stratum-target.h.  */

void
process_stratum_target::follow_fork (inferior *child_inf, ptid_t child_ptid,
				     target_waitkind fork_kind,
				     bool follow_child,
				     bool detach_on_fork)
{
  if (child_inf != nullptr)
    {
      child_inf->push_target (this);
      add_thread_silent (this, child_ptid);
    }
}

/* See process-stratum-target.h.  */

void
process_stratum_target::maybe_add_resumed_with_pending_wait_status
  (thread_info *thread)
{
  gdb_assert (!thread->resumed_with_pending_wait_status_node.is_linked ());

  if (thread->internal_state () == THREAD_INT_RESUMED_PENDING_STATUS)
    {
      gdb_assert (thread->has_pending_waitstatus ());
      infrun_debug_printf ("adding to resumed threads with event list: %s",
			   thread->ptid.to_string ().c_str ());
      m_resumed_with_pending_wait_status.push_back (*thread);
    }
}

/* See process-stratum-target.h.  */

void
process_stratum_target::maybe_remove_resumed_with_pending_wait_status
  (thread_info *thread)
{
  if (thread->internal_state () == THREAD_INT_RESUMED_PENDING_STATUS)
    {
      gdb_assert (thread->has_pending_waitstatus ());
      infrun_debug_printf ("removing from resumed threads with event list: %s",
			   thread->ptid.to_string ().c_str ());
      gdb_assert (thread->resumed_with_pending_wait_status_node.is_linked ());
      auto it = m_resumed_with_pending_wait_status.iterator_to (*thread);
      m_resumed_with_pending_wait_status.erase (it);
    }
  else
    gdb_assert (!thread->resumed_with_pending_wait_status_node.is_linked ());
}

/* See process-stratum-target.h.  */

thread_info *
process_stratum_target::random_resumed_with_pending_wait_status
  (inferior *inf, ptid_t filter_ptid)
{
  auto matches = [inf, filter_ptid] (const thread_info &thread)
    {
      return thread.inf == inf && thread.ptid.matches (filter_ptid);
    };

  /* First see how many matching events we have.  */
  const auto &l = m_resumed_with_pending_wait_status;
  unsigned int count = std::count_if (l.begin (), l.end (), matches);

  if (count == 0)
    return nullptr;

  /* Now randomly pick a thread out of those that match the criteria.  */
  int random_selector
    = (int) ((count * (double) rand ()) / (RAND_MAX + 1.0));

  if (count > 1)
    infrun_debug_printf ("Found %u events, selecting #%d",
			 count, random_selector);

  /* Select the Nth thread that matches.  */
  auto it = std::find_if (l.begin (), l.end (),
			  [&random_selector, &matches]
			  (const thread_info &thread)
    {
      if (!matches (thread))
	return false;

      return random_selector-- == 0;
    });

  gdb_assert (it != l.end ());

  return &*it;
}

/* See process-stratum-target.h.  */

thread_info *
process_stratum_target::find_thread (ptid_t ptid)
{
  inferior *inf = find_inferior_ptid (this, ptid);
  if (inf == NULL)
    return NULL;
  return inf->find_thread (ptid);
}

/* See process-stratum-target.h.  */

gdb::unordered_set<process_stratum_target *>
all_non_exited_process_targets ()
{
  /* Inferiors may share targets.  To eliminate duplicates, use a set.  */
  gdb::unordered_set<process_stratum_target *> targets;
  for (inferior *inf : all_non_exited_inferiors ())
    targets.insert (inf->process_target ());

  return targets;
}

/* See process-stratum-target.h.  */

void
switch_to_target_no_thread (process_stratum_target *target)
{
  for (inferior *inf : all_inferiors (target))
    {
      switch_to_inferior_no_thread (inf);
      break;
    }
}
