xref: /dflybsd-src/contrib/gdb-7/gdb/thread.c (revision cf7f2e2d389e8012d562650bd94d7e433f449d6e)
15796c8dcSSimon Schubert /* Multi-process/thread control for GDB, the GNU debugger.
25796c8dcSSimon Schubert 
35796c8dcSSimon Schubert    Copyright (C) 1986, 1987, 1988, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
4*cf7f2e2dSJohn Marino    2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010
55796c8dcSSimon Schubert    Free Software Foundation, Inc.
65796c8dcSSimon Schubert 
75796c8dcSSimon Schubert    Contributed by Lynx Real-Time Systems, Inc.  Los Gatos, CA.
85796c8dcSSimon Schubert 
95796c8dcSSimon Schubert    This file is part of GDB.
105796c8dcSSimon Schubert 
115796c8dcSSimon Schubert    This program is free software; you can redistribute it and/or modify
125796c8dcSSimon Schubert    it under the terms of the GNU General Public License as published by
135796c8dcSSimon Schubert    the Free Software Foundation; either version 3 of the License, or
145796c8dcSSimon Schubert    (at your option) any later version.
155796c8dcSSimon Schubert 
165796c8dcSSimon Schubert    This program is distributed in the hope that it will be useful,
175796c8dcSSimon Schubert    but WITHOUT ANY WARRANTY; without even the implied warranty of
185796c8dcSSimon Schubert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
195796c8dcSSimon Schubert    GNU General Public License for more details.
205796c8dcSSimon Schubert 
215796c8dcSSimon Schubert    You should have received a copy of the GNU General Public License
225796c8dcSSimon Schubert    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
235796c8dcSSimon Schubert 
245796c8dcSSimon Schubert #include "defs.h"
255796c8dcSSimon Schubert #include "symtab.h"
265796c8dcSSimon Schubert #include "frame.h"
275796c8dcSSimon Schubert #include "inferior.h"
285796c8dcSSimon Schubert #include "environ.h"
295796c8dcSSimon Schubert #include "value.h"
305796c8dcSSimon Schubert #include "target.h"
315796c8dcSSimon Schubert #include "gdbthread.h"
325796c8dcSSimon Schubert #include "exceptions.h"
335796c8dcSSimon Schubert #include "command.h"
345796c8dcSSimon Schubert #include "gdbcmd.h"
355796c8dcSSimon Schubert #include "regcache.h"
365796c8dcSSimon Schubert #include "gdb.h"
375796c8dcSSimon Schubert #include "gdb_string.h"
385796c8dcSSimon Schubert 
395796c8dcSSimon Schubert #include <ctype.h>
405796c8dcSSimon Schubert #include <sys/types.h>
415796c8dcSSimon Schubert #include <signal.h>
425796c8dcSSimon Schubert #include "ui-out.h"
435796c8dcSSimon Schubert #include "observer.h"
445796c8dcSSimon Schubert #include "annotate.h"
455796c8dcSSimon Schubert #include "cli/cli-decode.h"
465796c8dcSSimon Schubert 
475796c8dcSSimon Schubert /* Definition of struct thread_info exported to gdbthread.h */
485796c8dcSSimon Schubert 
495796c8dcSSimon Schubert /* Prototypes for exported functions. */
505796c8dcSSimon Schubert 
515796c8dcSSimon Schubert void _initialize_thread (void);
525796c8dcSSimon Schubert 
535796c8dcSSimon Schubert /* Prototypes for local functions. */
545796c8dcSSimon Schubert 
555796c8dcSSimon Schubert static struct thread_info *thread_list = NULL;
565796c8dcSSimon Schubert static int highest_thread_num;
575796c8dcSSimon Schubert 
585796c8dcSSimon Schubert static void thread_command (char *tidstr, int from_tty);
595796c8dcSSimon Schubert static void thread_apply_all_command (char *, int);
605796c8dcSSimon Schubert static int thread_alive (struct thread_info *);
615796c8dcSSimon Schubert static void info_threads_command (char *, int);
625796c8dcSSimon Schubert static void thread_apply_command (char *, int);
635796c8dcSSimon Schubert static void restore_current_thread (ptid_t);
645796c8dcSSimon Schubert static void prune_threads (void);
655796c8dcSSimon Schubert 
665796c8dcSSimon Schubert /* Frontend view of the thread state.  Possible extensions: stepping,
675796c8dcSSimon Schubert    finishing, until(ling),...  */
685796c8dcSSimon Schubert enum thread_state
695796c8dcSSimon Schubert {
705796c8dcSSimon Schubert   THREAD_STOPPED,
715796c8dcSSimon Schubert   THREAD_RUNNING,
725796c8dcSSimon Schubert   THREAD_EXITED,
735796c8dcSSimon Schubert };
745796c8dcSSimon Schubert 
755796c8dcSSimon Schubert struct thread_info*
765796c8dcSSimon Schubert inferior_thread (void)
775796c8dcSSimon Schubert {
785796c8dcSSimon Schubert   struct thread_info *tp = find_thread_ptid (inferior_ptid);
795796c8dcSSimon Schubert   gdb_assert (tp);
805796c8dcSSimon Schubert   return tp;
815796c8dcSSimon Schubert }
825796c8dcSSimon Schubert 
835796c8dcSSimon Schubert void
845796c8dcSSimon Schubert delete_step_resume_breakpoint (struct thread_info *tp)
855796c8dcSSimon Schubert {
865796c8dcSSimon Schubert   if (tp && tp->step_resume_breakpoint)
875796c8dcSSimon Schubert     {
885796c8dcSSimon Schubert       delete_breakpoint (tp->step_resume_breakpoint);
895796c8dcSSimon Schubert       tp->step_resume_breakpoint = NULL;
905796c8dcSSimon Schubert     }
915796c8dcSSimon Schubert }
925796c8dcSSimon Schubert 
935796c8dcSSimon Schubert static void
945796c8dcSSimon Schubert clear_thread_inferior_resources (struct thread_info *tp)
955796c8dcSSimon Schubert {
965796c8dcSSimon Schubert   /* NOTE: this will take care of any left-over step_resume breakpoints,
975796c8dcSSimon Schubert      but not any user-specified thread-specific breakpoints.  We can not
985796c8dcSSimon Schubert      delete the breakpoint straight-off, because the inferior might not
995796c8dcSSimon Schubert      be stopped at the moment.  */
1005796c8dcSSimon Schubert   if (tp->step_resume_breakpoint)
1015796c8dcSSimon Schubert     {
1025796c8dcSSimon Schubert       tp->step_resume_breakpoint->disposition = disp_del_at_next_stop;
1035796c8dcSSimon Schubert       tp->step_resume_breakpoint = NULL;
1045796c8dcSSimon Schubert     }
1055796c8dcSSimon Schubert 
1065796c8dcSSimon Schubert   bpstat_clear (&tp->stop_bpstat);
1075796c8dcSSimon Schubert 
1085796c8dcSSimon Schubert   discard_all_intermediate_continuations_thread (tp);
1095796c8dcSSimon Schubert   discard_all_continuations_thread (tp);
1105796c8dcSSimon Schubert }
1115796c8dcSSimon Schubert 
1125796c8dcSSimon Schubert static void
1135796c8dcSSimon Schubert free_thread (struct thread_info *tp)
1145796c8dcSSimon Schubert {
1155796c8dcSSimon Schubert   clear_thread_inferior_resources (tp);
1165796c8dcSSimon Schubert 
1175796c8dcSSimon Schubert   if (tp->private)
118*cf7f2e2dSJohn Marino     {
119*cf7f2e2dSJohn Marino       if (tp->private_dtor)
120*cf7f2e2dSJohn Marino 	tp->private_dtor (tp->private);
121*cf7f2e2dSJohn Marino       else
1225796c8dcSSimon Schubert 	xfree (tp->private);
123*cf7f2e2dSJohn Marino     }
1245796c8dcSSimon Schubert 
1255796c8dcSSimon Schubert   xfree (tp);
1265796c8dcSSimon Schubert }
1275796c8dcSSimon Schubert 
1285796c8dcSSimon Schubert void
1295796c8dcSSimon Schubert init_thread_list (void)
1305796c8dcSSimon Schubert {
1315796c8dcSSimon Schubert   struct thread_info *tp, *tpnext;
1325796c8dcSSimon Schubert 
1335796c8dcSSimon Schubert   highest_thread_num = 0;
1345796c8dcSSimon Schubert 
1355796c8dcSSimon Schubert   if (!thread_list)
1365796c8dcSSimon Schubert     return;
1375796c8dcSSimon Schubert 
1385796c8dcSSimon Schubert   for (tp = thread_list; tp; tp = tpnext)
1395796c8dcSSimon Schubert     {
1405796c8dcSSimon Schubert       tpnext = tp->next;
1415796c8dcSSimon Schubert       free_thread (tp);
1425796c8dcSSimon Schubert     }
1435796c8dcSSimon Schubert 
1445796c8dcSSimon Schubert   thread_list = NULL;
1455796c8dcSSimon Schubert }
1465796c8dcSSimon Schubert 
1475796c8dcSSimon Schubert /* Allocate a new thread with target id PTID and add it to the thread
1485796c8dcSSimon Schubert    list.  */
1495796c8dcSSimon Schubert 
1505796c8dcSSimon Schubert static struct thread_info *
1515796c8dcSSimon Schubert new_thread (ptid_t ptid)
1525796c8dcSSimon Schubert {
1535796c8dcSSimon Schubert   struct thread_info *tp;
1545796c8dcSSimon Schubert 
1555796c8dcSSimon Schubert   tp = xcalloc (1, sizeof (*tp));
1565796c8dcSSimon Schubert 
1575796c8dcSSimon Schubert   tp->ptid = ptid;
1585796c8dcSSimon Schubert   tp->num = ++highest_thread_num;
1595796c8dcSSimon Schubert   tp->next = thread_list;
1605796c8dcSSimon Schubert   thread_list = tp;
1615796c8dcSSimon Schubert 
1625796c8dcSSimon Schubert   /* Nothing to follow yet.  */
1635796c8dcSSimon Schubert   tp->pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
1645796c8dcSSimon Schubert   tp->state_ = THREAD_STOPPED;
1655796c8dcSSimon Schubert 
1665796c8dcSSimon Schubert   return tp;
1675796c8dcSSimon Schubert }
1685796c8dcSSimon Schubert 
1695796c8dcSSimon Schubert struct thread_info *
1705796c8dcSSimon Schubert add_thread_silent (ptid_t ptid)
1715796c8dcSSimon Schubert {
1725796c8dcSSimon Schubert   struct thread_info *tp;
1735796c8dcSSimon Schubert 
1745796c8dcSSimon Schubert   tp = find_thread_ptid (ptid);
1755796c8dcSSimon Schubert   if (tp)
1765796c8dcSSimon Schubert     /* Found an old thread with the same id.  It has to be dead,
1775796c8dcSSimon Schubert        otherwise we wouldn't be adding a new thread with the same id.
1785796c8dcSSimon Schubert        The OS is reusing this id --- delete it, and recreate a new
1795796c8dcSSimon Schubert        one.  */
1805796c8dcSSimon Schubert     {
1815796c8dcSSimon Schubert       /* In addition to deleting the thread, if this is the current
1825796c8dcSSimon Schubert 	 thread, then we need to take care that delete_thread doesn't
1835796c8dcSSimon Schubert 	 really delete the thread if it is inferior_ptid.  Create a
1845796c8dcSSimon Schubert 	 new template thread in the list with an invalid ptid, switch
1855796c8dcSSimon Schubert 	 to it, delete the original thread, reset the new thread's
1865796c8dcSSimon Schubert 	 ptid, and switch to it.  */
1875796c8dcSSimon Schubert 
1885796c8dcSSimon Schubert       if (ptid_equal (inferior_ptid, ptid))
1895796c8dcSSimon Schubert 	{
190*cf7f2e2dSJohn Marino 	  tp = new_thread (null_ptid);
1915796c8dcSSimon Schubert 
1925796c8dcSSimon Schubert 	  /* Make switch_to_thread not read from the thread.  */
1935796c8dcSSimon Schubert 	  tp->state_ = THREAD_EXITED;
194*cf7f2e2dSJohn Marino 	  switch_to_thread (null_ptid);
1955796c8dcSSimon Schubert 
1965796c8dcSSimon Schubert 	  /* Now we can delete it.  */
1975796c8dcSSimon Schubert 	  delete_thread (ptid);
1985796c8dcSSimon Schubert 
1995796c8dcSSimon Schubert 	  /* Now reset its ptid, and reswitch inferior_ptid to it.  */
2005796c8dcSSimon Schubert 	  tp->ptid = ptid;
2015796c8dcSSimon Schubert 	  tp->state_ = THREAD_STOPPED;
2025796c8dcSSimon Schubert 	  switch_to_thread (ptid);
2035796c8dcSSimon Schubert 
2045796c8dcSSimon Schubert 	  observer_notify_new_thread (tp);
2055796c8dcSSimon Schubert 
2065796c8dcSSimon Schubert 	  /* All done.  */
2075796c8dcSSimon Schubert 	  return tp;
2085796c8dcSSimon Schubert 	}
2095796c8dcSSimon Schubert       else
2105796c8dcSSimon Schubert 	/* Just go ahead and delete it.  */
2115796c8dcSSimon Schubert 	delete_thread (ptid);
2125796c8dcSSimon Schubert     }
2135796c8dcSSimon Schubert 
2145796c8dcSSimon Schubert   tp = new_thread (ptid);
2155796c8dcSSimon Schubert   observer_notify_new_thread (tp);
2165796c8dcSSimon Schubert 
2175796c8dcSSimon Schubert   return tp;
2185796c8dcSSimon Schubert }
2195796c8dcSSimon Schubert 
2205796c8dcSSimon Schubert struct thread_info *
2215796c8dcSSimon Schubert add_thread_with_info (ptid_t ptid, struct private_thread_info *private)
2225796c8dcSSimon Schubert {
2235796c8dcSSimon Schubert   struct thread_info *result = add_thread_silent (ptid);
2245796c8dcSSimon Schubert 
2255796c8dcSSimon Schubert   result->private = private;
2265796c8dcSSimon Schubert 
2275796c8dcSSimon Schubert   if (print_thread_events)
2285796c8dcSSimon Schubert     printf_unfiltered (_("[New %s]\n"), target_pid_to_str (ptid));
2295796c8dcSSimon Schubert 
2305796c8dcSSimon Schubert   annotate_new_thread ();
2315796c8dcSSimon Schubert   return result;
2325796c8dcSSimon Schubert }
2335796c8dcSSimon Schubert 
2345796c8dcSSimon Schubert struct thread_info *
2355796c8dcSSimon Schubert add_thread (ptid_t ptid)
2365796c8dcSSimon Schubert {
2375796c8dcSSimon Schubert   return add_thread_with_info (ptid, NULL);
2385796c8dcSSimon Schubert }
2395796c8dcSSimon Schubert 
2405796c8dcSSimon Schubert /* Delete thread PTID.  If SILENT, don't notify the observer of this
2415796c8dcSSimon Schubert    exit.  */
2425796c8dcSSimon Schubert static void
2435796c8dcSSimon Schubert delete_thread_1 (ptid_t ptid, int silent)
2445796c8dcSSimon Schubert {
2455796c8dcSSimon Schubert   struct thread_info *tp, *tpprev;
2465796c8dcSSimon Schubert 
2475796c8dcSSimon Schubert   tpprev = NULL;
2485796c8dcSSimon Schubert 
2495796c8dcSSimon Schubert   for (tp = thread_list; tp; tpprev = tp, tp = tp->next)
2505796c8dcSSimon Schubert     if (ptid_equal (tp->ptid, ptid))
2515796c8dcSSimon Schubert       break;
2525796c8dcSSimon Schubert 
2535796c8dcSSimon Schubert   if (!tp)
2545796c8dcSSimon Schubert     return;
2555796c8dcSSimon Schubert 
2565796c8dcSSimon Schubert   /* If this is the current thread, or there's code out there that
2575796c8dcSSimon Schubert      relies on it existing (refcount > 0) we can't delete yet.  Mark
2585796c8dcSSimon Schubert      it as exited, and notify it.  */
2595796c8dcSSimon Schubert   if (tp->refcount > 0
2605796c8dcSSimon Schubert       || ptid_equal (tp->ptid, inferior_ptid))
2615796c8dcSSimon Schubert     {
2625796c8dcSSimon Schubert       if (tp->state_ != THREAD_EXITED)
2635796c8dcSSimon Schubert 	{
2645796c8dcSSimon Schubert 	  observer_notify_thread_exit (tp, silent);
2655796c8dcSSimon Schubert 
2665796c8dcSSimon Schubert 	  /* Tag it as exited.  */
2675796c8dcSSimon Schubert 	  tp->state_ = THREAD_EXITED;
2685796c8dcSSimon Schubert 
2695796c8dcSSimon Schubert 	  /* Clear breakpoints, etc. associated with this thread.  */
2705796c8dcSSimon Schubert 	  clear_thread_inferior_resources (tp);
2715796c8dcSSimon Schubert 	}
2725796c8dcSSimon Schubert 
2735796c8dcSSimon Schubert        /* Will be really deleted some other time.  */
2745796c8dcSSimon Schubert        return;
2755796c8dcSSimon Schubert      }
2765796c8dcSSimon Schubert 
2775796c8dcSSimon Schubert   if (tpprev)
2785796c8dcSSimon Schubert     tpprev->next = tp->next;
2795796c8dcSSimon Schubert   else
2805796c8dcSSimon Schubert     thread_list = tp->next;
2815796c8dcSSimon Schubert 
2825796c8dcSSimon Schubert   /* Notify thread exit, but only if we haven't already.  */
2835796c8dcSSimon Schubert   if (tp->state_ != THREAD_EXITED)
2845796c8dcSSimon Schubert     observer_notify_thread_exit (tp, silent);
2855796c8dcSSimon Schubert 
2865796c8dcSSimon Schubert   free_thread (tp);
2875796c8dcSSimon Schubert }
2885796c8dcSSimon Schubert 
2895796c8dcSSimon Schubert /* Delete thread PTID and notify of thread exit.  If this is
2905796c8dcSSimon Schubert    inferior_ptid, don't actually delete it, but tag it as exited and
2915796c8dcSSimon Schubert    do the notification.  If PTID is the user selected thread, clear
2925796c8dcSSimon Schubert    it.  */
2935796c8dcSSimon Schubert void
2945796c8dcSSimon Schubert delete_thread (ptid_t ptid)
2955796c8dcSSimon Schubert {
2965796c8dcSSimon Schubert   delete_thread_1 (ptid, 0 /* not silent */);
2975796c8dcSSimon Schubert }
2985796c8dcSSimon Schubert 
2995796c8dcSSimon Schubert void
3005796c8dcSSimon Schubert delete_thread_silent (ptid_t ptid)
3015796c8dcSSimon Schubert {
3025796c8dcSSimon Schubert   delete_thread_1 (ptid, 1 /* silent */);
3035796c8dcSSimon Schubert }
3045796c8dcSSimon Schubert 
3055796c8dcSSimon Schubert struct thread_info *
3065796c8dcSSimon Schubert find_thread_id (int num)
3075796c8dcSSimon Schubert {
3085796c8dcSSimon Schubert   struct thread_info *tp;
3095796c8dcSSimon Schubert 
3105796c8dcSSimon Schubert   for (tp = thread_list; tp; tp = tp->next)
3115796c8dcSSimon Schubert     if (tp->num == num)
3125796c8dcSSimon Schubert       return tp;
3135796c8dcSSimon Schubert 
3145796c8dcSSimon Schubert   return NULL;
3155796c8dcSSimon Schubert }
3165796c8dcSSimon Schubert 
3175796c8dcSSimon Schubert /* Find a thread_info by matching PTID.  */
3185796c8dcSSimon Schubert struct thread_info *
3195796c8dcSSimon Schubert find_thread_ptid (ptid_t ptid)
3205796c8dcSSimon Schubert {
3215796c8dcSSimon Schubert   struct thread_info *tp;
3225796c8dcSSimon Schubert 
3235796c8dcSSimon Schubert   for (tp = thread_list; tp; tp = tp->next)
3245796c8dcSSimon Schubert     if (ptid_equal (tp->ptid, ptid))
3255796c8dcSSimon Schubert       return tp;
3265796c8dcSSimon Schubert 
3275796c8dcSSimon Schubert   return NULL;
3285796c8dcSSimon Schubert }
3295796c8dcSSimon Schubert 
3305796c8dcSSimon Schubert /*
3315796c8dcSSimon Schubert  * Thread iterator function.
3325796c8dcSSimon Schubert  *
3335796c8dcSSimon Schubert  * Calls a callback function once for each thread, so long as
3345796c8dcSSimon Schubert  * the callback function returns false.  If the callback function
3355796c8dcSSimon Schubert  * returns true, the iteration will end and the current thread
3365796c8dcSSimon Schubert  * will be returned.  This can be useful for implementing a
3375796c8dcSSimon Schubert  * search for a thread with arbitrary attributes, or for applying
3385796c8dcSSimon Schubert  * some operation to every thread.
3395796c8dcSSimon Schubert  *
3405796c8dcSSimon Schubert  * FIXME: some of the existing functionality, such as
3415796c8dcSSimon Schubert  * "Thread apply all", might be rewritten using this functionality.
3425796c8dcSSimon Schubert  */
3435796c8dcSSimon Schubert 
3445796c8dcSSimon Schubert struct thread_info *
3455796c8dcSSimon Schubert iterate_over_threads (int (*callback) (struct thread_info *, void *),
3465796c8dcSSimon Schubert 		      void *data)
3475796c8dcSSimon Schubert {
3485796c8dcSSimon Schubert   struct thread_info *tp, *next;
3495796c8dcSSimon Schubert 
3505796c8dcSSimon Schubert   for (tp = thread_list; tp; tp = next)
3515796c8dcSSimon Schubert     {
3525796c8dcSSimon Schubert       next = tp->next;
3535796c8dcSSimon Schubert       if ((*callback) (tp, data))
3545796c8dcSSimon Schubert 	return tp;
3555796c8dcSSimon Schubert     }
3565796c8dcSSimon Schubert 
3575796c8dcSSimon Schubert   return NULL;
3585796c8dcSSimon Schubert }
3595796c8dcSSimon Schubert 
3605796c8dcSSimon Schubert int
3615796c8dcSSimon Schubert thread_count (void)
3625796c8dcSSimon Schubert {
3635796c8dcSSimon Schubert   int result = 0;
3645796c8dcSSimon Schubert   struct thread_info *tp;
3655796c8dcSSimon Schubert 
3665796c8dcSSimon Schubert   for (tp = thread_list; tp; tp = tp->next)
3675796c8dcSSimon Schubert     ++result;
3685796c8dcSSimon Schubert 
3695796c8dcSSimon Schubert   return result;
3705796c8dcSSimon Schubert }
3715796c8dcSSimon Schubert 
3725796c8dcSSimon Schubert int
3735796c8dcSSimon Schubert valid_thread_id (int num)
3745796c8dcSSimon Schubert {
3755796c8dcSSimon Schubert   struct thread_info *tp;
3765796c8dcSSimon Schubert 
3775796c8dcSSimon Schubert   for (tp = thread_list; tp; tp = tp->next)
3785796c8dcSSimon Schubert     if (tp->num == num)
3795796c8dcSSimon Schubert       return 1;
3805796c8dcSSimon Schubert 
3815796c8dcSSimon Schubert   return 0;
3825796c8dcSSimon Schubert }
3835796c8dcSSimon Schubert 
3845796c8dcSSimon Schubert int
3855796c8dcSSimon Schubert pid_to_thread_id (ptid_t ptid)
3865796c8dcSSimon Schubert {
3875796c8dcSSimon Schubert   struct thread_info *tp;
3885796c8dcSSimon Schubert 
3895796c8dcSSimon Schubert   for (tp = thread_list; tp; tp = tp->next)
3905796c8dcSSimon Schubert     if (ptid_equal (tp->ptid, ptid))
3915796c8dcSSimon Schubert       return tp->num;
3925796c8dcSSimon Schubert 
3935796c8dcSSimon Schubert   return 0;
3945796c8dcSSimon Schubert }
3955796c8dcSSimon Schubert 
3965796c8dcSSimon Schubert ptid_t
3975796c8dcSSimon Schubert thread_id_to_pid (int num)
3985796c8dcSSimon Schubert {
3995796c8dcSSimon Schubert   struct thread_info *thread = find_thread_id (num);
400*cf7f2e2dSJohn Marino 
4015796c8dcSSimon Schubert   if (thread)
4025796c8dcSSimon Schubert     return thread->ptid;
4035796c8dcSSimon Schubert   else
4045796c8dcSSimon Schubert     return pid_to_ptid (-1);
4055796c8dcSSimon Schubert }
4065796c8dcSSimon Schubert 
4075796c8dcSSimon Schubert int
4085796c8dcSSimon Schubert in_thread_list (ptid_t ptid)
4095796c8dcSSimon Schubert {
4105796c8dcSSimon Schubert   struct thread_info *tp;
4115796c8dcSSimon Schubert 
4125796c8dcSSimon Schubert   for (tp = thread_list; tp; tp = tp->next)
4135796c8dcSSimon Schubert     if (ptid_equal (tp->ptid, ptid))
4145796c8dcSSimon Schubert       return 1;
4155796c8dcSSimon Schubert 
4165796c8dcSSimon Schubert   return 0;			/* Never heard of 'im */
4175796c8dcSSimon Schubert }
4185796c8dcSSimon Schubert 
4195796c8dcSSimon Schubert /* Finds the first thread of the inferior given by PID.  If PID is -1,
4205796c8dcSSimon Schubert    return the first thread in the list.  */
4215796c8dcSSimon Schubert 
4225796c8dcSSimon Schubert struct thread_info *
4235796c8dcSSimon Schubert first_thread_of_process (int pid)
4245796c8dcSSimon Schubert {
4255796c8dcSSimon Schubert   struct thread_info *tp, *ret = NULL;
4265796c8dcSSimon Schubert 
4275796c8dcSSimon Schubert   for (tp = thread_list; tp; tp = tp->next)
4285796c8dcSSimon Schubert     if (pid == -1 || ptid_get_pid (tp->ptid) == pid)
4295796c8dcSSimon Schubert       if (ret == NULL || tp->num < ret->num)
4305796c8dcSSimon Schubert 	ret = tp;
4315796c8dcSSimon Schubert 
4325796c8dcSSimon Schubert   return ret;
4335796c8dcSSimon Schubert }
4345796c8dcSSimon Schubert 
4355796c8dcSSimon Schubert struct thread_info *
4365796c8dcSSimon Schubert any_thread_of_process (int pid)
4375796c8dcSSimon Schubert {
4385796c8dcSSimon Schubert   struct thread_info *tp;
4395796c8dcSSimon Schubert 
4405796c8dcSSimon Schubert   for (tp = thread_list; tp; tp = tp->next)
4415796c8dcSSimon Schubert     if (ptid_get_pid (tp->ptid) == pid)
4425796c8dcSSimon Schubert       return tp;
4435796c8dcSSimon Schubert 
4445796c8dcSSimon Schubert   return NULL;
4455796c8dcSSimon Schubert }
4465796c8dcSSimon Schubert 
447*cf7f2e2dSJohn Marino struct thread_info *
448*cf7f2e2dSJohn Marino any_live_thread_of_process (int pid)
449*cf7f2e2dSJohn Marino {
450*cf7f2e2dSJohn Marino   struct thread_info *tp;
451*cf7f2e2dSJohn Marino   struct thread_info *tp_running = NULL;
452*cf7f2e2dSJohn Marino 
453*cf7f2e2dSJohn Marino   for (tp = thread_list; tp; tp = tp->next)
454*cf7f2e2dSJohn Marino     if (ptid_get_pid (tp->ptid) == pid)
455*cf7f2e2dSJohn Marino       {
456*cf7f2e2dSJohn Marino 	if (tp->state_ == THREAD_STOPPED)
457*cf7f2e2dSJohn Marino 	  return tp;
458*cf7f2e2dSJohn Marino 	else if (tp->state_ == THREAD_RUNNING)
459*cf7f2e2dSJohn Marino 	  tp_running = tp;
460*cf7f2e2dSJohn Marino       }
461*cf7f2e2dSJohn Marino 
462*cf7f2e2dSJohn Marino   return tp_running;
463*cf7f2e2dSJohn Marino }
464*cf7f2e2dSJohn Marino 
4655796c8dcSSimon Schubert /* Print a list of thread ids currently known, and the total number of
4665796c8dcSSimon Schubert    threads. To be used from within catch_errors. */
4675796c8dcSSimon Schubert static int
4685796c8dcSSimon Schubert do_captured_list_thread_ids (struct ui_out *uiout, void *arg)
4695796c8dcSSimon Schubert {
4705796c8dcSSimon Schubert   struct thread_info *tp;
4715796c8dcSSimon Schubert   int num = 0;
4725796c8dcSSimon Schubert   struct cleanup *cleanup_chain;
4735796c8dcSSimon Schubert   int current_thread = -1;
4745796c8dcSSimon Schubert 
475*cf7f2e2dSJohn Marino   update_thread_list ();
4765796c8dcSSimon Schubert 
4775796c8dcSSimon Schubert   cleanup_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "thread-ids");
4785796c8dcSSimon Schubert 
4795796c8dcSSimon Schubert   for (tp = thread_list; tp; tp = tp->next)
4805796c8dcSSimon Schubert     {
4815796c8dcSSimon Schubert       if (tp->state_ == THREAD_EXITED)
4825796c8dcSSimon Schubert 	continue;
4835796c8dcSSimon Schubert 
4845796c8dcSSimon Schubert       if (ptid_equal (tp->ptid, inferior_ptid))
4855796c8dcSSimon Schubert 	current_thread = tp->num;
4865796c8dcSSimon Schubert 
4875796c8dcSSimon Schubert       num++;
4885796c8dcSSimon Schubert       ui_out_field_int (uiout, "thread-id", tp->num);
4895796c8dcSSimon Schubert     }
4905796c8dcSSimon Schubert 
4915796c8dcSSimon Schubert   do_cleanups (cleanup_chain);
4925796c8dcSSimon Schubert 
4935796c8dcSSimon Schubert   if (current_thread != -1)
4945796c8dcSSimon Schubert     ui_out_field_int (uiout, "current-thread-id", current_thread);
4955796c8dcSSimon Schubert   ui_out_field_int (uiout, "number-of-threads", num);
4965796c8dcSSimon Schubert   return GDB_RC_OK;
4975796c8dcSSimon Schubert }
4985796c8dcSSimon Schubert 
4995796c8dcSSimon Schubert /* Official gdblib interface function to get a list of thread ids and
5005796c8dcSSimon Schubert    the total number. */
5015796c8dcSSimon Schubert enum gdb_rc
5025796c8dcSSimon Schubert gdb_list_thread_ids (struct ui_out *uiout, char **error_message)
5035796c8dcSSimon Schubert {
5045796c8dcSSimon Schubert   if (catch_exceptions_with_msg (uiout, do_captured_list_thread_ids, NULL,
5055796c8dcSSimon Schubert 				 error_message, RETURN_MASK_ALL) < 0)
5065796c8dcSSimon Schubert     return GDB_RC_FAIL;
5075796c8dcSSimon Schubert   return GDB_RC_OK;
5085796c8dcSSimon Schubert }
5095796c8dcSSimon Schubert 
5105796c8dcSSimon Schubert /* Return true if TP is an active thread. */
5115796c8dcSSimon Schubert static int
5125796c8dcSSimon Schubert thread_alive (struct thread_info *tp)
5135796c8dcSSimon Schubert {
5145796c8dcSSimon Schubert   if (tp->state_ == THREAD_EXITED)
5155796c8dcSSimon Schubert     return 0;
5165796c8dcSSimon Schubert   if (!target_thread_alive (tp->ptid))
5175796c8dcSSimon Schubert     return 0;
5185796c8dcSSimon Schubert   return 1;
5195796c8dcSSimon Schubert }
5205796c8dcSSimon Schubert 
5215796c8dcSSimon Schubert static void
5225796c8dcSSimon Schubert prune_threads (void)
5235796c8dcSSimon Schubert {
5245796c8dcSSimon Schubert   struct thread_info *tp, *next;
5255796c8dcSSimon Schubert 
5265796c8dcSSimon Schubert   for (tp = thread_list; tp; tp = next)
5275796c8dcSSimon Schubert     {
5285796c8dcSSimon Schubert       next = tp->next;
5295796c8dcSSimon Schubert       if (!thread_alive (tp))
5305796c8dcSSimon Schubert 	delete_thread (tp->ptid);
5315796c8dcSSimon Schubert     }
5325796c8dcSSimon Schubert }
5335796c8dcSSimon Schubert 
5345796c8dcSSimon Schubert void
5355796c8dcSSimon Schubert thread_change_ptid (ptid_t old_ptid, ptid_t new_ptid)
5365796c8dcSSimon Schubert {
5375796c8dcSSimon Schubert   struct inferior *inf;
5385796c8dcSSimon Schubert   struct thread_info *tp;
5395796c8dcSSimon Schubert 
5405796c8dcSSimon Schubert   /* It can happen that what we knew as the target inferior id
5415796c8dcSSimon Schubert      changes.  E.g, target remote may only discover the remote process
5425796c8dcSSimon Schubert      pid after adding the inferior to GDB's list.  */
5435796c8dcSSimon Schubert   inf = find_inferior_pid (ptid_get_pid (old_ptid));
5445796c8dcSSimon Schubert   inf->pid = ptid_get_pid (new_ptid);
5455796c8dcSSimon Schubert 
5465796c8dcSSimon Schubert   tp = find_thread_ptid (old_ptid);
5475796c8dcSSimon Schubert   tp->ptid = new_ptid;
5485796c8dcSSimon Schubert 
5495796c8dcSSimon Schubert   observer_notify_thread_ptid_changed (old_ptid, new_ptid);
5505796c8dcSSimon Schubert }
5515796c8dcSSimon Schubert 
5525796c8dcSSimon Schubert void
5535796c8dcSSimon Schubert set_running (ptid_t ptid, int running)
5545796c8dcSSimon Schubert {
5555796c8dcSSimon Schubert   struct thread_info *tp;
5565796c8dcSSimon Schubert   int all = ptid_equal (ptid, minus_one_ptid);
5575796c8dcSSimon Schubert 
5585796c8dcSSimon Schubert   /* We try not to notify the observer if no thread has actually changed
5595796c8dcSSimon Schubert      the running state -- merely to reduce the number of messages to
5605796c8dcSSimon Schubert      frontend.  Frontend is supposed to handle multiple *running just fine.  */
5615796c8dcSSimon Schubert   if (all || ptid_is_pid (ptid))
5625796c8dcSSimon Schubert     {
5635796c8dcSSimon Schubert       int any_started = 0;
564*cf7f2e2dSJohn Marino 
5655796c8dcSSimon Schubert       for (tp = thread_list; tp; tp = tp->next)
5665796c8dcSSimon Schubert 	if (all || ptid_get_pid (tp->ptid) == ptid_get_pid (ptid))
5675796c8dcSSimon Schubert 	  {
5685796c8dcSSimon Schubert 	    if (tp->state_ == THREAD_EXITED)
5695796c8dcSSimon Schubert 	      continue;
5705796c8dcSSimon Schubert 	    if (running && tp->state_ == THREAD_STOPPED)
5715796c8dcSSimon Schubert 	      any_started = 1;
5725796c8dcSSimon Schubert 	    tp->state_ = running ? THREAD_RUNNING : THREAD_STOPPED;
5735796c8dcSSimon Schubert 	  }
5745796c8dcSSimon Schubert       if (any_started)
5755796c8dcSSimon Schubert 	observer_notify_target_resumed (ptid);
5765796c8dcSSimon Schubert     }
5775796c8dcSSimon Schubert   else
5785796c8dcSSimon Schubert     {
5795796c8dcSSimon Schubert       int started = 0;
580*cf7f2e2dSJohn Marino 
5815796c8dcSSimon Schubert       tp = find_thread_ptid (ptid);
5825796c8dcSSimon Schubert       gdb_assert (tp);
5835796c8dcSSimon Schubert       gdb_assert (tp->state_ != THREAD_EXITED);
5845796c8dcSSimon Schubert       if (running && tp->state_ == THREAD_STOPPED)
5855796c8dcSSimon Schubert  	started = 1;
5865796c8dcSSimon Schubert       tp->state_ = running ? THREAD_RUNNING : THREAD_STOPPED;
5875796c8dcSSimon Schubert       if (started)
5885796c8dcSSimon Schubert   	observer_notify_target_resumed (ptid);
5895796c8dcSSimon Schubert     }
5905796c8dcSSimon Schubert }
5915796c8dcSSimon Schubert 
5925796c8dcSSimon Schubert static int
5935796c8dcSSimon Schubert is_thread_state (ptid_t ptid, enum thread_state state)
5945796c8dcSSimon Schubert {
5955796c8dcSSimon Schubert   struct thread_info *tp;
5965796c8dcSSimon Schubert 
5975796c8dcSSimon Schubert   tp = find_thread_ptid (ptid);
5985796c8dcSSimon Schubert   gdb_assert (tp);
5995796c8dcSSimon Schubert   return tp->state_ == state;
6005796c8dcSSimon Schubert }
6015796c8dcSSimon Schubert 
6025796c8dcSSimon Schubert int
6035796c8dcSSimon Schubert is_stopped (ptid_t ptid)
6045796c8dcSSimon Schubert {
6055796c8dcSSimon Schubert   return is_thread_state (ptid, THREAD_STOPPED);
6065796c8dcSSimon Schubert }
6075796c8dcSSimon Schubert 
6085796c8dcSSimon Schubert int
6095796c8dcSSimon Schubert is_exited (ptid_t ptid)
6105796c8dcSSimon Schubert {
6115796c8dcSSimon Schubert   return is_thread_state (ptid, THREAD_EXITED);
6125796c8dcSSimon Schubert }
6135796c8dcSSimon Schubert 
6145796c8dcSSimon Schubert int
6155796c8dcSSimon Schubert is_running (ptid_t ptid)
6165796c8dcSSimon Schubert {
6175796c8dcSSimon Schubert   return is_thread_state (ptid, THREAD_RUNNING);
6185796c8dcSSimon Schubert }
6195796c8dcSSimon Schubert 
6205796c8dcSSimon Schubert int
6215796c8dcSSimon Schubert any_running (void)
6225796c8dcSSimon Schubert {
6235796c8dcSSimon Schubert   struct thread_info *tp;
6245796c8dcSSimon Schubert 
6255796c8dcSSimon Schubert   for (tp = thread_list; tp; tp = tp->next)
6265796c8dcSSimon Schubert     if (tp->state_ == THREAD_RUNNING)
6275796c8dcSSimon Schubert       return 1;
6285796c8dcSSimon Schubert 
6295796c8dcSSimon Schubert   return 0;
6305796c8dcSSimon Schubert }
6315796c8dcSSimon Schubert 
6325796c8dcSSimon Schubert int
6335796c8dcSSimon Schubert is_executing (ptid_t ptid)
6345796c8dcSSimon Schubert {
6355796c8dcSSimon Schubert   struct thread_info *tp;
6365796c8dcSSimon Schubert 
6375796c8dcSSimon Schubert   tp = find_thread_ptid (ptid);
6385796c8dcSSimon Schubert   gdb_assert (tp);
6395796c8dcSSimon Schubert   return tp->executing_;
6405796c8dcSSimon Schubert }
6415796c8dcSSimon Schubert 
6425796c8dcSSimon Schubert void
6435796c8dcSSimon Schubert set_executing (ptid_t ptid, int executing)
6445796c8dcSSimon Schubert {
6455796c8dcSSimon Schubert   struct thread_info *tp;
6465796c8dcSSimon Schubert   int all = ptid_equal (ptid, minus_one_ptid);
6475796c8dcSSimon Schubert 
6485796c8dcSSimon Schubert   if (all || ptid_is_pid (ptid))
6495796c8dcSSimon Schubert     {
6505796c8dcSSimon Schubert       for (tp = thread_list; tp; tp = tp->next)
6515796c8dcSSimon Schubert 	if (all || ptid_get_pid (tp->ptid) == ptid_get_pid (ptid))
6525796c8dcSSimon Schubert 	  tp->executing_ = executing;
6535796c8dcSSimon Schubert     }
6545796c8dcSSimon Schubert   else
6555796c8dcSSimon Schubert     {
6565796c8dcSSimon Schubert       tp = find_thread_ptid (ptid);
6575796c8dcSSimon Schubert       gdb_assert (tp);
6585796c8dcSSimon Schubert       tp->executing_ = executing;
6595796c8dcSSimon Schubert     }
6605796c8dcSSimon Schubert }
6615796c8dcSSimon Schubert 
6625796c8dcSSimon Schubert void
6635796c8dcSSimon Schubert set_stop_requested (ptid_t ptid, int stop)
6645796c8dcSSimon Schubert {
6655796c8dcSSimon Schubert   struct thread_info *tp;
6665796c8dcSSimon Schubert   int all = ptid_equal (ptid, minus_one_ptid);
6675796c8dcSSimon Schubert 
6685796c8dcSSimon Schubert   if (all || ptid_is_pid (ptid))
6695796c8dcSSimon Schubert     {
6705796c8dcSSimon Schubert       for (tp = thread_list; tp; tp = tp->next)
6715796c8dcSSimon Schubert 	if (all || ptid_get_pid (tp->ptid) == ptid_get_pid (ptid))
6725796c8dcSSimon Schubert 	  tp->stop_requested = stop;
6735796c8dcSSimon Schubert     }
6745796c8dcSSimon Schubert   else
6755796c8dcSSimon Schubert     {
6765796c8dcSSimon Schubert       tp = find_thread_ptid (ptid);
6775796c8dcSSimon Schubert       gdb_assert (tp);
6785796c8dcSSimon Schubert       tp->stop_requested = stop;
6795796c8dcSSimon Schubert     }
6805796c8dcSSimon Schubert 
6815796c8dcSSimon Schubert   /* Call the stop requested observer so other components of GDB can
6825796c8dcSSimon Schubert      react to this request.  */
6835796c8dcSSimon Schubert   if (stop)
6845796c8dcSSimon Schubert     observer_notify_thread_stop_requested (ptid);
6855796c8dcSSimon Schubert }
6865796c8dcSSimon Schubert 
6875796c8dcSSimon Schubert void
6885796c8dcSSimon Schubert finish_thread_state (ptid_t ptid)
6895796c8dcSSimon Schubert {
6905796c8dcSSimon Schubert   struct thread_info *tp;
6915796c8dcSSimon Schubert   int all;
6925796c8dcSSimon Schubert   int any_started = 0;
6935796c8dcSSimon Schubert 
6945796c8dcSSimon Schubert   all = ptid_equal (ptid, minus_one_ptid);
6955796c8dcSSimon Schubert 
6965796c8dcSSimon Schubert   if (all || ptid_is_pid (ptid))
6975796c8dcSSimon Schubert     {
6985796c8dcSSimon Schubert       for (tp = thread_list; tp; tp = tp->next)
6995796c8dcSSimon Schubert 	{
7005796c8dcSSimon Schubert  	  if (tp->state_ == THREAD_EXITED)
7015796c8dcSSimon Schubert   	    continue;
7025796c8dcSSimon Schubert 	  if (all || ptid_get_pid (ptid) == ptid_get_pid (tp->ptid))
7035796c8dcSSimon Schubert 	    {
7045796c8dcSSimon Schubert 	      if (tp->executing_ && tp->state_ == THREAD_STOPPED)
7055796c8dcSSimon Schubert 		any_started = 1;
7065796c8dcSSimon Schubert 	      tp->state_ = tp->executing_ ? THREAD_RUNNING : THREAD_STOPPED;
7075796c8dcSSimon Schubert 	    }
7085796c8dcSSimon Schubert 	}
7095796c8dcSSimon Schubert     }
7105796c8dcSSimon Schubert   else
7115796c8dcSSimon Schubert     {
7125796c8dcSSimon Schubert       tp = find_thread_ptid (ptid);
7135796c8dcSSimon Schubert       gdb_assert (tp);
7145796c8dcSSimon Schubert       if (tp->state_ != THREAD_EXITED)
7155796c8dcSSimon Schubert 	{
7165796c8dcSSimon Schubert 	  if (tp->executing_ && tp->state_ == THREAD_STOPPED)
7175796c8dcSSimon Schubert 	    any_started = 1;
7185796c8dcSSimon Schubert 	  tp->state_ = tp->executing_ ? THREAD_RUNNING : THREAD_STOPPED;
7195796c8dcSSimon Schubert 	}
7205796c8dcSSimon Schubert     }
7215796c8dcSSimon Schubert 
7225796c8dcSSimon Schubert   if (any_started)
7235796c8dcSSimon Schubert     observer_notify_target_resumed (ptid);
7245796c8dcSSimon Schubert }
7255796c8dcSSimon Schubert 
7265796c8dcSSimon Schubert void
7275796c8dcSSimon Schubert finish_thread_state_cleanup (void *arg)
7285796c8dcSSimon Schubert {
7295796c8dcSSimon Schubert   ptid_t *ptid_p = arg;
7305796c8dcSSimon Schubert 
7315796c8dcSSimon Schubert   gdb_assert (arg);
7325796c8dcSSimon Schubert 
7335796c8dcSSimon Schubert   finish_thread_state (*ptid_p);
7345796c8dcSSimon Schubert }
7355796c8dcSSimon Schubert 
7365796c8dcSSimon Schubert /* Prints the list of threads and their details on UIOUT.
7375796c8dcSSimon Schubert    This is a version of 'info_thread_command' suitable for
7385796c8dcSSimon Schubert    use from MI.
7395796c8dcSSimon Schubert    If REQUESTED_THREAD is not -1, it's the GDB id of the thread
7405796c8dcSSimon Schubert    that should be printed.  Otherwise, all threads are
7415796c8dcSSimon Schubert    printed.
7425796c8dcSSimon Schubert    If PID is not -1, only print threads from the process PID.
7435796c8dcSSimon Schubert    Otherwise, threads from all attached PIDs are printed.
7445796c8dcSSimon Schubert    If both REQUESTED_THREAD and PID are not -1, then the thread
7455796c8dcSSimon Schubert    is printed if it belongs to the specified process.  Otherwise,
7465796c8dcSSimon Schubert    an error is raised.  */
7475796c8dcSSimon Schubert void
7485796c8dcSSimon Schubert print_thread_info (struct ui_out *uiout, int requested_thread, int pid)
7495796c8dcSSimon Schubert {
7505796c8dcSSimon Schubert   struct thread_info *tp;
7515796c8dcSSimon Schubert   ptid_t current_ptid;
7525796c8dcSSimon Schubert   struct cleanup *old_chain;
7535796c8dcSSimon Schubert   char *extra_info;
7545796c8dcSSimon Schubert   int current_thread = -1;
7555796c8dcSSimon Schubert 
756*cf7f2e2dSJohn Marino   update_thread_list ();
7575796c8dcSSimon Schubert   current_ptid = inferior_ptid;
7585796c8dcSSimon Schubert 
7595796c8dcSSimon Schubert   /* We'll be switching threads temporarily.  */
7605796c8dcSSimon Schubert   old_chain = make_cleanup_restore_current_thread ();
7615796c8dcSSimon Schubert 
7625796c8dcSSimon Schubert   make_cleanup_ui_out_list_begin_end (uiout, "threads");
7635796c8dcSSimon Schubert   for (tp = thread_list; tp; tp = tp->next)
7645796c8dcSSimon Schubert     {
7655796c8dcSSimon Schubert       struct cleanup *chain2;
766*cf7f2e2dSJohn Marino       int core;
7675796c8dcSSimon Schubert 
7685796c8dcSSimon Schubert       if (requested_thread != -1 && tp->num != requested_thread)
7695796c8dcSSimon Schubert 	continue;
7705796c8dcSSimon Schubert 
7715796c8dcSSimon Schubert       if (pid != -1 && PIDGET (tp->ptid) != pid)
7725796c8dcSSimon Schubert 	{
7735796c8dcSSimon Schubert 	  if (requested_thread != -1)
7745796c8dcSSimon Schubert 	    error (_("Requested thread not found in requested process"));
7755796c8dcSSimon Schubert 	  continue;
7765796c8dcSSimon Schubert 	}
7775796c8dcSSimon Schubert 
7785796c8dcSSimon Schubert       if (ptid_equal (tp->ptid, current_ptid))
7795796c8dcSSimon Schubert 	current_thread = tp->num;
7805796c8dcSSimon Schubert 
7815796c8dcSSimon Schubert       if (tp->state_ == THREAD_EXITED)
7825796c8dcSSimon Schubert 	continue;
7835796c8dcSSimon Schubert 
7845796c8dcSSimon Schubert       chain2 = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
7855796c8dcSSimon Schubert 
7865796c8dcSSimon Schubert       if (ptid_equal (tp->ptid, current_ptid))
7875796c8dcSSimon Schubert 	ui_out_text (uiout, "* ");
7885796c8dcSSimon Schubert       else
7895796c8dcSSimon Schubert 	ui_out_text (uiout, "  ");
7905796c8dcSSimon Schubert 
7915796c8dcSSimon Schubert       ui_out_field_int (uiout, "id", tp->num);
7925796c8dcSSimon Schubert       ui_out_text (uiout, " ");
7935796c8dcSSimon Schubert       ui_out_field_string (uiout, "target-id", target_pid_to_str (tp->ptid));
7945796c8dcSSimon Schubert 
7955796c8dcSSimon Schubert       extra_info = target_extra_thread_info (tp);
7965796c8dcSSimon Schubert       if (extra_info)
7975796c8dcSSimon Schubert 	{
7985796c8dcSSimon Schubert 	  ui_out_text (uiout, " (");
7995796c8dcSSimon Schubert 	  ui_out_field_string (uiout, "details", extra_info);
8005796c8dcSSimon Schubert 	  ui_out_text (uiout, ")");
8015796c8dcSSimon Schubert 	}
8025796c8dcSSimon Schubert       ui_out_text (uiout, "  ");
8035796c8dcSSimon Schubert 
8045796c8dcSSimon Schubert       if (tp->state_ == THREAD_RUNNING)
8055796c8dcSSimon Schubert 	ui_out_text (uiout, "(running)\n");
8065796c8dcSSimon Schubert       else
8075796c8dcSSimon Schubert 	{
8085796c8dcSSimon Schubert 	  /* The switch below puts us at the top of the stack (leaf
8095796c8dcSSimon Schubert 	     frame).  */
8105796c8dcSSimon Schubert 	  switch_to_thread (tp->ptid);
8115796c8dcSSimon Schubert 	  print_stack_frame (get_selected_frame (NULL),
8125796c8dcSSimon Schubert 			     /* For MI output, print frame level.  */
8135796c8dcSSimon Schubert 			     ui_out_is_mi_like_p (uiout),
8145796c8dcSSimon Schubert 			     LOCATION);
8155796c8dcSSimon Schubert 	}
8165796c8dcSSimon Schubert 
8175796c8dcSSimon Schubert       if (ui_out_is_mi_like_p (uiout))
8185796c8dcSSimon Schubert 	{
8195796c8dcSSimon Schubert 	  char *state = "stopped";
820*cf7f2e2dSJohn Marino 
8215796c8dcSSimon Schubert 	  if (tp->state_ == THREAD_RUNNING)
8225796c8dcSSimon Schubert 	    state = "running";
8235796c8dcSSimon Schubert 	  ui_out_field_string (uiout, "state", state);
8245796c8dcSSimon Schubert 	}
8255796c8dcSSimon Schubert 
826*cf7f2e2dSJohn Marino       core = target_core_of_thread (tp->ptid);
827*cf7f2e2dSJohn Marino       if (ui_out_is_mi_like_p (uiout) && core != -1)
828*cf7f2e2dSJohn Marino 	ui_out_field_int (uiout, "core", core);
829*cf7f2e2dSJohn Marino 
8305796c8dcSSimon Schubert       do_cleanups (chain2);
8315796c8dcSSimon Schubert     }
8325796c8dcSSimon Schubert 
8335796c8dcSSimon Schubert   /* Restores the current thread and the frame selected before
8345796c8dcSSimon Schubert      the "info threads" command.  */
8355796c8dcSSimon Schubert   do_cleanups (old_chain);
8365796c8dcSSimon Schubert 
8375796c8dcSSimon Schubert   if (pid == -1 && requested_thread == -1)
8385796c8dcSSimon Schubert     {
8395796c8dcSSimon Schubert       gdb_assert (current_thread != -1
8405796c8dcSSimon Schubert 		  || !thread_list
8415796c8dcSSimon Schubert 		  || ptid_equal (inferior_ptid, null_ptid));
8425796c8dcSSimon Schubert       if (current_thread != -1 && ui_out_is_mi_like_p (uiout))
8435796c8dcSSimon Schubert 	ui_out_field_int (uiout, "current-thread-id", current_thread);
8445796c8dcSSimon Schubert 
8455796c8dcSSimon Schubert       if (current_thread != -1 && is_exited (current_ptid))
8465796c8dcSSimon Schubert 	ui_out_message (uiout, 0, "\n\
8475796c8dcSSimon Schubert The current thread <Thread ID %d> has terminated.  See `help thread'.\n",
8485796c8dcSSimon Schubert 			current_thread);
8495796c8dcSSimon Schubert       else if (thread_list
8505796c8dcSSimon Schubert 	       && current_thread == -1
8515796c8dcSSimon Schubert 	       && ptid_equal (current_ptid, null_ptid))
8525796c8dcSSimon Schubert 	ui_out_message (uiout, 0, "\n\
8535796c8dcSSimon Schubert No selected thread.  See `help thread'.\n");
8545796c8dcSSimon Schubert     }
8555796c8dcSSimon Schubert }
8565796c8dcSSimon Schubert 
8575796c8dcSSimon Schubert 
8585796c8dcSSimon Schubert /* Print information about currently known threads
8595796c8dcSSimon Schubert 
8605796c8dcSSimon Schubert  * Note: this has the drawback that it _really_ switches
8615796c8dcSSimon Schubert  *       threads, which frees the frame cache.  A no-side
8625796c8dcSSimon Schubert  *       effects info-threads command would be nicer.
8635796c8dcSSimon Schubert  */
8645796c8dcSSimon Schubert 
8655796c8dcSSimon Schubert static void
8665796c8dcSSimon Schubert info_threads_command (char *arg, int from_tty)
8675796c8dcSSimon Schubert {
8685796c8dcSSimon Schubert   print_thread_info (uiout, -1, -1);
8695796c8dcSSimon Schubert }
8705796c8dcSSimon Schubert 
8715796c8dcSSimon Schubert /* Switch from one thread to another. */
8725796c8dcSSimon Schubert 
8735796c8dcSSimon Schubert void
8745796c8dcSSimon Schubert switch_to_thread (ptid_t ptid)
8755796c8dcSSimon Schubert {
876*cf7f2e2dSJohn Marino   /* Switch the program space as well, if we can infer it from the now
877*cf7f2e2dSJohn Marino      current thread.  Otherwise, it's up to the caller to select the
878*cf7f2e2dSJohn Marino      space it wants.  */
879*cf7f2e2dSJohn Marino   if (!ptid_equal (ptid, null_ptid))
880*cf7f2e2dSJohn Marino     {
881*cf7f2e2dSJohn Marino       struct inferior *inf;
882*cf7f2e2dSJohn Marino 
883*cf7f2e2dSJohn Marino       inf = find_inferior_pid (ptid_get_pid (ptid));
884*cf7f2e2dSJohn Marino       gdb_assert (inf != NULL);
885*cf7f2e2dSJohn Marino       set_current_program_space (inf->pspace);
886*cf7f2e2dSJohn Marino       set_current_inferior (inf);
887*cf7f2e2dSJohn Marino     }
888*cf7f2e2dSJohn Marino 
8895796c8dcSSimon Schubert   if (ptid_equal (ptid, inferior_ptid))
8905796c8dcSSimon Schubert     return;
8915796c8dcSSimon Schubert 
8925796c8dcSSimon Schubert   inferior_ptid = ptid;
8935796c8dcSSimon Schubert   reinit_frame_cache ();
8945796c8dcSSimon Schubert   registers_changed ();
8955796c8dcSSimon Schubert 
8965796c8dcSSimon Schubert   /* We don't check for is_stopped, because we're called at times
8975796c8dcSSimon Schubert      while in the TARGET_RUNNING state, e.g., while handling an
8985796c8dcSSimon Schubert      internal event.  */
8995796c8dcSSimon Schubert   if (!ptid_equal (inferior_ptid, null_ptid)
9005796c8dcSSimon Schubert       && !is_exited (ptid)
9015796c8dcSSimon Schubert       && !is_executing (ptid))
9025796c8dcSSimon Schubert     stop_pc = regcache_read_pc (get_thread_regcache (ptid));
9035796c8dcSSimon Schubert   else
9045796c8dcSSimon Schubert     stop_pc = ~(CORE_ADDR) 0;
9055796c8dcSSimon Schubert }
9065796c8dcSSimon Schubert 
9075796c8dcSSimon Schubert static void
9085796c8dcSSimon Schubert restore_current_thread (ptid_t ptid)
9095796c8dcSSimon Schubert {
9105796c8dcSSimon Schubert   switch_to_thread (ptid);
9115796c8dcSSimon Schubert }
9125796c8dcSSimon Schubert 
9135796c8dcSSimon Schubert static void
9145796c8dcSSimon Schubert restore_selected_frame (struct frame_id a_frame_id, int frame_level)
9155796c8dcSSimon Schubert {
9165796c8dcSSimon Schubert   struct frame_info *frame = NULL;
9175796c8dcSSimon Schubert   int count;
9185796c8dcSSimon Schubert 
9195796c8dcSSimon Schubert   gdb_assert (frame_level >= 0);
9205796c8dcSSimon Schubert 
9215796c8dcSSimon Schubert   /* Restore by level first, check if the frame id is the same as
9225796c8dcSSimon Schubert      expected.  If that fails, try restoring by frame id.  If that
9235796c8dcSSimon Schubert      fails, nothing to do, just warn the user.  */
9245796c8dcSSimon Schubert 
9255796c8dcSSimon Schubert   count = frame_level;
9265796c8dcSSimon Schubert   frame = find_relative_frame (get_current_frame (), &count);
9275796c8dcSSimon Schubert   if (count == 0
9285796c8dcSSimon Schubert       && frame != NULL
9295796c8dcSSimon Schubert       /* The frame ids must match - either both valid or both outer_frame_id.
9305796c8dcSSimon Schubert 	 The latter case is not failsafe, but since it's highly unlikely
9315796c8dcSSimon Schubert 	 the search by level finds the wrong frame, it's 99.9(9)% of
9325796c8dcSSimon Schubert 	 the time (for all practical purposes) safe.  */
9335796c8dcSSimon Schubert       && frame_id_eq (get_frame_id (frame), a_frame_id))
9345796c8dcSSimon Schubert     {
9355796c8dcSSimon Schubert       /* Cool, all is fine.  */
9365796c8dcSSimon Schubert       select_frame (frame);
9375796c8dcSSimon Schubert       return;
9385796c8dcSSimon Schubert     }
9395796c8dcSSimon Schubert 
9405796c8dcSSimon Schubert   frame = frame_find_by_id (a_frame_id);
9415796c8dcSSimon Schubert   if (frame != NULL)
9425796c8dcSSimon Schubert     {
9435796c8dcSSimon Schubert       /* Cool, refound it.  */
9445796c8dcSSimon Schubert       select_frame (frame);
9455796c8dcSSimon Schubert       return;
9465796c8dcSSimon Schubert     }
9475796c8dcSSimon Schubert 
9485796c8dcSSimon Schubert   /* Nothing else to do, the frame layout really changed.  Select the
9495796c8dcSSimon Schubert      innermost stack frame.  */
9505796c8dcSSimon Schubert   select_frame (get_current_frame ());
9515796c8dcSSimon Schubert 
9525796c8dcSSimon Schubert   /* Warn the user.  */
953*cf7f2e2dSJohn Marino   if (frame_level > 0 && !ui_out_is_mi_like_p (uiout))
9545796c8dcSSimon Schubert     {
9555796c8dcSSimon Schubert       warning (_("\
9565796c8dcSSimon Schubert Couldn't restore frame #%d in current thread, at reparsed frame #0\n"),
9575796c8dcSSimon Schubert 	       frame_level);
9585796c8dcSSimon Schubert       /* For MI, we should probably have a notification about
9595796c8dcSSimon Schubert 	 current frame change.  But this error is not very
9605796c8dcSSimon Schubert 	 likely, so don't bother for now.  */
9615796c8dcSSimon Schubert       print_stack_frame (get_selected_frame (NULL), 1, SRC_LINE);
9625796c8dcSSimon Schubert     }
9635796c8dcSSimon Schubert }
9645796c8dcSSimon Schubert 
9655796c8dcSSimon Schubert struct current_thread_cleanup
9665796c8dcSSimon Schubert {
9675796c8dcSSimon Schubert   ptid_t inferior_ptid;
9685796c8dcSSimon Schubert   struct frame_id selected_frame_id;
9695796c8dcSSimon Schubert   int selected_frame_level;
9705796c8dcSSimon Schubert   int was_stopped;
971*cf7f2e2dSJohn Marino   int inf_id;
9725796c8dcSSimon Schubert };
9735796c8dcSSimon Schubert 
9745796c8dcSSimon Schubert static void
9755796c8dcSSimon Schubert do_restore_current_thread_cleanup (void *arg)
9765796c8dcSSimon Schubert {
9775796c8dcSSimon Schubert   struct thread_info *tp;
9785796c8dcSSimon Schubert   struct current_thread_cleanup *old = arg;
9795796c8dcSSimon Schubert 
9805796c8dcSSimon Schubert   tp = find_thread_ptid (old->inferior_ptid);
9815796c8dcSSimon Schubert 
9825796c8dcSSimon Schubert   /* If the previously selected thread belonged to a process that has
9835796c8dcSSimon Schubert      in the mean time been deleted (due to normal exit, detach, etc.),
9845796c8dcSSimon Schubert      then don't revert back to it, but instead simply drop back to no
9855796c8dcSSimon Schubert      thread selected.  */
9865796c8dcSSimon Schubert   if (tp
9875796c8dcSSimon Schubert       && find_inferior_pid (ptid_get_pid (tp->ptid)) != NULL)
9885796c8dcSSimon Schubert     restore_current_thread (old->inferior_ptid);
9895796c8dcSSimon Schubert   else
990*cf7f2e2dSJohn Marino     {
9915796c8dcSSimon Schubert       restore_current_thread (null_ptid);
992*cf7f2e2dSJohn Marino       set_current_inferior (find_inferior_id (old->inf_id));
993*cf7f2e2dSJohn Marino     }
9945796c8dcSSimon Schubert 
9955796c8dcSSimon Schubert   /* The running state of the originally selected thread may have
9965796c8dcSSimon Schubert      changed, so we have to recheck it here.  */
9975796c8dcSSimon Schubert   if (!ptid_equal (inferior_ptid, null_ptid)
9985796c8dcSSimon Schubert       && old->was_stopped
9995796c8dcSSimon Schubert       && is_stopped (inferior_ptid)
10005796c8dcSSimon Schubert       && target_has_registers
10015796c8dcSSimon Schubert       && target_has_stack
10025796c8dcSSimon Schubert       && target_has_memory)
10035796c8dcSSimon Schubert     restore_selected_frame (old->selected_frame_id,
10045796c8dcSSimon Schubert 			    old->selected_frame_level);
10055796c8dcSSimon Schubert }
10065796c8dcSSimon Schubert 
10075796c8dcSSimon Schubert static void
10085796c8dcSSimon Schubert restore_current_thread_cleanup_dtor (void *arg)
10095796c8dcSSimon Schubert {
10105796c8dcSSimon Schubert   struct current_thread_cleanup *old = arg;
10115796c8dcSSimon Schubert   struct thread_info *tp;
1012*cf7f2e2dSJohn Marino 
10135796c8dcSSimon Schubert   tp = find_thread_ptid (old->inferior_ptid);
10145796c8dcSSimon Schubert   if (tp)
10155796c8dcSSimon Schubert     tp->refcount--;
10165796c8dcSSimon Schubert   xfree (old);
10175796c8dcSSimon Schubert }
10185796c8dcSSimon Schubert 
10195796c8dcSSimon Schubert struct cleanup *
10205796c8dcSSimon Schubert make_cleanup_restore_current_thread (void)
10215796c8dcSSimon Schubert {
10225796c8dcSSimon Schubert   struct thread_info *tp;
10235796c8dcSSimon Schubert   struct frame_info *frame;
10245796c8dcSSimon Schubert   struct current_thread_cleanup *old;
10255796c8dcSSimon Schubert 
10265796c8dcSSimon Schubert   old = xmalloc (sizeof (struct current_thread_cleanup));
10275796c8dcSSimon Schubert   old->inferior_ptid = inferior_ptid;
1028*cf7f2e2dSJohn Marino   old->inf_id = current_inferior ()->num;
10295796c8dcSSimon Schubert 
10305796c8dcSSimon Schubert   if (!ptid_equal (inferior_ptid, null_ptid))
10315796c8dcSSimon Schubert     {
10325796c8dcSSimon Schubert       old->was_stopped = is_stopped (inferior_ptid);
10335796c8dcSSimon Schubert       if (old->was_stopped
10345796c8dcSSimon Schubert 	  && target_has_registers
10355796c8dcSSimon Schubert 	  && target_has_stack
10365796c8dcSSimon Schubert 	  && target_has_memory)
10375796c8dcSSimon Schubert 	frame = get_selected_frame (NULL);
10385796c8dcSSimon Schubert       else
10395796c8dcSSimon Schubert 	frame = NULL;
10405796c8dcSSimon Schubert 
10415796c8dcSSimon Schubert       old->selected_frame_id = get_frame_id (frame);
10425796c8dcSSimon Schubert       old->selected_frame_level = frame_relative_level (frame);
10435796c8dcSSimon Schubert 
10445796c8dcSSimon Schubert       tp = find_thread_ptid (inferior_ptid);
10455796c8dcSSimon Schubert       if (tp)
10465796c8dcSSimon Schubert 	tp->refcount++;
10475796c8dcSSimon Schubert     }
10485796c8dcSSimon Schubert 
10495796c8dcSSimon Schubert   return make_cleanup_dtor (do_restore_current_thread_cleanup, old,
10505796c8dcSSimon Schubert 			    restore_current_thread_cleanup_dtor);
10515796c8dcSSimon Schubert }
10525796c8dcSSimon Schubert 
10535796c8dcSSimon Schubert /* Apply a GDB command to a list of threads.  List syntax is a whitespace
10545796c8dcSSimon Schubert    seperated list of numbers, or ranges, or the keyword `all'.  Ranges consist
10555796c8dcSSimon Schubert    of two numbers seperated by a hyphen.  Examples:
10565796c8dcSSimon Schubert 
10575796c8dcSSimon Schubert    thread apply 1 2 7 4 backtrace       Apply backtrace cmd to threads 1,2,7,4
10585796c8dcSSimon Schubert    thread apply 2-7 9 p foo(1)  Apply p foo(1) cmd to threads 2->7 & 9
10595796c8dcSSimon Schubert    thread apply all p x/i $pc   Apply x/i $pc cmd to all threads
10605796c8dcSSimon Schubert  */
10615796c8dcSSimon Schubert 
10625796c8dcSSimon Schubert static void
10635796c8dcSSimon Schubert thread_apply_all_command (char *cmd, int from_tty)
10645796c8dcSSimon Schubert {
10655796c8dcSSimon Schubert   struct thread_info *tp;
10665796c8dcSSimon Schubert   struct cleanup *old_chain;
10675796c8dcSSimon Schubert   char *saved_cmd;
10685796c8dcSSimon Schubert 
10695796c8dcSSimon Schubert   if (cmd == NULL || *cmd == '\000')
10705796c8dcSSimon Schubert     error (_("Please specify a command following the thread ID list"));
10715796c8dcSSimon Schubert 
1072*cf7f2e2dSJohn Marino   update_thread_list ();
10735796c8dcSSimon Schubert 
10745796c8dcSSimon Schubert   old_chain = make_cleanup_restore_current_thread ();
10755796c8dcSSimon Schubert 
10765796c8dcSSimon Schubert   /* Save a copy of the command in case it is clobbered by
10775796c8dcSSimon Schubert      execute_command */
10785796c8dcSSimon Schubert   saved_cmd = xstrdup (cmd);
10795796c8dcSSimon Schubert   make_cleanup (xfree, saved_cmd);
10805796c8dcSSimon Schubert   for (tp = thread_list; tp; tp = tp->next)
10815796c8dcSSimon Schubert     if (thread_alive (tp))
10825796c8dcSSimon Schubert       {
10835796c8dcSSimon Schubert 	switch_to_thread (tp->ptid);
10845796c8dcSSimon Schubert 
10855796c8dcSSimon Schubert 	printf_filtered (_("\nThread %d (%s):\n"),
10865796c8dcSSimon Schubert 			 tp->num, target_pid_to_str (inferior_ptid));
10875796c8dcSSimon Schubert 	execute_command (cmd, from_tty);
10885796c8dcSSimon Schubert 	strcpy (cmd, saved_cmd);	/* Restore exact command used previously */
10895796c8dcSSimon Schubert       }
10905796c8dcSSimon Schubert 
10915796c8dcSSimon Schubert   do_cleanups (old_chain);
10925796c8dcSSimon Schubert }
10935796c8dcSSimon Schubert 
10945796c8dcSSimon Schubert static void
10955796c8dcSSimon Schubert thread_apply_command (char *tidlist, int from_tty)
10965796c8dcSSimon Schubert {
10975796c8dcSSimon Schubert   char *cmd;
10985796c8dcSSimon Schubert   char *p;
10995796c8dcSSimon Schubert   struct cleanup *old_chain;
11005796c8dcSSimon Schubert   char *saved_cmd;
11015796c8dcSSimon Schubert 
11025796c8dcSSimon Schubert   if (tidlist == NULL || *tidlist == '\000')
11035796c8dcSSimon Schubert     error (_("Please specify a thread ID list"));
11045796c8dcSSimon Schubert 
11055796c8dcSSimon Schubert   for (cmd = tidlist; *cmd != '\000' && !isalpha (*cmd); cmd++);
11065796c8dcSSimon Schubert 
11075796c8dcSSimon Schubert   if (*cmd == '\000')
11085796c8dcSSimon Schubert     error (_("Please specify a command following the thread ID list"));
11095796c8dcSSimon Schubert 
11105796c8dcSSimon Schubert   /* Save a copy of the command in case it is clobbered by
11115796c8dcSSimon Schubert      execute_command */
11125796c8dcSSimon Schubert   saved_cmd = xstrdup (cmd);
11135796c8dcSSimon Schubert   old_chain = make_cleanup (xfree, saved_cmd);
11145796c8dcSSimon Schubert   while (tidlist < cmd)
11155796c8dcSSimon Schubert     {
11165796c8dcSSimon Schubert       struct thread_info *tp;
11175796c8dcSSimon Schubert       int start, end;
11185796c8dcSSimon Schubert 
11195796c8dcSSimon Schubert       start = strtol (tidlist, &p, 10);
11205796c8dcSSimon Schubert       if (p == tidlist)
11215796c8dcSSimon Schubert 	error (_("Error parsing %s"), tidlist);
11225796c8dcSSimon Schubert       tidlist = p;
11235796c8dcSSimon Schubert 
11245796c8dcSSimon Schubert       while (*tidlist == ' ' || *tidlist == '\t')
11255796c8dcSSimon Schubert 	tidlist++;
11265796c8dcSSimon Schubert 
11275796c8dcSSimon Schubert       if (*tidlist == '-')	/* Got a range of IDs? */
11285796c8dcSSimon Schubert 	{
11295796c8dcSSimon Schubert 	  tidlist++;		/* Skip the - */
11305796c8dcSSimon Schubert 	  end = strtol (tidlist, &p, 10);
11315796c8dcSSimon Schubert 	  if (p == tidlist)
11325796c8dcSSimon Schubert 	    error (_("Error parsing %s"), tidlist);
11335796c8dcSSimon Schubert 	  tidlist = p;
11345796c8dcSSimon Schubert 
11355796c8dcSSimon Schubert 	  while (*tidlist == ' ' || *tidlist == '\t')
11365796c8dcSSimon Schubert 	    tidlist++;
11375796c8dcSSimon Schubert 	}
11385796c8dcSSimon Schubert       else
11395796c8dcSSimon Schubert 	end = start;
11405796c8dcSSimon Schubert 
11415796c8dcSSimon Schubert       make_cleanup_restore_current_thread ();
11425796c8dcSSimon Schubert 
11435796c8dcSSimon Schubert       for (; start <= end; start++)
11445796c8dcSSimon Schubert 	{
11455796c8dcSSimon Schubert 	  tp = find_thread_id (start);
11465796c8dcSSimon Schubert 
11475796c8dcSSimon Schubert 	  if (!tp)
11485796c8dcSSimon Schubert 	    warning (_("Unknown thread %d."), start);
11495796c8dcSSimon Schubert 	  else if (!thread_alive (tp))
11505796c8dcSSimon Schubert 	    warning (_("Thread %d has terminated."), start);
11515796c8dcSSimon Schubert 	  else
11525796c8dcSSimon Schubert 	    {
11535796c8dcSSimon Schubert 	      switch_to_thread (tp->ptid);
11545796c8dcSSimon Schubert 
11555796c8dcSSimon Schubert 	      printf_filtered (_("\nThread %d (%s):\n"), tp->num,
11565796c8dcSSimon Schubert 			       target_pid_to_str (inferior_ptid));
11575796c8dcSSimon Schubert 	      execute_command (cmd, from_tty);
11585796c8dcSSimon Schubert 
11595796c8dcSSimon Schubert 	      /* Restore exact command used previously.  */
11605796c8dcSSimon Schubert 	      strcpy (cmd, saved_cmd);
11615796c8dcSSimon Schubert 	    }
11625796c8dcSSimon Schubert 	}
11635796c8dcSSimon Schubert     }
11645796c8dcSSimon Schubert 
11655796c8dcSSimon Schubert   do_cleanups (old_chain);
11665796c8dcSSimon Schubert }
11675796c8dcSSimon Schubert 
11685796c8dcSSimon Schubert /* Switch to the specified thread.  Will dispatch off to thread_apply_command
11695796c8dcSSimon Schubert    if prefix of arg is `apply'.  */
11705796c8dcSSimon Schubert 
11715796c8dcSSimon Schubert static void
11725796c8dcSSimon Schubert thread_command (char *tidstr, int from_tty)
11735796c8dcSSimon Schubert {
11745796c8dcSSimon Schubert   if (!tidstr)
11755796c8dcSSimon Schubert     {
11765796c8dcSSimon Schubert       if (ptid_equal (inferior_ptid, null_ptid))
11775796c8dcSSimon Schubert 	error (_("No thread selected"));
11785796c8dcSSimon Schubert 
11795796c8dcSSimon Schubert       if (target_has_stack)
11805796c8dcSSimon Schubert 	{
11815796c8dcSSimon Schubert 	  if (is_exited (inferior_ptid))
11825796c8dcSSimon Schubert 	    printf_filtered (_("[Current thread is %d (%s) (exited)]\n"),
11835796c8dcSSimon Schubert 			     pid_to_thread_id (inferior_ptid),
11845796c8dcSSimon Schubert 			     target_pid_to_str (inferior_ptid));
11855796c8dcSSimon Schubert 	  else
11865796c8dcSSimon Schubert 	    printf_filtered (_("[Current thread is %d (%s)]\n"),
11875796c8dcSSimon Schubert 			     pid_to_thread_id (inferior_ptid),
11885796c8dcSSimon Schubert 			     target_pid_to_str (inferior_ptid));
11895796c8dcSSimon Schubert 	}
11905796c8dcSSimon Schubert       else
11915796c8dcSSimon Schubert 	error (_("No stack."));
11925796c8dcSSimon Schubert       return;
11935796c8dcSSimon Schubert     }
11945796c8dcSSimon Schubert 
11955796c8dcSSimon Schubert   gdb_thread_select (uiout, tidstr, NULL);
11965796c8dcSSimon Schubert }
11975796c8dcSSimon Schubert 
11985796c8dcSSimon Schubert /* Print notices when new threads are attached and detached.  */
11995796c8dcSSimon Schubert int print_thread_events = 1;
12005796c8dcSSimon Schubert static void
12015796c8dcSSimon Schubert show_print_thread_events (struct ui_file *file, int from_tty,
12025796c8dcSSimon Schubert                           struct cmd_list_element *c, const char *value)
12035796c8dcSSimon Schubert {
12045796c8dcSSimon Schubert   fprintf_filtered (file, _("\
12055796c8dcSSimon Schubert Printing of thread events is %s.\n"),
12065796c8dcSSimon Schubert                     value);
12075796c8dcSSimon Schubert }
12085796c8dcSSimon Schubert 
12095796c8dcSSimon Schubert static int
12105796c8dcSSimon Schubert do_captured_thread_select (struct ui_out *uiout, void *tidstr)
12115796c8dcSSimon Schubert {
12125796c8dcSSimon Schubert   int num;
12135796c8dcSSimon Schubert   struct thread_info *tp;
12145796c8dcSSimon Schubert 
12155796c8dcSSimon Schubert   num = value_as_long (parse_and_eval (tidstr));
12165796c8dcSSimon Schubert 
12175796c8dcSSimon Schubert   tp = find_thread_id (num);
12185796c8dcSSimon Schubert 
12195796c8dcSSimon Schubert   if (!tp)
12205796c8dcSSimon Schubert     error (_("Thread ID %d not known."), num);
12215796c8dcSSimon Schubert 
12225796c8dcSSimon Schubert   if (!thread_alive (tp))
12235796c8dcSSimon Schubert     error (_("Thread ID %d has terminated."), num);
12245796c8dcSSimon Schubert 
12255796c8dcSSimon Schubert   switch_to_thread (tp->ptid);
12265796c8dcSSimon Schubert 
12275796c8dcSSimon Schubert   annotate_thread_changed ();
12285796c8dcSSimon Schubert 
12295796c8dcSSimon Schubert   ui_out_text (uiout, "[Switching to thread ");
12305796c8dcSSimon Schubert   ui_out_field_int (uiout, "new-thread-id", pid_to_thread_id (inferior_ptid));
12315796c8dcSSimon Schubert   ui_out_text (uiout, " (");
12325796c8dcSSimon Schubert   ui_out_text (uiout, target_pid_to_str (inferior_ptid));
12335796c8dcSSimon Schubert   ui_out_text (uiout, ")]");
12345796c8dcSSimon Schubert 
12355796c8dcSSimon Schubert   /* Note that we can't reach this with an exited thread, due to the
12365796c8dcSSimon Schubert      thread_alive check above.  */
12375796c8dcSSimon Schubert   if (tp->state_ == THREAD_RUNNING)
12385796c8dcSSimon Schubert     ui_out_text (uiout, "(running)\n");
12395796c8dcSSimon Schubert   else
12405796c8dcSSimon Schubert     print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC);
12415796c8dcSSimon Schubert 
12425796c8dcSSimon Schubert   /* Since the current thread may have changed, see if there is any
12435796c8dcSSimon Schubert      exited thread we can now delete.  */
12445796c8dcSSimon Schubert   prune_threads ();
12455796c8dcSSimon Schubert 
12465796c8dcSSimon Schubert   return GDB_RC_OK;
12475796c8dcSSimon Schubert }
12485796c8dcSSimon Schubert 
12495796c8dcSSimon Schubert enum gdb_rc
12505796c8dcSSimon Schubert gdb_thread_select (struct ui_out *uiout, char *tidstr, char **error_message)
12515796c8dcSSimon Schubert {
12525796c8dcSSimon Schubert   if (catch_exceptions_with_msg (uiout, do_captured_thread_select, tidstr,
12535796c8dcSSimon Schubert 				 error_message, RETURN_MASK_ALL) < 0)
12545796c8dcSSimon Schubert     return GDB_RC_FAIL;
12555796c8dcSSimon Schubert   return GDB_RC_OK;
12565796c8dcSSimon Schubert }
12575796c8dcSSimon Schubert 
1258*cf7f2e2dSJohn Marino void
1259*cf7f2e2dSJohn Marino update_thread_list (void)
1260*cf7f2e2dSJohn Marino {
1261*cf7f2e2dSJohn Marino   prune_threads ();
1262*cf7f2e2dSJohn Marino   target_find_new_threads ();
1263*cf7f2e2dSJohn Marino }
1264*cf7f2e2dSJohn Marino 
1265*cf7f2e2dSJohn Marino /* Return a new value for the selected thread's id.  Return a value of 0 if
1266*cf7f2e2dSJohn Marino    no thread is selected, or no threads exist.  */
1267*cf7f2e2dSJohn Marino 
1268*cf7f2e2dSJohn Marino static struct value *
1269*cf7f2e2dSJohn Marino thread_id_make_value (struct gdbarch *gdbarch, struct internalvar *var)
1270*cf7f2e2dSJohn Marino {
1271*cf7f2e2dSJohn Marino   struct thread_info *tp = find_thread_ptid (inferior_ptid);
1272*cf7f2e2dSJohn Marino 
1273*cf7f2e2dSJohn Marino   return value_from_longest (builtin_type (gdbarch)->builtin_int,
1274*cf7f2e2dSJohn Marino 			     (tp ? tp->num : 0));
1275*cf7f2e2dSJohn Marino }
1276*cf7f2e2dSJohn Marino 
12775796c8dcSSimon Schubert /* Commands with a prefix of `thread'.  */
12785796c8dcSSimon Schubert struct cmd_list_element *thread_cmd_list = NULL;
12795796c8dcSSimon Schubert 
12805796c8dcSSimon Schubert void
12815796c8dcSSimon Schubert _initialize_thread (void)
12825796c8dcSSimon Schubert {
12835796c8dcSSimon Schubert   static struct cmd_list_element *thread_apply_list = NULL;
12845796c8dcSSimon Schubert 
12855796c8dcSSimon Schubert   add_info ("threads", info_threads_command,
12865796c8dcSSimon Schubert 	    _("IDs of currently known threads."));
12875796c8dcSSimon Schubert 
12885796c8dcSSimon Schubert   add_prefix_cmd ("thread", class_run, thread_command, _("\
12895796c8dcSSimon Schubert Use this command to switch between threads.\n\
12905796c8dcSSimon Schubert The new thread ID must be currently known."),
12915796c8dcSSimon Schubert 		  &thread_cmd_list, "thread ", 1, &cmdlist);
12925796c8dcSSimon Schubert 
12935796c8dcSSimon Schubert   add_prefix_cmd ("apply", class_run, thread_apply_command,
12945796c8dcSSimon Schubert 		  _("Apply a command to a list of threads."),
12955796c8dcSSimon Schubert 		  &thread_apply_list, "thread apply ", 1, &thread_cmd_list);
12965796c8dcSSimon Schubert 
12975796c8dcSSimon Schubert   add_cmd ("all", class_run, thread_apply_all_command,
12985796c8dcSSimon Schubert 	   _("Apply a command to all threads."), &thread_apply_list);
12995796c8dcSSimon Schubert 
13005796c8dcSSimon Schubert   if (!xdb_commands)
13015796c8dcSSimon Schubert     add_com_alias ("t", "thread", class_run, 1);
13025796c8dcSSimon Schubert 
13035796c8dcSSimon Schubert   add_setshow_boolean_cmd ("thread-events", no_class,
13045796c8dcSSimon Schubert          &print_thread_events, _("\
13055796c8dcSSimon Schubert Set printing of thread events (such as thread start and exit)."), _("\
13065796c8dcSSimon Schubert Show printing of thread events (such as thread start and exit)."), NULL,
13075796c8dcSSimon Schubert          NULL,
13085796c8dcSSimon Schubert          show_print_thread_events,
13095796c8dcSSimon Schubert          &setprintlist, &showprintlist);
1310*cf7f2e2dSJohn Marino 
1311*cf7f2e2dSJohn Marino   create_internalvar_type_lazy ("_thread", thread_id_make_value);
13125796c8dcSSimon Schubert }
1313