+/* Callback for iterate over threads. If the thread is stopped, but
+ the user/frontend doesn't know about that yet, go through
+ normal_stop, as if the thread had just stopped now. ARG points at
+ a ptid. If PTID is MINUS_ONE_PTID, applies to all threads. If
+ ptid_is_pid(PTID) is true, applies to all threads of the process
+ pointed at by PTID. Otherwise, apply only to the thread pointed by
+ PTID. */
+
+static int
+infrun_thread_stop_requested_callback (struct thread_info *info, void *arg)
+{
+ ptid_t ptid = * (ptid_t *) arg;
+
+ if ((ptid_equal (info->ptid, ptid)
+ || ptid_equal (minus_one_ptid, ptid)
+ || (ptid_is_pid (ptid)
+ && ptid_get_pid (ptid) == ptid_get_pid (info->ptid)))
+ && is_running (info->ptid)
+ && !is_executing (info->ptid))
+ {
+ struct cleanup *old_chain;
+ struct execution_control_state ecss;
+ struct execution_control_state *ecs = &ecss;
+
+ memset (ecs, 0, sizeof (*ecs));
+
+ old_chain = make_cleanup_restore_current_thread ();
+
+ switch_to_thread (info->ptid);
+
+ /* Go through handle_inferior_event/normal_stop, so we always
+ have consistent output as if the stop event had been
+ reported. */
+ ecs->ptid = info->ptid;
+ ecs->event_thread = find_thread_ptid (info->ptid);
+ ecs->ws.kind = TARGET_WAITKIND_STOPPED;
+ ecs->ws.value.sig = TARGET_SIGNAL_0;
+
+ handle_inferior_event (ecs);
+
+ if (!ecs->wait_some_more)
+ {
+ struct thread_info *tp;
+
+ normal_stop ();
+
+ /* Finish off the continuations. The continations
+ themselves are responsible for realising the thread
+ didn't finish what it was supposed to do. */
+ tp = inferior_thread ();
+ do_all_intermediate_continuations_thread (tp);
+ do_all_continuations_thread (tp);
+ }
+
+ do_cleanups (old_chain);
+ }
+
+ return 0;
+}
+
+/* This function is attached as a "thread_stop_requested" observer.
+ Cleanup local state that assumed the PTID was to be resumed, and
+ report the stop to the frontend. */
+
+static void
+infrun_thread_stop_requested (ptid_t ptid)
+{
+ struct displaced_step_request *it, *next, *prev = NULL;
+
+ /* PTID was requested to stop. Remove it from the displaced
+ stepping queue, so we don't try to resume it automatically. */
+ for (it = displaced_step_request_queue; it; it = next)
+ {
+ next = it->next;
+
+ if (ptid_equal (it->ptid, ptid)
+ || ptid_equal (minus_one_ptid, ptid)
+ || (ptid_is_pid (ptid)
+ && ptid_get_pid (ptid) == ptid_get_pid (it->ptid)))
+ {
+ if (displaced_step_request_queue == it)
+ displaced_step_request_queue = it->next;
+ else
+ prev->next = it->next;
+
+ xfree (it);
+ }
+ else
+ prev = it;
+ }
+
+ iterate_over_threads (infrun_thread_stop_requested_callback, &ptid);
+}
+
+static void
+infrun_thread_thread_exit (struct thread_info *tp, int silent)
+{
+ if (ptid_equal (target_last_wait_ptid, tp->ptid))
+ nullify_last_target_wait_ptid ();
+}
+
+/* Callback for iterate_over_threads. */
+
+static int
+delete_step_resume_breakpoint_callback (struct thread_info *info, void *data)
+{
+ if (is_exited (info->ptid))
+ return 0;
+
+ delete_step_resume_breakpoint (info);
+ return 0;
+}
+
+/* In all-stop, delete the step resume breakpoint of any thread that
+ had one. In non-stop, delete the step resume breakpoint of the
+ thread that just stopped. */
+
+static void
+delete_step_thread_step_resume_breakpoint (void)
+{
+ if (!target_has_execution
+ || ptid_equal (inferior_ptid, null_ptid))
+ /* If the inferior has exited, we have already deleted the step
+ resume breakpoints out of GDB's lists. */
+ return;
+
+ if (non_stop)
+ {
+ /* If in non-stop mode, only delete the step-resume or
+ longjmp-resume breakpoint of the thread that just stopped
+ stepping. */
+ struct thread_info *tp = inferior_thread ();
+ delete_step_resume_breakpoint (tp);
+ }
+ else
+ /* In all-stop mode, delete all step-resume and longjmp-resume
+ breakpoints of any thread that had them. */
+ iterate_over_threads (delete_step_resume_breakpoint_callback, NULL);
+}
+
+/* A cleanup wrapper. */
+
+static void
+delete_step_thread_step_resume_breakpoint_cleanup (void *arg)
+{
+ delete_step_thread_step_resume_breakpoint ();
+}
+
+/* Pretty print the results of target_wait, for debugging purposes. */
+
+static void
+print_target_wait_results (ptid_t waiton_ptid, ptid_t result_ptid,
+ const struct target_waitstatus *ws)
+{
+ char *status_string = target_waitstatus_to_string (ws);
+ struct ui_file *tmp_stream = mem_fileopen ();
+ char *text;
+ long len;
+
+ /* The text is split over several lines because it was getting too long.
+ Call fprintf_unfiltered (gdb_stdlog) once so that the text is still
+ output as a unit; we want only one timestamp printed if debug_timestamp
+ is set. */
+
+ fprintf_unfiltered (tmp_stream,
+ "infrun: target_wait (%d", PIDGET (waiton_ptid));
+ if (PIDGET (waiton_ptid) != -1)
+ fprintf_unfiltered (tmp_stream,
+ " [%s]", target_pid_to_str (waiton_ptid));
+ fprintf_unfiltered (tmp_stream, ", status) =\n");
+ fprintf_unfiltered (tmp_stream,
+ "infrun: %d [%s],\n",
+ PIDGET (result_ptid), target_pid_to_str (result_ptid));
+ fprintf_unfiltered (tmp_stream,
+ "infrun: %s\n",
+ status_string);
+
+ text = ui_file_xstrdup (tmp_stream, &len);
+
+ /* This uses %s in part to handle %'s in the text, but also to avoid
+ a gcc error: the format attribute requires a string literal. */
+ fprintf_unfiltered (gdb_stdlog, "%s", text);
+
+ xfree (status_string);
+ xfree (text);
+ ui_file_delete (tmp_stream);
+}
+