| OLD | NEW |
| 1 /* Multi-process/thread control for GDB, the GNU debugger. | 1 /* Multi-process/thread control for GDB, the GNU debugger. |
| 2 | 2 |
| 3 Copyright (C) 1986-1988, 1993-2004, 2007-2012 Free Software | 3 Copyright (C) 1986-1988, 1993-2004, 2007-2012 Free Software |
| 4 Foundation, Inc. | 4 Foundation, Inc. |
| 5 | 5 |
| 6 Contributed by Lynx Real-Time Systems, Inc. Los Gatos, CA. | 6 Contributed by Lynx Real-Time Systems, Inc. Los Gatos, CA. |
| 7 | 7 |
| 8 This file is part of GDB. | 8 This file is part of GDB. |
| 9 | 9 |
| 10 This program is free software; you can redistribute it and/or modify | 10 This program is free software; you can redistribute it and/or modify |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 #include "continuations.h" | 47 #include "continuations.h" |
| 48 | 48 |
| 49 /* Definition of struct thread_info exported to gdbthread.h. */ | 49 /* Definition of struct thread_info exported to gdbthread.h. */ |
| 50 | 50 |
| 51 /* Prototypes for exported functions. */ | 51 /* Prototypes for exported functions. */ |
| 52 | 52 |
| 53 void _initialize_thread (void); | 53 void _initialize_thread (void); |
| 54 | 54 |
| 55 /* Prototypes for local functions. */ | 55 /* Prototypes for local functions. */ |
| 56 | 56 |
| 57 static struct thread_info *thread_list = NULL; | 57 struct thread_info *thread_list = NULL; |
| 58 static int highest_thread_num; | 58 static int highest_thread_num; |
| 59 | 59 |
| 60 static void thread_command (char *tidstr, int from_tty); | 60 static void thread_command (char *tidstr, int from_tty); |
| 61 static void thread_apply_all_command (char *, int); | 61 static void thread_apply_all_command (char *, int); |
| 62 static int thread_alive (struct thread_info *); | 62 static int thread_alive (struct thread_info *); |
| 63 static void info_threads_command (char *, int); | 63 static void info_threads_command (char *, int); |
| 64 static void thread_apply_command (char *, int); | 64 static void thread_apply_command (char *, int); |
| 65 static void restore_current_thread (ptid_t); | 65 static void restore_current_thread (ptid_t); |
| 66 static void prune_threads (void); | 66 static void prune_threads (void); |
| 67 | 67 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 tp->control.step_resume_breakpoint = NULL; | 106 tp->control.step_resume_breakpoint = NULL; |
| 107 } | 107 } |
| 108 | 108 |
| 109 if (tp->control.exception_resume_breakpoint) | 109 if (tp->control.exception_resume_breakpoint) |
| 110 { | 110 { |
| 111 tp->control.exception_resume_breakpoint->disposition | 111 tp->control.exception_resume_breakpoint->disposition |
| 112 = disp_del_at_next_stop; | 112 = disp_del_at_next_stop; |
| 113 tp->control.exception_resume_breakpoint = NULL; | 113 tp->control.exception_resume_breakpoint = NULL; |
| 114 } | 114 } |
| 115 | 115 |
| 116 delete_longjmp_breakpoint_at_next_stop (tp->num); |
| 117 |
| 116 bpstat_clear (&tp->control.stop_bpstat); | 118 bpstat_clear (&tp->control.stop_bpstat); |
| 117 | 119 |
| 118 do_all_intermediate_continuations_thread (tp, 1); | 120 do_all_intermediate_continuations_thread (tp, 1); |
| 119 do_all_continuations_thread (tp, 1); | 121 do_all_continuations_thread (tp, 1); |
| 120 | |
| 121 delete_longjmp_breakpoint (tp->num); | |
| 122 } | 122 } |
| 123 | 123 |
| 124 static void | 124 static void |
| 125 free_thread (struct thread_info *tp) | 125 free_thread (struct thread_info *tp) |
| 126 { | 126 { |
| 127 if (tp->private) | 127 if (tp->private) |
| 128 { | 128 { |
| 129 if (tp->private_dtor) | 129 if (tp->private_dtor) |
| 130 tp->private_dtor (tp->private); | 130 tp->private_dtor (tp->private); |
| 131 else | 131 else |
| (...skipping 933 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1065 } | 1065 } |
| 1066 } | 1066 } |
| 1067 | 1067 |
| 1068 struct current_thread_cleanup | 1068 struct current_thread_cleanup |
| 1069 { | 1069 { |
| 1070 ptid_t inferior_ptid; | 1070 ptid_t inferior_ptid; |
| 1071 struct frame_id selected_frame_id; | 1071 struct frame_id selected_frame_id; |
| 1072 int selected_frame_level; | 1072 int selected_frame_level; |
| 1073 int was_stopped; | 1073 int was_stopped; |
| 1074 int inf_id; | 1074 int inf_id; |
| 1075 int was_removable; |
| 1075 }; | 1076 }; |
| 1076 | 1077 |
| 1077 static void | 1078 static void |
| 1078 do_restore_current_thread_cleanup (void *arg) | 1079 do_restore_current_thread_cleanup (void *arg) |
| 1079 { | 1080 { |
| 1080 struct thread_info *tp; | 1081 struct thread_info *tp; |
| 1081 struct current_thread_cleanup *old = arg; | 1082 struct current_thread_cleanup *old = arg; |
| 1082 | 1083 |
| 1083 tp = find_thread_ptid (old->inferior_ptid); | 1084 tp = find_thread_ptid (old->inferior_ptid); |
| 1084 | 1085 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1105 && target_has_memory) | 1106 && target_has_memory) |
| 1106 restore_selected_frame (old->selected_frame_id, | 1107 restore_selected_frame (old->selected_frame_id, |
| 1107 old->selected_frame_level); | 1108 old->selected_frame_level); |
| 1108 } | 1109 } |
| 1109 | 1110 |
| 1110 static void | 1111 static void |
| 1111 restore_current_thread_cleanup_dtor (void *arg) | 1112 restore_current_thread_cleanup_dtor (void *arg) |
| 1112 { | 1113 { |
| 1113 struct current_thread_cleanup *old = arg; | 1114 struct current_thread_cleanup *old = arg; |
| 1114 struct thread_info *tp; | 1115 struct thread_info *tp; |
| 1116 struct inferior *inf; |
| 1115 | 1117 |
| 1116 tp = find_thread_ptid (old->inferior_ptid); | 1118 tp = find_thread_ptid (old->inferior_ptid); |
| 1117 if (tp) | 1119 if (tp) |
| 1118 tp->refcount--; | 1120 tp->refcount--; |
| 1121 inf = find_inferior_id (old->inf_id); |
| 1122 if (inf != NULL) |
| 1123 inf->removable = old->was_removable; |
| 1119 xfree (old); | 1124 xfree (old); |
| 1120 } | 1125 } |
| 1121 | 1126 |
| 1122 struct cleanup * | 1127 struct cleanup * |
| 1123 make_cleanup_restore_current_thread (void) | 1128 make_cleanup_restore_current_thread (void) |
| 1124 { | 1129 { |
| 1125 struct thread_info *tp; | 1130 struct thread_info *tp; |
| 1126 struct frame_info *frame; | 1131 struct frame_info *frame; |
| 1127 struct current_thread_cleanup *old; | 1132 struct current_thread_cleanup *old; |
| 1128 | 1133 |
| 1129 old = xmalloc (sizeof (struct current_thread_cleanup)); | 1134 old = xmalloc (sizeof (struct current_thread_cleanup)); |
| 1130 old->inferior_ptid = inferior_ptid; | 1135 old->inferior_ptid = inferior_ptid; |
| 1131 old->inf_id = current_inferior ()->num; | 1136 old->inf_id = current_inferior ()->num; |
| 1137 old->was_removable = current_inferior ()->removable; |
| 1132 | 1138 |
| 1133 if (!ptid_equal (inferior_ptid, null_ptid)) | 1139 if (!ptid_equal (inferior_ptid, null_ptid)) |
| 1134 { | 1140 { |
| 1135 old->was_stopped = is_stopped (inferior_ptid); | 1141 old->was_stopped = is_stopped (inferior_ptid); |
| 1136 if (old->was_stopped | 1142 if (old->was_stopped |
| 1137 && target_has_registers | 1143 && target_has_registers |
| 1138 && target_has_stack | 1144 && target_has_stack |
| 1139 && target_has_memory) | 1145 && target_has_memory) |
| 1140 { | 1146 { |
| 1141 /* When processing internal events, there might not be a | 1147 /* When processing internal events, there might not be a |
| 1142 selected frame. If we naively call get_selected_frame | 1148 selected frame. If we naively call get_selected_frame |
| 1143 here, then we can end up reading debuginfo for the | 1149 here, then we can end up reading debuginfo for the |
| 1144 current frame, but we don't generally need the debuginfo | 1150 current frame, but we don't generally need the debuginfo |
| 1145 at this point. */ | 1151 at this point. */ |
| 1146 frame = get_selected_frame_if_set (); | 1152 frame = get_selected_frame_if_set (); |
| 1147 } | 1153 } |
| 1148 else | 1154 else |
| 1149 frame = NULL; | 1155 frame = NULL; |
| 1150 | 1156 |
| 1151 old->selected_frame_id = get_frame_id (frame); | 1157 old->selected_frame_id = get_frame_id (frame); |
| 1152 old->selected_frame_level = frame_relative_level (frame); | 1158 old->selected_frame_level = frame_relative_level (frame); |
| 1153 | 1159 |
| 1154 tp = find_thread_ptid (inferior_ptid); | 1160 tp = find_thread_ptid (inferior_ptid); |
| 1155 if (tp) | 1161 if (tp) |
| 1156 tp->refcount++; | 1162 tp->refcount++; |
| 1157 } | 1163 } |
| 1158 | 1164 |
| 1165 current_inferior ()->removable = 0; |
| 1166 |
| 1159 return make_cleanup_dtor (do_restore_current_thread_cleanup, old, | 1167 return make_cleanup_dtor (do_restore_current_thread_cleanup, old, |
| 1160 restore_current_thread_cleanup_dtor); | 1168 restore_current_thread_cleanup_dtor); |
| 1161 } | 1169 } |
| 1162 | 1170 |
| 1163 /* Apply a GDB command to a list of threads. List syntax is a whitespace | 1171 /* Apply a GDB command to a list of threads. List syntax is a whitespace |
| 1164 seperated list of numbers, or ranges, or the keyword `all'. Ranges consist | 1172 seperated list of numbers, or ranges, or the keyword `all'. Ranges consist |
| 1165 of two numbers seperated by a hyphen. Examples: | 1173 of two numbers seperated by a hyphen. Examples: |
| 1166 | 1174 |
| 1167 thread apply 1 2 7 4 backtrace Apply backtrace cmd to threads 1,2,7,4 | 1175 thread apply 1 2 7 4 backtrace Apply backtrace cmd to threads 1,2,7,4 |
| 1168 thread apply 2-7 9 p foo(1) Apply p foo(1) cmd to threads 2->7 & 9 | 1176 thread apply 2-7 9 p foo(1) Apply p foo(1) cmd to threads 2->7 & 9 |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1424 update_thread_list (void) | 1432 update_thread_list (void) |
| 1425 { | 1433 { |
| 1426 prune_threads (); | 1434 prune_threads (); |
| 1427 target_find_new_threads (); | 1435 target_find_new_threads (); |
| 1428 } | 1436 } |
| 1429 | 1437 |
| 1430 /* Return a new value for the selected thread's id. Return a value of 0 if | 1438 /* Return a new value for the selected thread's id. Return a value of 0 if |
| 1431 no thread is selected, or no threads exist. */ | 1439 no thread is selected, or no threads exist. */ |
| 1432 | 1440 |
| 1433 static struct value * | 1441 static struct value * |
| 1434 thread_id_make_value (struct gdbarch *gdbarch, struct internalvar *var) | 1442 thread_id_make_value (struct gdbarch *gdbarch, struct internalvar *var, |
| 1443 » » void *ignore) |
| 1435 { | 1444 { |
| 1436 struct thread_info *tp = find_thread_ptid (inferior_ptid); | 1445 struct thread_info *tp = find_thread_ptid (inferior_ptid); |
| 1437 | 1446 |
| 1438 return value_from_longest (builtin_type (gdbarch)->builtin_int, | 1447 return value_from_longest (builtin_type (gdbarch)->builtin_int, |
| 1439 (tp ? tp->num : 0)); | 1448 (tp ? tp->num : 0)); |
| 1440 } | 1449 } |
| 1441 | 1450 |
| 1442 /* Commands with a prefix of `thread'. */ | 1451 /* Commands with a prefix of `thread'. */ |
| 1443 struct cmd_list_element *thread_cmd_list = NULL; | 1452 struct cmd_list_element *thread_cmd_list = NULL; |
| 1444 | 1453 |
| 1454 /* Implementation of `thread' variable. */ |
| 1455 |
| 1456 static const struct internalvar_funcs thread_funcs = |
| 1457 { |
| 1458 thread_id_make_value, |
| 1459 NULL, |
| 1460 NULL |
| 1461 }; |
| 1462 |
| 1445 void | 1463 void |
| 1446 _initialize_thread (void) | 1464 _initialize_thread (void) |
| 1447 { | 1465 { |
| 1448 static struct cmd_list_element *thread_apply_list = NULL; | 1466 static struct cmd_list_element *thread_apply_list = NULL; |
| 1449 | 1467 |
| 1450 add_info ("threads", info_threads_command, | 1468 add_info ("threads", info_threads_command, |
| 1451 _("Display currently known threads.\n\ | 1469 _("Display currently known threads.\n\ |
| 1452 Usage: info threads [ID]...\n\ | 1470 Usage: info threads [ID]...\n\ |
| 1453 Optional arguments are thread IDs with spaces between.\n\ | 1471 Optional arguments are thread IDs with spaces between.\n\ |
| 1454 If no arguments, all threads are displayed.")); | 1472 If no arguments, all threads are displayed.")); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1480 add_com_alias ("t", "thread", class_run, 1); | 1498 add_com_alias ("t", "thread", class_run, 1); |
| 1481 | 1499 |
| 1482 add_setshow_boolean_cmd ("thread-events", no_class, | 1500 add_setshow_boolean_cmd ("thread-events", no_class, |
| 1483 &print_thread_events, _("\ | 1501 &print_thread_events, _("\ |
| 1484 Set printing of thread events (such as thread start and exit)."), _("\ | 1502 Set printing of thread events (such as thread start and exit)."), _("\ |
| 1485 Show printing of thread events (such as thread start and exit)."), NULL, | 1503 Show printing of thread events (such as thread start and exit)."), NULL, |
| 1486 NULL, | 1504 NULL, |
| 1487 show_print_thread_events, | 1505 show_print_thread_events, |
| 1488 &setprintlist, &showprintlist); | 1506 &setprintlist, &showprintlist); |
| 1489 | 1507 |
| 1490 create_internalvar_type_lazy ("_thread", thread_id_make_value); | 1508 create_internalvar_type_lazy ("_thread", &thread_funcs, NULL); |
| 1491 } | 1509 } |
| OLD | NEW |