+2014-10-15  Pedro Alves  <palves@redhat.com>
+
+       * gdbthread.h (ALL_NON_EXITED_THREADS_SAFE): New macro.
+       * remote.c (remote_update_thread_list): Skip calling prune_threads
+       if any thread listing method is supported, and instead walk over
+       the set of remote threads listed, deleting those that are not
+       found in GDB's thread list.
+
 2014-10-15  Pedro Alves  <palves@redhat.com>
 
        * ada-tasks.c (print_ada_task_info, task_command_1): Adjust.
 
   for (T = thread_list; T; T = T->next) \
     if ((T)->state != THREAD_EXITED)
 
+/* Like ALL_NON_EXITED_THREADS, but allows deleting the currently
+   iterated thread.  */
+#define ALL_NON_EXITED_THREADS_SAFE(T, TMP)    \
+  for ((T) = thread_list;                      \
+       (T) != NULL ? ((TMP) = (T)->next, 1): 0;        \
+       (T) = (TMP))                            \
+    if ((T)->state != THREAD_EXITED)
+
 extern int thread_count (void);
 
 /* Switch from one thread to another.  */
 
   struct remote_state *rs = get_remote_state ();
   struct threads_listing_context context;
   struct cleanup *old_chain;
-
-  /* Delete GDB-side threads no longer found on the target.  */
-  prune_threads ();
+  int got_list = 0;
 
   context.items = NULL;
   old_chain = make_cleanup (clear_threads_listing_context, &context);
     {
       int i;
       struct thread_item *item;
+      struct thread_info *tp, *tmp;
+
+      got_list = 1;
+
+      /* 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;
+           }
 
-      /* Now 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)
        }
     }
 
+  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);
 }