15796c8dcSSimon Schubert /* Multi-process/thread control for GDB, the GNU debugger. 25796c8dcSSimon Schubert 3*a45ae5f8SJohn Marino Copyright (C) 1986-1988, 1993-2004, 2007-2012 Free Software 4*a45ae5f8SJohn Marino Foundation, Inc. 55796c8dcSSimon Schubert 65796c8dcSSimon Schubert Contributed by Lynx Real-Time Systems, Inc. Los Gatos, CA. 75796c8dcSSimon Schubert 85796c8dcSSimon Schubert This file is part of GDB. 95796c8dcSSimon Schubert 105796c8dcSSimon Schubert This program is free software; you can redistribute it and/or modify 115796c8dcSSimon Schubert it under the terms of the GNU General Public License as published by 125796c8dcSSimon Schubert the Free Software Foundation; either version 3 of the License, or 135796c8dcSSimon Schubert (at your option) any later version. 145796c8dcSSimon Schubert 155796c8dcSSimon Schubert This program is distributed in the hope that it will be useful, 165796c8dcSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of 175796c8dcSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 185796c8dcSSimon Schubert GNU General Public License for more details. 195796c8dcSSimon Schubert 205796c8dcSSimon Schubert You should have received a copy of the GNU General Public License 215796c8dcSSimon Schubert along with this program. If not, see <http://www.gnu.org/licenses/>. */ 225796c8dcSSimon Schubert 235796c8dcSSimon Schubert #include "defs.h" 245796c8dcSSimon Schubert #include "symtab.h" 255796c8dcSSimon Schubert #include "frame.h" 265796c8dcSSimon Schubert #include "inferior.h" 275796c8dcSSimon Schubert #include "environ.h" 285796c8dcSSimon Schubert #include "value.h" 295796c8dcSSimon Schubert #include "target.h" 305796c8dcSSimon Schubert #include "gdbthread.h" 315796c8dcSSimon Schubert #include "exceptions.h" 325796c8dcSSimon Schubert #include "command.h" 335796c8dcSSimon Schubert #include "gdbcmd.h" 345796c8dcSSimon Schubert #include "regcache.h" 355796c8dcSSimon Schubert #include "gdb.h" 365796c8dcSSimon Schubert #include "gdb_string.h" 375796c8dcSSimon Schubert 385796c8dcSSimon Schubert #include <ctype.h> 395796c8dcSSimon Schubert #include <sys/types.h> 405796c8dcSSimon Schubert #include <signal.h> 415796c8dcSSimon Schubert #include "ui-out.h" 425796c8dcSSimon Schubert #include "observer.h" 435796c8dcSSimon Schubert #include "annotate.h" 445796c8dcSSimon Schubert #include "cli/cli-decode.h" 45c50c785cSJohn Marino #include "gdb_regex.h" 46c50c785cSJohn Marino #include "cli/cli-utils.h" 47*a45ae5f8SJohn Marino #include "continuations.h" 485796c8dcSSimon Schubert 49c50c785cSJohn Marino /* Definition of struct thread_info exported to gdbthread.h. */ 505796c8dcSSimon Schubert 515796c8dcSSimon Schubert /* Prototypes for exported functions. */ 525796c8dcSSimon Schubert 535796c8dcSSimon Schubert void _initialize_thread (void); 545796c8dcSSimon Schubert 555796c8dcSSimon Schubert /* Prototypes for local functions. */ 565796c8dcSSimon Schubert 575796c8dcSSimon Schubert static struct thread_info *thread_list = NULL; 585796c8dcSSimon Schubert static int highest_thread_num; 595796c8dcSSimon Schubert 605796c8dcSSimon Schubert static void thread_command (char *tidstr, int from_tty); 615796c8dcSSimon Schubert static void thread_apply_all_command (char *, int); 625796c8dcSSimon Schubert static int thread_alive (struct thread_info *); 635796c8dcSSimon Schubert static void info_threads_command (char *, int); 645796c8dcSSimon Schubert static void thread_apply_command (char *, int); 655796c8dcSSimon Schubert static void restore_current_thread (ptid_t); 665796c8dcSSimon Schubert static void prune_threads (void); 675796c8dcSSimon Schubert 685796c8dcSSimon Schubert struct thread_info* 695796c8dcSSimon Schubert inferior_thread (void) 705796c8dcSSimon Schubert { 715796c8dcSSimon Schubert struct thread_info *tp = find_thread_ptid (inferior_ptid); 725796c8dcSSimon Schubert gdb_assert (tp); 735796c8dcSSimon Schubert return tp; 745796c8dcSSimon Schubert } 755796c8dcSSimon Schubert 765796c8dcSSimon Schubert void 775796c8dcSSimon Schubert delete_step_resume_breakpoint (struct thread_info *tp) 785796c8dcSSimon Schubert { 79c50c785cSJohn Marino if (tp && tp->control.step_resume_breakpoint) 805796c8dcSSimon Schubert { 81c50c785cSJohn Marino delete_breakpoint (tp->control.step_resume_breakpoint); 82c50c785cSJohn Marino tp->control.step_resume_breakpoint = NULL; 83c50c785cSJohn Marino } 84c50c785cSJohn Marino } 85c50c785cSJohn Marino 86c50c785cSJohn Marino void 87c50c785cSJohn Marino delete_exception_resume_breakpoint (struct thread_info *tp) 88c50c785cSJohn Marino { 89c50c785cSJohn Marino if (tp && tp->control.exception_resume_breakpoint) 90c50c785cSJohn Marino { 91c50c785cSJohn Marino delete_breakpoint (tp->control.exception_resume_breakpoint); 92c50c785cSJohn Marino tp->control.exception_resume_breakpoint = NULL; 935796c8dcSSimon Schubert } 945796c8dcSSimon Schubert } 955796c8dcSSimon Schubert 965796c8dcSSimon Schubert static void 975796c8dcSSimon Schubert clear_thread_inferior_resources (struct thread_info *tp) 985796c8dcSSimon Schubert { 995796c8dcSSimon Schubert /* NOTE: this will take care of any left-over step_resume breakpoints, 1005796c8dcSSimon Schubert but not any user-specified thread-specific breakpoints. We can not 1015796c8dcSSimon Schubert delete the breakpoint straight-off, because the inferior might not 1025796c8dcSSimon Schubert be stopped at the moment. */ 103c50c785cSJohn Marino if (tp->control.step_resume_breakpoint) 1045796c8dcSSimon Schubert { 105c50c785cSJohn Marino tp->control.step_resume_breakpoint->disposition = disp_del_at_next_stop; 106c50c785cSJohn Marino tp->control.step_resume_breakpoint = NULL; 1075796c8dcSSimon Schubert } 1085796c8dcSSimon Schubert 109c50c785cSJohn Marino if (tp->control.exception_resume_breakpoint) 110c50c785cSJohn Marino { 111c50c785cSJohn Marino tp->control.exception_resume_breakpoint->disposition 112c50c785cSJohn Marino = disp_del_at_next_stop; 113c50c785cSJohn Marino tp->control.exception_resume_breakpoint = NULL; 114c50c785cSJohn Marino } 115c50c785cSJohn Marino 116c50c785cSJohn Marino bpstat_clear (&tp->control.stop_bpstat); 1175796c8dcSSimon Schubert 118*a45ae5f8SJohn Marino do_all_intermediate_continuations_thread (tp, 1); 119*a45ae5f8SJohn Marino do_all_continuations_thread (tp, 1); 120c50c785cSJohn Marino 121c50c785cSJohn Marino delete_longjmp_breakpoint (tp->num); 1225796c8dcSSimon Schubert } 1235796c8dcSSimon Schubert 1245796c8dcSSimon Schubert static void 1255796c8dcSSimon Schubert free_thread (struct thread_info *tp) 1265796c8dcSSimon Schubert { 1275796c8dcSSimon Schubert if (tp->private) 128cf7f2e2dSJohn Marino { 129cf7f2e2dSJohn Marino if (tp->private_dtor) 130cf7f2e2dSJohn Marino tp->private_dtor (tp->private); 131cf7f2e2dSJohn Marino else 1325796c8dcSSimon Schubert xfree (tp->private); 133cf7f2e2dSJohn Marino } 1345796c8dcSSimon Schubert 135c50c785cSJohn Marino xfree (tp->name); 1365796c8dcSSimon Schubert xfree (tp); 1375796c8dcSSimon Schubert } 1385796c8dcSSimon Schubert 1395796c8dcSSimon Schubert void 1405796c8dcSSimon Schubert init_thread_list (void) 1415796c8dcSSimon Schubert { 1425796c8dcSSimon Schubert struct thread_info *tp, *tpnext; 1435796c8dcSSimon Schubert 1445796c8dcSSimon Schubert highest_thread_num = 0; 1455796c8dcSSimon Schubert 1465796c8dcSSimon Schubert if (!thread_list) 1475796c8dcSSimon Schubert return; 1485796c8dcSSimon Schubert 1495796c8dcSSimon Schubert for (tp = thread_list; tp; tp = tpnext) 1505796c8dcSSimon Schubert { 1515796c8dcSSimon Schubert tpnext = tp->next; 1525796c8dcSSimon Schubert free_thread (tp); 1535796c8dcSSimon Schubert } 1545796c8dcSSimon Schubert 1555796c8dcSSimon Schubert thread_list = NULL; 1565796c8dcSSimon Schubert } 1575796c8dcSSimon Schubert 1585796c8dcSSimon Schubert /* Allocate a new thread with target id PTID and add it to the thread 1595796c8dcSSimon Schubert list. */ 1605796c8dcSSimon Schubert 1615796c8dcSSimon Schubert static struct thread_info * 1625796c8dcSSimon Schubert new_thread (ptid_t ptid) 1635796c8dcSSimon Schubert { 1645796c8dcSSimon Schubert struct thread_info *tp; 1655796c8dcSSimon Schubert 1665796c8dcSSimon Schubert tp = xcalloc (1, sizeof (*tp)); 1675796c8dcSSimon Schubert 1685796c8dcSSimon Schubert tp->ptid = ptid; 1695796c8dcSSimon Schubert tp->num = ++highest_thread_num; 1705796c8dcSSimon Schubert tp->next = thread_list; 1715796c8dcSSimon Schubert thread_list = tp; 1725796c8dcSSimon Schubert 1735796c8dcSSimon Schubert /* Nothing to follow yet. */ 1745796c8dcSSimon Schubert tp->pending_follow.kind = TARGET_WAITKIND_SPURIOUS; 175*a45ae5f8SJohn Marino tp->state = THREAD_STOPPED; 1765796c8dcSSimon Schubert 1775796c8dcSSimon Schubert return tp; 1785796c8dcSSimon Schubert } 1795796c8dcSSimon Schubert 1805796c8dcSSimon Schubert struct thread_info * 1815796c8dcSSimon Schubert add_thread_silent (ptid_t ptid) 1825796c8dcSSimon Schubert { 1835796c8dcSSimon Schubert struct thread_info *tp; 1845796c8dcSSimon Schubert 1855796c8dcSSimon Schubert tp = find_thread_ptid (ptid); 1865796c8dcSSimon Schubert if (tp) 1875796c8dcSSimon Schubert /* Found an old thread with the same id. It has to be dead, 1885796c8dcSSimon Schubert otherwise we wouldn't be adding a new thread with the same id. 1895796c8dcSSimon Schubert The OS is reusing this id --- delete it, and recreate a new 1905796c8dcSSimon Schubert one. */ 1915796c8dcSSimon Schubert { 1925796c8dcSSimon Schubert /* In addition to deleting the thread, if this is the current 1935796c8dcSSimon Schubert thread, then we need to take care that delete_thread doesn't 1945796c8dcSSimon Schubert really delete the thread if it is inferior_ptid. Create a 1955796c8dcSSimon Schubert new template thread in the list with an invalid ptid, switch 1965796c8dcSSimon Schubert to it, delete the original thread, reset the new thread's 1975796c8dcSSimon Schubert ptid, and switch to it. */ 1985796c8dcSSimon Schubert 1995796c8dcSSimon Schubert if (ptid_equal (inferior_ptid, ptid)) 2005796c8dcSSimon Schubert { 201cf7f2e2dSJohn Marino tp = new_thread (null_ptid); 2025796c8dcSSimon Schubert 2035796c8dcSSimon Schubert /* Make switch_to_thread not read from the thread. */ 204*a45ae5f8SJohn Marino tp->state = THREAD_EXITED; 205cf7f2e2dSJohn Marino switch_to_thread (null_ptid); 2065796c8dcSSimon Schubert 2075796c8dcSSimon Schubert /* Now we can delete it. */ 2085796c8dcSSimon Schubert delete_thread (ptid); 2095796c8dcSSimon Schubert 2105796c8dcSSimon Schubert /* Now reset its ptid, and reswitch inferior_ptid to it. */ 2115796c8dcSSimon Schubert tp->ptid = ptid; 212*a45ae5f8SJohn Marino tp->state = THREAD_STOPPED; 2135796c8dcSSimon Schubert switch_to_thread (ptid); 2145796c8dcSSimon Schubert 2155796c8dcSSimon Schubert observer_notify_new_thread (tp); 2165796c8dcSSimon Schubert 2175796c8dcSSimon Schubert /* All done. */ 2185796c8dcSSimon Schubert return tp; 2195796c8dcSSimon Schubert } 2205796c8dcSSimon Schubert else 2215796c8dcSSimon Schubert /* Just go ahead and delete it. */ 2225796c8dcSSimon Schubert delete_thread (ptid); 2235796c8dcSSimon Schubert } 2245796c8dcSSimon Schubert 2255796c8dcSSimon Schubert tp = new_thread (ptid); 2265796c8dcSSimon Schubert observer_notify_new_thread (tp); 2275796c8dcSSimon Schubert 2285796c8dcSSimon Schubert return tp; 2295796c8dcSSimon Schubert } 2305796c8dcSSimon Schubert 2315796c8dcSSimon Schubert struct thread_info * 2325796c8dcSSimon Schubert add_thread_with_info (ptid_t ptid, struct private_thread_info *private) 2335796c8dcSSimon Schubert { 2345796c8dcSSimon Schubert struct thread_info *result = add_thread_silent (ptid); 2355796c8dcSSimon Schubert 2365796c8dcSSimon Schubert result->private = private; 2375796c8dcSSimon Schubert 2385796c8dcSSimon Schubert if (print_thread_events) 2395796c8dcSSimon Schubert printf_unfiltered (_("[New %s]\n"), target_pid_to_str (ptid)); 2405796c8dcSSimon Schubert 2415796c8dcSSimon Schubert annotate_new_thread (); 2425796c8dcSSimon Schubert return result; 2435796c8dcSSimon Schubert } 2445796c8dcSSimon Schubert 2455796c8dcSSimon Schubert struct thread_info * 2465796c8dcSSimon Schubert add_thread (ptid_t ptid) 2475796c8dcSSimon Schubert { 2485796c8dcSSimon Schubert return add_thread_with_info (ptid, NULL); 2495796c8dcSSimon Schubert } 2505796c8dcSSimon Schubert 2515796c8dcSSimon Schubert /* Delete thread PTID. If SILENT, don't notify the observer of this 2525796c8dcSSimon Schubert exit. */ 2535796c8dcSSimon Schubert static void 2545796c8dcSSimon Schubert delete_thread_1 (ptid_t ptid, int silent) 2555796c8dcSSimon Schubert { 2565796c8dcSSimon Schubert struct thread_info *tp, *tpprev; 2575796c8dcSSimon Schubert 2585796c8dcSSimon Schubert tpprev = NULL; 2595796c8dcSSimon Schubert 2605796c8dcSSimon Schubert for (tp = thread_list; tp; tpprev = tp, tp = tp->next) 2615796c8dcSSimon Schubert if (ptid_equal (tp->ptid, ptid)) 2625796c8dcSSimon Schubert break; 2635796c8dcSSimon Schubert 2645796c8dcSSimon Schubert if (!tp) 2655796c8dcSSimon Schubert return; 2665796c8dcSSimon Schubert 2675796c8dcSSimon Schubert /* If this is the current thread, or there's code out there that 2685796c8dcSSimon Schubert relies on it existing (refcount > 0) we can't delete yet. Mark 2695796c8dcSSimon Schubert it as exited, and notify it. */ 2705796c8dcSSimon Schubert if (tp->refcount > 0 2715796c8dcSSimon Schubert || ptid_equal (tp->ptid, inferior_ptid)) 2725796c8dcSSimon Schubert { 273*a45ae5f8SJohn Marino if (tp->state != THREAD_EXITED) 2745796c8dcSSimon Schubert { 2755796c8dcSSimon Schubert observer_notify_thread_exit (tp, silent); 2765796c8dcSSimon Schubert 2775796c8dcSSimon Schubert /* Tag it as exited. */ 278*a45ae5f8SJohn Marino tp->state = THREAD_EXITED; 2795796c8dcSSimon Schubert 2805796c8dcSSimon Schubert /* Clear breakpoints, etc. associated with this thread. */ 2815796c8dcSSimon Schubert clear_thread_inferior_resources (tp); 2825796c8dcSSimon Schubert } 2835796c8dcSSimon Schubert 2845796c8dcSSimon Schubert /* Will be really deleted some other time. */ 2855796c8dcSSimon Schubert return; 2865796c8dcSSimon Schubert } 2875796c8dcSSimon Schubert 288*a45ae5f8SJohn Marino /* Notify thread exit, but only if we haven't already. */ 289*a45ae5f8SJohn Marino if (tp->state != THREAD_EXITED) 290*a45ae5f8SJohn Marino observer_notify_thread_exit (tp, silent); 291*a45ae5f8SJohn Marino 292*a45ae5f8SJohn Marino /* Tag it as exited. */ 293*a45ae5f8SJohn Marino tp->state = THREAD_EXITED; 294*a45ae5f8SJohn Marino clear_thread_inferior_resources (tp); 295*a45ae5f8SJohn Marino 2965796c8dcSSimon Schubert if (tpprev) 2975796c8dcSSimon Schubert tpprev->next = tp->next; 2985796c8dcSSimon Schubert else 2995796c8dcSSimon Schubert thread_list = tp->next; 3005796c8dcSSimon Schubert 3015796c8dcSSimon Schubert free_thread (tp); 3025796c8dcSSimon Schubert } 3035796c8dcSSimon Schubert 3045796c8dcSSimon Schubert /* Delete thread PTID and notify of thread exit. If this is 3055796c8dcSSimon Schubert inferior_ptid, don't actually delete it, but tag it as exited and 3065796c8dcSSimon Schubert do the notification. If PTID is the user selected thread, clear 3075796c8dcSSimon Schubert it. */ 3085796c8dcSSimon Schubert void 3095796c8dcSSimon Schubert delete_thread (ptid_t ptid) 3105796c8dcSSimon Schubert { 3115796c8dcSSimon Schubert delete_thread_1 (ptid, 0 /* not silent */); 3125796c8dcSSimon Schubert } 3135796c8dcSSimon Schubert 3145796c8dcSSimon Schubert void 3155796c8dcSSimon Schubert delete_thread_silent (ptid_t ptid) 3165796c8dcSSimon Schubert { 3175796c8dcSSimon Schubert delete_thread_1 (ptid, 1 /* silent */); 3185796c8dcSSimon Schubert } 3195796c8dcSSimon Schubert 3205796c8dcSSimon Schubert struct thread_info * 3215796c8dcSSimon Schubert find_thread_id (int num) 3225796c8dcSSimon Schubert { 3235796c8dcSSimon Schubert struct thread_info *tp; 3245796c8dcSSimon Schubert 3255796c8dcSSimon Schubert for (tp = thread_list; tp; tp = tp->next) 3265796c8dcSSimon Schubert if (tp->num == num) 3275796c8dcSSimon Schubert return tp; 3285796c8dcSSimon Schubert 3295796c8dcSSimon Schubert return NULL; 3305796c8dcSSimon Schubert } 3315796c8dcSSimon Schubert 3325796c8dcSSimon Schubert /* Find a thread_info by matching PTID. */ 3335796c8dcSSimon Schubert struct thread_info * 3345796c8dcSSimon Schubert find_thread_ptid (ptid_t ptid) 3355796c8dcSSimon Schubert { 3365796c8dcSSimon Schubert struct thread_info *tp; 3375796c8dcSSimon Schubert 3385796c8dcSSimon Schubert for (tp = thread_list; tp; tp = tp->next) 3395796c8dcSSimon Schubert if (ptid_equal (tp->ptid, ptid)) 3405796c8dcSSimon Schubert return tp; 3415796c8dcSSimon Schubert 3425796c8dcSSimon Schubert return NULL; 3435796c8dcSSimon Schubert } 3445796c8dcSSimon Schubert 3455796c8dcSSimon Schubert /* 3465796c8dcSSimon Schubert * Thread iterator function. 3475796c8dcSSimon Schubert * 3485796c8dcSSimon Schubert * Calls a callback function once for each thread, so long as 3495796c8dcSSimon Schubert * the callback function returns false. If the callback function 3505796c8dcSSimon Schubert * returns true, the iteration will end and the current thread 3515796c8dcSSimon Schubert * will be returned. This can be useful for implementing a 3525796c8dcSSimon Schubert * search for a thread with arbitrary attributes, or for applying 3535796c8dcSSimon Schubert * some operation to every thread. 3545796c8dcSSimon Schubert * 3555796c8dcSSimon Schubert * FIXME: some of the existing functionality, such as 3565796c8dcSSimon Schubert * "Thread apply all", might be rewritten using this functionality. 3575796c8dcSSimon Schubert */ 3585796c8dcSSimon Schubert 3595796c8dcSSimon Schubert struct thread_info * 3605796c8dcSSimon Schubert iterate_over_threads (int (*callback) (struct thread_info *, void *), 3615796c8dcSSimon Schubert void *data) 3625796c8dcSSimon Schubert { 3635796c8dcSSimon Schubert struct thread_info *tp, *next; 3645796c8dcSSimon Schubert 3655796c8dcSSimon Schubert for (tp = thread_list; tp; tp = next) 3665796c8dcSSimon Schubert { 3675796c8dcSSimon Schubert next = tp->next; 3685796c8dcSSimon Schubert if ((*callback) (tp, data)) 3695796c8dcSSimon Schubert return tp; 3705796c8dcSSimon Schubert } 3715796c8dcSSimon Schubert 3725796c8dcSSimon Schubert return NULL; 3735796c8dcSSimon Schubert } 3745796c8dcSSimon Schubert 3755796c8dcSSimon Schubert int 3765796c8dcSSimon Schubert thread_count (void) 3775796c8dcSSimon Schubert { 3785796c8dcSSimon Schubert int result = 0; 3795796c8dcSSimon Schubert struct thread_info *tp; 3805796c8dcSSimon Schubert 3815796c8dcSSimon Schubert for (tp = thread_list; tp; tp = tp->next) 3825796c8dcSSimon Schubert ++result; 3835796c8dcSSimon Schubert 3845796c8dcSSimon Schubert return result; 3855796c8dcSSimon Schubert } 3865796c8dcSSimon Schubert 3875796c8dcSSimon Schubert int 3885796c8dcSSimon Schubert valid_thread_id (int num) 3895796c8dcSSimon Schubert { 3905796c8dcSSimon Schubert struct thread_info *tp; 3915796c8dcSSimon Schubert 3925796c8dcSSimon Schubert for (tp = thread_list; tp; tp = tp->next) 3935796c8dcSSimon Schubert if (tp->num == num) 3945796c8dcSSimon Schubert return 1; 3955796c8dcSSimon Schubert 3965796c8dcSSimon Schubert return 0; 3975796c8dcSSimon Schubert } 3985796c8dcSSimon Schubert 3995796c8dcSSimon Schubert int 4005796c8dcSSimon Schubert pid_to_thread_id (ptid_t ptid) 4015796c8dcSSimon Schubert { 4025796c8dcSSimon Schubert struct thread_info *tp; 4035796c8dcSSimon Schubert 4045796c8dcSSimon Schubert for (tp = thread_list; tp; tp = tp->next) 4055796c8dcSSimon Schubert if (ptid_equal (tp->ptid, ptid)) 4065796c8dcSSimon Schubert return tp->num; 4075796c8dcSSimon Schubert 4085796c8dcSSimon Schubert return 0; 4095796c8dcSSimon Schubert } 4105796c8dcSSimon Schubert 4115796c8dcSSimon Schubert ptid_t 4125796c8dcSSimon Schubert thread_id_to_pid (int num) 4135796c8dcSSimon Schubert { 4145796c8dcSSimon Schubert struct thread_info *thread = find_thread_id (num); 415cf7f2e2dSJohn Marino 4165796c8dcSSimon Schubert if (thread) 4175796c8dcSSimon Schubert return thread->ptid; 4185796c8dcSSimon Schubert else 4195796c8dcSSimon Schubert return pid_to_ptid (-1); 4205796c8dcSSimon Schubert } 4215796c8dcSSimon Schubert 4225796c8dcSSimon Schubert int 4235796c8dcSSimon Schubert in_thread_list (ptid_t ptid) 4245796c8dcSSimon Schubert { 4255796c8dcSSimon Schubert struct thread_info *tp; 4265796c8dcSSimon Schubert 4275796c8dcSSimon Schubert for (tp = thread_list; tp; tp = tp->next) 4285796c8dcSSimon Schubert if (ptid_equal (tp->ptid, ptid)) 4295796c8dcSSimon Schubert return 1; 4305796c8dcSSimon Schubert 431c50c785cSJohn Marino return 0; /* Never heard of 'im. */ 4325796c8dcSSimon Schubert } 4335796c8dcSSimon Schubert 4345796c8dcSSimon Schubert /* Finds the first thread of the inferior given by PID. If PID is -1, 4355796c8dcSSimon Schubert return the first thread in the list. */ 4365796c8dcSSimon Schubert 4375796c8dcSSimon Schubert struct thread_info * 4385796c8dcSSimon Schubert first_thread_of_process (int pid) 4395796c8dcSSimon Schubert { 4405796c8dcSSimon Schubert struct thread_info *tp, *ret = NULL; 4415796c8dcSSimon Schubert 4425796c8dcSSimon Schubert for (tp = thread_list; tp; tp = tp->next) 4435796c8dcSSimon Schubert if (pid == -1 || ptid_get_pid (tp->ptid) == pid) 4445796c8dcSSimon Schubert if (ret == NULL || tp->num < ret->num) 4455796c8dcSSimon Schubert ret = tp; 4465796c8dcSSimon Schubert 4475796c8dcSSimon Schubert return ret; 4485796c8dcSSimon Schubert } 4495796c8dcSSimon Schubert 4505796c8dcSSimon Schubert struct thread_info * 4515796c8dcSSimon Schubert any_thread_of_process (int pid) 4525796c8dcSSimon Schubert { 4535796c8dcSSimon Schubert struct thread_info *tp; 4545796c8dcSSimon Schubert 4555796c8dcSSimon Schubert for (tp = thread_list; tp; tp = tp->next) 4565796c8dcSSimon Schubert if (ptid_get_pid (tp->ptid) == pid) 4575796c8dcSSimon Schubert return tp; 4585796c8dcSSimon Schubert 4595796c8dcSSimon Schubert return NULL; 4605796c8dcSSimon Schubert } 4615796c8dcSSimon Schubert 462cf7f2e2dSJohn Marino struct thread_info * 463cf7f2e2dSJohn Marino any_live_thread_of_process (int pid) 464cf7f2e2dSJohn Marino { 465cf7f2e2dSJohn Marino struct thread_info *tp; 466c50c785cSJohn Marino struct thread_info *tp_executing = NULL; 467cf7f2e2dSJohn Marino 468cf7f2e2dSJohn Marino for (tp = thread_list; tp; tp = tp->next) 469*a45ae5f8SJohn Marino if (tp->state != THREAD_EXITED && ptid_get_pid (tp->ptid) == pid) 470cf7f2e2dSJohn Marino { 471*a45ae5f8SJohn Marino if (tp->executing) 472c50c785cSJohn Marino tp_executing = tp; 473c50c785cSJohn Marino else 474cf7f2e2dSJohn Marino return tp; 475cf7f2e2dSJohn Marino } 476cf7f2e2dSJohn Marino 477c50c785cSJohn Marino return tp_executing; 478cf7f2e2dSJohn Marino } 479cf7f2e2dSJohn Marino 4805796c8dcSSimon Schubert /* Print a list of thread ids currently known, and the total number of 4815796c8dcSSimon Schubert threads. To be used from within catch_errors. */ 4825796c8dcSSimon Schubert static int 4835796c8dcSSimon Schubert do_captured_list_thread_ids (struct ui_out *uiout, void *arg) 4845796c8dcSSimon Schubert { 4855796c8dcSSimon Schubert struct thread_info *tp; 4865796c8dcSSimon Schubert int num = 0; 4875796c8dcSSimon Schubert struct cleanup *cleanup_chain; 4885796c8dcSSimon Schubert int current_thread = -1; 4895796c8dcSSimon Schubert 490cf7f2e2dSJohn Marino update_thread_list (); 4915796c8dcSSimon Schubert 4925796c8dcSSimon Schubert cleanup_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "thread-ids"); 4935796c8dcSSimon Schubert 4945796c8dcSSimon Schubert for (tp = thread_list; tp; tp = tp->next) 4955796c8dcSSimon Schubert { 496*a45ae5f8SJohn Marino if (tp->state == THREAD_EXITED) 4975796c8dcSSimon Schubert continue; 4985796c8dcSSimon Schubert 4995796c8dcSSimon Schubert if (ptid_equal (tp->ptid, inferior_ptid)) 5005796c8dcSSimon Schubert current_thread = tp->num; 5015796c8dcSSimon Schubert 5025796c8dcSSimon Schubert num++; 5035796c8dcSSimon Schubert ui_out_field_int (uiout, "thread-id", tp->num); 5045796c8dcSSimon Schubert } 5055796c8dcSSimon Schubert 5065796c8dcSSimon Schubert do_cleanups (cleanup_chain); 5075796c8dcSSimon Schubert 5085796c8dcSSimon Schubert if (current_thread != -1) 5095796c8dcSSimon Schubert ui_out_field_int (uiout, "current-thread-id", current_thread); 5105796c8dcSSimon Schubert ui_out_field_int (uiout, "number-of-threads", num); 5115796c8dcSSimon Schubert return GDB_RC_OK; 5125796c8dcSSimon Schubert } 5135796c8dcSSimon Schubert 5145796c8dcSSimon Schubert /* Official gdblib interface function to get a list of thread ids and 5155796c8dcSSimon Schubert the total number. */ 5165796c8dcSSimon Schubert enum gdb_rc 5175796c8dcSSimon Schubert gdb_list_thread_ids (struct ui_out *uiout, char **error_message) 5185796c8dcSSimon Schubert { 5195796c8dcSSimon Schubert if (catch_exceptions_with_msg (uiout, do_captured_list_thread_ids, NULL, 5205796c8dcSSimon Schubert error_message, RETURN_MASK_ALL) < 0) 5215796c8dcSSimon Schubert return GDB_RC_FAIL; 5225796c8dcSSimon Schubert return GDB_RC_OK; 5235796c8dcSSimon Schubert } 5245796c8dcSSimon Schubert 5255796c8dcSSimon Schubert /* Return true if TP is an active thread. */ 5265796c8dcSSimon Schubert static int 5275796c8dcSSimon Schubert thread_alive (struct thread_info *tp) 5285796c8dcSSimon Schubert { 529*a45ae5f8SJohn Marino if (tp->state == THREAD_EXITED) 5305796c8dcSSimon Schubert return 0; 5315796c8dcSSimon Schubert if (!target_thread_alive (tp->ptid)) 5325796c8dcSSimon Schubert return 0; 5335796c8dcSSimon Schubert return 1; 5345796c8dcSSimon Schubert } 5355796c8dcSSimon Schubert 5365796c8dcSSimon Schubert static void 5375796c8dcSSimon Schubert prune_threads (void) 5385796c8dcSSimon Schubert { 5395796c8dcSSimon Schubert struct thread_info *tp, *next; 5405796c8dcSSimon Schubert 5415796c8dcSSimon Schubert for (tp = thread_list; tp; tp = next) 5425796c8dcSSimon Schubert { 5435796c8dcSSimon Schubert next = tp->next; 5445796c8dcSSimon Schubert if (!thread_alive (tp)) 5455796c8dcSSimon Schubert delete_thread (tp->ptid); 5465796c8dcSSimon Schubert } 5475796c8dcSSimon Schubert } 5485796c8dcSSimon Schubert 5495796c8dcSSimon Schubert void 5505796c8dcSSimon Schubert thread_change_ptid (ptid_t old_ptid, ptid_t new_ptid) 5515796c8dcSSimon Schubert { 5525796c8dcSSimon Schubert struct inferior *inf; 5535796c8dcSSimon Schubert struct thread_info *tp; 5545796c8dcSSimon Schubert 5555796c8dcSSimon Schubert /* It can happen that what we knew as the target inferior id 5565796c8dcSSimon Schubert changes. E.g, target remote may only discover the remote process 5575796c8dcSSimon Schubert pid after adding the inferior to GDB's list. */ 5585796c8dcSSimon Schubert inf = find_inferior_pid (ptid_get_pid (old_ptid)); 5595796c8dcSSimon Schubert inf->pid = ptid_get_pid (new_ptid); 5605796c8dcSSimon Schubert 5615796c8dcSSimon Schubert tp = find_thread_ptid (old_ptid); 5625796c8dcSSimon Schubert tp->ptid = new_ptid; 5635796c8dcSSimon Schubert 5645796c8dcSSimon Schubert observer_notify_thread_ptid_changed (old_ptid, new_ptid); 5655796c8dcSSimon Schubert } 5665796c8dcSSimon Schubert 5675796c8dcSSimon Schubert void 5685796c8dcSSimon Schubert set_running (ptid_t ptid, int running) 5695796c8dcSSimon Schubert { 5705796c8dcSSimon Schubert struct thread_info *tp; 5715796c8dcSSimon Schubert int all = ptid_equal (ptid, minus_one_ptid); 5725796c8dcSSimon Schubert 5735796c8dcSSimon Schubert /* We try not to notify the observer if no thread has actually changed 5745796c8dcSSimon Schubert the running state -- merely to reduce the number of messages to 5755796c8dcSSimon Schubert frontend. Frontend is supposed to handle multiple *running just fine. */ 5765796c8dcSSimon Schubert if (all || ptid_is_pid (ptid)) 5775796c8dcSSimon Schubert { 5785796c8dcSSimon Schubert int any_started = 0; 579cf7f2e2dSJohn Marino 5805796c8dcSSimon Schubert for (tp = thread_list; tp; tp = tp->next) 5815796c8dcSSimon Schubert if (all || ptid_get_pid (tp->ptid) == ptid_get_pid (ptid)) 5825796c8dcSSimon Schubert { 583*a45ae5f8SJohn Marino if (tp->state == THREAD_EXITED) 5845796c8dcSSimon Schubert continue; 585*a45ae5f8SJohn Marino if (running && tp->state == THREAD_STOPPED) 5865796c8dcSSimon Schubert any_started = 1; 587*a45ae5f8SJohn Marino tp->state = running ? THREAD_RUNNING : THREAD_STOPPED; 5885796c8dcSSimon Schubert } 5895796c8dcSSimon Schubert if (any_started) 5905796c8dcSSimon Schubert observer_notify_target_resumed (ptid); 5915796c8dcSSimon Schubert } 5925796c8dcSSimon Schubert else 5935796c8dcSSimon Schubert { 5945796c8dcSSimon Schubert int started = 0; 595cf7f2e2dSJohn Marino 5965796c8dcSSimon Schubert tp = find_thread_ptid (ptid); 5975796c8dcSSimon Schubert gdb_assert (tp); 598*a45ae5f8SJohn Marino gdb_assert (tp->state != THREAD_EXITED); 599*a45ae5f8SJohn Marino if (running && tp->state == THREAD_STOPPED) 6005796c8dcSSimon Schubert started = 1; 601*a45ae5f8SJohn Marino tp->state = running ? THREAD_RUNNING : THREAD_STOPPED; 6025796c8dcSSimon Schubert if (started) 6035796c8dcSSimon Schubert observer_notify_target_resumed (ptid); 6045796c8dcSSimon Schubert } 6055796c8dcSSimon Schubert } 6065796c8dcSSimon Schubert 6075796c8dcSSimon Schubert static int 6085796c8dcSSimon Schubert is_thread_state (ptid_t ptid, enum thread_state state) 6095796c8dcSSimon Schubert { 6105796c8dcSSimon Schubert struct thread_info *tp; 6115796c8dcSSimon Schubert 6125796c8dcSSimon Schubert tp = find_thread_ptid (ptid); 6135796c8dcSSimon Schubert gdb_assert (tp); 614*a45ae5f8SJohn Marino return tp->state == state; 6155796c8dcSSimon Schubert } 6165796c8dcSSimon Schubert 6175796c8dcSSimon Schubert int 6185796c8dcSSimon Schubert is_stopped (ptid_t ptid) 6195796c8dcSSimon Schubert { 6205796c8dcSSimon Schubert return is_thread_state (ptid, THREAD_STOPPED); 6215796c8dcSSimon Schubert } 6225796c8dcSSimon Schubert 6235796c8dcSSimon Schubert int 6245796c8dcSSimon Schubert is_exited (ptid_t ptid) 6255796c8dcSSimon Schubert { 6265796c8dcSSimon Schubert return is_thread_state (ptid, THREAD_EXITED); 6275796c8dcSSimon Schubert } 6285796c8dcSSimon Schubert 6295796c8dcSSimon Schubert int 6305796c8dcSSimon Schubert is_running (ptid_t ptid) 6315796c8dcSSimon Schubert { 6325796c8dcSSimon Schubert return is_thread_state (ptid, THREAD_RUNNING); 6335796c8dcSSimon Schubert } 6345796c8dcSSimon Schubert 6355796c8dcSSimon Schubert int 6365796c8dcSSimon Schubert any_running (void) 6375796c8dcSSimon Schubert { 6385796c8dcSSimon Schubert struct thread_info *tp; 6395796c8dcSSimon Schubert 6405796c8dcSSimon Schubert for (tp = thread_list; tp; tp = tp->next) 641*a45ae5f8SJohn Marino if (tp->state == THREAD_RUNNING) 6425796c8dcSSimon Schubert return 1; 6435796c8dcSSimon Schubert 6445796c8dcSSimon Schubert return 0; 6455796c8dcSSimon Schubert } 6465796c8dcSSimon Schubert 6475796c8dcSSimon Schubert int 6485796c8dcSSimon Schubert is_executing (ptid_t ptid) 6495796c8dcSSimon Schubert { 6505796c8dcSSimon Schubert struct thread_info *tp; 6515796c8dcSSimon Schubert 6525796c8dcSSimon Schubert tp = find_thread_ptid (ptid); 6535796c8dcSSimon Schubert gdb_assert (tp); 654*a45ae5f8SJohn Marino return tp->executing; 6555796c8dcSSimon Schubert } 6565796c8dcSSimon Schubert 6575796c8dcSSimon Schubert void 6585796c8dcSSimon Schubert set_executing (ptid_t ptid, int executing) 6595796c8dcSSimon Schubert { 6605796c8dcSSimon Schubert struct thread_info *tp; 6615796c8dcSSimon Schubert int all = ptid_equal (ptid, minus_one_ptid); 6625796c8dcSSimon Schubert 6635796c8dcSSimon Schubert if (all || ptid_is_pid (ptid)) 6645796c8dcSSimon Schubert { 6655796c8dcSSimon Schubert for (tp = thread_list; tp; tp = tp->next) 6665796c8dcSSimon Schubert if (all || ptid_get_pid (tp->ptid) == ptid_get_pid (ptid)) 667*a45ae5f8SJohn Marino tp->executing = executing; 6685796c8dcSSimon Schubert } 6695796c8dcSSimon Schubert else 6705796c8dcSSimon Schubert { 6715796c8dcSSimon Schubert tp = find_thread_ptid (ptid); 6725796c8dcSSimon Schubert gdb_assert (tp); 673*a45ae5f8SJohn Marino tp->executing = executing; 6745796c8dcSSimon Schubert } 6755796c8dcSSimon Schubert } 6765796c8dcSSimon Schubert 6775796c8dcSSimon Schubert void 6785796c8dcSSimon Schubert set_stop_requested (ptid_t ptid, int stop) 6795796c8dcSSimon Schubert { 6805796c8dcSSimon Schubert struct thread_info *tp; 6815796c8dcSSimon Schubert int all = ptid_equal (ptid, minus_one_ptid); 6825796c8dcSSimon Schubert 6835796c8dcSSimon Schubert if (all || ptid_is_pid (ptid)) 6845796c8dcSSimon Schubert { 6855796c8dcSSimon Schubert for (tp = thread_list; tp; tp = tp->next) 6865796c8dcSSimon Schubert if (all || ptid_get_pid (tp->ptid) == ptid_get_pid (ptid)) 6875796c8dcSSimon Schubert tp->stop_requested = stop; 6885796c8dcSSimon Schubert } 6895796c8dcSSimon Schubert else 6905796c8dcSSimon Schubert { 6915796c8dcSSimon Schubert tp = find_thread_ptid (ptid); 6925796c8dcSSimon Schubert gdb_assert (tp); 6935796c8dcSSimon Schubert tp->stop_requested = stop; 6945796c8dcSSimon Schubert } 6955796c8dcSSimon Schubert 6965796c8dcSSimon Schubert /* Call the stop requested observer so other components of GDB can 6975796c8dcSSimon Schubert react to this request. */ 6985796c8dcSSimon Schubert if (stop) 6995796c8dcSSimon Schubert observer_notify_thread_stop_requested (ptid); 7005796c8dcSSimon Schubert } 7015796c8dcSSimon Schubert 7025796c8dcSSimon Schubert void 7035796c8dcSSimon Schubert finish_thread_state (ptid_t ptid) 7045796c8dcSSimon Schubert { 7055796c8dcSSimon Schubert struct thread_info *tp; 7065796c8dcSSimon Schubert int all; 7075796c8dcSSimon Schubert int any_started = 0; 7085796c8dcSSimon Schubert 7095796c8dcSSimon Schubert all = ptid_equal (ptid, minus_one_ptid); 7105796c8dcSSimon Schubert 7115796c8dcSSimon Schubert if (all || ptid_is_pid (ptid)) 7125796c8dcSSimon Schubert { 7135796c8dcSSimon Schubert for (tp = thread_list; tp; tp = tp->next) 7145796c8dcSSimon Schubert { 715*a45ae5f8SJohn Marino if (tp->state == THREAD_EXITED) 7165796c8dcSSimon Schubert continue; 7175796c8dcSSimon Schubert if (all || ptid_get_pid (ptid) == ptid_get_pid (tp->ptid)) 7185796c8dcSSimon Schubert { 719*a45ae5f8SJohn Marino if (tp->executing && tp->state == THREAD_STOPPED) 7205796c8dcSSimon Schubert any_started = 1; 721*a45ae5f8SJohn Marino tp->state = tp->executing ? THREAD_RUNNING : THREAD_STOPPED; 7225796c8dcSSimon Schubert } 7235796c8dcSSimon Schubert } 7245796c8dcSSimon Schubert } 7255796c8dcSSimon Schubert else 7265796c8dcSSimon Schubert { 7275796c8dcSSimon Schubert tp = find_thread_ptid (ptid); 7285796c8dcSSimon Schubert gdb_assert (tp); 729*a45ae5f8SJohn Marino if (tp->state != THREAD_EXITED) 7305796c8dcSSimon Schubert { 731*a45ae5f8SJohn Marino if (tp->executing && tp->state == THREAD_STOPPED) 7325796c8dcSSimon Schubert any_started = 1; 733*a45ae5f8SJohn Marino tp->state = tp->executing ? THREAD_RUNNING : THREAD_STOPPED; 7345796c8dcSSimon Schubert } 7355796c8dcSSimon Schubert } 7365796c8dcSSimon Schubert 7375796c8dcSSimon Schubert if (any_started) 7385796c8dcSSimon Schubert observer_notify_target_resumed (ptid); 7395796c8dcSSimon Schubert } 7405796c8dcSSimon Schubert 7415796c8dcSSimon Schubert void 7425796c8dcSSimon Schubert finish_thread_state_cleanup (void *arg) 7435796c8dcSSimon Schubert { 7445796c8dcSSimon Schubert ptid_t *ptid_p = arg; 7455796c8dcSSimon Schubert 7465796c8dcSSimon Schubert gdb_assert (arg); 7475796c8dcSSimon Schubert 7485796c8dcSSimon Schubert finish_thread_state (*ptid_p); 7495796c8dcSSimon Schubert } 7505796c8dcSSimon Schubert 7515796c8dcSSimon Schubert /* Prints the list of threads and their details on UIOUT. 752c50c785cSJohn Marino This is a version of 'info_threads_command' suitable for 7535796c8dcSSimon Schubert use from MI. 7545796c8dcSSimon Schubert If REQUESTED_THREAD is not -1, it's the GDB id of the thread 7555796c8dcSSimon Schubert that should be printed. Otherwise, all threads are 7565796c8dcSSimon Schubert printed. 7575796c8dcSSimon Schubert If PID is not -1, only print threads from the process PID. 7585796c8dcSSimon Schubert Otherwise, threads from all attached PIDs are printed. 7595796c8dcSSimon Schubert If both REQUESTED_THREAD and PID are not -1, then the thread 7605796c8dcSSimon Schubert is printed if it belongs to the specified process. Otherwise, 7615796c8dcSSimon Schubert an error is raised. */ 7625796c8dcSSimon Schubert void 763c50c785cSJohn Marino print_thread_info (struct ui_out *uiout, char *requested_threads, int pid) 7645796c8dcSSimon Schubert { 7655796c8dcSSimon Schubert struct thread_info *tp; 7665796c8dcSSimon Schubert ptid_t current_ptid; 7675796c8dcSSimon Schubert struct cleanup *old_chain; 768c50c785cSJohn Marino char *extra_info, *name, *target_id; 7695796c8dcSSimon Schubert int current_thread = -1; 7705796c8dcSSimon Schubert 771cf7f2e2dSJohn Marino update_thread_list (); 7725796c8dcSSimon Schubert current_ptid = inferior_ptid; 7735796c8dcSSimon Schubert 7745796c8dcSSimon Schubert /* We'll be switching threads temporarily. */ 7755796c8dcSSimon Schubert old_chain = make_cleanup_restore_current_thread (); 7765796c8dcSSimon Schubert 777c50c785cSJohn Marino /* For backward compatibility, we make a list for MI. A table is 778c50c785cSJohn Marino preferable for the CLI, though, because it shows table 779c50c785cSJohn Marino headers. */ 780c50c785cSJohn Marino if (ui_out_is_mi_like_p (uiout)) 7815796c8dcSSimon Schubert make_cleanup_ui_out_list_begin_end (uiout, "threads"); 782c50c785cSJohn Marino else 783c50c785cSJohn Marino { 784c50c785cSJohn Marino int n_threads = 0; 785c50c785cSJohn Marino 786c50c785cSJohn Marino for (tp = thread_list; tp; tp = tp->next) 787c50c785cSJohn Marino { 788c50c785cSJohn Marino if (!number_is_in_list (requested_threads, tp->num)) 789c50c785cSJohn Marino continue; 790c50c785cSJohn Marino 791c50c785cSJohn Marino if (pid != -1 && PIDGET (tp->ptid) != pid) 792c50c785cSJohn Marino continue; 793c50c785cSJohn Marino 794*a45ae5f8SJohn Marino if (tp->state == THREAD_EXITED) 795c50c785cSJohn Marino continue; 796c50c785cSJohn Marino 797c50c785cSJohn Marino ++n_threads; 798c50c785cSJohn Marino } 799c50c785cSJohn Marino 800c50c785cSJohn Marino if (n_threads == 0) 801c50c785cSJohn Marino { 802c50c785cSJohn Marino if (requested_threads == NULL || *requested_threads == '\0') 803c50c785cSJohn Marino ui_out_message (uiout, 0, _("No threads.\n")); 804c50c785cSJohn Marino else 805c50c785cSJohn Marino ui_out_message (uiout, 0, _("No threads match '%s'.\n"), 806c50c785cSJohn Marino requested_threads); 807c50c785cSJohn Marino do_cleanups (old_chain); 808c50c785cSJohn Marino return; 809c50c785cSJohn Marino } 810c50c785cSJohn Marino 811c50c785cSJohn Marino make_cleanup_ui_out_table_begin_end (uiout, 4, n_threads, "threads"); 812c50c785cSJohn Marino 813c50c785cSJohn Marino ui_out_table_header (uiout, 1, ui_left, "current", ""); 814c50c785cSJohn Marino ui_out_table_header (uiout, 4, ui_left, "id", "Id"); 815c50c785cSJohn Marino ui_out_table_header (uiout, 17, ui_left, "target-id", "Target Id"); 816c50c785cSJohn Marino ui_out_table_header (uiout, 1, ui_left, "frame", "Frame"); 817c50c785cSJohn Marino ui_out_table_body (uiout); 818c50c785cSJohn Marino } 819c50c785cSJohn Marino 8205796c8dcSSimon Schubert for (tp = thread_list; tp; tp = tp->next) 8215796c8dcSSimon Schubert { 8225796c8dcSSimon Schubert struct cleanup *chain2; 823cf7f2e2dSJohn Marino int core; 8245796c8dcSSimon Schubert 825c50c785cSJohn Marino if (!number_is_in_list (requested_threads, tp->num)) 8265796c8dcSSimon Schubert continue; 8275796c8dcSSimon Schubert 8285796c8dcSSimon Schubert if (pid != -1 && PIDGET (tp->ptid) != pid) 8295796c8dcSSimon Schubert { 830c50c785cSJohn Marino if (requested_threads != NULL && *requested_threads != '\0') 8315796c8dcSSimon Schubert error (_("Requested thread not found in requested process")); 8325796c8dcSSimon Schubert continue; 8335796c8dcSSimon Schubert } 8345796c8dcSSimon Schubert 8355796c8dcSSimon Schubert if (ptid_equal (tp->ptid, current_ptid)) 8365796c8dcSSimon Schubert current_thread = tp->num; 8375796c8dcSSimon Schubert 838*a45ae5f8SJohn Marino if (tp->state == THREAD_EXITED) 8395796c8dcSSimon Schubert continue; 8405796c8dcSSimon Schubert 8415796c8dcSSimon Schubert chain2 = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); 8425796c8dcSSimon Schubert 843c50c785cSJohn Marino if (ui_out_is_mi_like_p (uiout)) 844c50c785cSJohn Marino { 845c50c785cSJohn Marino /* Compatibility. */ 8465796c8dcSSimon Schubert if (ptid_equal (tp->ptid, current_ptid)) 8475796c8dcSSimon Schubert ui_out_text (uiout, "* "); 8485796c8dcSSimon Schubert else 8495796c8dcSSimon Schubert ui_out_text (uiout, " "); 850c50c785cSJohn Marino } 851c50c785cSJohn Marino else 852c50c785cSJohn Marino { 853c50c785cSJohn Marino if (ptid_equal (tp->ptid, current_ptid)) 854c50c785cSJohn Marino ui_out_field_string (uiout, "current", "*"); 855c50c785cSJohn Marino else 856c50c785cSJohn Marino ui_out_field_skip (uiout, "current"); 857c50c785cSJohn Marino } 8585796c8dcSSimon Schubert 8595796c8dcSSimon Schubert ui_out_field_int (uiout, "id", tp->num); 8605796c8dcSSimon Schubert 861c50c785cSJohn Marino /* For the CLI, we stuff everything into the target-id field. 862c50c785cSJohn Marino This is a gross hack to make the output come out looking 863c50c785cSJohn Marino correct. The underlying problem here is that ui-out has no 864c50c785cSJohn Marino way to specify that a field's space allocation should be 865c50c785cSJohn Marino shared by several fields. For MI, we do the right thing 866c50c785cSJohn Marino instead. */ 867c50c785cSJohn Marino 868c50c785cSJohn Marino target_id = target_pid_to_str (tp->ptid); 8695796c8dcSSimon Schubert extra_info = target_extra_thread_info (tp); 870c50c785cSJohn Marino name = tp->name ? tp->name : target_thread_name (tp); 871c50c785cSJohn Marino 872c50c785cSJohn Marino if (ui_out_is_mi_like_p (uiout)) 8735796c8dcSSimon Schubert { 874c50c785cSJohn Marino ui_out_field_string (uiout, "target-id", target_id); 875c50c785cSJohn Marino if (extra_info) 8765796c8dcSSimon Schubert ui_out_field_string (uiout, "details", extra_info); 877c50c785cSJohn Marino if (name) 878c50c785cSJohn Marino ui_out_field_string (uiout, "name", name); 8795796c8dcSSimon Schubert } 880c50c785cSJohn Marino else 881c50c785cSJohn Marino { 882c50c785cSJohn Marino struct cleanup *str_cleanup; 883c50c785cSJohn Marino char *contents; 884c50c785cSJohn Marino 885c50c785cSJohn Marino if (extra_info && name) 886c50c785cSJohn Marino contents = xstrprintf ("%s \"%s\" (%s)", target_id, 887c50c785cSJohn Marino name, extra_info); 888c50c785cSJohn Marino else if (extra_info) 889c50c785cSJohn Marino contents = xstrprintf ("%s (%s)", target_id, extra_info); 890c50c785cSJohn Marino else if (name) 891c50c785cSJohn Marino contents = xstrprintf ("%s \"%s\"", target_id, name); 892c50c785cSJohn Marino else 893c50c785cSJohn Marino contents = xstrdup (target_id); 894c50c785cSJohn Marino str_cleanup = make_cleanup (xfree, contents); 895c50c785cSJohn Marino 896c50c785cSJohn Marino ui_out_field_string (uiout, "target-id", contents); 897c50c785cSJohn Marino do_cleanups (str_cleanup); 898c50c785cSJohn Marino } 8995796c8dcSSimon Schubert 900*a45ae5f8SJohn Marino if (tp->state == THREAD_RUNNING) 9015796c8dcSSimon Schubert ui_out_text (uiout, "(running)\n"); 9025796c8dcSSimon Schubert else 9035796c8dcSSimon Schubert { 9045796c8dcSSimon Schubert /* The switch below puts us at the top of the stack (leaf 9055796c8dcSSimon Schubert frame). */ 9065796c8dcSSimon Schubert switch_to_thread (tp->ptid); 9075796c8dcSSimon Schubert print_stack_frame (get_selected_frame (NULL), 9085796c8dcSSimon Schubert /* For MI output, print frame level. */ 9095796c8dcSSimon Schubert ui_out_is_mi_like_p (uiout), 9105796c8dcSSimon Schubert LOCATION); 9115796c8dcSSimon Schubert } 9125796c8dcSSimon Schubert 9135796c8dcSSimon Schubert if (ui_out_is_mi_like_p (uiout)) 9145796c8dcSSimon Schubert { 9155796c8dcSSimon Schubert char *state = "stopped"; 916cf7f2e2dSJohn Marino 917*a45ae5f8SJohn Marino if (tp->state == THREAD_RUNNING) 9185796c8dcSSimon Schubert state = "running"; 9195796c8dcSSimon Schubert ui_out_field_string (uiout, "state", state); 9205796c8dcSSimon Schubert } 9215796c8dcSSimon Schubert 922cf7f2e2dSJohn Marino core = target_core_of_thread (tp->ptid); 923cf7f2e2dSJohn Marino if (ui_out_is_mi_like_p (uiout) && core != -1) 924cf7f2e2dSJohn Marino ui_out_field_int (uiout, "core", core); 925cf7f2e2dSJohn Marino 9265796c8dcSSimon Schubert do_cleanups (chain2); 9275796c8dcSSimon Schubert } 9285796c8dcSSimon Schubert 9295796c8dcSSimon Schubert /* Restores the current thread and the frame selected before 9305796c8dcSSimon Schubert the "info threads" command. */ 9315796c8dcSSimon Schubert do_cleanups (old_chain); 9325796c8dcSSimon Schubert 933c50c785cSJohn Marino if (pid == -1 && requested_threads == NULL) 9345796c8dcSSimon Schubert { 9355796c8dcSSimon Schubert gdb_assert (current_thread != -1 9365796c8dcSSimon Schubert || !thread_list 9375796c8dcSSimon Schubert || ptid_equal (inferior_ptid, null_ptid)); 9385796c8dcSSimon Schubert if (current_thread != -1 && ui_out_is_mi_like_p (uiout)) 9395796c8dcSSimon Schubert ui_out_field_int (uiout, "current-thread-id", current_thread); 9405796c8dcSSimon Schubert 9415796c8dcSSimon Schubert if (current_thread != -1 && is_exited (current_ptid)) 9425796c8dcSSimon Schubert ui_out_message (uiout, 0, "\n\ 9435796c8dcSSimon Schubert The current thread <Thread ID %d> has terminated. See `help thread'.\n", 9445796c8dcSSimon Schubert current_thread); 9455796c8dcSSimon Schubert else if (thread_list 9465796c8dcSSimon Schubert && current_thread == -1 9475796c8dcSSimon Schubert && ptid_equal (current_ptid, null_ptid)) 9485796c8dcSSimon Schubert ui_out_message (uiout, 0, "\n\ 9495796c8dcSSimon Schubert No selected thread. See `help thread'.\n"); 9505796c8dcSSimon Schubert } 9515796c8dcSSimon Schubert } 9525796c8dcSSimon Schubert 9535796c8dcSSimon Schubert /* Print information about currently known threads 9545796c8dcSSimon Schubert 955c50c785cSJohn Marino Optional ARG is a thread id, or list of thread ids. 956c50c785cSJohn Marino 957c50c785cSJohn Marino Note: this has the drawback that it _really_ switches 958c50c785cSJohn Marino threads, which frees the frame cache. A no-side 959c50c785cSJohn Marino effects info-threads command would be nicer. */ 9605796c8dcSSimon Schubert 9615796c8dcSSimon Schubert static void 9625796c8dcSSimon Schubert info_threads_command (char *arg, int from_tty) 9635796c8dcSSimon Schubert { 964*a45ae5f8SJohn Marino print_thread_info (current_uiout, arg, -1); 9655796c8dcSSimon Schubert } 9665796c8dcSSimon Schubert 9675796c8dcSSimon Schubert /* Switch from one thread to another. */ 9685796c8dcSSimon Schubert 9695796c8dcSSimon Schubert void 9705796c8dcSSimon Schubert switch_to_thread (ptid_t ptid) 9715796c8dcSSimon Schubert { 972cf7f2e2dSJohn Marino /* Switch the program space as well, if we can infer it from the now 973cf7f2e2dSJohn Marino current thread. Otherwise, it's up to the caller to select the 974cf7f2e2dSJohn Marino space it wants. */ 975cf7f2e2dSJohn Marino if (!ptid_equal (ptid, null_ptid)) 976cf7f2e2dSJohn Marino { 977cf7f2e2dSJohn Marino struct inferior *inf; 978cf7f2e2dSJohn Marino 979cf7f2e2dSJohn Marino inf = find_inferior_pid (ptid_get_pid (ptid)); 980cf7f2e2dSJohn Marino gdb_assert (inf != NULL); 981cf7f2e2dSJohn Marino set_current_program_space (inf->pspace); 982cf7f2e2dSJohn Marino set_current_inferior (inf); 983cf7f2e2dSJohn Marino } 984cf7f2e2dSJohn Marino 9855796c8dcSSimon Schubert if (ptid_equal (ptid, inferior_ptid)) 9865796c8dcSSimon Schubert return; 9875796c8dcSSimon Schubert 9885796c8dcSSimon Schubert inferior_ptid = ptid; 9895796c8dcSSimon Schubert reinit_frame_cache (); 9905796c8dcSSimon Schubert registers_changed (); 9915796c8dcSSimon Schubert 9925796c8dcSSimon Schubert /* We don't check for is_stopped, because we're called at times 9935796c8dcSSimon Schubert while in the TARGET_RUNNING state, e.g., while handling an 9945796c8dcSSimon Schubert internal event. */ 9955796c8dcSSimon Schubert if (!ptid_equal (inferior_ptid, null_ptid) 9965796c8dcSSimon Schubert && !is_exited (ptid) 9975796c8dcSSimon Schubert && !is_executing (ptid)) 9985796c8dcSSimon Schubert stop_pc = regcache_read_pc (get_thread_regcache (ptid)); 9995796c8dcSSimon Schubert else 10005796c8dcSSimon Schubert stop_pc = ~(CORE_ADDR) 0; 10015796c8dcSSimon Schubert } 10025796c8dcSSimon Schubert 10035796c8dcSSimon Schubert static void 10045796c8dcSSimon Schubert restore_current_thread (ptid_t ptid) 10055796c8dcSSimon Schubert { 10065796c8dcSSimon Schubert switch_to_thread (ptid); 10075796c8dcSSimon Schubert } 10085796c8dcSSimon Schubert 10095796c8dcSSimon Schubert static void 10105796c8dcSSimon Schubert restore_selected_frame (struct frame_id a_frame_id, int frame_level) 10115796c8dcSSimon Schubert { 10125796c8dcSSimon Schubert struct frame_info *frame = NULL; 10135796c8dcSSimon Schubert int count; 10145796c8dcSSimon Schubert 1015c50c785cSJohn Marino /* This means there was no selected frame. */ 1016c50c785cSJohn Marino if (frame_level == -1) 1017c50c785cSJohn Marino { 1018c50c785cSJohn Marino select_frame (NULL); 1019c50c785cSJohn Marino return; 1020c50c785cSJohn Marino } 1021c50c785cSJohn Marino 10225796c8dcSSimon Schubert gdb_assert (frame_level >= 0); 10235796c8dcSSimon Schubert 10245796c8dcSSimon Schubert /* Restore by level first, check if the frame id is the same as 10255796c8dcSSimon Schubert expected. If that fails, try restoring by frame id. If that 10265796c8dcSSimon Schubert fails, nothing to do, just warn the user. */ 10275796c8dcSSimon Schubert 10285796c8dcSSimon Schubert count = frame_level; 10295796c8dcSSimon Schubert frame = find_relative_frame (get_current_frame (), &count); 10305796c8dcSSimon Schubert if (count == 0 10315796c8dcSSimon Schubert && frame != NULL 10325796c8dcSSimon Schubert /* The frame ids must match - either both valid or both outer_frame_id. 10335796c8dcSSimon Schubert The latter case is not failsafe, but since it's highly unlikely 10345796c8dcSSimon Schubert the search by level finds the wrong frame, it's 99.9(9)% of 10355796c8dcSSimon Schubert the time (for all practical purposes) safe. */ 10365796c8dcSSimon Schubert && frame_id_eq (get_frame_id (frame), a_frame_id)) 10375796c8dcSSimon Schubert { 10385796c8dcSSimon Schubert /* Cool, all is fine. */ 10395796c8dcSSimon Schubert select_frame (frame); 10405796c8dcSSimon Schubert return; 10415796c8dcSSimon Schubert } 10425796c8dcSSimon Schubert 10435796c8dcSSimon Schubert frame = frame_find_by_id (a_frame_id); 10445796c8dcSSimon Schubert if (frame != NULL) 10455796c8dcSSimon Schubert { 10465796c8dcSSimon Schubert /* Cool, refound it. */ 10475796c8dcSSimon Schubert select_frame (frame); 10485796c8dcSSimon Schubert return; 10495796c8dcSSimon Schubert } 10505796c8dcSSimon Schubert 10515796c8dcSSimon Schubert /* Nothing else to do, the frame layout really changed. Select the 10525796c8dcSSimon Schubert innermost stack frame. */ 10535796c8dcSSimon Schubert select_frame (get_current_frame ()); 10545796c8dcSSimon Schubert 10555796c8dcSSimon Schubert /* Warn the user. */ 1056*a45ae5f8SJohn Marino if (frame_level > 0 && !ui_out_is_mi_like_p (current_uiout)) 10575796c8dcSSimon Schubert { 1058c50c785cSJohn Marino warning (_("Couldn't restore frame #%d in " 1059c50c785cSJohn Marino "current thread, at reparsed frame #0\n"), 10605796c8dcSSimon Schubert frame_level); 10615796c8dcSSimon Schubert /* For MI, we should probably have a notification about 10625796c8dcSSimon Schubert current frame change. But this error is not very 10635796c8dcSSimon Schubert likely, so don't bother for now. */ 10645796c8dcSSimon Schubert print_stack_frame (get_selected_frame (NULL), 1, SRC_LINE); 10655796c8dcSSimon Schubert } 10665796c8dcSSimon Schubert } 10675796c8dcSSimon Schubert 10685796c8dcSSimon Schubert struct current_thread_cleanup 10695796c8dcSSimon Schubert { 10705796c8dcSSimon Schubert ptid_t inferior_ptid; 10715796c8dcSSimon Schubert struct frame_id selected_frame_id; 10725796c8dcSSimon Schubert int selected_frame_level; 10735796c8dcSSimon Schubert int was_stopped; 1074cf7f2e2dSJohn Marino int inf_id; 10755796c8dcSSimon Schubert }; 10765796c8dcSSimon Schubert 10775796c8dcSSimon Schubert static void 10785796c8dcSSimon Schubert do_restore_current_thread_cleanup (void *arg) 10795796c8dcSSimon Schubert { 10805796c8dcSSimon Schubert struct thread_info *tp; 10815796c8dcSSimon Schubert struct current_thread_cleanup *old = arg; 10825796c8dcSSimon Schubert 10835796c8dcSSimon Schubert tp = find_thread_ptid (old->inferior_ptid); 10845796c8dcSSimon Schubert 10855796c8dcSSimon Schubert /* If the previously selected thread belonged to a process that has 10865796c8dcSSimon Schubert in the mean time been deleted (due to normal exit, detach, etc.), 10875796c8dcSSimon Schubert then don't revert back to it, but instead simply drop back to no 10885796c8dcSSimon Schubert thread selected. */ 10895796c8dcSSimon Schubert if (tp 10905796c8dcSSimon Schubert && find_inferior_pid (ptid_get_pid (tp->ptid)) != NULL) 10915796c8dcSSimon Schubert restore_current_thread (old->inferior_ptid); 10925796c8dcSSimon Schubert else 1093cf7f2e2dSJohn Marino { 10945796c8dcSSimon Schubert restore_current_thread (null_ptid); 1095cf7f2e2dSJohn Marino set_current_inferior (find_inferior_id (old->inf_id)); 1096cf7f2e2dSJohn Marino } 10975796c8dcSSimon Schubert 10985796c8dcSSimon Schubert /* The running state of the originally selected thread may have 10995796c8dcSSimon Schubert changed, so we have to recheck it here. */ 11005796c8dcSSimon Schubert if (!ptid_equal (inferior_ptid, null_ptid) 11015796c8dcSSimon Schubert && old->was_stopped 11025796c8dcSSimon Schubert && is_stopped (inferior_ptid) 11035796c8dcSSimon Schubert && target_has_registers 11045796c8dcSSimon Schubert && target_has_stack 11055796c8dcSSimon Schubert && target_has_memory) 11065796c8dcSSimon Schubert restore_selected_frame (old->selected_frame_id, 11075796c8dcSSimon Schubert old->selected_frame_level); 11085796c8dcSSimon Schubert } 11095796c8dcSSimon Schubert 11105796c8dcSSimon Schubert static void 11115796c8dcSSimon Schubert restore_current_thread_cleanup_dtor (void *arg) 11125796c8dcSSimon Schubert { 11135796c8dcSSimon Schubert struct current_thread_cleanup *old = arg; 11145796c8dcSSimon Schubert struct thread_info *tp; 1115cf7f2e2dSJohn Marino 11165796c8dcSSimon Schubert tp = find_thread_ptid (old->inferior_ptid); 11175796c8dcSSimon Schubert if (tp) 11185796c8dcSSimon Schubert tp->refcount--; 11195796c8dcSSimon Schubert xfree (old); 11205796c8dcSSimon Schubert } 11215796c8dcSSimon Schubert 11225796c8dcSSimon Schubert struct cleanup * 11235796c8dcSSimon Schubert make_cleanup_restore_current_thread (void) 11245796c8dcSSimon Schubert { 11255796c8dcSSimon Schubert struct thread_info *tp; 11265796c8dcSSimon Schubert struct frame_info *frame; 11275796c8dcSSimon Schubert struct current_thread_cleanup *old; 11285796c8dcSSimon Schubert 11295796c8dcSSimon Schubert old = xmalloc (sizeof (struct current_thread_cleanup)); 11305796c8dcSSimon Schubert old->inferior_ptid = inferior_ptid; 1131cf7f2e2dSJohn Marino old->inf_id = current_inferior ()->num; 11325796c8dcSSimon Schubert 11335796c8dcSSimon Schubert if (!ptid_equal (inferior_ptid, null_ptid)) 11345796c8dcSSimon Schubert { 11355796c8dcSSimon Schubert old->was_stopped = is_stopped (inferior_ptid); 11365796c8dcSSimon Schubert if (old->was_stopped 11375796c8dcSSimon Schubert && target_has_registers 11385796c8dcSSimon Schubert && target_has_stack 11395796c8dcSSimon Schubert && target_has_memory) 1140c50c785cSJohn Marino { 1141c50c785cSJohn Marino /* When processing internal events, there might not be a 1142c50c785cSJohn Marino selected frame. If we naively call get_selected_frame 1143c50c785cSJohn Marino here, then we can end up reading debuginfo for the 1144c50c785cSJohn Marino current frame, but we don't generally need the debuginfo 1145c50c785cSJohn Marino at this point. */ 1146c50c785cSJohn Marino frame = get_selected_frame_if_set (); 1147c50c785cSJohn Marino } 11485796c8dcSSimon Schubert else 11495796c8dcSSimon Schubert frame = NULL; 11505796c8dcSSimon Schubert 11515796c8dcSSimon Schubert old->selected_frame_id = get_frame_id (frame); 11525796c8dcSSimon Schubert old->selected_frame_level = frame_relative_level (frame); 11535796c8dcSSimon Schubert 11545796c8dcSSimon Schubert tp = find_thread_ptid (inferior_ptid); 11555796c8dcSSimon Schubert if (tp) 11565796c8dcSSimon Schubert tp->refcount++; 11575796c8dcSSimon Schubert } 11585796c8dcSSimon Schubert 11595796c8dcSSimon Schubert return make_cleanup_dtor (do_restore_current_thread_cleanup, old, 11605796c8dcSSimon Schubert restore_current_thread_cleanup_dtor); 11615796c8dcSSimon Schubert } 11625796c8dcSSimon Schubert 11635796c8dcSSimon Schubert /* Apply a GDB command to a list of threads. List syntax is a whitespace 11645796c8dcSSimon Schubert seperated list of numbers, or ranges, or the keyword `all'. Ranges consist 11655796c8dcSSimon Schubert of two numbers seperated by a hyphen. Examples: 11665796c8dcSSimon Schubert 11675796c8dcSSimon Schubert thread apply 1 2 7 4 backtrace Apply backtrace cmd to threads 1,2,7,4 11685796c8dcSSimon Schubert thread apply 2-7 9 p foo(1) Apply p foo(1) cmd to threads 2->7 & 9 1169c50c785cSJohn Marino thread apply all p x/i $pc Apply x/i $pc cmd to all threads. */ 11705796c8dcSSimon Schubert 11715796c8dcSSimon Schubert static void 11725796c8dcSSimon Schubert thread_apply_all_command (char *cmd, int from_tty) 11735796c8dcSSimon Schubert { 11745796c8dcSSimon Schubert struct thread_info *tp; 11755796c8dcSSimon Schubert struct cleanup *old_chain; 11765796c8dcSSimon Schubert char *saved_cmd; 11775796c8dcSSimon Schubert 11785796c8dcSSimon Schubert if (cmd == NULL || *cmd == '\000') 11795796c8dcSSimon Schubert error (_("Please specify a command following the thread ID list")); 11805796c8dcSSimon Schubert 1181cf7f2e2dSJohn Marino update_thread_list (); 11825796c8dcSSimon Schubert 11835796c8dcSSimon Schubert old_chain = make_cleanup_restore_current_thread (); 11845796c8dcSSimon Schubert 11855796c8dcSSimon Schubert /* Save a copy of the command in case it is clobbered by 1186c50c785cSJohn Marino execute_command. */ 11875796c8dcSSimon Schubert saved_cmd = xstrdup (cmd); 11885796c8dcSSimon Schubert make_cleanup (xfree, saved_cmd); 11895796c8dcSSimon Schubert for (tp = thread_list; tp; tp = tp->next) 11905796c8dcSSimon Schubert if (thread_alive (tp)) 11915796c8dcSSimon Schubert { 11925796c8dcSSimon Schubert switch_to_thread (tp->ptid); 11935796c8dcSSimon Schubert 11945796c8dcSSimon Schubert printf_filtered (_("\nThread %d (%s):\n"), 11955796c8dcSSimon Schubert tp->num, target_pid_to_str (inferior_ptid)); 11965796c8dcSSimon Schubert execute_command (cmd, from_tty); 1197c50c785cSJohn Marino strcpy (cmd, saved_cmd); /* Restore exact command used 1198c50c785cSJohn Marino previously. */ 11995796c8dcSSimon Schubert } 12005796c8dcSSimon Schubert 12015796c8dcSSimon Schubert do_cleanups (old_chain); 12025796c8dcSSimon Schubert } 12035796c8dcSSimon Schubert 12045796c8dcSSimon Schubert static void 12055796c8dcSSimon Schubert thread_apply_command (char *tidlist, int from_tty) 12065796c8dcSSimon Schubert { 12075796c8dcSSimon Schubert char *cmd; 12085796c8dcSSimon Schubert struct cleanup *old_chain; 12095796c8dcSSimon Schubert char *saved_cmd; 1210c50c785cSJohn Marino struct get_number_or_range_state state; 12115796c8dcSSimon Schubert 12125796c8dcSSimon Schubert if (tidlist == NULL || *tidlist == '\000') 12135796c8dcSSimon Schubert error (_("Please specify a thread ID list")); 12145796c8dcSSimon Schubert 12155796c8dcSSimon Schubert for (cmd = tidlist; *cmd != '\000' && !isalpha (*cmd); cmd++); 12165796c8dcSSimon Schubert 12175796c8dcSSimon Schubert if (*cmd == '\000') 12185796c8dcSSimon Schubert error (_("Please specify a command following the thread ID list")); 12195796c8dcSSimon Schubert 12205796c8dcSSimon Schubert /* Save a copy of the command in case it is clobbered by 1221c50c785cSJohn Marino execute_command. */ 12225796c8dcSSimon Schubert saved_cmd = xstrdup (cmd); 12235796c8dcSSimon Schubert old_chain = make_cleanup (xfree, saved_cmd); 1224c50c785cSJohn Marino 1225c50c785cSJohn Marino init_number_or_range (&state, tidlist); 1226c50c785cSJohn Marino while (!state.finished && state.string < cmd) 12275796c8dcSSimon Schubert { 12285796c8dcSSimon Schubert struct thread_info *tp; 1229c50c785cSJohn Marino int start; 1230c50c785cSJohn Marino char *p = tidlist; 12315796c8dcSSimon Schubert 1232c50c785cSJohn Marino start = get_number_or_range (&state); 12335796c8dcSSimon Schubert 12345796c8dcSSimon Schubert make_cleanup_restore_current_thread (); 12355796c8dcSSimon Schubert 12365796c8dcSSimon Schubert tp = find_thread_id (start); 12375796c8dcSSimon Schubert 12385796c8dcSSimon Schubert if (!tp) 12395796c8dcSSimon Schubert warning (_("Unknown thread %d."), start); 12405796c8dcSSimon Schubert else if (!thread_alive (tp)) 12415796c8dcSSimon Schubert warning (_("Thread %d has terminated."), start); 12425796c8dcSSimon Schubert else 12435796c8dcSSimon Schubert { 12445796c8dcSSimon Schubert switch_to_thread (tp->ptid); 12455796c8dcSSimon Schubert 12465796c8dcSSimon Schubert printf_filtered (_("\nThread %d (%s):\n"), tp->num, 12475796c8dcSSimon Schubert target_pid_to_str (inferior_ptid)); 12485796c8dcSSimon Schubert execute_command (cmd, from_tty); 12495796c8dcSSimon Schubert 12505796c8dcSSimon Schubert /* Restore exact command used previously. */ 12515796c8dcSSimon Schubert strcpy (cmd, saved_cmd); 12525796c8dcSSimon Schubert } 12535796c8dcSSimon Schubert } 12545796c8dcSSimon Schubert 12555796c8dcSSimon Schubert do_cleanups (old_chain); 12565796c8dcSSimon Schubert } 12575796c8dcSSimon Schubert 12585796c8dcSSimon Schubert /* Switch to the specified thread. Will dispatch off to thread_apply_command 12595796c8dcSSimon Schubert if prefix of arg is `apply'. */ 12605796c8dcSSimon Schubert 12615796c8dcSSimon Schubert static void 12625796c8dcSSimon Schubert thread_command (char *tidstr, int from_tty) 12635796c8dcSSimon Schubert { 12645796c8dcSSimon Schubert if (!tidstr) 12655796c8dcSSimon Schubert { 12665796c8dcSSimon Schubert if (ptid_equal (inferior_ptid, null_ptid)) 12675796c8dcSSimon Schubert error (_("No thread selected")); 12685796c8dcSSimon Schubert 12695796c8dcSSimon Schubert if (target_has_stack) 12705796c8dcSSimon Schubert { 12715796c8dcSSimon Schubert if (is_exited (inferior_ptid)) 12725796c8dcSSimon Schubert printf_filtered (_("[Current thread is %d (%s) (exited)]\n"), 12735796c8dcSSimon Schubert pid_to_thread_id (inferior_ptid), 12745796c8dcSSimon Schubert target_pid_to_str (inferior_ptid)); 12755796c8dcSSimon Schubert else 12765796c8dcSSimon Schubert printf_filtered (_("[Current thread is %d (%s)]\n"), 12775796c8dcSSimon Schubert pid_to_thread_id (inferior_ptid), 12785796c8dcSSimon Schubert target_pid_to_str (inferior_ptid)); 12795796c8dcSSimon Schubert } 12805796c8dcSSimon Schubert else 12815796c8dcSSimon Schubert error (_("No stack.")); 12825796c8dcSSimon Schubert return; 12835796c8dcSSimon Schubert } 12845796c8dcSSimon Schubert 1285*a45ae5f8SJohn Marino gdb_thread_select (current_uiout, tidstr, NULL); 12865796c8dcSSimon Schubert } 12875796c8dcSSimon Schubert 1288c50c785cSJohn Marino /* Implementation of `thread name'. */ 1289c50c785cSJohn Marino 1290c50c785cSJohn Marino static void 1291c50c785cSJohn Marino thread_name_command (char *arg, int from_tty) 1292c50c785cSJohn Marino { 1293c50c785cSJohn Marino struct thread_info *info; 1294c50c785cSJohn Marino 1295c50c785cSJohn Marino if (ptid_equal (inferior_ptid, null_ptid)) 1296c50c785cSJohn Marino error (_("No thread selected")); 1297c50c785cSJohn Marino 1298c50c785cSJohn Marino while (arg && isspace (*arg)) 1299c50c785cSJohn Marino ++arg; 1300c50c785cSJohn Marino 1301c50c785cSJohn Marino info = inferior_thread (); 1302c50c785cSJohn Marino xfree (info->name); 1303c50c785cSJohn Marino info->name = arg ? xstrdup (arg) : NULL; 1304c50c785cSJohn Marino } 1305c50c785cSJohn Marino 1306c50c785cSJohn Marino /* Find thread ids with a name, target pid, or extra info matching ARG. */ 1307c50c785cSJohn Marino 1308c50c785cSJohn Marino static void 1309c50c785cSJohn Marino thread_find_command (char *arg, int from_tty) 1310c50c785cSJohn Marino { 1311c50c785cSJohn Marino struct thread_info *tp; 1312c50c785cSJohn Marino char *tmp; 1313c50c785cSJohn Marino unsigned long match = 0; 1314c50c785cSJohn Marino 1315c50c785cSJohn Marino if (arg == NULL || *arg == '\0') 1316c50c785cSJohn Marino error (_("Command requires an argument.")); 1317c50c785cSJohn Marino 1318c50c785cSJohn Marino tmp = re_comp (arg); 1319c50c785cSJohn Marino if (tmp != 0) 1320c50c785cSJohn Marino error (_("Invalid regexp (%s): %s"), tmp, arg); 1321c50c785cSJohn Marino 1322c50c785cSJohn Marino update_thread_list (); 1323c50c785cSJohn Marino for (tp = thread_list; tp; tp = tp->next) 1324c50c785cSJohn Marino { 1325c50c785cSJohn Marino if (tp->name != NULL && re_exec (tp->name)) 1326c50c785cSJohn Marino { 1327c50c785cSJohn Marino printf_filtered (_("Thread %d has name '%s'\n"), 1328c50c785cSJohn Marino tp->num, tp->name); 1329c50c785cSJohn Marino match++; 1330c50c785cSJohn Marino } 1331c50c785cSJohn Marino 1332c50c785cSJohn Marino tmp = target_thread_name (tp); 1333c50c785cSJohn Marino if (tmp != NULL && re_exec (tmp)) 1334c50c785cSJohn Marino { 1335c50c785cSJohn Marino printf_filtered (_("Thread %d has target name '%s'\n"), 1336c50c785cSJohn Marino tp->num, tmp); 1337c50c785cSJohn Marino match++; 1338c50c785cSJohn Marino } 1339c50c785cSJohn Marino 1340c50c785cSJohn Marino tmp = target_pid_to_str (tp->ptid); 1341c50c785cSJohn Marino if (tmp != NULL && re_exec (tmp)) 1342c50c785cSJohn Marino { 1343c50c785cSJohn Marino printf_filtered (_("Thread %d has target id '%s'\n"), 1344c50c785cSJohn Marino tp->num, tmp); 1345c50c785cSJohn Marino match++; 1346c50c785cSJohn Marino } 1347c50c785cSJohn Marino 1348c50c785cSJohn Marino tmp = target_extra_thread_info (tp); 1349c50c785cSJohn Marino if (tmp != NULL && re_exec (tmp)) 1350c50c785cSJohn Marino { 1351c50c785cSJohn Marino printf_filtered (_("Thread %d has extra info '%s'\n"), 1352c50c785cSJohn Marino tp->num, tmp); 1353c50c785cSJohn Marino match++; 1354c50c785cSJohn Marino } 1355c50c785cSJohn Marino } 1356c50c785cSJohn Marino if (!match) 1357c50c785cSJohn Marino printf_filtered (_("No threads match '%s'\n"), arg); 1358c50c785cSJohn Marino } 1359c50c785cSJohn Marino 13605796c8dcSSimon Schubert /* Print notices when new threads are attached and detached. */ 13615796c8dcSSimon Schubert int print_thread_events = 1; 13625796c8dcSSimon Schubert static void 13635796c8dcSSimon Schubert show_print_thread_events (struct ui_file *file, int from_tty, 13645796c8dcSSimon Schubert struct cmd_list_element *c, const char *value) 13655796c8dcSSimon Schubert { 1366c50c785cSJohn Marino fprintf_filtered (file, 1367c50c785cSJohn Marino _("Printing of thread events is %s.\n"), 13685796c8dcSSimon Schubert value); 13695796c8dcSSimon Schubert } 13705796c8dcSSimon Schubert 13715796c8dcSSimon Schubert static int 13725796c8dcSSimon Schubert do_captured_thread_select (struct ui_out *uiout, void *tidstr) 13735796c8dcSSimon Schubert { 13745796c8dcSSimon Schubert int num; 13755796c8dcSSimon Schubert struct thread_info *tp; 13765796c8dcSSimon Schubert 13775796c8dcSSimon Schubert num = value_as_long (parse_and_eval (tidstr)); 13785796c8dcSSimon Schubert 13795796c8dcSSimon Schubert tp = find_thread_id (num); 13805796c8dcSSimon Schubert 13815796c8dcSSimon Schubert if (!tp) 13825796c8dcSSimon Schubert error (_("Thread ID %d not known."), num); 13835796c8dcSSimon Schubert 13845796c8dcSSimon Schubert if (!thread_alive (tp)) 13855796c8dcSSimon Schubert error (_("Thread ID %d has terminated."), num); 13865796c8dcSSimon Schubert 13875796c8dcSSimon Schubert switch_to_thread (tp->ptid); 13885796c8dcSSimon Schubert 13895796c8dcSSimon Schubert annotate_thread_changed (); 13905796c8dcSSimon Schubert 13915796c8dcSSimon Schubert ui_out_text (uiout, "[Switching to thread "); 13925796c8dcSSimon Schubert ui_out_field_int (uiout, "new-thread-id", pid_to_thread_id (inferior_ptid)); 13935796c8dcSSimon Schubert ui_out_text (uiout, " ("); 13945796c8dcSSimon Schubert ui_out_text (uiout, target_pid_to_str (inferior_ptid)); 13955796c8dcSSimon Schubert ui_out_text (uiout, ")]"); 13965796c8dcSSimon Schubert 13975796c8dcSSimon Schubert /* Note that we can't reach this with an exited thread, due to the 13985796c8dcSSimon Schubert thread_alive check above. */ 1399*a45ae5f8SJohn Marino if (tp->state == THREAD_RUNNING) 14005796c8dcSSimon Schubert ui_out_text (uiout, "(running)\n"); 14015796c8dcSSimon Schubert else 1402c50c785cSJohn Marino { 1403c50c785cSJohn Marino ui_out_text (uiout, "\n"); 14045796c8dcSSimon Schubert print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC); 1405c50c785cSJohn Marino } 14065796c8dcSSimon Schubert 14075796c8dcSSimon Schubert /* Since the current thread may have changed, see if there is any 14085796c8dcSSimon Schubert exited thread we can now delete. */ 14095796c8dcSSimon Schubert prune_threads (); 14105796c8dcSSimon Schubert 14115796c8dcSSimon Schubert return GDB_RC_OK; 14125796c8dcSSimon Schubert } 14135796c8dcSSimon Schubert 14145796c8dcSSimon Schubert enum gdb_rc 14155796c8dcSSimon Schubert gdb_thread_select (struct ui_out *uiout, char *tidstr, char **error_message) 14165796c8dcSSimon Schubert { 14175796c8dcSSimon Schubert if (catch_exceptions_with_msg (uiout, do_captured_thread_select, tidstr, 14185796c8dcSSimon Schubert error_message, RETURN_MASK_ALL) < 0) 14195796c8dcSSimon Schubert return GDB_RC_FAIL; 14205796c8dcSSimon Schubert return GDB_RC_OK; 14215796c8dcSSimon Schubert } 14225796c8dcSSimon Schubert 1423cf7f2e2dSJohn Marino void 1424cf7f2e2dSJohn Marino update_thread_list (void) 1425cf7f2e2dSJohn Marino { 1426cf7f2e2dSJohn Marino prune_threads (); 1427cf7f2e2dSJohn Marino target_find_new_threads (); 1428cf7f2e2dSJohn Marino } 1429cf7f2e2dSJohn Marino 1430cf7f2e2dSJohn Marino /* Return a new value for the selected thread's id. Return a value of 0 if 1431cf7f2e2dSJohn Marino no thread is selected, or no threads exist. */ 1432cf7f2e2dSJohn Marino 1433cf7f2e2dSJohn Marino static struct value * 1434cf7f2e2dSJohn Marino thread_id_make_value (struct gdbarch *gdbarch, struct internalvar *var) 1435cf7f2e2dSJohn Marino { 1436cf7f2e2dSJohn Marino struct thread_info *tp = find_thread_ptid (inferior_ptid); 1437cf7f2e2dSJohn Marino 1438cf7f2e2dSJohn Marino return value_from_longest (builtin_type (gdbarch)->builtin_int, 1439cf7f2e2dSJohn Marino (tp ? tp->num : 0)); 1440cf7f2e2dSJohn Marino } 1441cf7f2e2dSJohn Marino 14425796c8dcSSimon Schubert /* Commands with a prefix of `thread'. */ 14435796c8dcSSimon Schubert struct cmd_list_element *thread_cmd_list = NULL; 14445796c8dcSSimon Schubert 14455796c8dcSSimon Schubert void 14465796c8dcSSimon Schubert _initialize_thread (void) 14475796c8dcSSimon Schubert { 14485796c8dcSSimon Schubert static struct cmd_list_element *thread_apply_list = NULL; 14495796c8dcSSimon Schubert 14505796c8dcSSimon Schubert add_info ("threads", info_threads_command, 1451c50c785cSJohn Marino _("Display currently known threads.\n\ 1452c50c785cSJohn Marino Usage: info threads [ID]...\n\ 1453c50c785cSJohn Marino Optional arguments are thread IDs with spaces between.\n\ 1454c50c785cSJohn Marino If no arguments, all threads are displayed.")); 14555796c8dcSSimon Schubert 14565796c8dcSSimon Schubert add_prefix_cmd ("thread", class_run, thread_command, _("\ 14575796c8dcSSimon Schubert Use this command to switch between threads.\n\ 14585796c8dcSSimon Schubert The new thread ID must be currently known."), 14595796c8dcSSimon Schubert &thread_cmd_list, "thread ", 1, &cmdlist); 14605796c8dcSSimon Schubert 14615796c8dcSSimon Schubert add_prefix_cmd ("apply", class_run, thread_apply_command, 14625796c8dcSSimon Schubert _("Apply a command to a list of threads."), 14635796c8dcSSimon Schubert &thread_apply_list, "thread apply ", 1, &thread_cmd_list); 14645796c8dcSSimon Schubert 14655796c8dcSSimon Schubert add_cmd ("all", class_run, thread_apply_all_command, 14665796c8dcSSimon Schubert _("Apply a command to all threads."), &thread_apply_list); 14675796c8dcSSimon Schubert 1468c50c785cSJohn Marino add_cmd ("name", class_run, thread_name_command, 1469c50c785cSJohn Marino _("Set the current thread's name.\n\ 1470c50c785cSJohn Marino Usage: thread name [NAME]\n\ 1471c50c785cSJohn Marino If NAME is not given, then any existing name is removed."), &thread_cmd_list); 1472c50c785cSJohn Marino 1473c50c785cSJohn Marino add_cmd ("find", class_run, thread_find_command, _("\ 1474c50c785cSJohn Marino Find threads that match a regular expression.\n\ 1475c50c785cSJohn Marino Usage: thread find REGEXP\n\ 1476c50c785cSJohn Marino Will display thread ids whose name, target ID, or extra info matches REGEXP."), 1477c50c785cSJohn Marino &thread_cmd_list); 1478c50c785cSJohn Marino 14795796c8dcSSimon Schubert if (!xdb_commands) 14805796c8dcSSimon Schubert add_com_alias ("t", "thread", class_run, 1); 14815796c8dcSSimon Schubert 14825796c8dcSSimon Schubert add_setshow_boolean_cmd ("thread-events", no_class, 14835796c8dcSSimon Schubert &print_thread_events, _("\ 14845796c8dcSSimon Schubert Set printing of thread events (such as thread start and exit)."), _("\ 14855796c8dcSSimon Schubert Show printing of thread events (such as thread start and exit)."), NULL, 14865796c8dcSSimon Schubert NULL, 14875796c8dcSSimon Schubert show_print_thread_events, 14885796c8dcSSimon Schubert &setprintlist, &showprintlist); 1489cf7f2e2dSJohn Marino 1490cf7f2e2dSJohn Marino create_internalvar_type_lazy ("_thread", thread_id_make_value); 14915796c8dcSSimon Schubert } 1492