/* Multi-thread control defs for remote server for GDB.
   Copyright (C) 1993-2024 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/>.  */

#ifndef GDBSERVER_GDBTHREAD_H
#define GDBSERVER_GDBTHREAD_H

#include "gdbsupport/function-view.h"
#include "gdbsupport/intrusive_list.h"
#include <memory>

struct btrace_target_info;
struct regcache;

struct thread_info : public intrusive_list_node<thread_info>
{
  thread_info (ptid_t id, process_info *process, void *target_data)
    : id (id), m_process (process), m_target_data (target_data)
  {}

  /* Return the process owning this thread.  */
  process_info *process () const
  { return m_process; }

  struct regcache *regcache ()
  { return m_regcache.get (); }

  void set_regcache (std::unique_ptr<struct regcache> regcache)
  { m_regcache = std::move (regcache); }

  void *target_data ()
  { return m_target_data; }

  /* The id of this thread.  */
  ptid_t id;

  /* The last resume GDB requested on this thread.  */
  enum resume_kind last_resume_kind = resume_continue;

  /* The last wait status reported for this thread.  */
  struct target_waitstatus last_status;

  /* True if LAST_STATUS hasn't been reported to GDB yet.  */
  int status_pending_p = 0;

  /* Given `while-stepping', a thread may be collecting data for more
     than one tracepoint simultaneously.  E.g.:

    ff0001  INSN1 <-- TP1, while-stepping 10 collect $regs
    ff0002  INSN2
    ff0003  INSN3 <-- TP2, collect $regs
    ff0004  INSN4 <-- TP3, while-stepping 10 collect $regs
    ff0005  INSN5

   Notice that when instruction INSN5 is reached, the while-stepping
   actions of both TP1 and TP3 are still being collected, and that TP2
   had been collected meanwhile.  The whole range of ff0001-ff0005
   should be single-stepped, due to at least TP1's while-stepping
   action covering the whole range.

   On the other hand, the same tracepoint with a while-stepping action
   may be hit by more than one thread simultaneously, hence we can't
   keep the current step count in the tracepoint itself.

   This is the head of the list of the states of `while-stepping'
   tracepoint actions this thread is now collecting; NULL if empty.
   Each item in the list holds the current step of the while-stepping
   action.  */
  struct wstep_state *while_stepping = nullptr;

  /* Branch trace target information for this thread.  */
  struct btrace_target_info *btrace = nullptr;

  /* Thread options GDB requested with QThreadOptions.  */
  gdb_thread_options thread_options = 0;
  
private:
  process_info *m_process;
  std::unique_ptr<struct regcache> m_regcache = nullptr;
  void *m_target_data;
};

/* Return a pointer to the first thread, or NULL if there isn't one.  */

thread_info *get_first_thread (void);

thread_info *find_thread_ptid (ptid_t ptid);

/* Find any thread of the PID process.  Returns NULL if none is
   found.  */
thread_info *find_any_thread_of_pid (int pid);

/* Find the first thread for which FUNC returns true.  Return NULL if no thread
   satisfying FUNC is found.  */

thread_info *find_thread (gdb::function_view<bool (thread_info *)> func);

/* Like the above, but only consider threads with pid PID.  */

thread_info *find_thread (int pid,
			  gdb::function_view<bool (thread_info *)> func);

/* Find the first thread that matches FILTER for which FUNC returns true.
   Return NULL if no thread satisfying these conditions is found.  */

thread_info *find_thread (ptid_t filter,
			  gdb::function_view<bool (thread_info *)> func);

/* Invoke FUNC for each thread.  */

void for_each_thread (gdb::function_view<void (thread_info *)> func);

/* Like the above, but only consider threads matching PTID.  */

void for_each_thread
  (ptid_t ptid, gdb::function_view<void (thread_info *)> func);

/* Find a random thread that matches PTID and for which FUNC (THREAD)
   returns true.  If no entry is found then return nullptr.  */

thread_info *find_thread_in_random
  (gdb::function_view<bool (thread_info *)> func);

/* Like the above, but only consider threads matching PTID.  */

thread_info *find_thread_in_random
  (ptid_t ptid, gdb::function_view<bool (thread_info *)> func);

/* Switch the current thread.  */

void switch_to_thread (thread_info *thread);

/* Save/restore current thread.  */

class scoped_restore_current_thread
{
public:
  scoped_restore_current_thread ();
  ~scoped_restore_current_thread ();

  DISABLE_COPY_AND_ASSIGN (scoped_restore_current_thread);

  /* Cancel restoring on scope exit.  */
  void dont_restore () { m_dont_restore = true; }

private:
  bool m_dont_restore = false;
  process_info *m_process;
  thread_info *m_thread;
};

#endif /* GDBSERVER_GDBTHREAD_H */
