GDB (API)
|
00001 /* Multi-process/thread control for GDB, the GNU debugger. 00002 00003 Copyright (C) 1986-2013 Free Software Foundation, Inc. 00004 00005 Contributed by Lynx Real-Time Systems, Inc. Los Gatos, CA. 00006 00007 This file is part of GDB. 00008 00009 This program is free software; you can redistribute it and/or modify 00010 it under the terms of the GNU General Public License as published by 00011 the Free Software Foundation; either version 3 of the License, or 00012 (at your option) any later version. 00013 00014 This program is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 GNU General Public License for more details. 00018 00019 You should have received a copy of the GNU General Public License 00020 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00021 00022 #include "defs.h" 00023 #include "symtab.h" 00024 #include "frame.h" 00025 #include "inferior.h" 00026 #include "environ.h" 00027 #include "value.h" 00028 #include "target.h" 00029 #include "gdbthread.h" 00030 #include "exceptions.h" 00031 #include "command.h" 00032 #include "gdbcmd.h" 00033 #include "regcache.h" 00034 #include "gdb.h" 00035 #include "gdb_string.h" 00036 #include "btrace.h" 00037 00038 #include <ctype.h> 00039 #include <sys/types.h> 00040 #include <signal.h> 00041 #include "ui-out.h" 00042 #include "observer.h" 00043 #include "annotate.h" 00044 #include "cli/cli-decode.h" 00045 #include "gdb_regex.h" 00046 #include "cli/cli-utils.h" 00047 #include "continuations.h" 00048 00049 /* Definition of struct thread_info exported to gdbthread.h. */ 00050 00051 /* Prototypes for exported functions. */ 00052 00053 void _initialize_thread (void); 00054 00055 /* Prototypes for local functions. */ 00056 00057 struct thread_info *thread_list = NULL; 00058 static int highest_thread_num; 00059 00060 static void thread_command (char *tidstr, int from_tty); 00061 static void thread_apply_all_command (char *, int); 00062 static int thread_alive (struct thread_info *); 00063 static void info_threads_command (char *, int); 00064 static void thread_apply_command (char *, int); 00065 static void restore_current_thread (ptid_t); 00066 static void prune_threads (void); 00067 00068 /* Data to cleanup thread array. */ 00069 00070 struct thread_array_cleanup 00071 { 00072 /* Array of thread pointers used to set 00073 reference count. */ 00074 struct thread_info **tp_array; 00075 00076 /* Thread count in the array. */ 00077 int count; 00078 }; 00079 00080 00081 struct thread_info* 00082 inferior_thread (void) 00083 { 00084 struct thread_info *tp = find_thread_ptid (inferior_ptid); 00085 gdb_assert (tp); 00086 return tp; 00087 } 00088 00089 void 00090 delete_step_resume_breakpoint (struct thread_info *tp) 00091 { 00092 if (tp && tp->control.step_resume_breakpoint) 00093 { 00094 delete_breakpoint (tp->control.step_resume_breakpoint); 00095 tp->control.step_resume_breakpoint = NULL; 00096 } 00097 } 00098 00099 void 00100 delete_exception_resume_breakpoint (struct thread_info *tp) 00101 { 00102 if (tp && tp->control.exception_resume_breakpoint) 00103 { 00104 delete_breakpoint (tp->control.exception_resume_breakpoint); 00105 tp->control.exception_resume_breakpoint = NULL; 00106 } 00107 } 00108 00109 static void 00110 clear_thread_inferior_resources (struct thread_info *tp) 00111 { 00112 /* NOTE: this will take care of any left-over step_resume breakpoints, 00113 but not any user-specified thread-specific breakpoints. We can not 00114 delete the breakpoint straight-off, because the inferior might not 00115 be stopped at the moment. */ 00116 if (tp->control.step_resume_breakpoint) 00117 { 00118 tp->control.step_resume_breakpoint->disposition = disp_del_at_next_stop; 00119 tp->control.step_resume_breakpoint = NULL; 00120 } 00121 00122 if (tp->control.exception_resume_breakpoint) 00123 { 00124 tp->control.exception_resume_breakpoint->disposition 00125 = disp_del_at_next_stop; 00126 tp->control.exception_resume_breakpoint = NULL; 00127 } 00128 00129 delete_longjmp_breakpoint_at_next_stop (tp->num); 00130 00131 bpstat_clear (&tp->control.stop_bpstat); 00132 00133 btrace_teardown (tp); 00134 00135 do_all_intermediate_continuations_thread (tp, 1); 00136 do_all_continuations_thread (tp, 1); 00137 } 00138 00139 static void 00140 free_thread (struct thread_info *tp) 00141 { 00142 if (tp->private) 00143 { 00144 if (tp->private_dtor) 00145 tp->private_dtor (tp->private); 00146 else 00147 xfree (tp->private); 00148 } 00149 00150 xfree (tp->name); 00151 xfree (tp); 00152 } 00153 00154 void 00155 init_thread_list (void) 00156 { 00157 struct thread_info *tp, *tpnext; 00158 00159 highest_thread_num = 0; 00160 00161 if (!thread_list) 00162 return; 00163 00164 for (tp = thread_list; tp; tp = tpnext) 00165 { 00166 tpnext = tp->next; 00167 free_thread (tp); 00168 } 00169 00170 thread_list = NULL; 00171 } 00172 00173 /* Allocate a new thread with target id PTID and add it to the thread 00174 list. */ 00175 00176 static struct thread_info * 00177 new_thread (ptid_t ptid) 00178 { 00179 struct thread_info *tp; 00180 00181 tp = xcalloc (1, sizeof (*tp)); 00182 00183 tp->ptid = ptid; 00184 tp->num = ++highest_thread_num; 00185 tp->next = thread_list; 00186 thread_list = tp; 00187 00188 /* Nothing to follow yet. */ 00189 tp->pending_follow.kind = TARGET_WAITKIND_SPURIOUS; 00190 tp->state = THREAD_STOPPED; 00191 00192 return tp; 00193 } 00194 00195 struct thread_info * 00196 add_thread_silent (ptid_t ptid) 00197 { 00198 struct thread_info *tp; 00199 00200 tp = find_thread_ptid (ptid); 00201 if (tp) 00202 /* Found an old thread with the same id. It has to be dead, 00203 otherwise we wouldn't be adding a new thread with the same id. 00204 The OS is reusing this id --- delete it, and recreate a new 00205 one. */ 00206 { 00207 /* In addition to deleting the thread, if this is the current 00208 thread, then we need to take care that delete_thread doesn't 00209 really delete the thread if it is inferior_ptid. Create a 00210 new template thread in the list with an invalid ptid, switch 00211 to it, delete the original thread, reset the new thread's 00212 ptid, and switch to it. */ 00213 00214 if (ptid_equal (inferior_ptid, ptid)) 00215 { 00216 tp = new_thread (null_ptid); 00217 00218 /* Make switch_to_thread not read from the thread. */ 00219 tp->state = THREAD_EXITED; 00220 switch_to_thread (null_ptid); 00221 00222 /* Now we can delete it. */ 00223 delete_thread (ptid); 00224 00225 /* Now reset its ptid, and reswitch inferior_ptid to it. */ 00226 tp->ptid = ptid; 00227 tp->state = THREAD_STOPPED; 00228 switch_to_thread (ptid); 00229 00230 observer_notify_new_thread (tp); 00231 00232 /* All done. */ 00233 return tp; 00234 } 00235 else 00236 /* Just go ahead and delete it. */ 00237 delete_thread (ptid); 00238 } 00239 00240 tp = new_thread (ptid); 00241 observer_notify_new_thread (tp); 00242 00243 return tp; 00244 } 00245 00246 struct thread_info * 00247 add_thread_with_info (ptid_t ptid, struct private_thread_info *private) 00248 { 00249 struct thread_info *result = add_thread_silent (ptid); 00250 00251 result->private = private; 00252 00253 if (print_thread_events) 00254 printf_unfiltered (_("[New %s]\n"), target_pid_to_str (ptid)); 00255 00256 annotate_new_thread (); 00257 return result; 00258 } 00259 00260 struct thread_info * 00261 add_thread (ptid_t ptid) 00262 { 00263 return add_thread_with_info (ptid, NULL); 00264 } 00265 00266 /* Delete thread PTID. If SILENT, don't notify the observer of this 00267 exit. */ 00268 static void 00269 delete_thread_1 (ptid_t ptid, int silent) 00270 { 00271 struct thread_info *tp, *tpprev; 00272 00273 tpprev = NULL; 00274 00275 for (tp = thread_list; tp; tpprev = tp, tp = tp->next) 00276 if (ptid_equal (tp->ptid, ptid)) 00277 break; 00278 00279 if (!tp) 00280 return; 00281 00282 /* If this is the current thread, or there's code out there that 00283 relies on it existing (refcount > 0) we can't delete yet. Mark 00284 it as exited, and notify it. */ 00285 if (tp->refcount > 0 00286 || ptid_equal (tp->ptid, inferior_ptid)) 00287 { 00288 if (tp->state != THREAD_EXITED) 00289 { 00290 observer_notify_thread_exit (tp, silent); 00291 00292 /* Tag it as exited. */ 00293 tp->state = THREAD_EXITED; 00294 00295 /* Clear breakpoints, etc. associated with this thread. */ 00296 clear_thread_inferior_resources (tp); 00297 } 00298 00299 /* Will be really deleted some other time. */ 00300 return; 00301 } 00302 00303 /* Notify thread exit, but only if we haven't already. */ 00304 if (tp->state != THREAD_EXITED) 00305 observer_notify_thread_exit (tp, silent); 00306 00307 /* Tag it as exited. */ 00308 tp->state = THREAD_EXITED; 00309 clear_thread_inferior_resources (tp); 00310 00311 if (tpprev) 00312 tpprev->next = tp->next; 00313 else 00314 thread_list = tp->next; 00315 00316 free_thread (tp); 00317 } 00318 00319 /* Delete thread PTID and notify of thread exit. If this is 00320 inferior_ptid, don't actually delete it, but tag it as exited and 00321 do the notification. If PTID is the user selected thread, clear 00322 it. */ 00323 void 00324 delete_thread (ptid_t ptid) 00325 { 00326 delete_thread_1 (ptid, 0 /* not silent */); 00327 } 00328 00329 void 00330 delete_thread_silent (ptid_t ptid) 00331 { 00332 delete_thread_1 (ptid, 1 /* silent */); 00333 } 00334 00335 struct thread_info * 00336 find_thread_id (int num) 00337 { 00338 struct thread_info *tp; 00339 00340 for (tp = thread_list; tp; tp = tp->next) 00341 if (tp->num == num) 00342 return tp; 00343 00344 return NULL; 00345 } 00346 00347 /* Find a thread_info by matching PTID. */ 00348 struct thread_info * 00349 find_thread_ptid (ptid_t ptid) 00350 { 00351 struct thread_info *tp; 00352 00353 for (tp = thread_list; tp; tp = tp->next) 00354 if (ptid_equal (tp->ptid, ptid)) 00355 return tp; 00356 00357 return NULL; 00358 } 00359 00360 /* 00361 * Thread iterator function. 00362 * 00363 * Calls a callback function once for each thread, so long as 00364 * the callback function returns false. If the callback function 00365 * returns true, the iteration will end and the current thread 00366 * will be returned. This can be useful for implementing a 00367 * search for a thread with arbitrary attributes, or for applying 00368 * some operation to every thread. 00369 * 00370 * FIXME: some of the existing functionality, such as 00371 * "Thread apply all", might be rewritten using this functionality. 00372 */ 00373 00374 struct thread_info * 00375 iterate_over_threads (int (*callback) (struct thread_info *, void *), 00376 void *data) 00377 { 00378 struct thread_info *tp, *next; 00379 00380 for (tp = thread_list; tp; tp = next) 00381 { 00382 next = tp->next; 00383 if ((*callback) (tp, data)) 00384 return tp; 00385 } 00386 00387 return NULL; 00388 } 00389 00390 int 00391 thread_count (void) 00392 { 00393 int result = 0; 00394 struct thread_info *tp; 00395 00396 for (tp = thread_list; tp; tp = tp->next) 00397 ++result; 00398 00399 return result; 00400 } 00401 00402 int 00403 valid_thread_id (int num) 00404 { 00405 struct thread_info *tp; 00406 00407 for (tp = thread_list; tp; tp = tp->next) 00408 if (tp->num == num) 00409 return 1; 00410 00411 return 0; 00412 } 00413 00414 int 00415 pid_to_thread_id (ptid_t ptid) 00416 { 00417 struct thread_info *tp; 00418 00419 for (tp = thread_list; tp; tp = tp->next) 00420 if (ptid_equal (tp->ptid, ptid)) 00421 return tp->num; 00422 00423 return 0; 00424 } 00425 00426 ptid_t 00427 thread_id_to_pid (int num) 00428 { 00429 struct thread_info *thread = find_thread_id (num); 00430 00431 if (thread) 00432 return thread->ptid; 00433 else 00434 return pid_to_ptid (-1); 00435 } 00436 00437 int 00438 in_thread_list (ptid_t ptid) 00439 { 00440 struct thread_info *tp; 00441 00442 for (tp = thread_list; tp; tp = tp->next) 00443 if (ptid_equal (tp->ptid, ptid)) 00444 return 1; 00445 00446 return 0; /* Never heard of 'im. */ 00447 } 00448 00449 /* Finds the first thread of the inferior given by PID. If PID is -1, 00450 return the first thread in the list. */ 00451 00452 struct thread_info * 00453 first_thread_of_process (int pid) 00454 { 00455 struct thread_info *tp, *ret = NULL; 00456 00457 for (tp = thread_list; tp; tp = tp->next) 00458 if (pid == -1 || ptid_get_pid (tp->ptid) == pid) 00459 if (ret == NULL || tp->num < ret->num) 00460 ret = tp; 00461 00462 return ret; 00463 } 00464 00465 struct thread_info * 00466 any_thread_of_process (int pid) 00467 { 00468 struct thread_info *tp; 00469 00470 for (tp = thread_list; tp; tp = tp->next) 00471 if (ptid_get_pid (tp->ptid) == pid) 00472 return tp; 00473 00474 return NULL; 00475 } 00476 00477 struct thread_info * 00478 any_live_thread_of_process (int pid) 00479 { 00480 struct thread_info *tp; 00481 struct thread_info *tp_executing = NULL; 00482 00483 for (tp = thread_list; tp; tp = tp->next) 00484 if (tp->state != THREAD_EXITED && ptid_get_pid (tp->ptid) == pid) 00485 { 00486 if (tp->executing) 00487 tp_executing = tp; 00488 else 00489 return tp; 00490 } 00491 00492 return tp_executing; 00493 } 00494 00495 /* Print a list of thread ids currently known, and the total number of 00496 threads. To be used from within catch_errors. */ 00497 static int 00498 do_captured_list_thread_ids (struct ui_out *uiout, void *arg) 00499 { 00500 struct thread_info *tp; 00501 int num = 0; 00502 struct cleanup *cleanup_chain; 00503 int current_thread = -1; 00504 00505 update_thread_list (); 00506 00507 cleanup_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "thread-ids"); 00508 00509 for (tp = thread_list; tp; tp = tp->next) 00510 { 00511 if (tp->state == THREAD_EXITED) 00512 continue; 00513 00514 if (ptid_equal (tp->ptid, inferior_ptid)) 00515 current_thread = tp->num; 00516 00517 num++; 00518 ui_out_field_int (uiout, "thread-id", tp->num); 00519 } 00520 00521 do_cleanups (cleanup_chain); 00522 00523 if (current_thread != -1) 00524 ui_out_field_int (uiout, "current-thread-id", current_thread); 00525 ui_out_field_int (uiout, "number-of-threads", num); 00526 return GDB_RC_OK; 00527 } 00528 00529 /* Official gdblib interface function to get a list of thread ids and 00530 the total number. */ 00531 enum gdb_rc 00532 gdb_list_thread_ids (struct ui_out *uiout, char **error_message) 00533 { 00534 if (catch_exceptions_with_msg (uiout, do_captured_list_thread_ids, NULL, 00535 error_message, RETURN_MASK_ALL) < 0) 00536 return GDB_RC_FAIL; 00537 return GDB_RC_OK; 00538 } 00539 00540 /* Return true if TP is an active thread. */ 00541 static int 00542 thread_alive (struct thread_info *tp) 00543 { 00544 if (tp->state == THREAD_EXITED) 00545 return 0; 00546 if (!target_thread_alive (tp->ptid)) 00547 return 0; 00548 return 1; 00549 } 00550 00551 static void 00552 prune_threads (void) 00553 { 00554 struct thread_info *tp, *next; 00555 00556 for (tp = thread_list; tp; tp = next) 00557 { 00558 next = tp->next; 00559 if (!thread_alive (tp)) 00560 delete_thread (tp->ptid); 00561 } 00562 } 00563 00564 void 00565 thread_change_ptid (ptid_t old_ptid, ptid_t new_ptid) 00566 { 00567 struct inferior *inf; 00568 struct thread_info *tp; 00569 00570 /* It can happen that what we knew as the target inferior id 00571 changes. E.g, target remote may only discover the remote process 00572 pid after adding the inferior to GDB's list. */ 00573 inf = find_inferior_pid (ptid_get_pid (old_ptid)); 00574 inf->pid = ptid_get_pid (new_ptid); 00575 00576 tp = find_thread_ptid (old_ptid); 00577 tp->ptid = new_ptid; 00578 00579 observer_notify_thread_ptid_changed (old_ptid, new_ptid); 00580 } 00581 00582 void 00583 set_running (ptid_t ptid, int running) 00584 { 00585 struct thread_info *tp; 00586 int all = ptid_equal (ptid, minus_one_ptid); 00587 00588 /* We try not to notify the observer if no thread has actually changed 00589 the running state -- merely to reduce the number of messages to 00590 frontend. Frontend is supposed to handle multiple *running just fine. */ 00591 if (all || ptid_is_pid (ptid)) 00592 { 00593 int any_started = 0; 00594 00595 for (tp = thread_list; tp; tp = tp->next) 00596 if (all || ptid_get_pid (tp->ptid) == ptid_get_pid (ptid)) 00597 { 00598 if (tp->state == THREAD_EXITED) 00599 continue; 00600 if (running && tp->state == THREAD_STOPPED) 00601 any_started = 1; 00602 tp->state = running ? THREAD_RUNNING : THREAD_STOPPED; 00603 } 00604 if (any_started) 00605 observer_notify_target_resumed (ptid); 00606 } 00607 else 00608 { 00609 int started = 0; 00610 00611 tp = find_thread_ptid (ptid); 00612 gdb_assert (tp); 00613 gdb_assert (tp->state != THREAD_EXITED); 00614 if (running && tp->state == THREAD_STOPPED) 00615 started = 1; 00616 tp->state = running ? THREAD_RUNNING : THREAD_STOPPED; 00617 if (started) 00618 observer_notify_target_resumed (ptid); 00619 } 00620 } 00621 00622 static int 00623 is_thread_state (ptid_t ptid, enum thread_state state) 00624 { 00625 struct thread_info *tp; 00626 00627 tp = find_thread_ptid (ptid); 00628 gdb_assert (tp); 00629 return tp->state == state; 00630 } 00631 00632 int 00633 is_stopped (ptid_t ptid) 00634 { 00635 return is_thread_state (ptid, THREAD_STOPPED); 00636 } 00637 00638 int 00639 is_exited (ptid_t ptid) 00640 { 00641 return is_thread_state (ptid, THREAD_EXITED); 00642 } 00643 00644 int 00645 is_running (ptid_t ptid) 00646 { 00647 return is_thread_state (ptid, THREAD_RUNNING); 00648 } 00649 00650 int 00651 any_running (void) 00652 { 00653 struct thread_info *tp; 00654 00655 for (tp = thread_list; tp; tp = tp->next) 00656 if (tp->state == THREAD_RUNNING) 00657 return 1; 00658 00659 return 0; 00660 } 00661 00662 int 00663 is_executing (ptid_t ptid) 00664 { 00665 struct thread_info *tp; 00666 00667 tp = find_thread_ptid (ptid); 00668 gdb_assert (tp); 00669 return tp->executing; 00670 } 00671 00672 void 00673 set_executing (ptid_t ptid, int executing) 00674 { 00675 struct thread_info *tp; 00676 int all = ptid_equal (ptid, minus_one_ptid); 00677 00678 if (all || ptid_is_pid (ptid)) 00679 { 00680 for (tp = thread_list; tp; tp = tp->next) 00681 if (all || ptid_get_pid (tp->ptid) == ptid_get_pid (ptid)) 00682 tp->executing = executing; 00683 } 00684 else 00685 { 00686 tp = find_thread_ptid (ptid); 00687 gdb_assert (tp); 00688 tp->executing = executing; 00689 } 00690 } 00691 00692 void 00693 set_stop_requested (ptid_t ptid, int stop) 00694 { 00695 struct thread_info *tp; 00696 int all = ptid_equal (ptid, minus_one_ptid); 00697 00698 if (all || ptid_is_pid (ptid)) 00699 { 00700 for (tp = thread_list; tp; tp = tp->next) 00701 if (all || ptid_get_pid (tp->ptid) == ptid_get_pid (ptid)) 00702 tp->stop_requested = stop; 00703 } 00704 else 00705 { 00706 tp = find_thread_ptid (ptid); 00707 gdb_assert (tp); 00708 tp->stop_requested = stop; 00709 } 00710 00711 /* Call the stop requested observer so other components of GDB can 00712 react to this request. */ 00713 if (stop) 00714 observer_notify_thread_stop_requested (ptid); 00715 } 00716 00717 void 00718 finish_thread_state (ptid_t ptid) 00719 { 00720 struct thread_info *tp; 00721 int all; 00722 int any_started = 0; 00723 00724 all = ptid_equal (ptid, minus_one_ptid); 00725 00726 if (all || ptid_is_pid (ptid)) 00727 { 00728 for (tp = thread_list; tp; tp = tp->next) 00729 { 00730 if (tp->state == THREAD_EXITED) 00731 continue; 00732 if (all || ptid_get_pid (ptid) == ptid_get_pid (tp->ptid)) 00733 { 00734 if (tp->executing && tp->state == THREAD_STOPPED) 00735 any_started = 1; 00736 tp->state = tp->executing ? THREAD_RUNNING : THREAD_STOPPED; 00737 } 00738 } 00739 } 00740 else 00741 { 00742 tp = find_thread_ptid (ptid); 00743 gdb_assert (tp); 00744 if (tp->state != THREAD_EXITED) 00745 { 00746 if (tp->executing && tp->state == THREAD_STOPPED) 00747 any_started = 1; 00748 tp->state = tp->executing ? THREAD_RUNNING : THREAD_STOPPED; 00749 } 00750 } 00751 00752 if (any_started) 00753 observer_notify_target_resumed (ptid); 00754 } 00755 00756 void 00757 finish_thread_state_cleanup (void *arg) 00758 { 00759 ptid_t *ptid_p = arg; 00760 00761 gdb_assert (arg); 00762 00763 finish_thread_state (*ptid_p); 00764 } 00765 00766 int 00767 pc_in_thread_step_range (CORE_ADDR pc, struct thread_info *thread) 00768 { 00769 return (pc >= thread->control.step_range_start 00770 && pc < thread->control.step_range_end); 00771 } 00772 00773 /* Prints the list of threads and their details on UIOUT. 00774 This is a version of 'info_threads_command' suitable for 00775 use from MI. 00776 If REQUESTED_THREAD is not -1, it's the GDB id of the thread 00777 that should be printed. Otherwise, all threads are 00778 printed. 00779 If PID is not -1, only print threads from the process PID. 00780 Otherwise, threads from all attached PIDs are printed. 00781 If both REQUESTED_THREAD and PID are not -1, then the thread 00782 is printed if it belongs to the specified process. Otherwise, 00783 an error is raised. */ 00784 void 00785 print_thread_info (struct ui_out *uiout, char *requested_threads, int pid) 00786 { 00787 struct thread_info *tp; 00788 ptid_t current_ptid; 00789 struct cleanup *old_chain; 00790 char *extra_info, *name, *target_id; 00791 int current_thread = -1; 00792 00793 update_thread_list (); 00794 current_ptid = inferior_ptid; 00795 00796 /* We'll be switching threads temporarily. */ 00797 old_chain = make_cleanup_restore_current_thread (); 00798 00799 /* For backward compatibility, we make a list for MI. A table is 00800 preferable for the CLI, though, because it shows table 00801 headers. */ 00802 if (ui_out_is_mi_like_p (uiout)) 00803 make_cleanup_ui_out_list_begin_end (uiout, "threads"); 00804 else 00805 { 00806 int n_threads = 0; 00807 00808 for (tp = thread_list; tp; tp = tp->next) 00809 { 00810 if (!number_is_in_list (requested_threads, tp->num)) 00811 continue; 00812 00813 if (pid != -1 && ptid_get_pid (tp->ptid) != pid) 00814 continue; 00815 00816 if (tp->state == THREAD_EXITED) 00817 continue; 00818 00819 ++n_threads; 00820 } 00821 00822 if (n_threads == 0) 00823 { 00824 if (requested_threads == NULL || *requested_threads == '\0') 00825 ui_out_message (uiout, 0, _("No threads.\n")); 00826 else 00827 ui_out_message (uiout, 0, _("No threads match '%s'.\n"), 00828 requested_threads); 00829 do_cleanups (old_chain); 00830 return; 00831 } 00832 00833 make_cleanup_ui_out_table_begin_end (uiout, 4, n_threads, "threads"); 00834 00835 ui_out_table_header (uiout, 1, ui_left, "current", ""); 00836 ui_out_table_header (uiout, 4, ui_left, "id", "Id"); 00837 ui_out_table_header (uiout, 17, ui_left, "target-id", "Target Id"); 00838 ui_out_table_header (uiout, 1, ui_left, "frame", "Frame"); 00839 ui_out_table_body (uiout); 00840 } 00841 00842 for (tp = thread_list; tp; tp = tp->next) 00843 { 00844 struct cleanup *chain2; 00845 int core; 00846 00847 if (!number_is_in_list (requested_threads, tp->num)) 00848 continue; 00849 00850 if (pid != -1 && ptid_get_pid (tp->ptid) != pid) 00851 { 00852 if (requested_threads != NULL && *requested_threads != '\0') 00853 error (_("Requested thread not found in requested process")); 00854 continue; 00855 } 00856 00857 if (ptid_equal (tp->ptid, current_ptid)) 00858 current_thread = tp->num; 00859 00860 if (tp->state == THREAD_EXITED) 00861 continue; 00862 00863 chain2 = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); 00864 00865 if (ui_out_is_mi_like_p (uiout)) 00866 { 00867 /* Compatibility. */ 00868 if (ptid_equal (tp->ptid, current_ptid)) 00869 ui_out_text (uiout, "* "); 00870 else 00871 ui_out_text (uiout, " "); 00872 } 00873 else 00874 { 00875 if (ptid_equal (tp->ptid, current_ptid)) 00876 ui_out_field_string (uiout, "current", "*"); 00877 else 00878 ui_out_field_skip (uiout, "current"); 00879 } 00880 00881 ui_out_field_int (uiout, "id", tp->num); 00882 00883 /* For the CLI, we stuff everything into the target-id field. 00884 This is a gross hack to make the output come out looking 00885 correct. The underlying problem here is that ui-out has no 00886 way to specify that a field's space allocation should be 00887 shared by several fields. For MI, we do the right thing 00888 instead. */ 00889 00890 target_id = target_pid_to_str (tp->ptid); 00891 extra_info = target_extra_thread_info (tp); 00892 name = tp->name ? tp->name : target_thread_name (tp); 00893 00894 if (ui_out_is_mi_like_p (uiout)) 00895 { 00896 ui_out_field_string (uiout, "target-id", target_id); 00897 if (extra_info) 00898 ui_out_field_string (uiout, "details", extra_info); 00899 if (name) 00900 ui_out_field_string (uiout, "name", name); 00901 } 00902 else 00903 { 00904 struct cleanup *str_cleanup; 00905 char *contents; 00906 00907 if (extra_info && name) 00908 contents = xstrprintf ("%s \"%s\" (%s)", target_id, 00909 name, extra_info); 00910 else if (extra_info) 00911 contents = xstrprintf ("%s (%s)", target_id, extra_info); 00912 else if (name) 00913 contents = xstrprintf ("%s \"%s\"", target_id, name); 00914 else 00915 contents = xstrdup (target_id); 00916 str_cleanup = make_cleanup (xfree, contents); 00917 00918 ui_out_field_string (uiout, "target-id", contents); 00919 do_cleanups (str_cleanup); 00920 } 00921 00922 if (tp->state == THREAD_RUNNING) 00923 ui_out_text (uiout, "(running)\n"); 00924 else 00925 { 00926 /* The switch below puts us at the top of the stack (leaf 00927 frame). */ 00928 switch_to_thread (tp->ptid); 00929 print_stack_frame (get_selected_frame (NULL), 00930 /* For MI output, print frame level. */ 00931 ui_out_is_mi_like_p (uiout), 00932 LOCATION, 0); 00933 } 00934 00935 if (ui_out_is_mi_like_p (uiout)) 00936 { 00937 char *state = "stopped"; 00938 00939 if (tp->state == THREAD_RUNNING) 00940 state = "running"; 00941 ui_out_field_string (uiout, "state", state); 00942 } 00943 00944 core = target_core_of_thread (tp->ptid); 00945 if (ui_out_is_mi_like_p (uiout) && core != -1) 00946 ui_out_field_int (uiout, "core", core); 00947 00948 do_cleanups (chain2); 00949 } 00950 00951 /* Restores the current thread and the frame selected before 00952 the "info threads" command. */ 00953 do_cleanups (old_chain); 00954 00955 if (pid == -1 && requested_threads == NULL) 00956 { 00957 gdb_assert (current_thread != -1 00958 || !thread_list 00959 || ptid_equal (inferior_ptid, null_ptid)); 00960 if (current_thread != -1 && ui_out_is_mi_like_p (uiout)) 00961 ui_out_field_int (uiout, "current-thread-id", current_thread); 00962 00963 if (current_thread != -1 && is_exited (current_ptid)) 00964 ui_out_message (uiout, 0, "\n\ 00965 The current thread <Thread ID %d> has terminated. See `help thread'.\n", 00966 current_thread); 00967 else if (thread_list 00968 && current_thread == -1 00969 && ptid_equal (current_ptid, null_ptid)) 00970 ui_out_message (uiout, 0, "\n\ 00971 No selected thread. See `help thread'.\n"); 00972 } 00973 } 00974 00975 /* Print information about currently known threads 00976 00977 Optional ARG is a thread id, or list of thread ids. 00978 00979 Note: this has the drawback that it _really_ switches 00980 threads, which frees the frame cache. A no-side 00981 effects info-threads command would be nicer. */ 00982 00983 static void 00984 info_threads_command (char *arg, int from_tty) 00985 { 00986 print_thread_info (current_uiout, arg, -1); 00987 } 00988 00989 /* Switch from one thread to another. */ 00990 00991 void 00992 switch_to_thread (ptid_t ptid) 00993 { 00994 /* Switch the program space as well, if we can infer it from the now 00995 current thread. Otherwise, it's up to the caller to select the 00996 space it wants. */ 00997 if (!ptid_equal (ptid, null_ptid)) 00998 { 00999 struct inferior *inf; 01000 01001 inf = find_inferior_pid (ptid_get_pid (ptid)); 01002 gdb_assert (inf != NULL); 01003 set_current_program_space (inf->pspace); 01004 set_current_inferior (inf); 01005 } 01006 01007 if (ptid_equal (ptid, inferior_ptid)) 01008 return; 01009 01010 inferior_ptid = ptid; 01011 reinit_frame_cache (); 01012 01013 /* We don't check for is_stopped, because we're called at times 01014 while in the TARGET_RUNNING state, e.g., while handling an 01015 internal event. */ 01016 if (!ptid_equal (inferior_ptid, null_ptid) 01017 && !is_exited (ptid) 01018 && !is_executing (ptid)) 01019 stop_pc = regcache_read_pc (get_thread_regcache (ptid)); 01020 else 01021 stop_pc = ~(CORE_ADDR) 0; 01022 } 01023 01024 static void 01025 restore_current_thread (ptid_t ptid) 01026 { 01027 switch_to_thread (ptid); 01028 } 01029 01030 static void 01031 restore_selected_frame (struct frame_id a_frame_id, int frame_level) 01032 { 01033 struct frame_info *frame = NULL; 01034 int count; 01035 01036 /* This means there was no selected frame. */ 01037 if (frame_level == -1) 01038 { 01039 select_frame (NULL); 01040 return; 01041 } 01042 01043 gdb_assert (frame_level >= 0); 01044 01045 /* Restore by level first, check if the frame id is the same as 01046 expected. If that fails, try restoring by frame id. If that 01047 fails, nothing to do, just warn the user. */ 01048 01049 count = frame_level; 01050 frame = find_relative_frame (get_current_frame (), &count); 01051 if (count == 0 01052 && frame != NULL 01053 /* The frame ids must match - either both valid or both outer_frame_id. 01054 The latter case is not failsafe, but since it's highly unlikely 01055 the search by level finds the wrong frame, it's 99.9(9)% of 01056 the time (for all practical purposes) safe. */ 01057 && frame_id_eq (get_frame_id (frame), a_frame_id)) 01058 { 01059 /* Cool, all is fine. */ 01060 select_frame (frame); 01061 return; 01062 } 01063 01064 frame = frame_find_by_id (a_frame_id); 01065 if (frame != NULL) 01066 { 01067 /* Cool, refound it. */ 01068 select_frame (frame); 01069 return; 01070 } 01071 01072 /* Nothing else to do, the frame layout really changed. Select the 01073 innermost stack frame. */ 01074 select_frame (get_current_frame ()); 01075 01076 /* Warn the user. */ 01077 if (frame_level > 0 && !ui_out_is_mi_like_p (current_uiout)) 01078 { 01079 warning (_("Couldn't restore frame #%d in " 01080 "current thread. Bottom (innermost) frame selected:"), 01081 frame_level); 01082 /* For MI, we should probably have a notification about 01083 current frame change. But this error is not very 01084 likely, so don't bother for now. */ 01085 print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1); 01086 } 01087 } 01088 01089 struct current_thread_cleanup 01090 { 01091 ptid_t inferior_ptid; 01092 struct frame_id selected_frame_id; 01093 int selected_frame_level; 01094 int was_stopped; 01095 int inf_id; 01096 int was_removable; 01097 }; 01098 01099 static void 01100 do_restore_current_thread_cleanup (void *arg) 01101 { 01102 struct thread_info *tp; 01103 struct current_thread_cleanup *old = arg; 01104 01105 tp = find_thread_ptid (old->inferior_ptid); 01106 01107 /* If the previously selected thread belonged to a process that has 01108 in the mean time been deleted (due to normal exit, detach, etc.), 01109 then don't revert back to it, but instead simply drop back to no 01110 thread selected. */ 01111 if (tp 01112 && find_inferior_pid (ptid_get_pid (tp->ptid)) != NULL) 01113 restore_current_thread (old->inferior_ptid); 01114 else 01115 { 01116 restore_current_thread (null_ptid); 01117 set_current_inferior (find_inferior_id (old->inf_id)); 01118 } 01119 01120 /* The running state of the originally selected thread may have 01121 changed, so we have to recheck it here. */ 01122 if (!ptid_equal (inferior_ptid, null_ptid) 01123 && old->was_stopped 01124 && is_stopped (inferior_ptid) 01125 && target_has_registers 01126 && target_has_stack 01127 && target_has_memory) 01128 restore_selected_frame (old->selected_frame_id, 01129 old->selected_frame_level); 01130 } 01131 01132 static void 01133 restore_current_thread_cleanup_dtor (void *arg) 01134 { 01135 struct current_thread_cleanup *old = arg; 01136 struct thread_info *tp; 01137 struct inferior *inf; 01138 01139 tp = find_thread_ptid (old->inferior_ptid); 01140 if (tp) 01141 tp->refcount--; 01142 inf = find_inferior_id (old->inf_id); 01143 if (inf != NULL) 01144 inf->removable = old->was_removable; 01145 xfree (old); 01146 } 01147 01148 /* Set the thread reference count. */ 01149 01150 static void 01151 set_thread_refcount (void *data) 01152 { 01153 int k; 01154 struct thread_array_cleanup *ta_cleanup = data; 01155 01156 for (k = 0; k != ta_cleanup->count; k++) 01157 ta_cleanup->tp_array[k]->refcount--; 01158 } 01159 01160 struct cleanup * 01161 make_cleanup_restore_current_thread (void) 01162 { 01163 struct thread_info *tp; 01164 struct frame_info *frame; 01165 struct current_thread_cleanup *old; 01166 01167 old = xmalloc (sizeof (struct current_thread_cleanup)); 01168 old->inferior_ptid = inferior_ptid; 01169 old->inf_id = current_inferior ()->num; 01170 old->was_removable = current_inferior ()->removable; 01171 01172 if (!ptid_equal (inferior_ptid, null_ptid)) 01173 { 01174 old->was_stopped = is_stopped (inferior_ptid); 01175 if (old->was_stopped 01176 && target_has_registers 01177 && target_has_stack 01178 && target_has_memory) 01179 { 01180 /* When processing internal events, there might not be a 01181 selected frame. If we naively call get_selected_frame 01182 here, then we can end up reading debuginfo for the 01183 current frame, but we don't generally need the debuginfo 01184 at this point. */ 01185 frame = get_selected_frame_if_set (); 01186 } 01187 else 01188 frame = NULL; 01189 01190 old->selected_frame_id = get_frame_id (frame); 01191 old->selected_frame_level = frame_relative_level (frame); 01192 01193 tp = find_thread_ptid (inferior_ptid); 01194 if (tp) 01195 tp->refcount++; 01196 } 01197 01198 current_inferior ()->removable = 0; 01199 01200 return make_cleanup_dtor (do_restore_current_thread_cleanup, old, 01201 restore_current_thread_cleanup_dtor); 01202 } 01203 01204 /* Apply a GDB command to a list of threads. List syntax is a whitespace 01205 seperated list of numbers, or ranges, or the keyword `all'. Ranges consist 01206 of two numbers seperated by a hyphen. Examples: 01207 01208 thread apply 1 2 7 4 backtrace Apply backtrace cmd to threads 1,2,7,4 01209 thread apply 2-7 9 p foo(1) Apply p foo(1) cmd to threads 2->7 & 9 01210 thread apply all p x/i $pc Apply x/i $pc cmd to all threads. */ 01211 01212 static void 01213 thread_apply_all_command (char *cmd, int from_tty) 01214 { 01215 struct cleanup *old_chain; 01216 char *saved_cmd; 01217 int tc; 01218 struct thread_array_cleanup ta_cleanup; 01219 01220 if (cmd == NULL || *cmd == '\000') 01221 error (_("Please specify a command following the thread ID list")); 01222 01223 update_thread_list (); 01224 01225 old_chain = make_cleanup_restore_current_thread (); 01226 01227 /* Save a copy of the command in case it is clobbered by 01228 execute_command. */ 01229 saved_cmd = xstrdup (cmd); 01230 make_cleanup (xfree, saved_cmd); 01231 tc = thread_count (); 01232 01233 if (tc) 01234 { 01235 struct thread_info **tp_array; 01236 struct thread_info *tp; 01237 int i = 0, k; 01238 01239 /* Save a copy of the thread_list in case we execute detach 01240 command. */ 01241 tp_array = xmalloc (sizeof (struct thread_info *) * tc); 01242 make_cleanup (xfree, tp_array); 01243 ta_cleanup.tp_array = tp_array; 01244 ta_cleanup.count = tc; 01245 01246 ALL_THREADS (tp) 01247 { 01248 tp_array[i] = tp; 01249 tp->refcount++; 01250 i++; 01251 } 01252 01253 make_cleanup (set_thread_refcount, &ta_cleanup); 01254 01255 for (k = 0; k != i; k++) 01256 if (thread_alive (tp_array[k])) 01257 { 01258 switch_to_thread (tp_array[k]->ptid); 01259 printf_filtered (_("\nThread %d (%s):\n"), 01260 tp_array[k]->num, 01261 target_pid_to_str (inferior_ptid)); 01262 execute_command (cmd, from_tty); 01263 01264 /* Restore exact command used previously. */ 01265 strcpy (cmd, saved_cmd); 01266 } 01267 } 01268 01269 do_cleanups (old_chain); 01270 } 01271 01272 static void 01273 thread_apply_command (char *tidlist, int from_tty) 01274 { 01275 char *cmd; 01276 struct cleanup *old_chain; 01277 char *saved_cmd; 01278 struct get_number_or_range_state state; 01279 01280 if (tidlist == NULL || *tidlist == '\000') 01281 error (_("Please specify a thread ID list")); 01282 01283 for (cmd = tidlist; *cmd != '\000' && !isalpha (*cmd); cmd++); 01284 01285 if (*cmd == '\000') 01286 error (_("Please specify a command following the thread ID list")); 01287 01288 /* Save a copy of the command in case it is clobbered by 01289 execute_command. */ 01290 saved_cmd = xstrdup (cmd); 01291 old_chain = make_cleanup (xfree, saved_cmd); 01292 01293 init_number_or_range (&state, tidlist); 01294 while (!state.finished && state.string < cmd) 01295 { 01296 struct thread_info *tp; 01297 int start; 01298 01299 start = get_number_or_range (&state); 01300 01301 make_cleanup_restore_current_thread (); 01302 01303 tp = find_thread_id (start); 01304 01305 if (!tp) 01306 warning (_("Unknown thread %d."), start); 01307 else if (!thread_alive (tp)) 01308 warning (_("Thread %d has terminated."), start); 01309 else 01310 { 01311 switch_to_thread (tp->ptid); 01312 01313 printf_filtered (_("\nThread %d (%s):\n"), tp->num, 01314 target_pid_to_str (inferior_ptid)); 01315 execute_command (cmd, from_tty); 01316 01317 /* Restore exact command used previously. */ 01318 strcpy (cmd, saved_cmd); 01319 } 01320 } 01321 01322 do_cleanups (old_chain); 01323 } 01324 01325 /* Switch to the specified thread. Will dispatch off to thread_apply_command 01326 if prefix of arg is `apply'. */ 01327 01328 static void 01329 thread_command (char *tidstr, int from_tty) 01330 { 01331 if (!tidstr) 01332 { 01333 if (ptid_equal (inferior_ptid, null_ptid)) 01334 error (_("No thread selected")); 01335 01336 if (target_has_stack) 01337 { 01338 if (is_exited (inferior_ptid)) 01339 printf_filtered (_("[Current thread is %d (%s) (exited)]\n"), 01340 pid_to_thread_id (inferior_ptid), 01341 target_pid_to_str (inferior_ptid)); 01342 else 01343 printf_filtered (_("[Current thread is %d (%s)]\n"), 01344 pid_to_thread_id (inferior_ptid), 01345 target_pid_to_str (inferior_ptid)); 01346 } 01347 else 01348 error (_("No stack.")); 01349 return; 01350 } 01351 01352 gdb_thread_select (current_uiout, tidstr, NULL); 01353 } 01354 01355 /* Implementation of `thread name'. */ 01356 01357 static void 01358 thread_name_command (char *arg, int from_tty) 01359 { 01360 struct thread_info *info; 01361 01362 if (ptid_equal (inferior_ptid, null_ptid)) 01363 error (_("No thread selected")); 01364 01365 arg = skip_spaces (arg); 01366 01367 info = inferior_thread (); 01368 xfree (info->name); 01369 info->name = arg ? xstrdup (arg) : NULL; 01370 } 01371 01372 /* Find thread ids with a name, target pid, or extra info matching ARG. */ 01373 01374 static void 01375 thread_find_command (char *arg, int from_tty) 01376 { 01377 struct thread_info *tp; 01378 char *tmp; 01379 unsigned long match = 0; 01380 01381 if (arg == NULL || *arg == '\0') 01382 error (_("Command requires an argument.")); 01383 01384 tmp = re_comp (arg); 01385 if (tmp != 0) 01386 error (_("Invalid regexp (%s): %s"), tmp, arg); 01387 01388 update_thread_list (); 01389 for (tp = thread_list; tp; tp = tp->next) 01390 { 01391 if (tp->name != NULL && re_exec (tp->name)) 01392 { 01393 printf_filtered (_("Thread %d has name '%s'\n"), 01394 tp->num, tp->name); 01395 match++; 01396 } 01397 01398 tmp = target_thread_name (tp); 01399 if (tmp != NULL && re_exec (tmp)) 01400 { 01401 printf_filtered (_("Thread %d has target name '%s'\n"), 01402 tp->num, tmp); 01403 match++; 01404 } 01405 01406 tmp = target_pid_to_str (tp->ptid); 01407 if (tmp != NULL && re_exec (tmp)) 01408 { 01409 printf_filtered (_("Thread %d has target id '%s'\n"), 01410 tp->num, tmp); 01411 match++; 01412 } 01413 01414 tmp = target_extra_thread_info (tp); 01415 if (tmp != NULL && re_exec (tmp)) 01416 { 01417 printf_filtered (_("Thread %d has extra info '%s'\n"), 01418 tp->num, tmp); 01419 match++; 01420 } 01421 } 01422 if (!match) 01423 printf_filtered (_("No threads match '%s'\n"), arg); 01424 } 01425 01426 /* Print notices when new threads are attached and detached. */ 01427 int print_thread_events = 1; 01428 static void 01429 show_print_thread_events (struct ui_file *file, int from_tty, 01430 struct cmd_list_element *c, const char *value) 01431 { 01432 fprintf_filtered (file, 01433 _("Printing of thread events is %s.\n"), 01434 value); 01435 } 01436 01437 static int 01438 do_captured_thread_select (struct ui_out *uiout, void *tidstr) 01439 { 01440 int num; 01441 struct thread_info *tp; 01442 01443 num = value_as_long (parse_and_eval (tidstr)); 01444 01445 tp = find_thread_id (num); 01446 01447 if (!tp) 01448 error (_("Thread ID %d not known."), num); 01449 01450 if (!thread_alive (tp)) 01451 error (_("Thread ID %d has terminated."), num); 01452 01453 switch_to_thread (tp->ptid); 01454 01455 annotate_thread_changed (); 01456 01457 ui_out_text (uiout, "[Switching to thread "); 01458 ui_out_field_int (uiout, "new-thread-id", pid_to_thread_id (inferior_ptid)); 01459 ui_out_text (uiout, " ("); 01460 ui_out_text (uiout, target_pid_to_str (inferior_ptid)); 01461 ui_out_text (uiout, ")]"); 01462 01463 /* Note that we can't reach this with an exited thread, due to the 01464 thread_alive check above. */ 01465 if (tp->state == THREAD_RUNNING) 01466 ui_out_text (uiout, "(running)\n"); 01467 else 01468 { 01469 ui_out_text (uiout, "\n"); 01470 print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1); 01471 } 01472 01473 /* Since the current thread may have changed, see if there is any 01474 exited thread we can now delete. */ 01475 prune_threads (); 01476 01477 return GDB_RC_OK; 01478 } 01479 01480 enum gdb_rc 01481 gdb_thread_select (struct ui_out *uiout, char *tidstr, char **error_message) 01482 { 01483 if (catch_exceptions_with_msg (uiout, do_captured_thread_select, tidstr, 01484 error_message, RETURN_MASK_ALL) < 0) 01485 return GDB_RC_FAIL; 01486 return GDB_RC_OK; 01487 } 01488 01489 void 01490 update_thread_list (void) 01491 { 01492 prune_threads (); 01493 target_find_new_threads (); 01494 } 01495 01496 /* Return a new value for the selected thread's id. Return a value of 0 if 01497 no thread is selected, or no threads exist. */ 01498 01499 static struct value * 01500 thread_id_make_value (struct gdbarch *gdbarch, struct internalvar *var, 01501 void *ignore) 01502 { 01503 struct thread_info *tp = find_thread_ptid (inferior_ptid); 01504 01505 return value_from_longest (builtin_type (gdbarch)->builtin_int, 01506 (tp ? tp->num : 0)); 01507 } 01508 01509 /* Commands with a prefix of `thread'. */ 01510 struct cmd_list_element *thread_cmd_list = NULL; 01511 01512 /* Implementation of `thread' variable. */ 01513 01514 static const struct internalvar_funcs thread_funcs = 01515 { 01516 thread_id_make_value, 01517 NULL, 01518 NULL 01519 }; 01520 01521 void 01522 _initialize_thread (void) 01523 { 01524 static struct cmd_list_element *thread_apply_list = NULL; 01525 01526 add_info ("threads", info_threads_command, 01527 _("Display currently known threads.\n\ 01528 Usage: info threads [ID]...\n\ 01529 Optional arguments are thread IDs with spaces between.\n\ 01530 If no arguments, all threads are displayed.")); 01531 01532 add_prefix_cmd ("thread", class_run, thread_command, _("\ 01533 Use this command to switch between threads.\n\ 01534 The new thread ID must be currently known."), 01535 &thread_cmd_list, "thread ", 1, &cmdlist); 01536 01537 add_prefix_cmd ("apply", class_run, thread_apply_command, 01538 _("Apply a command to a list of threads."), 01539 &thread_apply_list, "thread apply ", 1, &thread_cmd_list); 01540 01541 add_cmd ("all", class_run, thread_apply_all_command, 01542 _("Apply a command to all threads."), &thread_apply_list); 01543 01544 add_cmd ("name", class_run, thread_name_command, 01545 _("Set the current thread's name.\n\ 01546 Usage: thread name [NAME]\n\ 01547 If NAME is not given, then any existing name is removed."), &thread_cmd_list); 01548 01549 add_cmd ("find", class_run, thread_find_command, _("\ 01550 Find threads that match a regular expression.\n\ 01551 Usage: thread find REGEXP\n\ 01552 Will display thread ids whose name, target ID, or extra info matches REGEXP."), 01553 &thread_cmd_list); 01554 01555 if (!xdb_commands) 01556 add_com_alias ("t", "thread", class_run, 1); 01557 01558 add_setshow_boolean_cmd ("thread-events", no_class, 01559 &print_thread_events, _("\ 01560 Set printing of thread events (such as thread start and exit)."), _("\ 01561 Show printing of thread events (such as thread start and exit)."), NULL, 01562 NULL, 01563 show_print_thread_events, 01564 &setprintlist, &showprintlist); 01565 01566 create_internalvar_type_lazy ("_thread", &thread_funcs, NULL); 01567 }