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