X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fremote.c;h=4b9b0991c65ffeeb6a817824266d450a76bc406a;hb=071436c6e94be13904438b6eb70ee79c73354a61;hp=3fa835fb115fcd7e07c2f4a72aaf557bca718d9f;hpb=6dc54d9124e8ef9ef3611e0ef3eefef5dcd87ee4;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/remote.c b/gdb/remote.c index 3fa835fb11..4b9b0991c6 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -1842,11 +1842,11 @@ set_general_process (void) } -/* Return nonzero if the thread PTID is still alive on the remote - system. */ +/* Return nonzero if this is the main thread that we made up ourselves + to model non-threaded targets as single-threaded. */ static int -remote_thread_alive (struct target_ops *ops, ptid_t ptid) +remote_thread_always_alive (struct target_ops *ops, ptid_t ptid) { struct remote_state *rs = get_remote_state (); char *p, *endp; @@ -1861,6 +1861,23 @@ remote_thread_alive (struct target_ops *ops, ptid_t ptid) multi-threading. */ return 1; + return 0; +} + +/* Return nonzero if the thread PTID is still alive on the remote + system. */ + +static int +remote_thread_alive (struct target_ops *ops, ptid_t ptid) +{ + struct remote_state *rs = get_remote_state (); + char *p, *endp; + + /* Check if this is a thread that we made up ourselves to model + non-threaded targets as single-threaded. */ + if (remote_thread_always_alive (ops, ptid)) + return 1; + p = rs->buf; endp = rs->buf + get_remote_packet_size (); @@ -2559,6 +2576,21 @@ struct threads_listing_context VEC (thread_item_t) *items; }; +/* Discard the contents of the constructed thread listing context. */ + +static void +clear_threads_listing_context (void *p) +{ + struct threads_listing_context *context = p; + int i; + struct thread_item *item; + + for (i = 0; VEC_iterate (thread_item_t, context->items, i, item); ++i) + xfree (item->extra); + + VEC_free (thread_item_t, context->items); +} + static int remote_newthread_step (threadref *ref, void *data) { @@ -2664,21 +2696,6 @@ const struct gdb_xml_element threads_elements[] = { { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } }; -/* Discard the contents of the constructed thread info context. */ - -static void -clear_threads_listing_context (void *p) -{ - struct threads_listing_context *context = p; - int i; - struct thread_item *item; - - for (i = 0; VEC_iterate (thread_item_t, context->items, i, item); ++i) - xfree (item->extra); - - VEC_free (thread_item_t, context->items); -} - #endif /* List remote threads using qXfer:threads:read. */ @@ -2753,15 +2770,16 @@ remote_get_threads_with_qthreadinfo (struct target_ops *ops, return 0; } -/* Implement the to_find_new_threads function for the remote +/* Implement the to_update_thread_list function for the remote targets. */ static void -remote_threads_info (struct target_ops *ops) +remote_update_thread_list (struct target_ops *ops) { struct remote_state *rs = get_remote_state (); struct threads_listing_context context; struct cleanup *old_chain; + int got_list = 0; context.items = NULL; old_chain = make_cleanup (clear_threads_listing_context, &context); @@ -2775,8 +2793,43 @@ remote_threads_info (struct target_ops *ops) { int i; struct thread_item *item; + struct thread_info *tp, *tmp; + + got_list = 1; + + if (VEC_empty (thread_item_t, context.items) + && remote_thread_always_alive (ops, inferior_ptid)) + { + /* Some targets don't really support threads, but still + reply an (empty) thread list in response to the thread + listing packets, instead of replying "packet not + supported". Exit early so we don't delete the main + thread. */ + do_cleanups (old_chain); + return; + } + + /* CONTEXT now holds the current thread list on the remote + target end. Delete GDB-side threads no longer found on the + target. */ + ALL_NON_EXITED_THREADS_SAFE (tp, tmp) + { + for (i = 0; + VEC_iterate (thread_item_t, context.items, i, item); + ++i) + { + if (ptid_equal (item->ptid, tp->ptid)) + break; + } - /* Add threads we don't know about yet to our list. */ + if (i == VEC_length (thread_item_t, context.items)) + { + /* Not found. */ + delete_thread (tp->ptid); + } + } + + /* And now add threads we don't know about yet to our list. */ for (i = 0; VEC_iterate (thread_item_t, context.items, i, item); ++i) @@ -2800,6 +2853,15 @@ remote_threads_info (struct target_ops *ops) } } + if (!got_list) + { + /* If no thread listing method is supported, then query whether + each known thread is alive, one by one, with the T packet. + If the target doesn't support threads at all, then this is a + no-op. See remote_thread_alive. */ + prune_threads (); + } + do_cleanups (old_chain); } @@ -3424,7 +3486,7 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p) controlling. We default to adding them in the running state. The '?' query below will then tell us about which threads are stopped. */ - remote_threads_info (target); + remote_update_thread_list (target); } else if (packet_support (PACKET_QNonStop) == PACKET_ENABLE) { @@ -3476,7 +3538,7 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p) } /* Fetch thread list. */ - target_find_new_threads (); + target_update_thread_list (); /* Let the stub know that we want it to return the thread. */ set_continue_thread (minus_one_ptid); @@ -4446,7 +4508,7 @@ extended_remote_attach_1 (struct target_ops *target, const char *args, struct thread_info *thread; /* Get list of threads. */ - remote_threads_info (target); + remote_update_thread_list (target); thread = first_thread_of_process (pid); if (thread) @@ -11456,7 +11518,7 @@ Specify the serial device it is connected to\n\ remote_ops.to_pass_signals = remote_pass_signals; remote_ops.to_program_signals = remote_program_signals; remote_ops.to_thread_alive = remote_thread_alive; - remote_ops.to_find_new_threads = remote_threads_info; + remote_ops.to_update_thread_list = remote_update_thread_list; remote_ops.to_pid_to_str = remote_pid_to_str; remote_ops.to_extra_thread_info = remote_threads_extra_info; remote_ops.to_get_ada_task_ptid = remote_get_ada_task_ptid;