X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fthread.c;h=7bc5271fedd1369c5efa4c10e7374f443f959b08;hb=9fb5010805bdfe0eb8fc5db01e7f4c93b04c8f29;hp=3090b692556ffaa0c9ff9096be5bc59855274daf;hpb=be34f8494e0befe68d8071f46edc16d9aa3c9238;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/thread.c b/gdb/thread.c index 3090b69255..7bc5271fed 100644 --- a/gdb/thread.c +++ b/gdb/thread.c @@ -1,8 +1,6 @@ /* Multi-process/thread control for GDB, the GNU debugger. - Copyright (C) 1986, 1987, 1988, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1986-2014 Free Software Foundation, Inc. Contributed by Lynx Real-Time Systems, Inc. Los Gatos, CA. @@ -34,7 +32,8 @@ #include "gdbcmd.h" #include "regcache.h" #include "gdb.h" -#include "gdb_string.h" +#include +#include "btrace.h" #include #include @@ -55,7 +54,7 @@ void _initialize_thread (void); /* Prototypes for local functions. */ -static struct thread_info *thread_list = NULL; +struct thread_info *thread_list = NULL; static int highest_thread_num; static void thread_command (char *tidstr, int from_tty); @@ -66,15 +65,19 @@ static void thread_apply_command (char *, int); static void restore_current_thread (ptid_t); static void prune_threads (void); -/* Frontend view of the thread state. Possible extensions: stepping, - finishing, until(ling),... */ -enum thread_state +/* Data to cleanup thread array. */ + +struct thread_array_cleanup { - THREAD_STOPPED, - THREAD_RUNNING, - THREAD_EXITED, + /* Array of thread pointers used to set + reference count. */ + struct thread_info **tp_array; + + /* Thread count in the array. */ + int count; }; + struct thread_info* inferior_thread (void) { @@ -123,19 +126,19 @@ clear_thread_inferior_resources (struct thread_info *tp) tp->control.exception_resume_breakpoint = NULL; } + delete_longjmp_breakpoint_at_next_stop (tp->num); + bpstat_clear (&tp->control.stop_bpstat); - discard_all_intermediate_continuations_thread (tp); - discard_all_continuations_thread (tp); + btrace_teardown (tp); - delete_longjmp_breakpoint (tp->num); + do_all_intermediate_continuations_thread (tp, 1); + do_all_continuations_thread (tp, 1); } static void free_thread (struct thread_info *tp) { - clear_thread_inferior_resources (tp); - if (tp->private) { if (tp->private_dtor) @@ -184,7 +187,7 @@ new_thread (ptid_t ptid) /* Nothing to follow yet. */ tp->pending_follow.kind = TARGET_WAITKIND_SPURIOUS; - tp->state_ = THREAD_STOPPED; + tp->state = THREAD_STOPPED; return tp; } @@ -213,7 +216,7 @@ add_thread_silent (ptid_t ptid) tp = new_thread (null_ptid); /* Make switch_to_thread not read from the thread. */ - tp->state_ = THREAD_EXITED; + tp->state = THREAD_EXITED; switch_to_thread (null_ptid); /* Now we can delete it. */ @@ -221,7 +224,7 @@ add_thread_silent (ptid_t ptid) /* Now reset its ptid, and reswitch inferior_ptid to it. */ tp->ptid = ptid; - tp->state_ = THREAD_STOPPED; + tp->state = THREAD_STOPPED; switch_to_thread (ptid); observer_notify_new_thread (tp); @@ -282,12 +285,12 @@ delete_thread_1 (ptid_t ptid, int silent) if (tp->refcount > 0 || ptid_equal (tp->ptid, inferior_ptid)) { - if (tp->state_ != THREAD_EXITED) + if (tp->state != THREAD_EXITED) { observer_notify_thread_exit (tp, silent); /* Tag it as exited. */ - tp->state_ = THREAD_EXITED; + tp->state = THREAD_EXITED; /* Clear breakpoints, etc. associated with this thread. */ clear_thread_inferior_resources (tp); @@ -297,15 +300,19 @@ delete_thread_1 (ptid_t ptid, int silent) return; } + /* Notify thread exit, but only if we haven't already. */ + if (tp->state != THREAD_EXITED) + observer_notify_thread_exit (tp, silent); + + /* Tag it as exited. */ + tp->state = THREAD_EXITED; + clear_thread_inferior_resources (tp); + if (tpprev) tpprev->next = tp->next; else thread_list = tp->next; - /* Notify thread exit, but only if we haven't already. */ - if (tp->state_ != THREAD_EXITED) - observer_notify_thread_exit (tp, silent); - free_thread (tp); } @@ -474,9 +481,9 @@ any_live_thread_of_process (int pid) struct thread_info *tp_executing = NULL; for (tp = thread_list; tp; tp = tp->next) - if (tp->state_ != THREAD_EXITED && ptid_get_pid (tp->ptid) == pid) + if (tp->state != THREAD_EXITED && ptid_get_pid (tp->ptid) == pid) { - if (tp->executing_) + if (tp->executing) tp_executing = tp; else return tp; @@ -501,7 +508,7 @@ do_captured_list_thread_ids (struct ui_out *uiout, void *arg) for (tp = thread_list; tp; tp = tp->next) { - if (tp->state_ == THREAD_EXITED) + if (tp->state == THREAD_EXITED) continue; if (ptid_equal (tp->ptid, inferior_ptid)) @@ -534,7 +541,7 @@ gdb_list_thread_ids (struct ui_out *uiout, char **error_message) static int thread_alive (struct thread_info *tp) { - if (tp->state_ == THREAD_EXITED) + if (tp->state == THREAD_EXITED) return 0; if (!target_thread_alive (tp->ptid)) return 0; @@ -588,11 +595,11 @@ set_running (ptid_t ptid, int running) for (tp = thread_list; tp; tp = tp->next) if (all || ptid_get_pid (tp->ptid) == ptid_get_pid (ptid)) { - if (tp->state_ == THREAD_EXITED) + if (tp->state == THREAD_EXITED) continue; - if (running && tp->state_ == THREAD_STOPPED) + if (running && tp->state == THREAD_STOPPED) any_started = 1; - tp->state_ = running ? THREAD_RUNNING : THREAD_STOPPED; + tp->state = running ? THREAD_RUNNING : THREAD_STOPPED; } if (any_started) observer_notify_target_resumed (ptid); @@ -603,10 +610,10 @@ set_running (ptid_t ptid, int running) tp = find_thread_ptid (ptid); gdb_assert (tp); - gdb_assert (tp->state_ != THREAD_EXITED); - if (running && tp->state_ == THREAD_STOPPED) + gdb_assert (tp->state != THREAD_EXITED); + if (running && tp->state == THREAD_STOPPED) started = 1; - tp->state_ = running ? THREAD_RUNNING : THREAD_STOPPED; + tp->state = running ? THREAD_RUNNING : THREAD_STOPPED; if (started) observer_notify_target_resumed (ptid); } @@ -619,7 +626,7 @@ is_thread_state (ptid_t ptid, enum thread_state state) tp = find_thread_ptid (ptid); gdb_assert (tp); - return tp->state_ == state; + return tp->state == state; } int @@ -646,7 +653,7 @@ any_running (void) struct thread_info *tp; for (tp = thread_list; tp; tp = tp->next) - if (tp->state_ == THREAD_RUNNING) + if (tp->state == THREAD_RUNNING) return 1; return 0; @@ -659,7 +666,7 @@ is_executing (ptid_t ptid) tp = find_thread_ptid (ptid); gdb_assert (tp); - return tp->executing_; + return tp->executing; } void @@ -672,13 +679,13 @@ set_executing (ptid_t ptid, int executing) { for (tp = thread_list; tp; tp = tp->next) if (all || ptid_get_pid (tp->ptid) == ptid_get_pid (ptid)) - tp->executing_ = executing; + tp->executing = executing; } else { tp = find_thread_ptid (ptid); gdb_assert (tp); - tp->executing_ = executing; + tp->executing = executing; } } @@ -720,13 +727,13 @@ finish_thread_state (ptid_t ptid) { for (tp = thread_list; tp; tp = tp->next) { - if (tp->state_ == THREAD_EXITED) + if (tp->state == THREAD_EXITED) continue; if (all || ptid_get_pid (ptid) == ptid_get_pid (tp->ptid)) { - if (tp->executing_ && tp->state_ == THREAD_STOPPED) + if (tp->executing && tp->state == THREAD_STOPPED) any_started = 1; - tp->state_ = tp->executing_ ? THREAD_RUNNING : THREAD_STOPPED; + tp->state = tp->executing ? THREAD_RUNNING : THREAD_STOPPED; } } } @@ -734,11 +741,11 @@ finish_thread_state (ptid_t ptid) { tp = find_thread_ptid (ptid); gdb_assert (tp); - if (tp->state_ != THREAD_EXITED) + if (tp->state != THREAD_EXITED) { - if (tp->executing_ && tp->state_ == THREAD_STOPPED) + if (tp->executing && tp->state == THREAD_STOPPED) any_started = 1; - tp->state_ = tp->executing_ ? THREAD_RUNNING : THREAD_STOPPED; + tp->state = tp->executing ? THREAD_RUNNING : THREAD_STOPPED; } } @@ -756,6 +763,13 @@ finish_thread_state_cleanup (void *arg) finish_thread_state (*ptid_p); } +int +pc_in_thread_step_range (CORE_ADDR pc, struct thread_info *thread) +{ + return (pc >= thread->control.step_range_start + && pc < thread->control.step_range_end); +} + /* Prints the list of threads and their details on UIOUT. This is a version of 'info_threads_command' suitable for use from MI. @@ -796,10 +810,10 @@ print_thread_info (struct ui_out *uiout, char *requested_threads, int pid) if (!number_is_in_list (requested_threads, tp->num)) continue; - if (pid != -1 && PIDGET (tp->ptid) != pid) + if (pid != -1 && ptid_get_pid (tp->ptid) != pid) continue; - if (tp->state_ == THREAD_EXITED) + if (tp->state == THREAD_EXITED) continue; ++n_threads; @@ -833,7 +847,7 @@ print_thread_info (struct ui_out *uiout, char *requested_threads, int pid) if (!number_is_in_list (requested_threads, tp->num)) continue; - if (pid != -1 && PIDGET (tp->ptid) != pid) + if (pid != -1 && ptid_get_pid (tp->ptid) != pid) { if (requested_threads != NULL && *requested_threads != '\0') error (_("Requested thread not found in requested process")); @@ -843,7 +857,7 @@ print_thread_info (struct ui_out *uiout, char *requested_threads, int pid) if (ptid_equal (tp->ptid, current_ptid)) current_thread = tp->num; - if (tp->state_ == THREAD_EXITED) + if (tp->state == THREAD_EXITED) continue; chain2 = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); @@ -905,7 +919,7 @@ print_thread_info (struct ui_out *uiout, char *requested_threads, int pid) do_cleanups (str_cleanup); } - if (tp->state_ == THREAD_RUNNING) + if (tp->state == THREAD_RUNNING) ui_out_text (uiout, "(running)\n"); else { @@ -915,14 +929,14 @@ print_thread_info (struct ui_out *uiout, char *requested_threads, int pid) print_stack_frame (get_selected_frame (NULL), /* For MI output, print frame level. */ ui_out_is_mi_like_p (uiout), - LOCATION); + LOCATION, 0); } if (ui_out_is_mi_like_p (uiout)) { char *state = "stopped"; - if (tp->state_ == THREAD_RUNNING) + if (tp->state == THREAD_RUNNING) state = "running"; ui_out_field_string (uiout, "state", state); } @@ -969,7 +983,7 @@ No selected thread. See `help thread'.\n"); static void info_threads_command (char *arg, int from_tty) { - print_thread_info (uiout, arg, -1); + print_thread_info (current_uiout, arg, -1); } /* Switch from one thread to another. */ @@ -995,7 +1009,6 @@ switch_to_thread (ptid_t ptid) inferior_ptid = ptid; reinit_frame_cache (); - registers_changed (); /* We don't check for is_stopped, because we're called at times while in the TARGET_RUNNING state, e.g., while handling an @@ -1061,15 +1074,15 @@ restore_selected_frame (struct frame_id a_frame_id, int frame_level) select_frame (get_current_frame ()); /* Warn the user. */ - if (frame_level > 0 && !ui_out_is_mi_like_p (uiout)) + if (frame_level > 0 && !ui_out_is_mi_like_p (current_uiout)) { warning (_("Couldn't restore frame #%d in " - "current thread, at reparsed frame #0\n"), + "current thread. Bottom (innermost) frame selected:"), frame_level); /* For MI, we should probably have a notification about current frame change. But this error is not very likely, so don't bother for now. */ - print_stack_frame (get_selected_frame (NULL), 1, SRC_LINE); + print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1); } } @@ -1080,6 +1093,7 @@ struct current_thread_cleanup int selected_frame_level; int was_stopped; int inf_id; + int was_removable; }; static void @@ -1120,13 +1134,29 @@ restore_current_thread_cleanup_dtor (void *arg) { struct current_thread_cleanup *old = arg; struct thread_info *tp; + struct inferior *inf; tp = find_thread_ptid (old->inferior_ptid); if (tp) tp->refcount--; + inf = find_inferior_id (old->inf_id); + if (inf != NULL) + inf->removable = old->was_removable; xfree (old); } +/* Set the thread reference count. */ + +static void +set_thread_refcount (void *data) +{ + int k; + struct thread_array_cleanup *ta_cleanup = data; + + for (k = 0; k != ta_cleanup->count; k++) + ta_cleanup->tp_array[k]->refcount--; +} + struct cleanup * make_cleanup_restore_current_thread (void) { @@ -1137,6 +1167,7 @@ make_cleanup_restore_current_thread (void) old = xmalloc (sizeof (struct current_thread_cleanup)); old->inferior_ptid = inferior_ptid; old->inf_id = current_inferior ()->num; + old->was_removable = current_inferior ()->removable; if (!ptid_equal (inferior_ptid, null_ptid)) { @@ -1164,6 +1195,8 @@ make_cleanup_restore_current_thread (void) tp->refcount++; } + current_inferior ()->removable = 0; + return make_cleanup_dtor (do_restore_current_thread_cleanup, old, restore_current_thread_cleanup_dtor); } @@ -1179,9 +1212,10 @@ make_cleanup_restore_current_thread (void) static void thread_apply_all_command (char *cmd, int from_tty) { - struct thread_info *tp; struct cleanup *old_chain; char *saved_cmd; + int tc; + struct thread_array_cleanup ta_cleanup; if (cmd == NULL || *cmd == '\000') error (_("Please specify a command following the thread ID list")); @@ -1194,17 +1228,43 @@ thread_apply_all_command (char *cmd, int from_tty) execute_command. */ saved_cmd = xstrdup (cmd); make_cleanup (xfree, saved_cmd); - for (tp = thread_list; tp; tp = tp->next) - if (thread_alive (tp)) - { - switch_to_thread (tp->ptid); + tc = thread_count (); - printf_filtered (_("\nThread %d (%s):\n"), - tp->num, target_pid_to_str (inferior_ptid)); - execute_command (cmd, from_tty); - strcpy (cmd, saved_cmd); /* Restore exact command used - previously. */ - } + if (tc) + { + struct thread_info **tp_array; + struct thread_info *tp; + int i = 0, k; + + /* Save a copy of the thread_list in case we execute detach + command. */ + tp_array = xmalloc (sizeof (struct thread_info *) * tc); + make_cleanup (xfree, tp_array); + ta_cleanup.tp_array = tp_array; + ta_cleanup.count = tc; + + ALL_THREADS (tp) + { + tp_array[i] = tp; + tp->refcount++; + i++; + } + + make_cleanup (set_thread_refcount, &ta_cleanup); + + for (k = 0; k != i; k++) + if (thread_alive (tp_array[k])) + { + switch_to_thread (tp_array[k]->ptid); + printf_filtered (_("\nThread %d (%s):\n"), + tp_array[k]->num, + target_pid_to_str (inferior_ptid)); + execute_command (cmd, from_tty); + + /* Restore exact command used previously. */ + strcpy (cmd, saved_cmd); + } + } do_cleanups (old_chain); } @@ -1235,7 +1295,6 @@ thread_apply_command (char *tidlist, int from_tty) { struct thread_info *tp; int start; - char *p = tidlist; start = get_number_or_range (&state); @@ -1290,7 +1349,7 @@ thread_command (char *tidstr, int from_tty) return; } - gdb_thread_select (uiout, tidstr, NULL); + gdb_thread_select (current_uiout, tidstr, NULL); } /* Implementation of `thread name'. */ @@ -1303,8 +1362,7 @@ thread_name_command (char *arg, int from_tty) if (ptid_equal (inferior_ptid, null_ptid)) error (_("No thread selected")); - while (arg && isspace (*arg)) - ++arg; + arg = skip_spaces (arg); info = inferior_thread (); xfree (info->name); @@ -1404,12 +1462,12 @@ do_captured_thread_select (struct ui_out *uiout, void *tidstr) /* Note that we can't reach this with an exited thread, due to the thread_alive check above. */ - if (tp->state_ == THREAD_RUNNING) + if (tp->state == THREAD_RUNNING) ui_out_text (uiout, "(running)\n"); else { ui_out_text (uiout, "\n"); - print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC); + print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1); } /* Since the current thread may have changed, see if there is any @@ -1439,7 +1497,8 @@ update_thread_list (void) no thread is selected, or no threads exist. */ static struct value * -thread_id_make_value (struct gdbarch *gdbarch, struct internalvar *var) +thread_id_make_value (struct gdbarch *gdbarch, struct internalvar *var, + void *ignore) { struct thread_info *tp = find_thread_ptid (inferior_ptid); @@ -1450,6 +1509,15 @@ thread_id_make_value (struct gdbarch *gdbarch, struct internalvar *var) /* Commands with a prefix of `thread'. */ struct cmd_list_element *thread_cmd_list = NULL; +/* Implementation of `thread' variable. */ + +static const struct internalvar_funcs thread_funcs = +{ + thread_id_make_value, + NULL, + NULL +}; + void _initialize_thread (void) { @@ -1495,5 +1563,5 @@ Show printing of thread events (such as thread start and exit)."), NULL, show_print_thread_events, &setprintlist, &showprintlist); - create_internalvar_type_lazy ("_thread", thread_id_make_value); + create_internalvar_type_lazy ("_thread", &thread_funcs, NULL); }