public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 00/30] Switch interpreters to use virtual methods
@ 2023-05-02 20:49 Simon Marchi
  2023-05-02 20:49 ` [PATCH 01/30] gdb/mi: fix ^running record with multiple MI interpreters Simon Marchi
                   ` (31 more replies)
  0 siblings, 32 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:49 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Interpreters currently get notified of events through observers, usually
doing this pattern:

  SWITCH_THRU_ALL_UIS ()
    {
      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());

      if (mi == NULL)
	continue;

      ...
    }

The example here is for MI interpreters, but the CLI does the same.

This series adds virtual methods to struct interp such that interpreters
get notified of things happening through virtual method calls instead.

The original reason for looking at that area was to fix some unstable
ordering between a breakpoint stop message and a message output in an
observer, related to the amd-dbgapi target.  Pedro suggested this design
change, which solves my ordering problem indirectly, and thought it was
a good idea as well.  The result looks much more like idiomatic C++ than
the original.  In particular, I like that each method implementation, in
mi-interp.c and cli-interp.c, only has to worry about the current
("this") interpreter, removing all those scattered SWITCH_THRU_ALL_UIS
calls.  It also removes the dynamic_casts hidden in as_mi_interp and
as_cli_interp_base.

The testsuite passes fine for me.  One thing I was wondering about is
that the MI interpreter currently has this:

    static struct mi_interp *
    find_mi_interp (void)
    {
      struct mi_interp *mi;

      mi = as_mi_interp (top_level_interpreter ());
      if (mi != NULL)
        return mi;

      mi = as_mi_interp (command_interp ());
      if (mi != NULL)
        return mi;

      return NULL;
    }

So, find_mi_interp sometimes returns the command_interp, if it's an MI
interpreter.  In my series, however, I only ever notify the top level
interpreter, using this templated function:

    /* Helper interps_notify_* functions.  Call METHOD on the top-level interpreter
       of all UIs.  */

    template <typename ...Args>
    void
    interps_notify (void (interp::*method) (Args...), Args... args)
    {
      SWITCH_THRU_ALL_UIS ()
        {
          interp *tli = top_level_interpreter ();
          if (tli != nullptr)
            (tli->*method) (args...);
        }
    }

I was wondering if I had to notify the command_interpreter at some
point.  Butwever I was not able to find a behavior change related to
this, caused by my series.  command_interpreter is set (temporarily) by
interp_exec, so in order to have an MI interpreter as the command
interpreter, you'd have to use an `interpreter-exec mi ...` command in
the CLI.

find_mi_interp is only used in a few observers observers that react to
target wait events (like mi_on_signal_received).  When I do, for
instance:

  (gdb) interpreter-exec mi -exec-continue

... then the command_interpreter is only set for the duration of the
-exec-continue command, which does not include consuming and handling
the target event.  Even with a synchronous target, the "wait" part is
done outside the continue command, after coming back to the event loop,
since 0b333c5e7d6c:

    @@ -3094,15 +3102,11 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)

       discard_cleanups (old_chain);

    -  /* Wait for it to stop (if not standalone)
    -     and in any case decode why it stopped, and act accordingly.  */
    -  /* Do this only if we are not using the event loop, or if the target
    -     does not support asynchronous execution.  */
    +  /* Tell the event loop to wait for it to stop.  If the target
    +     supports asynchronous execution, it'll do this from within
    +     target_resume.  */
       if (!target_can_async_p ())
    -    {
    -      wait_for_inferior ();
    -      normal_stop ();
    -    }
    +    mark_async_event_handler (infrun_async_inferior_event_token);
     }

This means that all the observers using find_mi_interp are called when
we are back at the event loop, after command_interpreter has been
reset.  And that would explain why my change looks good, despite never
notifying the command_interpreter.

Other than that, the first patch is a bug fix, fixing a problem I
noticed along the way.

Simon Marchi (30):
  gdb/mi: fix ^running record with multiple MI interpreters
  gdb/mi: make current_token a field of mi_interp
  gdb: add interp::on_signal_received method
  gdb: add interp::on_normal_stop method
  gdb: add interp::on_signal_exited method
  gdb: add interp::on_exited method
  gdb: add interp::on_no_history method
  gdb: add interp::on_sync_execution_done method
  gdb: add interp::on_command_error method
  gdb: add interp::on_user_selected_context_changed method
  gdb: add interp::on_new_thread method
  gdb: add interp::on_thread_exited method
  gdb: add interp::on_inferior_added method
  gdb: add interp::on_inferior_appeared method
  gdb: add interp::on_inferior_disappeared method
  gdb: add interp::on_inferior_removed method
  gdb: add interp::on_record_changed method
  gdb: add interp::on_target_resumed method
  gdb: add interp::on_solib_loaded method
  gdb: add interp::on_solib_unloaded method
  gdb: add interp::on_about_to_proceed method
  gdb: add interp::on_traceframe_changed method
  gdb: add interp::on_tsv_created method
  gdb: add interp::on_tsv_deleted method
  gdb: add interp::on_tsv_modified method
  gdb: add interp::on_breakpoint_created method
  gdb: add interp::on_breakpoint_deleted method
  gdb: add interp::on_breakpoint_modified method
  gdb: add interp::on_param_changed method
  gdb: add interp::on_memory_changed method

 gdb/breakpoint.c                             |  70 +-
 gdb/breakpoint.h                             |   5 +
 gdb/cli/cli-interp.c                         | 149 +--
 gdb/cli/cli-interp.h                         |   9 +
 gdb/cli/cli-setshow.c                        |  13 +-
 gdb/corefile.c                               |  13 +-
 gdb/inferior.c                               |  49 +-
 gdb/infrun.c                                 |  61 +-
 gdb/infrun.h                                 |  11 +
 gdb/interps.c                                | 217 +++++
 gdb/interps.h                                | 197 ++++
 gdb/main.c                                   |   2 +-
 gdb/mi/mi-cmd-break.c                        |   2 +-
 gdb/mi/mi-interp.c                           | 898 ++++++-------------
 gdb/mi/mi-interp.h                           |  39 +
 gdb/mi/mi-main.c                             |  33 +-
 gdb/mi/mi-main.h                             |   5 -
 gdb/observable.c                             |  11 -
 gdb/observable.h                             |  50 --
 gdb/record-btrace.c                          |   3 +-
 gdb/record-full.c                            |   3 +-
 gdb/record.c                                 |   3 +-
 gdb/remote.c                                 |   5 +-
 gdb/solib.c                                  |  24 +-
 gdb/source.c                                 |   5 +-
 gdb/stack.c                                  |   8 +-
 gdb/testsuite/gdb.mi/run-with-two-mi-uis.c   |   7 +
 gdb/testsuite/gdb.mi/run-with-two-mi-uis.exp |  67 ++
 gdb/testsuite/lib/mi-support.exp             |  26 +-
 gdb/thread.c                                 |  44 +-
 gdb/tracepoint.c                             |  17 +-
 31 files changed, 1109 insertions(+), 937 deletions(-)
 create mode 100644 gdb/testsuite/gdb.mi/run-with-two-mi-uis.c
 create mode 100644 gdb/testsuite/gdb.mi/run-with-two-mi-uis.exp

-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 01/30] gdb/mi: fix ^running record with multiple MI interpreters
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
@ 2023-05-02 20:49 ` Simon Marchi
  2023-05-03 14:42   ` Alexandra Petlanova Hajkova
  2023-05-29 14:53   ` Simon Marchi
  2023-05-02 20:49 ` [PATCH 02/30] gdb/mi: make current_token a field of mi_interp Simon Marchi
                   ` (30 subsequent siblings)
  31 siblings, 2 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:49 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

I stumbled on the mi_proceeded and running_result_record_printed
globals, which are shared by all MI interpreter instances (it's unlikely
that people use multiple MI interpreter instances, but it's possible).
After poking at it, I found this bug:

1. Start GDB in MI mode
2. Add a second MI interpreter with the new-ui command
3. Use -exec-run on the second interpreter

This is the output I get on the first interpreter:

    =thread-group-added,id="i1"
    ~"Reading symbols from a.out...\n"
    ~"New UI allocated\n"
    (gdb)
    =thread-group-started,id="i1",pid="94718"
    =thread-created,id="1",group-id="i1"
    ^running
    *running,thread-id="all"

And this is the output I get on the second intepreter:

    =thread-group-added,id="i1"
    (gdb)
    -exec-run
    =thread-group-started,id="i1",pid="94718"
    =thread-created,id="1",group-id="i1"
    *running,thread-id="all"

The problem here is that the `^running` reply to the -exec-run command
is printed on the wrong UI.  It is printed on the first one, it should
be printed on the second (the one on which we sent the -exec-run).

What happens under the hood is that captured_mi_execute_command, while
executing a command for the second intepreter, clears the
running_result_record_printed and mi_proceeded globals.
mi_about_to_proceed then sets mi_proceeded.  Then, mi_on_resume_1 gets
called for the first intepreter first.  Since the

    !running_result_record_printed && mi_proceeded

condition is true, it prints a ^running, and sets
running_result_record_printed.  When mi_on_resume_1 gets called for the
second interpreter, running_result_record_printed is already set, so
^running is not printed there.

It took me a while to understand the relationship between these two
variables.  I think that in the end, this is what we want to track:

 1. When executing an MI command, take note if that command causes a
    "proceed".  This is done in mi_about_to_proceed.
 2. In mi_on_resume_1, if the command indeed caused a "proceed", we want
    to output a ^running record.  And we want to remember that we did,
    because...
 3. Back in captured_mi_execute_command, if we did not output a
    ^running, we want to output a ^done.

Moving those two variables to the mi_interp struture appears to fix it.
Only for the interpreter doing the -exec-run command does the
running_result_record_printed flag get cleared, and therefore only or
that one does the ^running record get printed.

Add a new test for this, that does pretty much what the reproducer above
shows.  Without the fix, the test fails because
mi_send_resuming_command_raw never sees the ^running record.

Change-Id: I63ea30e6cb61a8e1dd5ef03377e6003381a9209b
---
 gdb/mi/mi-interp.c                           | 13 ++--
 gdb/mi/mi-interp.h                           |  6 ++
 gdb/mi/mi-main.c                             | 14 ++--
 gdb/mi/mi-main.h                             |  3 -
 gdb/testsuite/gdb.mi/run-with-two-mi-uis.c   |  7 ++
 gdb/testsuite/gdb.mi/run-with-two-mi-uis.exp | 67 ++++++++++++++++++++
 gdb/testsuite/lib/mi-support.exp             | 26 +++++---
 7 files changed, 111 insertions(+), 25 deletions(-)
 create mode 100644 gdb/testsuite/gdb.mi/run-with-two-mi-uis.c
 create mode 100644 gdb/testsuite/gdb.mi/run-with-two-mi-uis.exp

diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index ad33a21374ab..7d8dfd830a4f 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -676,7 +676,12 @@ mi_about_to_proceed (void)
 	return;
     }
 
-  mi_proceeded = 1;
+  mi_interp *mi = as_mi_interp (top_level_interpreter ());
+
+  if (mi == nullptr)
+    return;
+
+  mi->mi_proceeded = 1;
 }
 
 /* When the element is non-zero, no MI notifications will be emitted in
@@ -960,7 +965,7 @@ mi_on_resume_1 (struct mi_interp *mi,
      will make it impossible for frontend to know what's going on.
 
      In future (MI3), we'll be outputting "^done" here.  */
-  if (!running_result_record_printed && mi_proceeded)
+  if (!mi->running_result_record_printed && mi->mi_proceeded)
     {
       gdb_printf (mi->raw_stdout, "%s^running\n",
 		  current_token ? current_token : "");
@@ -976,9 +981,9 @@ mi_on_resume_1 (struct mi_interp *mi,
     for (thread_info *tp : all_non_exited_threads (targ, ptid))
       mi_output_running (tp);
 
-  if (!running_result_record_printed && mi_proceeded)
+  if (!mi->running_result_record_printed && mi->mi_proceeded)
     {
-      running_result_record_printed = 1;
+      mi->running_result_record_printed = 1;
       /* This is what gdb used to do historically -- printing prompt
 	 even if it cannot actually accept any input.  This will be
 	 surely removed for MI3, and may be removed even earlier.  */
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index e07be12f87ac..eb81cbe6cada 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -64,6 +64,12 @@ class mi_interp final : public interp
 
   /* MI's CLI builder (wraps OUT).  */
   struct ui_out *cli_uiout;
+
+  int running_result_record_printed = 1;
+
+  /* Flag indicating that the target has proceeded since the last
+     command was issued.  */
+  int mi_proceeded;
 };
 
 /* Output the shared object attributes to UIOUT.  */
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index 35c74c407ee8..ab9184bc3585 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -84,12 +84,6 @@ char *current_token;
    command including all option, and make it possible.  */
 static struct mi_parse *current_context;
 
-int running_result_record_printed = 1;
-
-/* Flag indicating that the target has proceeded since the last
-   command was issued.  */
-int mi_proceeded;
-
 static void mi_cmd_execute (struct mi_parse *parse);
 
 static void mi_execute_async_cli_command (const char *cli_command,
@@ -1803,8 +1797,8 @@ captured_mi_execute_command (struct ui_out *uiout, struct mi_parse *context)
   scoped_restore save_token = make_scoped_restore (&current_token,
 						   context->token);
 
-  running_result_record_printed = 0;
-  mi_proceeded = 0;
+  mi->running_result_record_printed = 0;
+  mi->mi_proceeded = 0;
   switch (context->op)
     {
     case MI_COMMAND:
@@ -1822,7 +1816,7 @@ captured_mi_execute_command (struct ui_out *uiout, struct mi_parse *context)
 	 to directly use the mi_interp's uiout, since the command
 	 could have reset the interpreter, in which case the current
 	 uiout will most likely crash in the mi_out_* routines.  */
-      if (!running_result_record_printed)
+      if (!mi->running_result_record_printed)
 	{
 	  gdb_puts (context->token, mi->raw_stdout);
 	  /* There's no particularly good reason why target-connect results
@@ -1861,7 +1855,7 @@ captured_mi_execute_command (struct ui_out *uiout, struct mi_parse *context)
 	    || current_interp_named_p (INTERP_MI3)
 	    || current_interp_named_p (INTERP_MI4))
 	  {
-	    if (!running_result_record_printed)
+	    if (!mi->running_result_record_printed)
 	      {
 		gdb_puts (context->token, mi->raw_stdout);
 		gdb_puts ("^done", mi->raw_stdout);
diff --git a/gdb/mi/mi-main.h b/gdb/mi/mi-main.h
index ff1d4ed84bc8..b9fe295d3306 100644
--- a/gdb/mi/mi-main.h
+++ b/gdb/mi/mi-main.h
@@ -36,9 +36,6 @@ extern int mi_async_p (void);
 
 extern char *current_token;
 
-extern int running_result_record_printed;
-extern int mi_proceeded;
-
 struct mi_suppress_notification
 {
   /* Breakpoint notification suppressed?  */
diff --git a/gdb/testsuite/gdb.mi/run-with-two-mi-uis.c b/gdb/testsuite/gdb.mi/run-with-two-mi-uis.c
new file mode 100644
index 000000000000..1e2428e0d544
--- /dev/null
+++ b/gdb/testsuite/gdb.mi/run-with-two-mi-uis.c
@@ -0,0 +1,7 @@
+#include <unistd.h>
+
+int
+main (void)
+{
+  sleep (1234);
+}
diff --git a/gdb/testsuite/gdb.mi/run-with-two-mi-uis.exp b/gdb/testsuite/gdb.mi/run-with-two-mi-uis.exp
new file mode 100644
index 000000000000..9a049c98ea7a
--- /dev/null
+++ b/gdb/testsuite/gdb.mi/run-with-two-mi-uis.exp
@@ -0,0 +1,67 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test doing an -exec-run while there are two MI UIs.
+
+load_lib mi-support.exp
+
+standard_testfile
+
+if {[build_executable $testfile.exp $testfile ${srcfile} "debug"] == -1} {
+    untested "failed to compile"
+    return
+}
+
+# Run one configuration of the test.
+#
+# UI_TO_RUN is the UI that should issue the run command.
+
+proc do_test { ui_to_run } {
+    if {[mi_clean_restart $::binfile "separate-mi-tty"] != 0} {
+	fail "could not start gdb"
+	return
+    }
+
+    with_spawn_id $::gdb_main_spawn_id {
+	lassign [create_mi_ui] second_mi_spawn_id second_mi_tty_name
+    }
+
+    with_spawn_id $second_mi_spawn_id {
+	gdb_expect {
+	    -re "=thread-group-added,id=\"i1\"\r\n$::mi_gdb_prompt$" {
+		pass "consume"
+	    }
+	}
+    }
+
+    if { $ui_to_run == "first" } {
+	set spawn_id_to_run $::mi_spawn_id
+    } elseif { $ui_to_run == "second" } {
+	set spawn_id_to_run $second_mi_spawn_id
+    } else {
+	error "invalid ui_to_run value"
+    }
+
+    with_spawn_id $spawn_id_to_run {
+	# mi_runto_main implicitly verifies that the UI doing the -exec-run gets
+	# the expected ^running record.
+	mi_runto_main
+    }
+}
+
+foreach_with_prefix ui_to_run {first second} {
+    do_test $ui_to_run
+}
+
diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp
index 0d830d8e4ae5..2ff4ab93ea82 100644
--- a/gdb/testsuite/lib/mi-support.exp
+++ b/gdb/testsuite/lib/mi-support.exp
@@ -131,6 +131,21 @@ proc mi_create_inferior_pty {} {
     }
 }
 
+# Create a new pty, and reate a new MI UI (using the new-ui command) on it.
+#
+# Return a list with the spawn id for that pty and the pty file name.
+
+proc create_mi_ui {} {
+    spawn -pty
+    set tty_name $spawn_out(slave,name)
+    gdb_test_multiple "new-ui mi $tty_name" "new-ui" {
+	-re "New UI allocated\r\n$::gdb_prompt $" {
+	}
+    }
+
+    return [list $spawn_id $tty_name]
+}
+
 #
 # Like default_mi_gdb_start below, but the MI is created as a separate
 # ui in a new tty.  The global MI_SPAWN_ID is updated to point at the
@@ -154,13 +169,7 @@ proc mi_gdb_start_separate_mi_tty { { flags {} } } {
     gdb_start
 
     # Create the new PTY for the MI UI.
-    spawn -pty
-    set mi_spawn_id $spawn_id
-    set mi_tty_name $spawn_out(slave,name)
-    gdb_test_multiple "new-ui mi $mi_tty_name" "new-ui" {
-	-re "New UI allocated\r\n$gdb_prompt $" {
-	}
-    }
+    lassign [create_mi_ui] mi_spawn_id mi_tty_name
 
     # Switch to the MI channel.
     set gdb_main_spawn_id $gdb_spawn_id
@@ -822,7 +831,7 @@ proc mi_gdb_test { args } {
 	    fail "$errmsg"
 	    return -1
 	}
-	 -re ".*$mi_gdb_prompt\[ \]*$" {
+	 -re "(.*$mi_gdb_prompt\[ \]*)$" {
 	    if {![string match "" $message]} {
 		fail "$message (unexpected output)"
 	    }
@@ -1082,6 +1091,7 @@ proc mi_runto_helper {func run_or_continue args} {
       # file.", etc. to the CLI stream.
       set extra_output "&\"\[^\r\n\]+\"\r\n"
   }
+
   mi_gdb_test "200-break-insert [join $extra_opts " "] -t $func" "${extra_output}200\\^done,$bp" \
       "breakpoint at $func"
 
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 02/30] gdb/mi: make current_token a field of mi_interp
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
  2023-05-02 20:49 ` [PATCH 01/30] gdb/mi: fix ^running record with multiple MI interpreters Simon Marchi
@ 2023-05-02 20:49 ` Simon Marchi
  2023-05-04 12:31   ` Alexandra Petlanova Hajkova
  2023-05-02 20:49 ` [PATCH 03/30] gdb: add interp::on_signal_received method Simon Marchi
                   ` (29 subsequent siblings)
  31 siblings, 1 reply; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:49 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Following the previous patch, I thought it would make sense to make
current_token a field of mi_interp.  This variable contains the token of
the currently handled MI command, like the 222 in:

    222-exec-continue

I didn't find any bug related to that, it's just a "that seems nicer"
cleanup, since the current token is a fundamentally per-interp thing.
There should be no user-visible change.

Change-Id: Ib52b3c0cba4b7c9d805b432c809692a86e4945ad
---
 gdb/mi/mi-interp.c |  2 +-
 gdb/mi/mi-interp.h |  2 ++
 gdb/mi/mi-main.c   | 17 ++++++++---------
 gdb/mi/mi-main.h   |  2 --
 4 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 7d8dfd830a4f..b791d6b9a2d3 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -968,7 +968,7 @@ mi_on_resume_1 (struct mi_interp *mi,
   if (!mi->running_result_record_printed && mi->mi_proceeded)
     {
       gdb_printf (mi->raw_stdout, "%s^running\n",
-		  current_token ? current_token : "");
+		  mi->current_token ? mi->current_token : "");
     }
 
   /* Backwards compatibility.  If doing a wildcard resume and there's
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index eb81cbe6cada..2d3a0013d4b0 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -70,6 +70,8 @@ class mi_interp final : public interp
   /* Flag indicating that the target has proceeded since the last
      command was issued.  */
   int mi_proceeded;
+
+  const char *current_token;
 };
 
 /* Output the shared object attributes to UIOUT.  */
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index ab9184bc3585..1be5d3becfcf 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -78,7 +78,6 @@ static struct mi_timestamp *current_command_ts;
 
 static int do_timings = 0;
 
-char *current_token;
 /* Few commands would like to know if options like --thread-group were
    explicitly specified.  This variable keeps the current parsed
    command including all option, and make it possible.  */
@@ -147,8 +146,8 @@ mi_cmd_gdb_exit (const char *command, char **argv, int argc)
   struct mi_interp *mi = (struct mi_interp *) current_interpreter ();
 
   /* We have to print everything right here because we never return.  */
-  if (current_token)
-    gdb_puts (current_token, mi->raw_stdout);
+  if (mi->current_token)
+    gdb_puts (mi->current_token, mi->raw_stdout);
   gdb_puts ("^exit\n", mi->raw_stdout);
   mi_out_put (current_uiout, mi->raw_stdout);
   gdb_flush (mi->raw_stdout);
@@ -1794,8 +1793,8 @@ captured_mi_execute_command (struct ui_out *uiout, struct mi_parse *context)
   if (do_timings)
     current_command_ts = context->cmd_start;
 
-  scoped_restore save_token = make_scoped_restore (&current_token,
-						   context->token);
+  scoped_restore save_token
+    = make_scoped_restore (&mi->current_token, context->token);
 
   mi->running_result_record_printed = 0;
   mi->mi_proceeded = 0;
@@ -2178,8 +2177,8 @@ mi_load_progress (const char *section_name,
       xfree (previous_sect_name);
       previous_sect_name = xstrdup (section_name);
 
-      if (current_token)
-	gdb_puts (current_token, mi->raw_stdout);
+      if (mi->current_token)
+	gdb_puts (mi->current_token, mi->raw_stdout);
       gdb_puts ("+download", mi->raw_stdout);
       {
 	ui_out_emit_tuple tuple_emitter (uiout.get (), NULL);
@@ -2196,8 +2195,8 @@ mi_load_progress (const char *section_name,
   if (time_now - last_update > milliseconds (500))
     {
       last_update = time_now;
-      if (current_token)
-	gdb_puts (current_token, mi->raw_stdout);
+      if (mi->current_token)
+	gdb_puts (mi->current_token, mi->raw_stdout);
       gdb_puts ("+download", mi->raw_stdout);
       {
 	ui_out_emit_tuple tuple_emitter (uiout.get (), NULL);
diff --git a/gdb/mi/mi-main.h b/gdb/mi/mi-main.h
index b9fe295d3306..119bb6111385 100644
--- a/gdb/mi/mi-main.h
+++ b/gdb/mi/mi-main.h
@@ -34,8 +34,6 @@ extern void mi_print_timing_maybe (struct ui_file *file);
 
 extern int mi_async_p (void);
 
-extern char *current_token;
-
 struct mi_suppress_notification
 {
   /* Breakpoint notification suppressed?  */
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 03/30] gdb: add interp::on_signal_received method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
  2023-05-02 20:49 ` [PATCH 01/30] gdb/mi: fix ^running record with multiple MI interpreters Simon Marchi
  2023-05-02 20:49 ` [PATCH 02/30] gdb/mi: make current_token a field of mi_interp Simon Marchi
@ 2023-05-02 20:49 ` Simon Marchi
  2023-05-04 14:38   ` Alexandra Petlanova Hajkova
  2023-05-02 20:49 ` [PATCH 04/30] gdb: add interp::on_normal_stop method Simon Marchi
                   ` (28 subsequent siblings)
  31 siblings, 1 reply; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:49 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Instead of having the interpreter code registering observers for the
signal_received observable, add a "signal_received" virtual method to
struct interp.  Add a interps_notify_signal_received function that loops
over all UIs and calls the signal_received method on the interpreter.
Finally, add a notify_signal_received function that calls
interps_notify_signal_received and then notifies the observers.  Replace
all existing notifications to the signal_received observers with calls
to notify_signal_received.

Before this patch, the CLI and MI code both register a signal_received
observer.  These observer go over all UIs, and, for those that have a
interpreter of the right kind, print the stop notifiation.

After this patch, we have just one "loop over all UIs", inside
interps_notify_signal_received.  Since the interp::on_signal_received
method gets called once for each interpreter, the implementations only
need to deal with the current interpreter (the "this" pointer).

The motivation for this patch comes from a future patch, that makes the
amdgpu code register an observer to print a warning after the CLI's
signal stop message.  Since the amdgpu and the CLI code both use
observers, the order of the two messages is not stable, unless we define
the priority using the observer dependency system.  However, the
approach of using virtual methods on the interpreters seems like a good
change anyway, I think it's more straightforward and simple to
understand than the current solution that uses observers.  We are sure
that the amdgpu message gets printed after the CLI message, since
observers are notified after interpreters.

Keep the signal_received, even if nothing uses if, because we will be
using it in the upcoming amdgpu patch implementing the warning described
above.

Change-Id: I4d8614bb8f6e0717f4bfc2a59abded3702f23ac4
---
 gdb/cli/cli-interp.c | 17 +++--------------
 gdb/cli/cli-interp.h |  2 ++
 gdb/infrun.c         | 14 ++++++++++++--
 gdb/infrun.h         |  4 ++++
 gdb/interps.c        | 23 +++++++++++++++++++++++
 gdb/interps.h        |  8 ++++++++
 gdb/mi/mi-interp.c   | 20 ++++----------------
 gdb/mi/mi-interp.h   |  2 ++
 gdb/remote.c         |  2 +-
 9 files changed, 59 insertions(+), 33 deletions(-)

diff --git a/gdb/cli/cli-interp.c b/gdb/cli/cli-interp.c
index 84fe34a10148..51c78d96ee20 100644
--- a/gdb/cli/cli-interp.c
+++ b/gdb/cli/cli-interp.c
@@ -137,19 +137,10 @@ cli_base_on_normal_stop (struct bpstat *bs, int print_frame)
     }
 }
 
-/* Observer for the signal_received notification.  */
-
-static void
-cli_base_on_signal_received (enum gdb_signal siggnal)
+void
+cli_interp_base::on_signal_received (enum gdb_signal siggnal)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      cli_interp_base *cli = as_cli_interp_base (top_level_interpreter ());
-      if (cli == nullptr)
-	continue;
-
-      print_signal_received_reason (cli->interp_ui_out (), siggnal);
-    }
+  print_signal_received_reason (this->interp_ui_out (), siggnal);
 }
 
 /* Observer for the signalled notification.  */
@@ -408,8 +399,6 @@ _initialize_cli_interp ()
   /* Note these all work for both the CLI and TUI interpreters.  */
   gdb::observers::normal_stop.attach (cli_base_on_normal_stop,
 				      "cli-interp-base");
-  gdb::observers::signal_received.attach (cli_base_on_signal_received,
-					  "cli-interp-base");
   gdb::observers::signal_exited.attach (cli_base_on_signal_exited,
 					"cli-interp-base");
   gdb::observers::exited.attach (cli_base_on_exited, "cli-interp-base");
diff --git a/gdb/cli/cli-interp.h b/gdb/cli/cli-interp.h
index 5ed998f58bd5..f7bee4530b42 100644
--- a/gdb/cli/cli-interp.h
+++ b/gdb/cli/cli-interp.h
@@ -33,6 +33,8 @@ class cli_interp_base : public interp
   void pre_command_loop () override;
   bool supports_command_editing () override;
 
+  void on_signal_received (gdb_signal sig) override;
+
 private:
   struct saved_output_files
   {
diff --git a/gdb/infrun.c b/gdb/infrun.c
index efe2c00c489a..4716d73571c5 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -76,6 +76,7 @@
 #include "gdbsupport/buildargv.h"
 #include "extension.h"
 #include "disasm.h"
+#include "interps.h"
 
 /* Prototypes for local functions */
 
@@ -6263,6 +6264,15 @@ finish_step_over (struct execution_control_state *ecs)
   return 0;
 }
 
+/* See infrun.h.  */
+
+void
+notify_signal_received (gdb_signal sig)
+{
+  interps_notify_signal_received (sig);
+  gdb::observers::signal_received.notify (sig);
+}
+
 /* Come here when the program has stopped with a signal.  */
 
 static void
@@ -6686,7 +6696,7 @@ handle_signal_stop (struct execution_control_state *ecs)
 	{
 	  /* The signal table tells us to print about this signal.  */
 	  target_terminal::ours_for_output ();
-	  gdb::observers::signal_received.notify (ecs->event_thread->stop_signal ());
+	  notify_signal_received (ecs->event_thread->stop_signal ());
 	  target_terminal::inferior ();
 	}
 
@@ -8828,7 +8838,7 @@ normal_stop ()
   update_thread_list ();
 
   if (last.kind () == TARGET_WAITKIND_STOPPED && stopped_by_random_signal)
-    gdb::observers::signal_received.notify (inferior_thread ()->stop_signal ());
+    notify_signal_received (inferior_thread ()->stop_signal ());
 
   /* As with the notification of thread events, we want to delay
      notifying the user that we've switched thread context until
diff --git a/gdb/infrun.h b/gdb/infrun.h
index 9513bc570e46..f7b60a4d9fb7 100644
--- a/gdb/infrun.h
+++ b/gdb/infrun.h
@@ -210,6 +210,10 @@ extern void set_step_info (thread_info *tp,
 			   frame_info_ptr frame,
 			   struct symtab_and_line sal);
 
+/* Notify interpreters and observers that the current inferior has stopped with
+   signal SIG.  */
+extern void notify_signal_received (gdb_signal sig);
+
 /* Several print_*_reason helper functions to print why the inferior
    has stopped to the passed in UIOUT.  */
 
diff --git a/gdb/interps.c b/gdb/interps.c
index e3f6ee685123..5d061ad52aff 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -383,6 +383,29 @@ current_interpreter (void)
   return current_ui->current_interpreter;
 }
 
+/* Helper interps_notify_* functions.  Call METHOD on the top-level interpreter
+   of all UIs.  */
+
+template <typename ...Args>
+void
+interps_notify (void (interp::*method) (Args...), Args... args)
+{
+  SWITCH_THRU_ALL_UIS ()
+    {
+      interp *tli = top_level_interpreter ();
+      if (tli != nullptr)
+	(tli->*method) (args...);
+    }
+}
+
+/* See interps.h.  */
+
+void
+interps_notify_signal_received (gdb_signal sig)
+{
+  interps_notify (&interp::on_signal_received, sig);
+}
+
 /* This just adds the "interpreter-exec" command.  */
 void _initialize_interpreter ();
 void
diff --git a/gdb/interps.h b/gdb/interps.h
index da78a5d89fae..4762c4c93ff1 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -82,6 +82,10 @@ class interp : public intrusive_list_node<interp>
   const char *name () const
   { return m_name; }
 
+  /* Notify the interpreter that the current inferior has stopped with signal
+     SIG.  */
+  virtual void on_signal_received (gdb_signal sig) {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
@@ -170,6 +174,10 @@ extern void interpreter_completer (struct cmd_list_element *ignore,
 				   const char *text,
 				   const char *word);
 
+/* Notify all interpreters that the current inferior has stopped with signal
+   SIG.  */
+extern void interps_notify_signal_received (gdb_signal sig);
+
 /* well-known interpreters */
 #define INTERP_CONSOLE		"console"
 #define INTERP_MI2             "mi2"
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index b791d6b9a2d3..43e49a9b94af 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -60,7 +60,6 @@ static int mi_interp_query_hook (const char *ctlstr, va_list ap)
 static void mi_insert_notify_hooks (void);
 static void mi_remove_notify_hooks (void);
 
-static void mi_on_signal_received (enum gdb_signal siggnal);
 static void mi_on_signal_exited (enum gdb_signal siggnal);
 static void mi_on_exited (int exitstatus);
 static void mi_on_normal_stop (struct bpstat *bs, int print_frame);
@@ -524,21 +523,11 @@ find_mi_interp (void)
    inferior has stopped to both the MI event channel and to the MI
    console.  If the MI interpreter is not active, print nothing.  */
 
-/* Observer for the signal_received notification.  */
-
-static void
-mi_on_signal_received (enum gdb_signal siggnal)
+void
+mi_interp::on_signal_received (enum gdb_signal siggnal)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = find_mi_interp ();
-
-      if (mi == NULL)
-	continue;
-
-      print_signal_received_reason (mi->mi_uiout, siggnal);
-      print_signal_received_reason (mi->cli_uiout, siggnal);
-    }
+  print_signal_received_reason (this->mi_uiout, siggnal);
+  print_signal_received_reason (this->cli_uiout, siggnal);
 }
 
 /* Observer for the signal_exited notification.  */
@@ -1303,7 +1292,6 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
 
-  gdb::observers::signal_received.attach (mi_on_signal_received, "mi-interp");
   gdb::observers::signal_exited.attach (mi_on_signal_exited, "mi-interp");
   gdb::observers::exited.attach (mi_on_exited, "mi-interp");
   gdb::observers::no_history.attach (mi_on_no_history, "mi-interp");
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index 2d3a0013d4b0..75c17568d6fc 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -42,6 +42,8 @@ class mi_interp final : public interp
 		    bool debug_redirect) override;
   void pre_command_loop () override;
 
+  void on_signal_received (gdb_signal sig) override;
+
   /* MI's output channels */
   mi_console_file *out;
   mi_console_file *err;
diff --git a/gdb/remote.c b/gdb/remote.c
index 8eaa1b2c4d15..829cdbdef757 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -4720,7 +4720,7 @@ remote_target::print_one_stopped_thread (thread_info *thread)
       enum gdb_signal sig = ws.sig ();
 
       if (signal_print_state (sig))
-	gdb::observers::signal_received.notify (sig);
+	notify_signal_received (sig);
     }
   gdb::observers::normal_stop.notify (NULL, 1);
 }
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 04/30] gdb: add interp::on_normal_stop method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (2 preceding siblings ...)
  2023-05-02 20:49 ` [PATCH 03/30] gdb: add interp::on_signal_received method Simon Marchi
@ 2023-05-02 20:49 ` Simon Marchi
  2023-05-02 20:49 ` [PATCH 05/30] gdb: add interp::on_signal_exited method Simon Marchi
                   ` (27 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:49 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same idea as the previous patch, but for the normal_stop event.

Change-Id: I4fc8ca8a51c63829dea390a2b6ce30b77f9fb863
---
 gdb/cli/cli-interp.c | 21 +++++-------------
 gdb/cli/cli-interp.h |  1 +
 gdb/infrun.c         | 19 +++++++++++------
 gdb/infrun.h         |  4 ++++
 gdb/interps.c        |  8 +++++++
 gdb/interps.h        |  7 ++++++
 gdb/mi/mi-interp.c   | 51 ++++++++++++++------------------------------
 gdb/mi/mi-interp.h   |  1 +
 gdb/remote.c         |  3 ++-
 9 files changed, 57 insertions(+), 58 deletions(-)

diff --git a/gdb/cli/cli-interp.c b/gdb/cli/cli-interp.c
index 51c78d96ee20..9508171e87d5 100644
--- a/gdb/cli/cli-interp.c
+++ b/gdb/cli/cli-interp.c
@@ -112,10 +112,8 @@ should_print_stop_to_console (struct interp *console_interp,
    interpreter-exec), print nothing.  These are named "cli_base" as
    they print to both CLI interpreters and TUI interpreters.  */
 
-/* Observer for the normal_stop notification.  */
-
-static void
-cli_base_on_normal_stop (struct bpstat *bs, int print_frame)
+void
+cli_interp_base::on_normal_stop (struct bpstat *bs, int print_frame)
 {
   if (!print_frame)
     return;
@@ -124,17 +122,10 @@ cli_base_on_normal_stop (struct bpstat *bs, int print_frame)
   if (cli_suppress_notification.normal_stop)
     return;
 
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct interp *interp = top_level_interpreter ();
-      cli_interp_base *cli = as_cli_interp_base (interp);
-      if (cli == nullptr)
-	continue;
+  thread_info *thread = inferior_thread ();
+  if (should_print_stop_to_console (this, thread))
+    print_stop_event (this->interp_ui_out ());
 
-      thread_info *thread = inferior_thread ();
-      if (should_print_stop_to_console (interp, thread))
-	print_stop_event (cli->interp_ui_out ());
-    }
 }
 
 void
@@ -397,8 +388,6 @@ _initialize_cli_interp ()
   interp_factory_register (INTERP_CONSOLE, cli_interp_factory);
 
   /* Note these all work for both the CLI and TUI interpreters.  */
-  gdb::observers::normal_stop.attach (cli_base_on_normal_stop,
-				      "cli-interp-base");
   gdb::observers::signal_exited.attach (cli_base_on_signal_exited,
 					"cli-interp-base");
   gdb::observers::exited.attach (cli_base_on_exited, "cli-interp-base");
diff --git a/gdb/cli/cli-interp.h b/gdb/cli/cli-interp.h
index f7bee4530b42..4fca801d4fd6 100644
--- a/gdb/cli/cli-interp.h
+++ b/gdb/cli/cli-interp.h
@@ -34,6 +34,7 @@ class cli_interp_base : public interp
   bool supports_command_editing () override;
 
   void on_signal_received (gdb_signal sig) override;
+  void on_normal_stop(bpstat *bs, int print_frame) override;
 
 private:
   struct saved_output_files
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 4716d73571c5..8fa2cacc4149 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -6273,6 +6273,15 @@ notify_signal_received (gdb_signal sig)
   gdb::observers::signal_received.notify (sig);
 }
 
+/* See infrun.h.  */
+
+void
+notify_normal_stop (bpstat *bs, int print_frame)
+{
+  interps_notify_normal_stop (bs, print_frame);
+  gdb::observers::normal_stop.notify (bs, print_frame);
+}
+
 /* Come here when the program has stopped with a signal.  */
 
 static void
@@ -8955,12 +8964,10 @@ normal_stop ()
 
   /* Notify observers about the stop.  This is where the interpreters
      print the stop event.  */
-  if (inferior_ptid != null_ptid)
-    gdb::observers::normal_stop.notify (inferior_thread ()->control.stop_bpstat,
-					stop_print_frame);
-  else
-    gdb::observers::normal_stop.notify (nullptr, stop_print_frame);
-
+  notify_normal_stop ((inferior_ptid != null_ptid
+		       ? inferior_thread ()->control.stop_bpstat
+		       : nullptr),
+		      stop_print_frame);
   annotate_stopped ();
 
   if (target_has_execution ())
diff --git a/gdb/infrun.h b/gdb/infrun.h
index f7b60a4d9fb7..cbafc3ea4407 100644
--- a/gdb/infrun.h
+++ b/gdb/infrun.h
@@ -214,6 +214,10 @@ extern void set_step_info (thread_info *tp,
    signal SIG.  */
 extern void notify_signal_received (gdb_signal sig);
 
+/* Notify interpreters and observers that the current inferior has stopped
+   normally.  */
+extern void notify_normal_stop (bpstat *bs, int print_frame);
+
 /* Several print_*_reason helper functions to print why the inferior
    has stopped to the passed in UIOUT.  */
 
diff --git a/gdb/interps.c b/gdb/interps.c
index 5d061ad52aff..80160bc45f34 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -406,6 +406,14 @@ interps_notify_signal_received (gdb_signal sig)
   interps_notify (&interp::on_signal_received, sig);
 }
 
+/* See interps.h.  */
+
+void
+interps_notify_normal_stop (bpstat *bs, int print_frame)
+{
+  interps_notify (&interp::on_normal_stop, bs, print_frame);
+}
+
 /* This just adds the "interpreter-exec" command.  */
 void _initialize_interpreter ();
 void
diff --git a/gdb/interps.h b/gdb/interps.h
index 4762c4c93ff1..dd5a9b70e339 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -24,6 +24,7 @@
 
 #include "gdbsupport/intrusive_list.h"
 
+struct bpstat;
 struct ui_out;
 struct interp;
 struct ui;
@@ -86,6 +87,9 @@ class interp : public intrusive_list_node<interp>
      SIG.  */
   virtual void on_signal_received (gdb_signal sig) {}
 
+  /* Notify the interpreter that the current inferior has stopped normally.  */
+  virtual void on_normal_stop (bpstat *bs, int print_frame) {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
@@ -178,6 +182,9 @@ extern void interpreter_completer (struct cmd_list_element *ignore,
    SIG.  */
 extern void interps_notify_signal_received (gdb_signal sig);
 
+/* Notify all interpreters that the current inferior has stopped normally.  */
+extern void interps_notify_normal_stop (bpstat *bs, int print_frame);
+
 /* well-known interpreters */
 #define INTERP_CONSOLE		"console"
 #define INTERP_MI2             "mi2"
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 43e49a9b94af..5aeba46c4c28 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -62,7 +62,6 @@ static void mi_remove_notify_hooks (void);
 
 static void mi_on_signal_exited (enum gdb_signal siggnal);
 static void mi_on_exited (int exitstatus);
-static void mi_on_normal_stop (struct bpstat *bs, int print_frame);
 static void mi_on_no_history (void);
 
 static void mi_new_thread (struct thread_info *t);
@@ -581,33 +580,28 @@ mi_on_no_history (void)
     }
 }
 
-static void
-mi_on_normal_stop_1 (struct bpstat *bs, int print_frame)
+void
+mi_interp::on_normal_stop (struct bpstat *bs, int print_frame)
 {
   /* Since this can be called when CLI command is executing,
      using cli interpreter, be sure to use MI uiout for output,
      not the current one.  */
-  struct ui_out *mi_uiout = top_level_interpreter ()->interp_ui_out ();
-  struct mi_interp *mi = (struct mi_interp *) top_level_interpreter ();
+  struct ui_out *mi_uiout = this->interp_ui_out ();
 
   if (print_frame)
     {
-      struct thread_info *tp;
-      int core;
-      struct interp *console_interp;
-
-      tp = inferior_thread ();
+      thread_info *tp = inferior_thread ();
 
       if (tp->thread_fsm () != nullptr
 	  && tp->thread_fsm ()->finished_p ())
 	{
-	  enum async_reply_reason reason;
-
-	  reason = tp->thread_fsm ()->async_reply_reason ();
+	  async_reply_reason reason
+	    = tp->thread_fsm ()->async_reply_reason ();
 	  mi_uiout->field_string ("reason", async_reason_lookup (reason));
 	}
 
-      console_interp = interp_lookup (current_ui, INTERP_CONSOLE);
+      interp *console_interp = interp_lookup (current_ui, INTERP_CONSOLE);
+
       /* We only want to print the displays once, and we want it to
 	 look just how it would on the console, so we use this to
 	 decide whether the MI stop should include them.  */
@@ -615,7 +609,7 @@ mi_on_normal_stop_1 (struct bpstat *bs, int print_frame)
       print_stop_event (mi_uiout, !console_print);
 
       if (console_print)
-	print_stop_event (mi->cli_uiout);
+	print_stop_event (this->cli_uiout);
 
       mi_uiout->field_signed ("thread-id", tp->global_num);
       if (non_stop)
@@ -627,29 +621,17 @@ mi_on_normal_stop_1 (struct bpstat *bs, int print_frame)
       else
 	mi_uiout->field_string ("stopped-threads", "all");
 
-      core = target_core_of_thread (tp->ptid);
+      int core = target_core_of_thread (tp->ptid);
       if (core != -1)
 	mi_uiout->field_signed ("core", core);
     }
-  
-  gdb_puts ("*stopped", mi->raw_stdout);
-  mi_out_put (mi_uiout, mi->raw_stdout);
-  mi_out_rewind (mi_uiout);
-  mi_print_timing_maybe (mi->raw_stdout);
-  gdb_puts ("\n", mi->raw_stdout);
-  gdb_flush (mi->raw_stdout);
-}
 
-static void
-mi_on_normal_stop (struct bpstat *bs, int print_frame)
-{
-  SWITCH_THRU_ALL_UIS ()
-    {
-      if (as_mi_interp (top_level_interpreter ()) == NULL)
-	continue;
-
-      mi_on_normal_stop_1 (bs, print_frame);
-    }
+  gdb_puts ("*stopped", this->raw_stdout);
+  mi_out_put (mi_uiout, this->raw_stdout);
+  mi_out_rewind (mi_uiout);
+  mi_print_timing_maybe (this->raw_stdout);
+  gdb_puts ("\n", this->raw_stdout);
+  gdb_flush (this->raw_stdout);
 }
 
 static void
@@ -1302,7 +1284,6 @@ _initialize_mi_interp ()
   gdb::observers::inferior_exit.attach (mi_inferior_exit, "mi-interp");
   gdb::observers::inferior_removed.attach (mi_inferior_removed, "mi-interp");
   gdb::observers::record_changed.attach (mi_record_changed, "mi-interp");
-  gdb::observers::normal_stop.attach (mi_on_normal_stop, "mi-interp");
   gdb::observers::target_resumed.attach (mi_on_resume, "mi-interp");
   gdb::observers::solib_loaded.attach (mi_solib_loaded, "mi-interp");
   gdb::observers::solib_unloaded.attach (mi_solib_unloaded, "mi-interp");
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index 75c17568d6fc..444625f22c88 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -43,6 +43,7 @@ class mi_interp final : public interp
   void pre_command_loop () override;
 
   void on_signal_received (gdb_signal sig) override;
+  void on_normal_stop (struct bpstat *bs, int print_frame) override;
 
   /* MI's output channels */
   mi_console_file *out;
diff --git a/gdb/remote.c b/gdb/remote.c
index 829cdbdef757..ec0dba239303 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -4722,7 +4722,8 @@ remote_target::print_one_stopped_thread (thread_info *thread)
       if (signal_print_state (sig))
 	notify_signal_received (sig);
     }
-  gdb::observers::normal_stop.notify (NULL, 1);
+
+  notify_normal_stop (nullptr, 1);
 }
 
 /* Process all initial stop replies the remote side sent in response
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 05/30] gdb: add interp::on_signal_exited method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (3 preceding siblings ...)
  2023-05-02 20:49 ` [PATCH 04/30] gdb: add interp::on_normal_stop method Simon Marchi
@ 2023-05-02 20:49 ` Simon Marchi
  2023-05-02 20:49 ` [PATCH 06/30] gdb: add interp::on_exited method Simon Marchi
                   ` (26 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:49 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same as previous patch, but for signal_exited.  Remove the signal_exited
observable, since nothing uses it anymore, and we don't have anything
coming that will use it.

Change-Id: I0dca1eab76338bf27be755786e3dad3241698b10
---
 gdb/cli/cli-interp.c | 17 +++--------------
 gdb/cli/cli-interp.h |  3 ++-
 gdb/infrun.c         |  2 +-
 gdb/interps.c        |  8 ++++++++
 gdb/interps.h        |  8 ++++++++
 gdb/mi/mi-interp.c   | 20 ++++----------------
 gdb/mi/mi-interp.h   |  1 +
 gdb/observable.c     |  1 -
 gdb/observable.h     |  3 ---
 9 files changed, 27 insertions(+), 36 deletions(-)

diff --git a/gdb/cli/cli-interp.c b/gdb/cli/cli-interp.c
index 9508171e87d5..aba73f142af8 100644
--- a/gdb/cli/cli-interp.c
+++ b/gdb/cli/cli-interp.c
@@ -134,19 +134,10 @@ cli_interp_base::on_signal_received (enum gdb_signal siggnal)
   print_signal_received_reason (this->interp_ui_out (), siggnal);
 }
 
-/* Observer for the signalled notification.  */
-
-static void
-cli_base_on_signal_exited (enum gdb_signal siggnal)
+void
+cli_interp_base::on_signal_exited (gdb_signal sig)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      cli_interp_base *cli = as_cli_interp_base (top_level_interpreter ());
-      if (cli == nullptr)
-	continue;
-
-      print_signal_exited_reason (cli->interp_ui_out (), siggnal);
-    }
+  print_signal_exited_reason (this->interp_ui_out (), sig);
 }
 
 /* Observer for the exited notification.  */
@@ -388,8 +379,6 @@ _initialize_cli_interp ()
   interp_factory_register (INTERP_CONSOLE, cli_interp_factory);
 
   /* Note these all work for both the CLI and TUI interpreters.  */
-  gdb::observers::signal_exited.attach (cli_base_on_signal_exited,
-					"cli-interp-base");
   gdb::observers::exited.attach (cli_base_on_exited, "cli-interp-base");
   gdb::observers::no_history.attach (cli_base_on_no_history, "cli-interp-base");
   gdb::observers::sync_execution_done.attach (cli_base_on_sync_execution_done,
diff --git a/gdb/cli/cli-interp.h b/gdb/cli/cli-interp.h
index 4fca801d4fd6..6342efa2dd59 100644
--- a/gdb/cli/cli-interp.h
+++ b/gdb/cli/cli-interp.h
@@ -34,7 +34,8 @@ class cli_interp_base : public interp
   bool supports_command_editing () override;
 
   void on_signal_received (gdb_signal sig) override;
-  void on_normal_stop(bpstat *bs, int print_frame) override;
+  void on_signal_exited (gdb_signal sig) override;
+  void on_normal_stop (bpstat *bs, int print_frame) override;
 
 private:
   struct saved_output_files
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 8fa2cacc4149..c458e559b1da 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -5754,7 +5754,7 @@ handle_inferior_event (struct execution_control_state *ecs)
 				   "signal number.");
 	    }
 
-	  gdb::observers::signal_exited.notify (ecs->ws.sig ());
+	  interps_notify_signal_exited (ecs->ws.sig ());
 	}
 
       gdb_flush (gdb_stdout);
diff --git a/gdb/interps.c b/gdb/interps.c
index 80160bc45f34..566b5e1195ab 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -408,6 +408,14 @@ interps_notify_signal_received (gdb_signal sig)
 
 /* See interps.h.  */
 
+void
+interps_notify_signal_exited (gdb_signal sig)
+{
+  interps_notify (&interp::on_signal_exited, sig);
+}
+
+/* See interps.h.  */
+
 void
 interps_notify_normal_stop (bpstat *bs, int print_frame)
 {
diff --git a/gdb/interps.h b/gdb/interps.h
index dd5a9b70e339..752f2e8ea61b 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -87,6 +87,10 @@ class interp : public intrusive_list_node<interp>
      SIG.  */
   virtual void on_signal_received (gdb_signal sig) {}
 
+  /* Notify the interpreter that the current inferior has exited with signal
+     SIG. */
+  virtual void on_signal_exited (gdb_signal sig) {}
+
   /* Notify the interpreter that the current inferior has stopped normally.  */
   virtual void on_normal_stop (bpstat *bs, int print_frame) {}
 
@@ -182,6 +186,10 @@ extern void interpreter_completer (struct cmd_list_element *ignore,
    SIG.  */
 extern void interps_notify_signal_received (gdb_signal sig);
 
+/* Notify all interpreters that the current inferior has exited with signal
+   SIG.  */
+extern void interps_notify_signal_exited (gdb_signal sig);
+
 /* Notify all interpreters that the current inferior has stopped normally.  */
 extern void interps_notify_normal_stop (bpstat *bs, int print_frame);
 
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 5aeba46c4c28..2bf9e69393d4 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -60,7 +60,6 @@ static int mi_interp_query_hook (const char *ctlstr, va_list ap)
 static void mi_insert_notify_hooks (void);
 static void mi_remove_notify_hooks (void);
 
-static void mi_on_signal_exited (enum gdb_signal siggnal);
 static void mi_on_exited (int exitstatus);
 static void mi_on_no_history (void);
 
@@ -529,21 +528,11 @@ mi_interp::on_signal_received (enum gdb_signal siggnal)
   print_signal_received_reason (this->cli_uiout, siggnal);
 }
 
-/* Observer for the signal_exited notification.  */
-
-static void
-mi_on_signal_exited (enum gdb_signal siggnal)
+void
+mi_interp::on_signal_exited (gdb_signal sig)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = find_mi_interp ();
-
-      if (mi == NULL)
-	continue;
-
-      print_signal_exited_reason (mi->mi_uiout, siggnal);
-      print_signal_exited_reason (mi->cli_uiout, siggnal);
-    }
+  print_signal_exited_reason (this->mi_uiout, sig);
+  print_signal_exited_reason (this->cli_uiout, sig);
 }
 
 /* Observer for the exited notification.  */
@@ -1274,7 +1263,6 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
 
-  gdb::observers::signal_exited.attach (mi_on_signal_exited, "mi-interp");
   gdb::observers::exited.attach (mi_on_exited, "mi-interp");
   gdb::observers::no_history.attach (mi_on_no_history, "mi-interp");
   gdb::observers::new_thread.attach (mi_new_thread, "mi-interp");
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index 444625f22c88..31e683319f89 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -43,6 +43,7 @@ class mi_interp final : public interp
   void pre_command_loop () override;
 
   void on_signal_received (gdb_signal sig) override;
+  void on_signal_exited (gdb_signal sig) override;
   void on_normal_stop (struct bpstat *bs, int print_frame) override;
 
   /* MI's output channels */
diff --git a/gdb/observable.c b/gdb/observable.c
index 82563e3fab47..8cbf0377b0bc 100644
--- a/gdb/observable.c
+++ b/gdb/observable.c
@@ -34,7 +34,6 @@ bool observer_debug = false;
 
 DEFINE_OBSERVABLE (normal_stop);
 DEFINE_OBSERVABLE (signal_received);
-DEFINE_OBSERVABLE (signal_exited);
 DEFINE_OBSERVABLE (exited);
 DEFINE_OBSERVABLE (no_history);
 DEFINE_OBSERVABLE (sync_execution_done);
diff --git a/gdb/observable.h b/gdb/observable.h
index e4e6f021f1a9..aaf1ddda4d42 100644
--- a/gdb/observable.h
+++ b/gdb/observable.h
@@ -57,9 +57,6 @@ extern observable<struct bpstat */* bs */, int /* print_frame */> normal_stop;
 /* The inferior was stopped by a signal.  */
 extern observable<enum gdb_signal /* siggnal */> signal_received;
 
-/* The inferior was terminated by a signal.  */
-extern observable<enum gdb_signal /* siggnal */> signal_exited;
-
 /* The inferior program is finished.  */
 extern observable<int /* exitstatus */> exited;
 
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 06/30] gdb: add interp::on_exited method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (4 preceding siblings ...)
  2023-05-02 20:49 ` [PATCH 05/30] gdb: add interp::on_signal_exited method Simon Marchi
@ 2023-05-02 20:49 ` Simon Marchi
  2023-05-02 20:49 ` [PATCH 07/30] gdb: add interp::on_no_history method Simon Marchi
                   ` (25 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:49 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same as previous patch, but for exited.  Remove the exited observable,
since nothing uses it anymore, and we don't have anything coming that
will use it.

Change-Id: I358cbea0159af56752dfee7510d6a86191e722bb
---
 gdb/cli/cli-interp.c | 16 +++-------------
 gdb/cli/cli-interp.h |  1 +
 gdb/infrun.c         |  2 +-
 gdb/interps.c        |  8 ++++++++
 gdb/interps.h        |  8 ++++++++
 gdb/mi/mi-interp.c   | 20 ++++----------------
 gdb/mi/mi-interp.h   |  1 +
 gdb/observable.c     |  1 -
 gdb/observable.h     |  3 ---
 9 files changed, 26 insertions(+), 34 deletions(-)

diff --git a/gdb/cli/cli-interp.c b/gdb/cli/cli-interp.c
index aba73f142af8..6cb315cb57d2 100644
--- a/gdb/cli/cli-interp.c
+++ b/gdb/cli/cli-interp.c
@@ -140,19 +140,10 @@ cli_interp_base::on_signal_exited (gdb_signal sig)
   print_signal_exited_reason (this->interp_ui_out (), sig);
 }
 
-/* Observer for the exited notification.  */
-
-static void
-cli_base_on_exited (int exitstatus)
+void
+cli_interp_base::on_exited (int status)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      cli_interp_base *cli = as_cli_interp_base (top_level_interpreter ());
-      if (cli == nullptr)
-	continue;
-
-      print_exited_reason (cli->interp_ui_out (), exitstatus);
-    }
+  print_exited_reason (this->interp_ui_out (), status);
 }
 
 /* Observer for the no_history notification.  */
@@ -379,7 +370,6 @@ _initialize_cli_interp ()
   interp_factory_register (INTERP_CONSOLE, cli_interp_factory);
 
   /* Note these all work for both the CLI and TUI interpreters.  */
-  gdb::observers::exited.attach (cli_base_on_exited, "cli-interp-base");
   gdb::observers::no_history.attach (cli_base_on_no_history, "cli-interp-base");
   gdb::observers::sync_execution_done.attach (cli_base_on_sync_execution_done,
 					      "cli-interp-base");
diff --git a/gdb/cli/cli-interp.h b/gdb/cli/cli-interp.h
index 6342efa2dd59..2e50860efa9e 100644
--- a/gdb/cli/cli-interp.h
+++ b/gdb/cli/cli-interp.h
@@ -36,6 +36,7 @@ class cli_interp_base : public interp
   void on_signal_received (gdb_signal sig) override;
   void on_signal_exited (gdb_signal sig) override;
   void on_normal_stop (bpstat *bs, int print_frame) override;
+  void on_exited (int status) override;
 
 private:
   struct saved_output_files
diff --git a/gdb/infrun.c b/gdb/infrun.c
index c458e559b1da..7320adb5b2ff 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -5727,7 +5727,7 @@ handle_inferior_event (struct execution_control_state *ecs)
 	  /* Support the --return-child-result option.  */
 	  return_child_result_value = ecs->ws.exit_status ();
 
-	  gdb::observers::exited.notify (ecs->ws.exit_status ());
+	  interps_notify_exited (ecs->ws.exit_status ());
 	}
       else
 	{
diff --git a/gdb/interps.c b/gdb/interps.c
index 566b5e1195ab..a7fede1d3312 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -422,6 +422,14 @@ interps_notify_normal_stop (bpstat *bs, int print_frame)
   interps_notify (&interp::on_normal_stop, bs, print_frame);
 }
 
+/* See interps.h.  */
+
+void
+interps_notify_exited (int status)
+{
+  interps_notify (&interp::on_exited, status);
+}
+
 /* This just adds the "interpreter-exec" command.  */
 void _initialize_interpreter ();
 void
diff --git a/gdb/interps.h b/gdb/interps.h
index 752f2e8ea61b..6c2656dd1b07 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -94,6 +94,10 @@ class interp : public intrusive_list_node<interp>
   /* Notify the interpreter that the current inferior has stopped normally.  */
   virtual void on_normal_stop (bpstat *bs, int print_frame) {}
 
+  /* Notify the intepreter that the current inferior has exited normally with
+     status STATUS.  */
+  virtual void on_exited (int status) {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
@@ -193,6 +197,10 @@ extern void interps_notify_signal_exited (gdb_signal sig);
 /* Notify all interpreters that the current inferior has stopped normally.  */
 extern void interps_notify_normal_stop (bpstat *bs, int print_frame);
 
+/* Notify all interpreters that the current inferior has exited normally with
+   status STATUS.  */
+extern void interps_notify_exited (int status);
+
 /* well-known interpreters */
 #define INTERP_CONSOLE		"console"
 #define INTERP_MI2             "mi2"
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 2bf9e69393d4..56c59f3ac462 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -60,7 +60,6 @@ static int mi_interp_query_hook (const char *ctlstr, va_list ap)
 static void mi_insert_notify_hooks (void);
 static void mi_remove_notify_hooks (void);
 
-static void mi_on_exited (int exitstatus);
 static void mi_on_no_history (void);
 
 static void mi_new_thread (struct thread_info *t);
@@ -535,21 +534,11 @@ mi_interp::on_signal_exited (gdb_signal sig)
   print_signal_exited_reason (this->cli_uiout, sig);
 }
 
-/* Observer for the exited notification.  */
-
-static void
-mi_on_exited (int exitstatus)
+void
+mi_interp::on_exited (int status)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = find_mi_interp ();
-
-      if (mi == NULL)
-	continue;
-
-      print_exited_reason (mi->mi_uiout, exitstatus);
-      print_exited_reason (mi->cli_uiout, exitstatus);
-    }
+  print_exited_reason (this->mi_uiout, status);
+  print_exited_reason (this->cli_uiout, status);
 }
 
 /* Observer for the no_history notification.  */
@@ -1263,7 +1252,6 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
 
-  gdb::observers::exited.attach (mi_on_exited, "mi-interp");
   gdb::observers::no_history.attach (mi_on_no_history, "mi-interp");
   gdb::observers::new_thread.attach (mi_new_thread, "mi-interp");
   gdb::observers::thread_exit.attach (mi_thread_exit, "mi-interp");
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index 31e683319f89..1c828b5c508f 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -45,6 +45,7 @@ class mi_interp final : public interp
   void on_signal_received (gdb_signal sig) override;
   void on_signal_exited (gdb_signal sig) override;
   void on_normal_stop (struct bpstat *bs, int print_frame) override;
+  void on_exited (int status) override;
 
   /* MI's output channels */
   mi_console_file *out;
diff --git a/gdb/observable.c b/gdb/observable.c
index 8cbf0377b0bc..843890023834 100644
--- a/gdb/observable.c
+++ b/gdb/observable.c
@@ -34,7 +34,6 @@ bool observer_debug = false;
 
 DEFINE_OBSERVABLE (normal_stop);
 DEFINE_OBSERVABLE (signal_received);
-DEFINE_OBSERVABLE (exited);
 DEFINE_OBSERVABLE (no_history);
 DEFINE_OBSERVABLE (sync_execution_done);
 DEFINE_OBSERVABLE (command_error);
diff --git a/gdb/observable.h b/gdb/observable.h
index aaf1ddda4d42..25af2da6e935 100644
--- a/gdb/observable.h
+++ b/gdb/observable.h
@@ -57,9 +57,6 @@ extern observable<struct bpstat */* bs */, int /* print_frame */> normal_stop;
 /* The inferior was stopped by a signal.  */
 extern observable<enum gdb_signal /* siggnal */> signal_received;
 
-/* The inferior program is finished.  */
-extern observable<int /* exitstatus */> exited;
-
 /* Reverse execution: target ran out of history info.  */
 extern observable<> no_history;
 
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 07/30] gdb: add interp::on_no_history method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (5 preceding siblings ...)
  2023-05-02 20:49 ` [PATCH 06/30] gdb: add interp::on_exited method Simon Marchi
@ 2023-05-02 20:49 ` Simon Marchi
  2023-05-02 20:49 ` [PATCH 08/30] gdb: add interp::on_sync_execution_done method Simon Marchi
                   ` (24 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:49 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same as previous patches, but for no_history.

Change-Id: I06930fe7cb4082138c6c5496c5118fe4951c10da
---
 gdb/cli/cli-interp.c | 16 +++-------------
 gdb/cli/cli-interp.h |  1 +
 gdb/infrun.c         |  2 +-
 gdb/interps.c        |  8 ++++++++
 gdb/interps.h        |  8 ++++++++
 gdb/mi/mi-interp.c   | 41 ++++-------------------------------------
 gdb/mi/mi-interp.h   |  1 +
 gdb/observable.c     |  1 -
 gdb/observable.h     |  3 ---
 9 files changed, 26 insertions(+), 55 deletions(-)

diff --git a/gdb/cli/cli-interp.c b/gdb/cli/cli-interp.c
index 6cb315cb57d2..98bc2033f2c6 100644
--- a/gdb/cli/cli-interp.c
+++ b/gdb/cli/cli-interp.c
@@ -146,19 +146,10 @@ cli_interp_base::on_exited (int status)
   print_exited_reason (this->interp_ui_out (), status);
 }
 
-/* Observer for the no_history notification.  */
-
-static void
-cli_base_on_no_history ()
+void
+cli_interp_base::on_no_history ()
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      cli_interp_base *cli = as_cli_interp_base (top_level_interpreter ());
-      if (cli == nullptr)
-	continue;
-
-      print_no_history_reason (cli->interp_ui_out ());
-    }
+  print_no_history_reason (this->interp_ui_out ());
 }
 
 /* Observer for the sync_execution_done notification.  */
@@ -370,7 +361,6 @@ _initialize_cli_interp ()
   interp_factory_register (INTERP_CONSOLE, cli_interp_factory);
 
   /* Note these all work for both the CLI and TUI interpreters.  */
-  gdb::observers::no_history.attach (cli_base_on_no_history, "cli-interp-base");
   gdb::observers::sync_execution_done.attach (cli_base_on_sync_execution_done,
 					      "cli-interp-base");
   gdb::observers::command_error.attach (cli_base_on_command_error,
diff --git a/gdb/cli/cli-interp.h b/gdb/cli/cli-interp.h
index 2e50860efa9e..7fc22a042d73 100644
--- a/gdb/cli/cli-interp.h
+++ b/gdb/cli/cli-interp.h
@@ -37,6 +37,7 @@ class cli_interp_base : public interp
   void on_signal_exited (gdb_signal sig) override;
   void on_normal_stop (bpstat *bs, int print_frame) override;
   void on_exited (int status) override;
+  void on_no_history () override;
 
 private:
   struct saved_output_files
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 7320adb5b2ff..f86ec7a2ed81 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -6038,7 +6038,7 @@ handle_inferior_event (struct execution_control_state *ecs)
       if (handle_stop_requested (ecs))
 	return;
 
-      gdb::observers::no_history.notify ();
+      interps_notify_no_history ();
       stop_waiting (ecs);
       return;
     }
diff --git a/gdb/interps.c b/gdb/interps.c
index a7fede1d3312..885bfc36ec70 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -416,6 +416,14 @@ interps_notify_signal_exited (gdb_signal sig)
 
 /* See interps.h.  */
 
+void
+interps_notify_no_history ()
+{
+  interps_notify (&interp::on_no_history);
+}
+
+/* See interps.h.  */
+
 void
 interps_notify_normal_stop (bpstat *bs, int print_frame)
 {
diff --git a/gdb/interps.h b/gdb/interps.h
index 6c2656dd1b07..915a5f74eb73 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -98,6 +98,10 @@ class interp : public intrusive_list_node<interp>
      status STATUS.  */
   virtual void on_exited (int status) {}
 
+  /* Notify the interpreter that the current inferior has stopped reverse
+     execution because there is no more history.  */
+  virtual void on_no_history () {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
@@ -197,6 +201,10 @@ extern void interps_notify_signal_exited (gdb_signal sig);
 /* Notify all interpreters that the current inferior has stopped normally.  */
 extern void interps_notify_normal_stop (bpstat *bs, int print_frame);
 
+/* Notify all interpreters that the current inferior has stopped reverse
+   execution because there is no more history.  */
+extern void interps_notify_no_history ();
+
 /* Notify all interpreters that the current inferior has exited normally with
    status STATUS.  */
 extern void interps_notify_exited (int status);
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 56c59f3ac462..a147c46ecf3b 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -60,8 +60,6 @@ static int mi_interp_query_hook (const char *ctlstr, va_list ap)
 static void mi_insert_notify_hooks (void);
 static void mi_remove_notify_hooks (void);
 
-static void mi_on_no_history (void);
-
 static void mi_new_thread (struct thread_info *t);
 static void mi_thread_exit (struct thread_info *t, int silent);
 static void mi_record_changed (struct inferior*, int, const char *,
@@ -496,26 +494,6 @@ mi_inferior_removed (struct inferior *inf)
     }
 }
 
-/* Return the MI interpreter, if it is active -- either because it's
-   the top-level interpreter or the interpreter executing the current
-   command.  Returns NULL if the MI interpreter is not being used.  */
-
-static struct mi_interp *
-find_mi_interp (void)
-{
-  struct mi_interp *mi;
-
-  mi = as_mi_interp (top_level_interpreter ());
-  if (mi != NULL)
-    return mi;
-
-  mi = as_mi_interp (command_interp ());
-  if (mi != NULL)
-    return mi;
-
-  return NULL;
-}
-
 /* Observers for several run control events that print why the
    inferior has stopped to both the MI event channel and to the MI
    console.  If the MI interpreter is not active, print nothing.  */
@@ -541,21 +519,11 @@ mi_interp::on_exited (int status)
   print_exited_reason (this->cli_uiout, status);
 }
 
-/* Observer for the no_history notification.  */
-
-static void
-mi_on_no_history (void)
+void
+mi_interp::on_no_history ()
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = find_mi_interp ();
-
-      if (mi == NULL)
-	continue;
-
-      print_no_history_reason (mi->mi_uiout);
-      print_no_history_reason (mi->cli_uiout);
-    }
+  print_no_history_reason (this->mi_uiout);
+  print_no_history_reason (this->cli_uiout);
 }
 
 void
@@ -1252,7 +1220,6 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
 
-  gdb::observers::no_history.attach (mi_on_no_history, "mi-interp");
   gdb::observers::new_thread.attach (mi_new_thread, "mi-interp");
   gdb::observers::thread_exit.attach (mi_thread_exit, "mi-interp");
   gdb::observers::inferior_added.attach (mi_inferior_added, "mi-interp");
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index 1c828b5c508f..aeebc3207526 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -46,6 +46,7 @@ class mi_interp final : public interp
   void on_signal_exited (gdb_signal sig) override;
   void on_normal_stop (struct bpstat *bs, int print_frame) override;
   void on_exited (int status) override;
+  void on_no_history () override;
 
   /* MI's output channels */
   mi_console_file *out;
diff --git a/gdb/observable.c b/gdb/observable.c
index 843890023834..502e2d988cd1 100644
--- a/gdb/observable.c
+++ b/gdb/observable.c
@@ -34,7 +34,6 @@ bool observer_debug = false;
 
 DEFINE_OBSERVABLE (normal_stop);
 DEFINE_OBSERVABLE (signal_received);
-DEFINE_OBSERVABLE (no_history);
 DEFINE_OBSERVABLE (sync_execution_done);
 DEFINE_OBSERVABLE (command_error);
 DEFINE_OBSERVABLE (target_changed);
diff --git a/gdb/observable.h b/gdb/observable.h
index 25af2da6e935..b06d13be0362 100644
--- a/gdb/observable.h
+++ b/gdb/observable.h
@@ -57,9 +57,6 @@ extern observable<struct bpstat */* bs */, int /* print_frame */> normal_stop;
 /* The inferior was stopped by a signal.  */
 extern observable<enum gdb_signal /* siggnal */> signal_received;
 
-/* Reverse execution: target ran out of history info.  */
-extern observable<> no_history;
-
 /* A synchronous command finished.  */
 extern observable<> sync_execution_done;
 
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 08/30] gdb: add interp::on_sync_execution_done method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (6 preceding siblings ...)
  2023-05-02 20:49 ` [PATCH 07/30] gdb: add interp::on_no_history method Simon Marchi
@ 2023-05-02 20:49 ` Simon Marchi
  2023-05-02 20:49 ` [PATCH 09/30] gdb: add interp::on_command_error method Simon Marchi
                   ` (23 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:49 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same as previous patches, but for sync_execution_done.  Except that
here, we only want to notify the interpreter that is executing the
command, not all interpreters.

Change-Id: I729c719447b5c5f29af65dbf6fed9132e2cd308b
---
 gdb/cli/cli-interp.c | 12 ++----------
 gdb/cli/cli-interp.h |  1 +
 gdb/infrun.c         |  2 +-
 gdb/interps.h        |  4 ++++
 gdb/mi/mi-interp.c   | 16 +++-------------
 gdb/mi/mi-interp.h   |  1 +
 gdb/observable.c     |  1 -
 gdb/observable.h     |  3 ---
 8 files changed, 12 insertions(+), 28 deletions(-)

diff --git a/gdb/cli/cli-interp.c b/gdb/cli/cli-interp.c
index 98bc2033f2c6..00310542a8db 100644
--- a/gdb/cli/cli-interp.c
+++ b/gdb/cli/cli-interp.c
@@ -152,15 +152,9 @@ cli_interp_base::on_no_history ()
   print_no_history_reason (this->interp_ui_out ());
 }
 
-/* Observer for the sync_execution_done notification.  */
-
-static void
-cli_base_on_sync_execution_done ()
+void
+cli_interp_base::on_sync_execution_done ()
 {
-  cli_interp_base *cli = as_cli_interp_base (top_level_interpreter ());
-  if (cli == nullptr)
-    return;
-
   display_gdb_prompt (NULL);
 }
 
@@ -361,8 +355,6 @@ _initialize_cli_interp ()
   interp_factory_register (INTERP_CONSOLE, cli_interp_factory);
 
   /* Note these all work for both the CLI and TUI interpreters.  */
-  gdb::observers::sync_execution_done.attach (cli_base_on_sync_execution_done,
-					      "cli-interp-base");
   gdb::observers::command_error.attach (cli_base_on_command_error,
 					"cli-interp-base");
   gdb::observers::user_selected_context_changed.attach
diff --git a/gdb/cli/cli-interp.h b/gdb/cli/cli-interp.h
index 7fc22a042d73..4680c8070fd0 100644
--- a/gdb/cli/cli-interp.h
+++ b/gdb/cli/cli-interp.h
@@ -38,6 +38,7 @@ class cli_interp_base : public interp
   void on_normal_stop (bpstat *bs, int print_frame) override;
   void on_exited (int status) override;
   void on_no_history () override;
+  void on_sync_execution_done () override;
 
 private:
   struct saved_output_files
diff --git a/gdb/infrun.c b/gdb/infrun.c
index f86ec7a2ed81..8d648cf04f0a 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -4206,7 +4206,7 @@ check_curr_ui_sync_execution_done (void)
       && !gdb_in_secondary_prompt_p (ui))
     {
       target_terminal::ours ();
-      gdb::observers::sync_execution_done.notify ();
+      top_level_interpreter ()->on_sync_execution_done ();
       ui->register_file_handler ();
     }
 }
diff --git a/gdb/interps.h b/gdb/interps.h
index 915a5f74eb73..349ffb1bdcf7 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -102,6 +102,10 @@ class interp : public intrusive_list_node<interp>
      execution because there is no more history.  */
   virtual void on_no_history () {}
 
+  /* Notify the interpreter that a synchronous command it started has
+     finished.  */
+  virtual void on_sync_execution_done () {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index a147c46ecf3b..21c0fb6e73f7 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -82,7 +82,6 @@ static void mi_breakpoint_modified (struct breakpoint *b);
 static void mi_command_param_changed (const char *param, const char *value);
 static void mi_memory_changed (struct inferior *inf, CORE_ADDR memaddr,
 			       ssize_t len, const bfd_byte *myaddr);
-static void mi_on_sync_execution_done (void);
 
 /* Display the MI prompt.  */
 
@@ -268,20 +267,13 @@ mi_execute_command_wrapper (const char *cmd)
   mi_execute_command (cmd, ui->instream == ui->stdin_stream);
 }
 
-/* Observer for the synchronous_command_done notification.  */
-
-static void
-mi_on_sync_execution_done (void)
+void
+mi_interp::on_sync_execution_done ()
 {
-  struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-  if (mi == NULL)
-    return;
-
   /* If MI is sync, then output the MI prompt now, indicating we're
      ready for further input.  */
   if (!mi_async_p ())
-    display_mi_prompt (mi);
+    display_mi_prompt (this);
 }
 
 /* mi_execute_command_wrapper wrapper suitable for INPUT_HANDLER.  */
@@ -1246,8 +1238,6 @@ _initialize_mi_interp ()
 						"mi-interp");
   gdb::observers::command_error.attach (mi_on_command_error, "mi-interp");
   gdb::observers::memory_changed.attach (mi_memory_changed, "mi-interp");
-  gdb::observers::sync_execution_done.attach (mi_on_sync_execution_done,
-					      "mi-interp");
   gdb::observers::user_selected_context_changed.attach
     (mi_user_selected_context_changed, "mi-interp");
 }
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index aeebc3207526..15ba8dab15bd 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -47,6 +47,7 @@ class mi_interp final : public interp
   void on_normal_stop (struct bpstat *bs, int print_frame) override;
   void on_exited (int status) override;
   void on_no_history () override;
+  void on_sync_execution_done () override;
 
   /* MI's output channels */
   mi_console_file *out;
diff --git a/gdb/observable.c b/gdb/observable.c
index 502e2d988cd1..f52989d7a638 100644
--- a/gdb/observable.c
+++ b/gdb/observable.c
@@ -34,7 +34,6 @@ bool observer_debug = false;
 
 DEFINE_OBSERVABLE (normal_stop);
 DEFINE_OBSERVABLE (signal_received);
-DEFINE_OBSERVABLE (sync_execution_done);
 DEFINE_OBSERVABLE (command_error);
 DEFINE_OBSERVABLE (target_changed);
 DEFINE_OBSERVABLE (executable_changed);
diff --git a/gdb/observable.h b/gdb/observable.h
index b06d13be0362..4be05efa0231 100644
--- a/gdb/observable.h
+++ b/gdb/observable.h
@@ -57,9 +57,6 @@ extern observable<struct bpstat */* bs */, int /* print_frame */> normal_stop;
 /* The inferior was stopped by a signal.  */
 extern observable<enum gdb_signal /* siggnal */> signal_received;
 
-/* A synchronous command finished.  */
-extern observable<> sync_execution_done;
-
 /* An error was caught while executing a command.  */
 extern observable<> command_error;
 
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 09/30] gdb: add interp::on_command_error method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (7 preceding siblings ...)
  2023-05-02 20:49 ` [PATCH 08/30] gdb: add interp::on_sync_execution_done method Simon Marchi
@ 2023-05-02 20:49 ` Simon Marchi
  2023-05-02 20:49 ` [PATCH 10/30] gdb: add interp::on_user_selected_context_changed method Simon Marchi
                   ` (22 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:49 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same idea as the previous patches, but for command_error.

Change-Id: If6098225dd72fad8be13b3023b35bc8bc48efb9d
---
 gdb/cli/cli-interp.c | 12 ++----------
 gdb/cli/cli-interp.h |  1 +
 gdb/interps.h        |  4 ++++
 gdb/main.c           |  2 +-
 gdb/mi/mi-interp.c   | 11 +++--------
 gdb/mi/mi-interp.h   |  1 +
 gdb/observable.c     |  1 -
 gdb/observable.h     |  3 ---
 8 files changed, 12 insertions(+), 23 deletions(-)

diff --git a/gdb/cli/cli-interp.c b/gdb/cli/cli-interp.c
index 00310542a8db..ffb40729fc61 100644
--- a/gdb/cli/cli-interp.c
+++ b/gdb/cli/cli-interp.c
@@ -158,15 +158,9 @@ cli_interp_base::on_sync_execution_done ()
   display_gdb_prompt (NULL);
 }
 
-/* Observer for the command_error notification.  */
-
-static void
-cli_base_on_command_error ()
+void
+cli_interp_base::on_command_error ()
 {
-  cli_interp_base *cli = as_cli_interp_base (top_level_interpreter ());
-  if (cli == nullptr)
-    return;
-
   display_gdb_prompt (NULL);
 }
 
@@ -355,8 +349,6 @@ _initialize_cli_interp ()
   interp_factory_register (INTERP_CONSOLE, cli_interp_factory);
 
   /* Note these all work for both the CLI and TUI interpreters.  */
-  gdb::observers::command_error.attach (cli_base_on_command_error,
-					"cli-interp-base");
   gdb::observers::user_selected_context_changed.attach
     (cli_base_on_user_selected_context_changed, "cli-interp-base");
 }
diff --git a/gdb/cli/cli-interp.h b/gdb/cli/cli-interp.h
index 4680c8070fd0..5020b2bc6ef4 100644
--- a/gdb/cli/cli-interp.h
+++ b/gdb/cli/cli-interp.h
@@ -39,6 +39,7 @@ class cli_interp_base : public interp
   void on_exited (int status) override;
   void on_no_history () override;
   void on_sync_execution_done () override;
+  void on_command_error () override;
 
 private:
   struct saved_output_files
diff --git a/gdb/interps.h b/gdb/interps.h
index 349ffb1bdcf7..53d951b8d637 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -106,6 +106,10 @@ class interp : public intrusive_list_node<interp>
      finished.  */
   virtual void on_sync_execution_done () {}
 
+  /* Notify the interpreter that an error was caught while executing a
+     command on this interpreter.  */
+  virtual void on_command_error () {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
diff --git a/gdb/main.c b/gdb/main.c
index 5c23714f52e0..47eec0e50730 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -430,7 +430,7 @@ start_event_loop ()
 	     get around to resetting the prompt, which leaves readline
 	     in a messed-up state.  Reset it here.  */
 	  current_ui->prompt_state = PROMPT_NEEDED;
-	  gdb::observers::command_error.notify ();
+	  top_level_interpreter ()->on_command_error ();
 	  /* This call looks bizarre, but it is required.  If the user
 	     entered a command that caused an error,
 	     after_char_processing_hook won't be called from
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 21c0fb6e73f7..45160571ce98 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -104,14 +104,10 @@ as_mi_interp (struct interp *interp)
   return dynamic_cast<mi_interp *> (interp);
 }
 
-/* Observer for the command_error notification.  */
-
-static void
-mi_on_command_error ()
+void
+mi_interp::on_command_error ()
 {
-  mi_interp *mi = as_mi_interp (top_level_interpreter ());
-  if (mi != nullptr)
-    display_mi_prompt (mi);
+  display_mi_prompt (this);
 }
 
 void
@@ -1236,7 +1232,6 @@ _initialize_mi_interp ()
 					      "mi-interp");
   gdb::observers::command_param_changed.attach (mi_command_param_changed,
 						"mi-interp");
-  gdb::observers::command_error.attach (mi_on_command_error, "mi-interp");
   gdb::observers::memory_changed.attach (mi_memory_changed, "mi-interp");
   gdb::observers::user_selected_context_changed.attach
     (mi_user_selected_context_changed, "mi-interp");
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index 15ba8dab15bd..08edaceb99cd 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -48,6 +48,7 @@ class mi_interp final : public interp
   void on_exited (int status) override;
   void on_no_history () override;
   void on_sync_execution_done () override;
+  void on_command_error () override;
 
   /* MI's output channels */
   mi_console_file *out;
diff --git a/gdb/observable.c b/gdb/observable.c
index f52989d7a638..bfb92b4fe15e 100644
--- a/gdb/observable.c
+++ b/gdb/observable.c
@@ -34,7 +34,6 @@ bool observer_debug = false;
 
 DEFINE_OBSERVABLE (normal_stop);
 DEFINE_OBSERVABLE (signal_received);
-DEFINE_OBSERVABLE (command_error);
 DEFINE_OBSERVABLE (target_changed);
 DEFINE_OBSERVABLE (executable_changed);
 DEFINE_OBSERVABLE (inferior_created);
diff --git a/gdb/observable.h b/gdb/observable.h
index 4be05efa0231..1ec927671e53 100644
--- a/gdb/observable.h
+++ b/gdb/observable.h
@@ -57,9 +57,6 @@ extern observable<struct bpstat */* bs */, int /* print_frame */> normal_stop;
 /* The inferior was stopped by a signal.  */
 extern observable<enum gdb_signal /* siggnal */> signal_received;
 
-/* An error was caught while executing a command.  */
-extern observable<> command_error;
-
 /* The target's register contents have changed.  */
 extern observable<struct target_ops */* target */> target_changed;
 
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 10/30] gdb: add interp::on_user_selected_context_changed method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (8 preceding siblings ...)
  2023-05-02 20:49 ` [PATCH 09/30] gdb: add interp::on_command_error method Simon Marchi
@ 2023-05-02 20:49 ` Simon Marchi
  2023-05-02 20:49 ` [PATCH 11/30] gdb: add interp::on_new_thread method Simon Marchi
                   ` (21 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:49 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same as previous patches, but for user_selected_context_changed.

Change-Id: I40de15be897671227d4bcf3e747f0fd595f0d5be
---
 gdb/cli/cli-interp.c | 36 +++++--------------------
 gdb/cli/cli-interp.h |  1 +
 gdb/inferior.c       |  4 +--
 gdb/infrun.c         |  8 ++++++
 gdb/infrun.h         |  3 +++
 gdb/interps.c        |  8 ++++++
 gdb/interps.h        |  8 ++++++
 gdb/mi/mi-interp.c   | 64 +++++++++++++++-----------------------------
 gdb/mi/mi-interp.h   |  1 +
 gdb/mi/mi-main.c     |  2 +-
 gdb/stack.c          |  8 +++---
 gdb/thread.c         |  6 ++---
 12 files changed, 66 insertions(+), 83 deletions(-)

diff --git a/gdb/cli/cli-interp.c b/gdb/cli/cli-interp.c
index ffb40729fc61..6a175f7baa13 100644
--- a/gdb/cli/cli-interp.c
+++ b/gdb/cli/cli-interp.c
@@ -67,15 +67,6 @@ cli_interp::cli_interp (const char *name)
 /* Suppress notification struct.  */
 struct cli_suppress_notification cli_suppress_notification;
 
-/* Returns the INTERP's data cast as cli_interp_base if INTERP is a
-   console-like interpreter, and returns NULL otherwise.  */
-
-static cli_interp_base *
-as_cli_interp_base (interp *interp)
-{
-  return dynamic_cast<cli_interp_base *> (interp);
-}
-
 /* See cli-interp.h.
 
    Breakpoint hits should always be mirrored to a console.  Deciding
@@ -164,10 +155,8 @@ cli_interp_base::on_command_error ()
   display_gdb_prompt (NULL);
 }
 
-/* Observer for the user_selected_context_changed notification.  */
-
-static void
-cli_base_on_user_selected_context_changed (user_selected_what selection)
+void
+cli_interp_base::on_user_selected_context_changed (user_selected_what selection)
 {
   /* This event is suppressed.  */
   if (cli_suppress_notification.user_selected_context)
@@ -175,19 +164,12 @@ cli_base_on_user_selected_context_changed (user_selected_what selection)
 
   thread_info *tp = inferior_ptid != null_ptid ? inferior_thread () : nullptr;
 
-  SWITCH_THRU_ALL_UIS ()
-    {
-      cli_interp_base *cli = as_cli_interp_base (top_level_interpreter ());
-      if (cli == nullptr)
-	continue;
-
-      if (selection & USER_SELECTED_INFERIOR)
-	print_selected_inferior (cli->interp_ui_out ());
+  if (selection & USER_SELECTED_INFERIOR)
+    print_selected_inferior (this->interp_ui_out ());
 
-      if (tp != nullptr
-	  && ((selection & (USER_SELECTED_THREAD | USER_SELECTED_FRAME))))
-	print_selected_thread_frame (cli->interp_ui_out (), selection);
-    }
+  if (tp != nullptr
+      && ((selection & (USER_SELECTED_THREAD | USER_SELECTED_FRAME))))
+    print_selected_thread_frame (this->interp_ui_out (), selection);
 }
 
 /* pre_command_loop implementation.  */
@@ -347,8 +329,4 @@ void
 _initialize_cli_interp ()
 {
   interp_factory_register (INTERP_CONSOLE, cli_interp_factory);
-
-  /* Note these all work for both the CLI and TUI interpreters.  */
-  gdb::observers::user_selected_context_changed.attach
-    (cli_base_on_user_selected_context_changed, "cli-interp-base");
 }
diff --git a/gdb/cli/cli-interp.h b/gdb/cli/cli-interp.h
index 5020b2bc6ef4..a1a20b678942 100644
--- a/gdb/cli/cli-interp.h
+++ b/gdb/cli/cli-interp.h
@@ -40,6 +40,7 @@ class cli_interp_base : public interp
   void on_no_history () override;
   void on_sync_execution_done () override;
   void on_command_error () override;
+  void on_user_selected_context_changed (user_selected_what selection) override;
 
 private:
   struct saved_output_files
diff --git a/gdb/inferior.c b/gdb/inferior.c
index fd451c87e709..8962b6401e34 100644
--- a/gdb/inferior.c
+++ b/gdb/inferior.c
@@ -745,7 +745,7 @@ inferior_command (const char *args, int from_tty)
 	      switch_to_thread (tp);
 	    }
 
-	  gdb::observers::user_selected_context_changed.notify
+	  notify_user_selected_context_changed
 	    (USER_SELECTED_INFERIOR
 	     | USER_SELECTED_THREAD
 	     | USER_SELECTED_FRAME);
@@ -754,7 +754,7 @@ inferior_command (const char *args, int from_tty)
 	{
 	  switch_to_inferior_no_thread (inf);
 
-	  gdb::observers::user_selected_context_changed.notify
+	  notify_user_selected_context_changed
 	    (USER_SELECTED_INFERIOR);
 	}
     }
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 8d648cf04f0a..aa2d34aa6b35 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -6282,6 +6282,14 @@ notify_normal_stop (bpstat *bs, int print_frame)
   gdb::observers::normal_stop.notify (bs, print_frame);
 }
 
+/* See infrun.h.  */
+
+void notify_user_selected_context_changed (user_selected_what selection)
+{
+  interps_notify_user_selected_context_changed (selection);
+  gdb::observers::user_selected_context_changed.notify (selection);
+}
+
 /* Come here when the program has stopped with a signal.  */
 
 static void
diff --git a/gdb/infrun.h b/gdb/infrun.h
index cbafc3ea4407..a343d27f72de 100644
--- a/gdb/infrun.h
+++ b/gdb/infrun.h
@@ -218,6 +218,9 @@ extern void notify_signal_received (gdb_signal sig);
    normally.  */
 extern void notify_normal_stop (bpstat *bs, int print_frame);
 
+/* Notify interpreters and observers that the user focus has changed.  */
+extern void notify_user_selected_context_changed (user_selected_what selection);
+
 /* Several print_*_reason helper functions to print why the inferior
    has stopped to the passed in UIOUT.  */
 
diff --git a/gdb/interps.c b/gdb/interps.c
index 885bfc36ec70..55abcb3c6e40 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -438,6 +438,14 @@ interps_notify_exited (int status)
   interps_notify (&interp::on_exited, status);
 }
 
+/* See interps.h.  */
+
+void
+interps_notify_user_selected_context_changed (user_selected_what selection)
+{
+  interps_notify (&interp::on_user_selected_context_changed, selection);
+}
+
 /* This just adds the "interpreter-exec" command.  */
 void _initialize_interpreter ();
 void
diff --git a/gdb/interps.h b/gdb/interps.h
index 53d951b8d637..4706c9bb63e7 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -110,6 +110,10 @@ class interp : public intrusive_list_node<interp>
      command on this interpreter.  */
   virtual void on_command_error () {}
 
+  /* Notify the interpreter that the user focus has changed.  */
+  virtual void on_user_selected_context_changed (user_selected_what selection)
+    {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
@@ -217,6 +221,10 @@ extern void interps_notify_no_history ();
    status STATUS.  */
 extern void interps_notify_exited (int status);
 
+/* Notify all interpreters that the user focus has changed.  */
+extern void interps_notify_user_selected_context_changed
+  (user_selected_what selection);
+
 /* well-known interpreters */
 #define INTERP_CONSOLE		"console"
 #define INTERP_MI2             "mi2"
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 45160571ce98..ab8c3efbb128 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -1086,60 +1086,40 @@ mi_memory_changed (struct inferior *inferior, CORE_ADDR memaddr,
     }
 }
 
-/* Emit an event when the selection context (inferior, thread, frame)
-   changed.  */
-
-static void
-mi_user_selected_context_changed (user_selected_what selection)
+void
+mi_interp::on_user_selected_context_changed (user_selected_what selection)
 {
-  struct thread_info *tp;
-
   /* Don't send an event if we're responding to an MI command.  */
   if (mi_suppress_notification.user_selected_context)
     return;
 
-  if (inferior_ptid != null_ptid)
-    tp = inferior_thread ();
-  else
-    tp = NULL;
+  thread_info *tp = inferior_ptid != null_ptid ? inferior_thread () : nullptr;
+  ui_out *mi_uiout = this->interp_ui_out ();
+  ui_out_redirect_pop redirect_popper (mi_uiout, this->event_channel);
 
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-      struct ui_out *mi_uiout;
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      if (mi == NULL)
-	continue;
+  if (selection & USER_SELECTED_INFERIOR)
+    print_selected_inferior (this->cli_uiout);
 
-      mi_uiout = top_level_interpreter ()->interp_ui_out ();
-
-      ui_out_redirect_pop redirect_popper (mi_uiout, mi->event_channel);
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  if (tp != NULL
+      && (selection & (USER_SELECTED_THREAD | USER_SELECTED_FRAME)))
+    {
+      print_selected_thread_frame (this->cli_uiout, selection);
 
-      if (selection & USER_SELECTED_INFERIOR)
-	print_selected_inferior (mi->cli_uiout);
+      gdb_printf (this->event_channel, "thread-selected,id=\"%d\"",
+		  tp->global_num);
 
-      if (tp != NULL
-	  && (selection & (USER_SELECTED_THREAD | USER_SELECTED_FRAME)))
+      if (tp->state != THREAD_RUNNING)
 	{
-	  print_selected_thread_frame (mi->cli_uiout, selection);
-
-	  gdb_printf (mi->event_channel,
-		      "thread-selected,id=\"%d\"",
-		      tp->global_num);
-
-	  if (tp->state != THREAD_RUNNING)
-	    {
-	      if (has_stack_frames ())
-		print_stack_frame_to_uiout (mi_uiout, get_selected_frame (NULL),
-					    1, SRC_AND_LOC, 1);
-	    }
+	  if (has_stack_frames ())
+	    print_stack_frame_to_uiout (mi_uiout, get_selected_frame (NULL),
+					1, SRC_AND_LOC, 1);
 	}
-
-      gdb_flush (mi->event_channel);
     }
+
+  gdb_flush (this->event_channel);
 }
 
 ui_out *
@@ -1233,6 +1213,4 @@ _initialize_mi_interp ()
   gdb::observers::command_param_changed.attach (mi_command_param_changed,
 						"mi-interp");
   gdb::observers::memory_changed.attach (mi_memory_changed, "mi-interp");
-  gdb::observers::user_selected_context_changed.attach
-    (mi_user_selected_context_changed, "mi-interp");
 }
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index 08edaceb99cd..430c61dbbf0a 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -49,6 +49,7 @@ class mi_interp final : public interp
   void on_no_history () override;
   void on_sync_execution_done () override;
   void on_command_error () override;
+  void on_user_selected_context_changed (user_selected_what selection) override;
 
   /* MI's output channels */
   mi_console_file *out;
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index 1be5d3becfcf..29bd236ef711 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -2107,7 +2107,7 @@ mi_cmd_execute (struct mi_parse *parse)
 
   if (!parse->cmd->preserve_user_selected_context ()
       && current_user_selected_context.has_changed ())
-    gdb::observers::user_selected_context_changed.notify
+    interps_notify_user_selected_context_changed
       (USER_SELECTED_THREAD | USER_SELECTED_FRAME);
 }
 
diff --git a/gdb/stack.c b/gdb/stack.c
index b1b25aa1c7e1..474f1ce5b879 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -1837,7 +1837,7 @@ select_frame_command_core (frame_info_ptr fi, bool ignored)
   frame_info_ptr prev_frame = get_selected_frame ();
   select_frame (fi);
   if (get_selected_frame () != prev_frame)
-    gdb::observers::user_selected_context_changed.notify (USER_SELECTED_FRAME);
+    notify_user_selected_context_changed (USER_SELECTED_FRAME);
 }
 
 /* The core of all the "frame" sub-commands.  Select frame FI, and if this
@@ -1850,7 +1850,7 @@ frame_command_core (frame_info_ptr fi, bool ignored)
   frame_info_ptr prev_frame = get_selected_frame ();
   select_frame (fi);
   if (get_selected_frame () != prev_frame)
-    gdb::observers::user_selected_context_changed.notify (USER_SELECTED_FRAME);
+    notify_user_selected_context_changed (USER_SELECTED_FRAME);
   else
     print_selected_thread_frame (current_uiout, USER_SELECTED_FRAME);
 }
@@ -2650,7 +2650,7 @@ static void
 up_command (const char *count_exp, int from_tty)
 {
   up_silently_base (count_exp);
-  gdb::observers::user_selected_context_changed.notify (USER_SELECTED_FRAME);
+  notify_user_selected_context_changed (USER_SELECTED_FRAME);
 }
 
 /* Select the frame down one or COUNT_EXP stack levels from the previously
@@ -2689,7 +2689,7 @@ static void
 down_command (const char *count_exp, int from_tty)
 {
   down_silently_base (count_exp);
-  gdb::observers::user_selected_context_changed.notify (USER_SELECTED_FRAME);
+  notify_user_selected_context_changed (USER_SELECTED_FRAME);
 }
 
 void
diff --git a/gdb/thread.c b/gdb/thread.c
index e9432f945e09..13db9f8747ea 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -1846,10 +1846,8 @@ thread_command (const char *tidstr, int from_tty)
 				       | USER_SELECTED_FRAME);
 	}
       else
-	{
-	  gdb::observers::user_selected_context_changed.notify
-	    (USER_SELECTED_THREAD | USER_SELECTED_FRAME);
-	}
+	notify_user_selected_context_changed
+	  (USER_SELECTED_THREAD | USER_SELECTED_FRAME);
     }
 }
 
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 11/30] gdb: add interp::on_new_thread method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (9 preceding siblings ...)
  2023-05-02 20:49 ` [PATCH 10/30] gdb: add interp::on_user_selected_context_changed method Simon Marchi
@ 2023-05-02 20:49 ` Simon Marchi
  2023-05-02 20:49 ` [PATCH 12/30] gdb: add interp::on_thread_exited method Simon Marchi
                   ` (20 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:49 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same idea as previous patches, but for new_thread.

Change-Id: Ib70ae3421b736fd69d86c4e7c708bec349aa256c
---
 gdb/interps.c      |  8 ++++++++
 gdb/interps.h      |  7 +++++++
 gdb/mi/mi-interp.c | 25 +++++++------------------
 gdb/mi/mi-interp.h |  1 +
 gdb/thread.c       | 12 +++++++++++-
 5 files changed, 34 insertions(+), 19 deletions(-)

diff --git a/gdb/interps.c b/gdb/interps.c
index 55abcb3c6e40..896484530aad 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -446,6 +446,14 @@ interps_notify_user_selected_context_changed (user_selected_what selection)
   interps_notify (&interp::on_user_selected_context_changed, selection);
 }
 
+/* See interps.h.  */
+
+void
+interps_notify_new_thread (thread_info *t)
+{
+  interps_notify (&interp::on_new_thread, t);
+}
+
 /* This just adds the "interpreter-exec" command.  */
 void _initialize_interpreter ();
 void
diff --git a/gdb/interps.h b/gdb/interps.h
index 4706c9bb63e7..05ea91e0cdaa 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -29,6 +29,7 @@ struct ui_out;
 struct interp;
 struct ui;
 class completion_tracker;
+struct thread_info;
 
 typedef struct interp *(*interp_factory_func) (const char *name);
 
@@ -114,6 +115,9 @@ class interp : public intrusive_list_node<interp>
   virtual void on_user_selected_context_changed (user_selected_what selection)
     {}
 
+  /* Notify the interpreter that thread T has been created.  */
+  virtual void on_new_thread (thread_info *t) {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
@@ -225,6 +229,9 @@ extern void interps_notify_exited (int status);
 extern void interps_notify_user_selected_context_changed
   (user_selected_what selection);
 
+/* Notify all interpreters that thread T has been created.  */
+extern void interps_notify_new_thread (thread_info *t);
+
 /* well-known interpreters */
 #define INTERP_CONSOLE		"console"
 #define INTERP_MI2             "mi2"
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index ab8c3efbb128..42ec1a7b522e 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -60,7 +60,6 @@ static int mi_interp_query_hook (const char *ctlstr, va_list ap)
 static void mi_insert_notify_hooks (void);
 static void mi_remove_notify_hooks (void);
 
-static void mi_new_thread (struct thread_info *t);
 static void mi_thread_exit (struct thread_info *t, int silent);
 static void mi_record_changed (struct inferior*, int, const char *,
 			       const char *);
@@ -306,24 +305,15 @@ mi_interp::pre_command_loop ()
   display_mi_prompt (mi);
 }
 
-static void
-mi_new_thread (struct thread_info *t)
+void
+mi_interp::on_new_thread (thread_info *t)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-      if (mi == NULL)
-	continue;
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      gdb_printf (mi->event_channel,
-		  "thread-created,id=\"%d\",group-id=\"i%d\"",
-		  t->global_num, t->inf->num);
-      gdb_flush (mi->event_channel);
-    }
+  gdb_printf (this->event_channel, "thread-created,id=\"%d\",group-id=\"i%d\"",
+	      t->global_num, t->inf->num);
+  gdb_flush (this->event_channel);
 }
 
 static void
@@ -1188,7 +1178,6 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
 
-  gdb::observers::new_thread.attach (mi_new_thread, "mi-interp");
   gdb::observers::thread_exit.attach (mi_thread_exit, "mi-interp");
   gdb::observers::inferior_added.attach (mi_inferior_added, "mi-interp");
   gdb::observers::inferior_appeared.attach (mi_inferior_appeared, "mi-interp");
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index 430c61dbbf0a..77fa708397ac 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -50,6 +50,7 @@ class mi_interp final : public interp
   void on_sync_execution_done () override;
   void on_command_error () override;
   void on_user_selected_context_changed (user_selected_what selection) override;
+  void on_new_thread (thread_info *t) override;
 
   /* MI's output channels */
   mi_console_file *out;
diff --git a/gdb/thread.c b/gdb/thread.c
index 13db9f8747ea..223ba1df96d9 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -49,6 +49,7 @@
 #include "gdbsupport/gdb_optional.h"
 #include "inline-frame.h"
 #include "stack.h"
+#include "interps.h"
 
 /* See gdbthread.h.  */
 
@@ -260,6 +261,15 @@ new_thread (struct inferior *inf, ptid_t ptid)
   return tp;
 }
 
+/* Notify interpreters and observers that thread T has been created.  */
+
+static void
+notify_new_thread (thread_info *t)
+{
+  interps_notify_new_thread (t);
+  gdb::observers::new_thread.notify (t);
+}
+
 struct thread_info *
 add_thread_silent (process_stratum_target *targ, ptid_t ptid)
 {
@@ -280,7 +290,7 @@ add_thread_silent (process_stratum_target *targ, ptid_t ptid)
     delete_thread (tp);
 
   tp = new_thread (inf, ptid);
-  gdb::observers::new_thread.notify (tp);
+  notify_new_thread (tp);
 
   return tp;
 }
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 12/30] gdb: add interp::on_thread_exited method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (10 preceding siblings ...)
  2023-05-02 20:49 ` [PATCH 11/30] gdb: add interp::on_new_thread method Simon Marchi
@ 2023-05-02 20:49 ` Simon Marchi
  2023-05-02 20:49 ` [PATCH 13/30] gdb: add interp::on_inferior_added method Simon Marchi
                   ` (19 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:49 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same idea as previous patches, but for thread_exited.

Change-Id: I4be974cbe58cf635453fef503c2d77c82522cbd9
---
 gdb/interps.c      |  8 ++++++++
 gdb/interps.h      |  6 ++++++
 gdb/mi/mi-interp.c | 25 +++++++------------------
 gdb/mi/mi-interp.h |  1 +
 gdb/thread.c       | 11 ++++++++++-
 5 files changed, 32 insertions(+), 19 deletions(-)

diff --git a/gdb/interps.c b/gdb/interps.c
index 896484530aad..be11fd835189 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -454,6 +454,14 @@ interps_notify_new_thread (thread_info *t)
   interps_notify (&interp::on_new_thread, t);
 }
 
+/* See interps.h.  */
+
+void
+interps_notify_thread_exited (thread_info *t, int silent)
+{
+  interps_notify (&interp::on_thread_exited, t, silent);
+}
+
 /* This just adds the "interpreter-exec" command.  */
 void _initialize_interpreter ();
 void
diff --git a/gdb/interps.h b/gdb/interps.h
index 05ea91e0cdaa..cd099381d002 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -118,6 +118,9 @@ class interp : public intrusive_list_node<interp>
   /* Notify the interpreter that thread T has been created.  */
   virtual void on_new_thread (thread_info *t) {}
 
+  /* Notify the interpreter that thread T has exited.  */
+  virtual void on_thread_exited (thread_info *, int silent) {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
@@ -232,6 +235,9 @@ extern void interps_notify_user_selected_context_changed
 /* Notify all interpreters that thread T has been created.  */
 extern void interps_notify_new_thread (thread_info *t);
 
+/* Notify all interpreters that thread T has exited.  */
+extern void interps_notify_thread_exited (thread_info *t, int silent);
+
 /* well-known interpreters */
 #define INTERP_CONSOLE		"console"
 #define INTERP_MI2             "mi2"
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 42ec1a7b522e..a1960b14046d 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -60,7 +60,6 @@ static int mi_interp_query_hook (const char *ctlstr, va_list ap)
 static void mi_insert_notify_hooks (void);
 static void mi_remove_notify_hooks (void);
 
-static void mi_thread_exit (struct thread_info *t, int silent);
 static void mi_record_changed (struct inferior*, int, const char *,
 			       const char *);
 static void mi_inferior_added (struct inferior *inf);
@@ -316,23 +315,14 @@ mi_interp::on_new_thread (thread_info *t)
   gdb_flush (this->event_channel);
 }
 
-static void
-mi_thread_exit (struct thread_info *t, int silent)
+void
+mi_interp::on_thread_exited (thread_info *t, int silent)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-      if (mi == NULL)
-	continue;
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
-      gdb_printf (mi->event_channel,
-		  "thread-exited,id=\"%d\",group-id=\"i%d\"",
-		  t->global_num, t->inf->num);
-      gdb_flush (mi->event_channel);
-    }
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
+  gdb_printf (this->event_channel, "thread-exited,id=\"%d\",group-id=\"i%d\"",
+	      t->global_num, t->inf->num);
+  gdb_flush (this->event_channel);
 }
 
 /* Emit notification on changing the state of record.  */
@@ -1178,7 +1168,6 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
 
-  gdb::observers::thread_exit.attach (mi_thread_exit, "mi-interp");
   gdb::observers::inferior_added.attach (mi_inferior_added, "mi-interp");
   gdb::observers::inferior_appeared.attach (mi_inferior_appeared, "mi-interp");
   gdb::observers::inferior_exit.attach (mi_inferior_exit, "mi-interp");
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index 77fa708397ac..443ec03465a7 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -51,6 +51,7 @@ class mi_interp final : public interp
   void on_command_error () override;
   void on_user_selected_context_changed (user_selected_what selection) override;
   void on_new_thread (thread_info *t) override;
+  void on_thread_exited (thread_info *t, int silent) override;
 
   /* MI's output channels */
   mi_console_file *out;
diff --git a/gdb/thread.c b/gdb/thread.c
index 223ba1df96d9..b7b5d9fdd993 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -191,6 +191,15 @@ clear_thread_inferior_resources (struct thread_info *tp)
   clear_inline_frame_state (tp);
 }
 
+/* Notify interpreters and observers that thread T has exited.  */
+
+static void
+notify_thread_exited (thread_info *t, int silent)
+{
+  interps_notify_thread_exited (t, silent);
+  gdb::observers::thread_exit.notify (t, silent);
+}
+
 /* See gdbthread.h.  */
 
 void
@@ -213,7 +222,7 @@ set_thread_exited (thread_info *tp, bool silent)
       if (proc_target != nullptr)
 	proc_target->maybe_remove_resumed_with_pending_wait_status (tp);
 
-      gdb::observers::thread_exit.notify (tp, silent);
+      notify_thread_exited (tp, silent);
 
       /* Tag it as exited.  */
       tp->state = THREAD_EXITED;
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 13/30] gdb: add interp::on_inferior_added method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (11 preceding siblings ...)
  2023-05-02 20:49 ` [PATCH 12/30] gdb: add interp::on_thread_exited method Simon Marchi
@ 2023-05-02 20:49 ` Simon Marchi
  2023-05-02 20:49 ` [PATCH 14/30] gdb: add interp::on_inferior_appeared method Simon Marchi
                   ` (18 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:49 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same idea as previous patches, but for inferior_added.

mi_interp::init avoided using mi_inferior_added, since, as the comment
used to say, it would notify all MI interpreters.  Now, it's easy to
only notify the new interpreter, so it's possible to just call the
on_inferior_added method in mi_interp::init.

Change-Id: I0eddbd5367217d1c982516982089913019ef309f
---
 gdb/inferior.c     | 12 +++++++++++-
 gdb/interps.c      |  8 ++++++++
 gdb/interps.h      |  7 +++++++
 gdb/mi/mi-interp.c | 46 ++++++++--------------------------------------
 gdb/mi/mi-interp.h |  1 +
 5 files changed, 35 insertions(+), 39 deletions(-)

diff --git a/gdb/inferior.c b/gdb/inferior.c
index 8962b6401e34..a70bbe412471 100644
--- a/gdb/inferior.c
+++ b/gdb/inferior.c
@@ -38,6 +38,7 @@
 #include "progspace-and-thread.h"
 #include "gdbsupport/buildargv.h"
 #include "cli/cli-style.h"
+#include "interps.h"
 
 intrusive_list<inferior> inferior_list;
 static int highest_inferior_num;
@@ -189,6 +190,15 @@ inferior::do_all_continuations ()
     }
 }
 
+/* Notify interpreters and observers that inferior INF was added.  */
+
+static void
+notify_inferior_added (inferior *inf)
+{
+  interps_notify_inferior_added (inf);
+  gdb::observers::inferior_added.notify (inf);
+}
+
 struct inferior *
 add_inferior_silent (int pid)
 {
@@ -196,7 +206,7 @@ add_inferior_silent (int pid)
 
   inferior_list.push_back (*inf);
 
-  gdb::observers::inferior_added.notify (inf);
+  notify_inferior_added (inf);
 
   if (pid != 0)
     inferior_appeared (inf, pid);
diff --git a/gdb/interps.c b/gdb/interps.c
index be11fd835189..f64869953088 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -462,6 +462,14 @@ interps_notify_thread_exited (thread_info *t, int silent)
   interps_notify (&interp::on_thread_exited, t, silent);
 }
 
+/* See interps.h.  */
+
+void
+interps_notify_inferior_added (inferior *inf)
+{
+  interps_notify (&interp::on_inferior_added, inf);
+}
+
 /* This just adds the "interpreter-exec" command.  */
 void _initialize_interpreter ();
 void
diff --git a/gdb/interps.h b/gdb/interps.h
index cd099381d002..0c73a1a7ce8a 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -30,6 +30,7 @@ struct interp;
 struct ui;
 class completion_tracker;
 struct thread_info;
+struct inferior;
 
 typedef struct interp *(*interp_factory_func) (const char *name);
 
@@ -121,6 +122,9 @@ class interp : public intrusive_list_node<interp>
   /* Notify the interpreter that thread T has exited.  */
   virtual void on_thread_exited (thread_info *, int silent) {}
 
+  /* Notify the intepreter that inferior INF was added.  */
+  virtual void on_inferior_added (inferior *inf) {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
@@ -238,6 +242,9 @@ extern void interps_notify_new_thread (thread_info *t);
 /* Notify all interpreters that thread T has exited.  */
 extern void interps_notify_thread_exited (thread_info *t, int silent);
 
+/* Notify all intepreters that inferior INF was added.  */
+extern void interps_notify_inferior_added (inferior *inf);
+
 /* well-known interpreters */
 #define INTERP_CONSOLE		"console"
 #define INTERP_MI2             "mi2"
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index a1960b14046d..c4903d7db3b7 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -62,7 +62,6 @@ static void mi_remove_notify_hooks (void);
 
 static void mi_record_changed (struct inferior*, int, const char *,
 			       const char *);
-static void mi_inferior_added (struct inferior *inf);
 static void mi_inferior_appeared (struct inferior *inf);
 static void mi_inferior_exit (struct inferior *inf);
 static void mi_inferior_removed (struct inferior *inf);
@@ -137,20 +136,10 @@ mi_interp::init (bool top_level)
 
 	 This is also called when additional MI interpreters are added (using
 	 the new-ui command), when multiple inferiors possibly exist, so we need
-	 to use iteration to report all the inferiors.  mi_inferior_added can't
-	 be used, because it would print the event on all the other MI UIs.  */
+	 to use iteration to report all the inferiors.  */
 
       for (inferior *inf : all_inferiors ())
-	{
-	  target_terminal::scoped_restore_terminal_state term_state;
-	  target_terminal::ours_for_output ();
-
-	  gdb_printf (mi->event_channel,
-		      "thread-group-added,id=\"i%d\"",
-		      inf->num);
-
-	  gdb_flush (mi->event_channel);
-	}
+	mi->on_inferior_added (inf);
   }
 }
 
@@ -369,32 +358,14 @@ mi_record_changed (struct inferior *inferior, int started, const char *method,
     }
 }
 
-static void
-mi_inferior_added (struct inferior *inf)
+void
+mi_interp::on_inferior_added (inferior *inf)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct interp *interp;
-      struct mi_interp *mi;
-
-      /* We'll be called once for the initial inferior, before the top
-	 level interpreter is set.  */
-      interp = top_level_interpreter ();
-      if (interp == NULL)
-	continue;
-
-      mi = as_mi_interp (interp);
-      if (mi == NULL)
-	continue;
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      gdb_printf (mi->event_channel,
-		  "thread-group-added,id=\"i%d\"",
-		  inf->num);
-      gdb_flush (mi->event_channel);
-    }
+  gdb_printf (this->event_channel, "thread-group-added,id=\"i%d\"", inf->num);
+  gdb_flush (this->event_channel);
 }
 
 static void
@@ -1168,7 +1139,6 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
 
-  gdb::observers::inferior_added.attach (mi_inferior_added, "mi-interp");
   gdb::observers::inferior_appeared.attach (mi_inferior_appeared, "mi-interp");
   gdb::observers::inferior_exit.attach (mi_inferior_exit, "mi-interp");
   gdb::observers::inferior_removed.attach (mi_inferior_removed, "mi-interp");
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index 443ec03465a7..1be0d8771cf5 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -52,6 +52,7 @@ class mi_interp final : public interp
   void on_user_selected_context_changed (user_selected_what selection) override;
   void on_new_thread (thread_info *t) override;
   void on_thread_exited (thread_info *t, int silent) override;
+  void on_inferior_added (inferior *inf) override;
 
   /* MI's output channels */
   mi_console_file *out;
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 14/30] gdb: add interp::on_inferior_appeared method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (12 preceding siblings ...)
  2023-05-02 20:49 ` [PATCH 13/30] gdb: add interp::on_inferior_added method Simon Marchi
@ 2023-05-02 20:49 ` Simon Marchi
  2023-05-02 20:49 ` [PATCH 15/30] gdb: add interp::on_inferior_disappeared method Simon Marchi
                   ` (17 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:49 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same idea as previous patches, but for inferior_appeared.

Change-Id: Ibe4feba34274549a886b1dfb5b3f8d59ae79e1b5
---
 gdb/inferior.c     | 11 ++++++++++-
 gdb/interps.c      |  8 ++++++++
 gdb/interps.h      | 10 ++++++++--
 gdb/mi/mi-interp.c | 25 +++++++------------------
 gdb/mi/mi-interp.h |  1 +
 5 files changed, 34 insertions(+), 21 deletions(-)

diff --git a/gdb/inferior.c b/gdb/inferior.c
index a70bbe412471..46d418a2be39 100644
--- a/gdb/inferior.c
+++ b/gdb/inferior.c
@@ -345,6 +345,15 @@ detach_inferior (inferior *inf)
 		target_pid_to_str (ptid_t (pid)).c_str ());
 }
 
+/* Notify interpreters and observers that inferior INF appeared.  */
+
+static void
+notify_inferior_appeared (inferior *inf)
+{
+  interps_notify_inferior_appeared (inf);
+  gdb::observers::inferior_appeared.notify (inf);
+}
+
 void
 inferior_appeared (struct inferior *inf, int pid)
 {
@@ -358,7 +367,7 @@ inferior_appeared (struct inferior *inf, int pid)
   inf->has_exit_code = false;
   inf->exit_code = 0;
 
-  gdb::observers::inferior_appeared.notify (inf);
+  notify_inferior_appeared (inf);
 }
 
 struct inferior *
diff --git a/gdb/interps.c b/gdb/interps.c
index f64869953088..ed33df2efd4c 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -470,6 +470,14 @@ interps_notify_inferior_added (inferior *inf)
   interps_notify (&interp::on_inferior_added, inf);
 }
 
+/* See interps.h.  */
+
+void
+interps_notify_inferior_appeared (inferior *inf)
+{
+  interps_notify (&interp::on_inferior_appeared, inf);
+}
+
 /* This just adds the "interpreter-exec" command.  */
 void _initialize_interpreter ();
 void
diff --git a/gdb/interps.h b/gdb/interps.h
index 0c73a1a7ce8a..09edaaeb0036 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -122,9 +122,12 @@ class interp : public intrusive_list_node<interp>
   /* Notify the interpreter that thread T has exited.  */
   virtual void on_thread_exited (thread_info *, int silent) {}
 
-  /* Notify the intepreter that inferior INF was added.  */
+  /* Notify the interpreter that inferior INF was added.  */
   virtual void on_inferior_added (inferior *inf) {}
 
+  /* Notify the interpreter that inferior INF was started or attached.  */
+  virtual void on_inferior_appeared (inferior *inf) {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
@@ -242,9 +245,12 @@ extern void interps_notify_new_thread (thread_info *t);
 /* Notify all interpreters that thread T has exited.  */
 extern void interps_notify_thread_exited (thread_info *t, int silent);
 
-/* Notify all intepreters that inferior INF was added.  */
+/* Notify all interpreters that inferior INF was added.  */
 extern void interps_notify_inferior_added (inferior *inf);
 
+/* Notify all interpreters that inferior INF was started or attached.  */
+extern void interps_notify_inferior_appeared (inferior *inf);
+
 /* well-known interpreters */
 #define INTERP_CONSOLE		"console"
 #define INTERP_MI2             "mi2"
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index c4903d7db3b7..3f0aaa7702a5 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -62,7 +62,6 @@ static void mi_remove_notify_hooks (void);
 
 static void mi_record_changed (struct inferior*, int, const char *,
 			       const char *);
-static void mi_inferior_appeared (struct inferior *inf);
 static void mi_inferior_exit (struct inferior *inf);
 static void mi_inferior_removed (struct inferior *inf);
 static void mi_on_resume (ptid_t ptid);
@@ -368,24 +367,15 @@ mi_interp::on_inferior_added (inferior *inf)
   gdb_flush (this->event_channel);
 }
 
-static void
-mi_inferior_appeared (struct inferior *inf)
+void
+mi_interp::on_inferior_appeared (inferior *inf)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-      if (mi == NULL)
-	continue;
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      gdb_printf (mi->event_channel,
-		  "thread-group-started,id=\"i%d\",pid=\"%d\"",
-		  inf->num, inf->pid);
-      gdb_flush (mi->event_channel);
-    }
+  gdb_printf (this->event_channel, "thread-group-started,id=\"i%d\",pid=\"%d\"",
+	      inf->num, inf->pid);
+  gdb_flush (this->event_channel);
 }
 
 static void
@@ -1139,7 +1129,6 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
 
-  gdb::observers::inferior_appeared.attach (mi_inferior_appeared, "mi-interp");
   gdb::observers::inferior_exit.attach (mi_inferior_exit, "mi-interp");
   gdb::observers::inferior_removed.attach (mi_inferior_removed, "mi-interp");
   gdb::observers::record_changed.attach (mi_record_changed, "mi-interp");
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index 1be0d8771cf5..3872577121cf 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -53,6 +53,7 @@ class mi_interp final : public interp
   void on_new_thread (thread_info *t) override;
   void on_thread_exited (thread_info *t, int silent) override;
   void on_inferior_added (inferior *inf) override;
+  void on_inferior_appeared (inferior *inf) override;
 
   /* MI's output channels */
   mi_console_file *out;
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 15/30] gdb: add interp::on_inferior_disappeared method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (13 preceding siblings ...)
  2023-05-02 20:49 ` [PATCH 14/30] gdb: add interp::on_inferior_appeared method Simon Marchi
@ 2023-05-02 20:49 ` Simon Marchi
  2023-05-02 20:49 ` [PATCH 16/30] gdb: add interp::on_inferior_removed method Simon Marchi
                   ` (16 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:49 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same idea as previous patches, but for inferior_disappeared.

For symmetry with on_inferior_appeared, I named this one
on_inferior_disappeared, despite the observer being called
inferior_exit.  This is called when detaching an inferior, so I think
that calling it "disappeared" is a bit less misleading (the observer
should probably be renamed later).

Change-Id: I372101586bc9454997953c1e540a2a6685f53ef6
---
 gdb/inferior.c     | 11 ++++++++++-
 gdb/interps.c      |  8 ++++++++
 gdb/interps.h      |  6 ++++++
 gdb/mi/mi-interp.c | 34 ++++++++++++----------------------
 gdb/mi/mi-interp.h |  1 +
 5 files changed, 37 insertions(+), 23 deletions(-)

diff --git a/gdb/inferior.c b/gdb/inferior.c
index 46d418a2be39..32fe9ccbd659 100644
--- a/gdb/inferior.c
+++ b/gdb/inferior.c
@@ -283,6 +283,15 @@ delete_inferior (struct inferior *inf)
   delete inf;
 }
 
+/* Notify interpreters and observers that inferior INF disappeared.  */
+
+static void
+notify_inferior_disappeared (inferior *inf)
+{
+  interps_notify_inferior_disappeared (inf);
+  gdb::observers::inferior_exit.notify (inf);
+}
+
 /* If SILENT then be quiet -- don't announce a inferior exit, or the
    exit of its threads.  */
 
@@ -291,7 +300,7 @@ exit_inferior_1 (struct inferior *inf, int silent)
 {
   inf->clear_thread_list (silent);
 
-  gdb::observers::inferior_exit.notify (inf);
+  notify_inferior_disappeared (inf);
 
   inf->pid = 0;
   inf->fake_pid_p = false;
diff --git a/gdb/interps.c b/gdb/interps.c
index ed33df2efd4c..46b0ecbd73fa 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -478,6 +478,14 @@ interps_notify_inferior_appeared (inferior *inf)
   interps_notify (&interp::on_inferior_appeared, inf);
 }
 
+/* See interps.h.  */
+
+void
+interps_notify_inferior_disappeared (inferior *inf)
+{
+  interps_notify (&interp::on_inferior_disappeared, inf);
+}
+
 /* This just adds the "interpreter-exec" command.  */
 void _initialize_interpreter ();
 void
diff --git a/gdb/interps.h b/gdb/interps.h
index 09edaaeb0036..b1aee5db8290 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -128,6 +128,9 @@ class interp : public intrusive_list_node<interp>
   /* Notify the interpreter that inferior INF was started or attached.  */
   virtual void on_inferior_appeared (inferior *inf) {}
 
+  /* Notify the interpreter that inferior INF exited or was detached.  */
+  virtual void on_inferior_disappeared (inferior *inf) {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
@@ -251,6 +254,9 @@ extern void interps_notify_inferior_added (inferior *inf);
 /* Notify all interpreters that inferior INF was started or attached.  */
 extern void interps_notify_inferior_appeared (inferior *inf);
 
+/* Notify all interpreters that inferior INF exited or was detached.  */
+extern void interps_notify_inferior_disappeared (inferior *inf);
+
 /* well-known interpreters */
 #define INTERP_CONSOLE		"console"
 #define INTERP_MI2             "mi2"
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 3f0aaa7702a5..f6ce077d8b9e 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -62,7 +62,6 @@ static void mi_remove_notify_hooks (void);
 
 static void mi_record_changed (struct inferior*, int, const char *,
 			       const char *);
-static void mi_inferior_exit (struct inferior *inf);
 static void mi_inferior_removed (struct inferior *inf);
 static void mi_on_resume (ptid_t ptid);
 static void mi_solib_loaded (struct so_list *solib);
@@ -378,29 +377,21 @@ mi_interp::on_inferior_appeared (inferior *inf)
   gdb_flush (this->event_channel);
 }
 
-static void
-mi_inferior_exit (struct inferior *inf)
+void
+mi_interp::on_inferior_disappeared (inferior *inf)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-      if (mi == NULL)
-	continue;
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      if (inf->has_exit_code)
-	gdb_printf (mi->event_channel,
-		    "thread-group-exited,id=\"i%d\",exit-code=\"%s\"",
-		    inf->num, int_string (inf->exit_code, 8, 0, 0, 1));
-      else
-	gdb_printf (mi->event_channel,
-		    "thread-group-exited,id=\"i%d\"", inf->num);
+  if (inf->has_exit_code)
+    gdb_printf (this->event_channel,
+		"thread-group-exited,id=\"i%d\",exit-code=\"%s\"",
+		inf->num, int_string (inf->exit_code, 8, 0, 0, 1));
+  else
+    gdb_printf (this->event_channel,
+		"thread-group-exited,id=\"i%d\"", inf->num);
 
-      gdb_flush (mi->event_channel);
-    }
+  gdb_flush (this->event_channel);
 }
 
 static void
@@ -1129,7 +1120,6 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
 
-  gdb::observers::inferior_exit.attach (mi_inferior_exit, "mi-interp");
   gdb::observers::inferior_removed.attach (mi_inferior_removed, "mi-interp");
   gdb::observers::record_changed.attach (mi_record_changed, "mi-interp");
   gdb::observers::target_resumed.attach (mi_on_resume, "mi-interp");
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index 3872577121cf..5db17a6d2684 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -54,6 +54,7 @@ class mi_interp final : public interp
   void on_thread_exited (thread_info *t, int silent) override;
   void on_inferior_added (inferior *inf) override;
   void on_inferior_appeared (inferior *inf) override;
+  void on_inferior_disappeared (inferior *inf) override;
 
   /* MI's output channels */
   mi_console_file *out;
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 16/30] gdb: add interp::on_inferior_removed method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (14 preceding siblings ...)
  2023-05-02 20:49 ` [PATCH 15/30] gdb: add interp::on_inferior_disappeared method Simon Marchi
@ 2023-05-02 20:49 ` Simon Marchi
  2023-05-02 20:49 ` [PATCH 17/30] gdb: add interp::on_record_changed method Simon Marchi
                   ` (15 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:49 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same idea as previous patches, but for inferior_removed.

Change-Id: I7971840bbbdcfabf77e2ded7584830c9dfdd10d0
---
 gdb/inferior.c     | 11 ++++++++++-
 gdb/interps.c      |  8 ++++++++
 gdb/interps.h      |  6 ++++++
 gdb/mi/mi-interp.c | 24 ++++++------------------
 gdb/mi/mi-interp.h |  1 +
 5 files changed, 31 insertions(+), 19 deletions(-)

diff --git a/gdb/inferior.c b/gdb/inferior.c
index 32fe9ccbd659..eee4785fbf76 100644
--- a/gdb/inferior.c
+++ b/gdb/inferior.c
@@ -260,6 +260,15 @@ inferior::clear_thread_list (bool silent)
   ptid_thread_map.clear ();
 }
 
+/* Notify interpreters and observers that inferior INF was removed.  */
+
+static void
+notify_inferior_removed (inferior *inf)
+{
+  interps_notify_inferior_removed (inf);
+  gdb::observers::inferior_removed.notify (inf);
+}
+
 void
 delete_inferior (struct inferior *inf)
 {
@@ -268,7 +277,7 @@ delete_inferior (struct inferior *inf)
   auto it = inferior_list.iterator_to (*inf);
   inferior_list.erase (it);
 
-  gdb::observers::inferior_removed.notify (inf);
+  notify_inferior_removed (inf);
 
   /* Pop all targets now, this ensures that inferior::unpush is called
      correctly.  As pop_all_targets ends up making a temporary switch to
diff --git a/gdb/interps.c b/gdb/interps.c
index 46b0ecbd73fa..1bcc33c2a8c1 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -486,6 +486,14 @@ interps_notify_inferior_disappeared (inferior *inf)
   interps_notify (&interp::on_inferior_disappeared, inf);
 }
 
+/* See interps.h.  */
+
+void
+interps_notify_inferior_removed (inferior *inf)
+{
+  interps_notify (&interp::on_inferior_removed, inf);
+}
+
 /* This just adds the "interpreter-exec" command.  */
 void _initialize_interpreter ();
 void
diff --git a/gdb/interps.h b/gdb/interps.h
index b1aee5db8290..ad351bbf807f 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -131,6 +131,9 @@ class interp : public intrusive_list_node<interp>
   /* Notify the interpreter that inferior INF exited or was detached.  */
   virtual void on_inferior_disappeared (inferior *inf) {}
 
+  /* Notify the interpreter that inferior INF was removed.  */
+  virtual void on_inferior_removed (inferior *inf) {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
@@ -257,6 +260,9 @@ extern void interps_notify_inferior_appeared (inferior *inf);
 /* Notify all interpreters that inferior INF exited or was detached.  */
 extern void interps_notify_inferior_disappeared (inferior *inf);
 
+/* Notify all interpreters that inferior INF was removed.  */
+extern void interps_notify_inferior_removed (inferior *inf);
+
 /* well-known interpreters */
 #define INTERP_CONSOLE		"console"
 #define INTERP_MI2             "mi2"
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index f6ce077d8b9e..e2e7eb56fb57 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -62,7 +62,6 @@ static void mi_remove_notify_hooks (void);
 
 static void mi_record_changed (struct inferior*, int, const char *,
 			       const char *);
-static void mi_inferior_removed (struct inferior *inf);
 static void mi_on_resume (ptid_t ptid);
 static void mi_solib_loaded (struct so_list *solib);
 static void mi_solib_unloaded (struct so_list *solib);
@@ -394,24 +393,14 @@ mi_interp::on_inferior_disappeared (inferior *inf)
   gdb_flush (this->event_channel);
 }
 
-static void
-mi_inferior_removed (struct inferior *inf)
+void
+mi_interp::on_inferior_removed (inferior *inf)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-      if (mi == NULL)
-	continue;
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      gdb_printf (mi->event_channel,
-		  "thread-group-removed,id=\"i%d\"",
-		  inf->num);
-      gdb_flush (mi->event_channel);
-    }
+  gdb_printf (this->event_channel, "thread-group-removed,id=\"i%d\"", inf->num);
+  gdb_flush (this->event_channel);
 }
 
 /* Observers for several run control events that print why the
@@ -1120,7 +1109,6 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
 
-  gdb::observers::inferior_removed.attach (mi_inferior_removed, "mi-interp");
   gdb::observers::record_changed.attach (mi_record_changed, "mi-interp");
   gdb::observers::target_resumed.attach (mi_on_resume, "mi-interp");
   gdb::observers::solib_loaded.attach (mi_solib_loaded, "mi-interp");
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index 5db17a6d2684..a970c3d0db98 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -55,6 +55,7 @@ class mi_interp final : public interp
   void on_inferior_added (inferior *inf) override;
   void on_inferior_appeared (inferior *inf) override;
   void on_inferior_disappeared (inferior *inf) override;
+  void on_inferior_removed (inferior *inf) override;
 
   /* MI's output channels */
   mi_console_file *out;
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 17/30] gdb: add interp::on_record_changed method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (15 preceding siblings ...)
  2023-05-02 20:49 ` [PATCH 16/30] gdb: add interp::on_inferior_removed method Simon Marchi
@ 2023-05-02 20:49 ` Simon Marchi
  2023-05-02 20:49 ` [PATCH 18/30] gdb: add interp::on_target_resumed method Simon Marchi
                   ` (14 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:49 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same idea as previous patches, but for record_changed

Change-Id: I5eeeacd703af8401c315060514c94e8e6439cc40
---
 gdb/interps.c       |  9 +++++++
 gdb/interps.h       | 18 +++++++++++++
 gdb/mi/mi-interp.c  | 63 ++++++++++++++++-----------------------------
 gdb/mi/mi-interp.h  |  2 ++
 gdb/observable.c    |  1 -
 gdb/observable.h    | 12 ---------
 gdb/record-btrace.c |  3 ++-
 gdb/record-full.c   |  3 ++-
 gdb/record.c        |  3 ++-
 9 files changed, 57 insertions(+), 57 deletions(-)

diff --git a/gdb/interps.c b/gdb/interps.c
index 1bcc33c2a8c1..986c5b755f84 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -494,6 +494,15 @@ interps_notify_inferior_removed (inferior *inf)
   interps_notify (&interp::on_inferior_removed, inf);
 }
 
+/* See interps.h.  */
+
+void
+interps_notify_record_changed (inferior *inf, int started, const char *method,
+			       const char *format)
+{
+  interps_notify (&interp::on_record_changed, inf, started, method, format);
+}
+
 /* This just adds the "interpreter-exec" command.  */
 void _initialize_interpreter ();
 void
diff --git a/gdb/interps.h b/gdb/interps.h
index ad351bbf807f..be3d6d92b99c 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -134,6 +134,11 @@ class interp : public intrusive_list_node<interp>
   /* Notify the interpreter that inferior INF was removed.  */
   virtual void on_inferior_removed (inferior *inf) {}
 
+  /* Notify the interpreter that the status of process record for INF
+     changed.  */
+  virtual void on_record_changed (inferior *inf, int started,
+				  const char *method, const char *format) {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
@@ -263,6 +268,19 @@ extern void interps_notify_inferior_disappeared (inferior *inf);
 /* Notify all interpreters that inferior INF was removed.  */
 extern void interps_notify_inferior_removed (inferior *inf);
 
+/* Notify all interpreters that the status of process record for INF changed.
+
+   The process record is started if STARTED is true, and the process record is
+   stopped if STARTED is false.
+
+   When STARTED is true, METHOD indicates the short name of the method used for
+   recording.  If the method supports multiple formats, FORMAT indicates which
+   one is being used, otherwise it is nullptr.  When STARTED is false, they are
+   both nullptr.  */
+extern void interps_notify_record_changed (inferior *inf, int started,
+					   const char *method,
+					   const char *format);
+
 /* well-known interpreters */
 #define INTERP_CONSOLE		"console"
 #define INTERP_MI2             "mi2"
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index e2e7eb56fb57..77050d0860fd 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -60,8 +60,6 @@ static int mi_interp_query_hook (const char *ctlstr, va_list ap)
 static void mi_insert_notify_hooks (void);
 static void mi_remove_notify_hooks (void);
 
-static void mi_record_changed (struct inferior*, int, const char *,
-			       const char *);
 static void mi_on_resume (ptid_t ptid);
 static void mi_solib_loaded (struct so_list *solib);
 static void mi_solib_unloaded (struct so_list *solib);
@@ -311,48 +309,32 @@ mi_interp::on_thread_exited (thread_info *t, int silent)
   gdb_flush (this->event_channel);
 }
 
-/* Emit notification on changing the state of record.  */
-
-static void
-mi_record_changed (struct inferior *inferior, int started, const char *method,
-		   const char *format)
+void
+mi_interp::on_record_changed (inferior *inferior, int started,
+			      const char *method, const char *format)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-      if (mi == NULL)
-	continue;
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      if (started)
-	{
-	  if (format != NULL)
-	    {
-	      gdb_printf (mi->event_channel,
-			  "record-started,thread-group=\"i%d\","
-			  "method=\"%s\",format=\"%s\"",
-			  inferior->num, method, format);
-	    }
-	  else
-	    {
-	      gdb_printf (mi->event_channel,
-			  "record-started,thread-group=\"i%d\","
-			  "method=\"%s\"",
-			  inferior->num, method);
-	    }
-	}
+  if (started)
+    {
+      if (format != NULL)
+	gdb_printf (this->event_channel,
+		    "record-started,thread-group=\"i%d\","
+		    "method=\"%s\",format=\"%s\"",
+		    inferior->num, method, format);
       else
-	{
-	  gdb_printf (mi->event_channel,
-		      "record-stopped,thread-group=\"i%d\"",
-		      inferior->num);
-	}
-
-      gdb_flush (mi->event_channel);
+	gdb_printf (this->event_channel,
+		    "record-started,thread-group=\"i%d\","
+		    "method=\"%s\"",
+		    inferior->num, method);
     }
+  else
+    gdb_printf (this->event_channel,
+		"record-stopped,thread-group=\"i%d\"",
+		inferior->num);
+
+  gdb_flush (this->event_channel);
 }
 
 void
@@ -1109,7 +1091,6 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
 
-  gdb::observers::record_changed.attach (mi_record_changed, "mi-interp");
   gdb::observers::target_resumed.attach (mi_on_resume, "mi-interp");
   gdb::observers::solib_loaded.attach (mi_solib_loaded, "mi-interp");
   gdb::observers::solib_unloaded.attach (mi_solib_unloaded, "mi-interp");
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index a970c3d0db98..29a437c14f26 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -56,6 +56,8 @@ class mi_interp final : public interp
   void on_inferior_appeared (inferior *inf) override;
   void on_inferior_disappeared (inferior *inf) override;
   void on_inferior_removed (inferior *inf) override;
+  void on_record_changed (inferior *inf, int started, const char *method,
+			  const char *format) override;
 
   /* MI's output channels */
   mi_console_file *out;
diff --git a/gdb/observable.c b/gdb/observable.c
index bfb92b4fe15e..5b78d48908b7 100644
--- a/gdb/observable.c
+++ b/gdb/observable.c
@@ -39,7 +39,6 @@ DEFINE_OBSERVABLE (executable_changed);
 DEFINE_OBSERVABLE (inferior_created);
 DEFINE_OBSERVABLE (inferior_execd);
 DEFINE_OBSERVABLE (inferior_forked);
-DEFINE_OBSERVABLE (record_changed);
 DEFINE_OBSERVABLE (solib_loaded);
 DEFINE_OBSERVABLE (solib_unloaded);
 DEFINE_OBSERVABLE (new_objfile);
diff --git a/gdb/observable.h b/gdb/observable.h
index 1ec927671e53..be7c6ca8dd23 100644
--- a/gdb/observable.h
+++ b/gdb/observable.h
@@ -88,18 +88,6 @@ extern observable<inferior */* exec_inf */, inferior */* follow_inf */>
 extern observable<inferior */* parent_inf */, inferior */* child_inf */,
 		  target_waitkind /* fork_kind */> inferior_forked;
 
-/* The status of process record for inferior inferior in gdb has
-   changed.  The process record is started if STARTED is true, and
-   the process record is stopped if STARTED is false.
-
-   When STARTED is true, METHOD indicates the short name of the
-   method used for recording.  If the method supports multiple
-   formats, FORMAT indicates which one is being used, otherwise it
-   is NULL.  When STARTED is false, they are both NULL.  */
-extern observable<struct inferior */* inferior */, int /* started */,
-		  const char */* method */, const char */* format */>
-    record_changed;
-
 /* The shared library specified by SOLIB has been loaded.  Note that
    when gdb calls this observer, the library's symbols probably
    haven't been loaded yet.  */
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 9dd8474673b8..e933a428f3af 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -45,6 +45,7 @@
 #include "async-event.h"
 #include <forward_list>
 #include "objfiles.h"
+#include "interps.h"
 
 static const target_info record_btrace_target_info = {
   "record-btrace",
@@ -347,7 +348,7 @@ record_btrace_push_target (void)
   record_btrace_generating_corefile = 0;
 
   format = btrace_format_short_string (record_btrace_conf.format);
-  gdb::observers::record_changed.notify (current_inferior (), 1, "btrace", format);
+  interps_notify_record_changed (current_inferior (), 1, "btrace", format);
 }
 
 /* Disable btrace on a set of threads on scope exit.  */
diff --git a/gdb/record-full.c b/gdb/record-full.c
index 026c309b674c..faf8b595d22c 100644
--- a/gdb/record-full.c
+++ b/gdb/record-full.c
@@ -40,6 +40,7 @@
 #include "gdbsupport/byte-vector.h"
 #include "async-event.h"
 #include "valprint.h"
+#include "interps.h"
 
 #include <signal.h>
 
@@ -981,7 +982,7 @@ record_full_open (const char *name, int from_tty)
 
   record_full_init_record_breakpoints ();
 
-  gdb::observers::record_changed.notify (current_inferior (),  1, "full", NULL);
+  interps_notify_record_changed (current_inferior (),  1, "full", NULL);
 }
 
 /* "close" target method.  Close the process record target.  */
diff --git a/gdb/record.c b/gdb/record.c
index f7c951535374..f7c82665b058 100644
--- a/gdb/record.c
+++ b/gdb/record.c
@@ -26,6 +26,7 @@
 #include "gdbsupport/common-utils.h"
 #include "cli/cli-utils.h"
 #include "disasm.h"
+#include "interps.h"
 
 #include <ctype.h>
 
@@ -311,7 +312,7 @@ cmd_record_stop (const char *args, int from_tty)
   gdb_printf (_("Process record is stopped and all execution "
 		"logs are deleted.\n"));
 
-  gdb::observers::record_changed.notify (current_inferior (), 0, NULL, NULL);
+  interps_notify_record_changed (current_inferior (), 0, NULL, NULL);
 }
 
 
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 18/30] gdb: add interp::on_target_resumed method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (16 preceding siblings ...)
  2023-05-02 20:49 ` [PATCH 17/30] gdb: add interp::on_record_changed method Simon Marchi
@ 2023-05-02 20:49 ` Simon Marchi
  2023-05-02 20:49 ` [PATCH 19/30] gdb: add interp::on_solib_loaded method Simon Marchi
                   ` (13 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:49 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same idea as previous patches, but for target_resumed.

Change-Id: I66fa28d1d41a1f3c4fb0d6a470137d493eac3c8c
---
 gdb/interps.c      |  8 ++++++++
 gdb/interps.h      |  6 ++++++
 gdb/mi/mi-interp.c | 20 +++++---------------
 gdb/mi/mi-interp.h |  1 +
 gdb/thread.c       | 15 ++++++++++++---
 5 files changed, 32 insertions(+), 18 deletions(-)

diff --git a/gdb/interps.c b/gdb/interps.c
index 986c5b755f84..17ea42499f95 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -503,6 +503,14 @@ interps_notify_record_changed (inferior *inf, int started, const char *method,
   interps_notify (&interp::on_record_changed, inf, started, method, format);
 }
 
+/* See interps.h.  */
+
+void
+interps_notify_target_resumed (ptid_t ptid)
+{
+  interps_notify (&interp::on_target_resumed, ptid);
+}
+
 /* This just adds the "interpreter-exec" command.  */
 void _initialize_interpreter ();
 void
diff --git a/gdb/interps.h b/gdb/interps.h
index be3d6d92b99c..0434efe40b3c 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -139,6 +139,9 @@ class interp : public intrusive_list_node<interp>
   virtual void on_record_changed (inferior *inf, int started,
 				  const char *method, const char *format) {}
 
+  /* Notify the interpreter that the target was resumed.  */
+  virtual void on_target_resumed (ptid_t ptid) {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
@@ -281,6 +284,9 @@ extern void interps_notify_record_changed (inferior *inf, int started,
 					   const char *method,
 					   const char *format);
 
+/* Notify all interpreters that the target was resumed.  */
+extern void interps_notify_target_resumed (ptid_t ptid);
+
 /* well-known interpreters */
 #define INTERP_CONSOLE		"console"
 #define INTERP_MI2             "mi2"
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 77050d0860fd..5c944febf427 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -60,7 +60,6 @@ static int mi_interp_query_hook (const char *ctlstr, va_list ap)
 static void mi_insert_notify_hooks (void);
 static void mi_remove_notify_hooks (void);
 
-static void mi_on_resume (ptid_t ptid);
 static void mi_solib_loaded (struct so_list *solib);
 static void mi_solib_unloaded (struct so_list *solib);
 static void mi_about_to_proceed (void);
@@ -801,8 +800,8 @@ mi_on_resume_1 (struct mi_interp *mi,
   gdb_flush (mi->raw_stdout);
 }
 
-static void
-mi_on_resume (ptid_t ptid)
+void
+mi_interp::on_target_resumed (ptid_t ptid)
 {
   struct thread_info *tp = NULL;
 
@@ -816,18 +815,10 @@ mi_on_resume (ptid_t ptid)
   if (tp->control.in_infcall)
     return;
 
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-      if (mi == NULL)
-	continue;
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      mi_on_resume_1 (mi, target, ptid);
-    }
+  mi_on_resume_1 (this, target, ptid);
 }
 
 /* See mi-interp.h.  */
@@ -1091,7 +1082,6 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
 
-  gdb::observers::target_resumed.attach (mi_on_resume, "mi-interp");
   gdb::observers::solib_loaded.attach (mi_solib_loaded, "mi-interp");
   gdb::observers::solib_unloaded.attach (mi_solib_unloaded, "mi-interp");
   gdb::observers::about_to_proceed.attach (mi_about_to_proceed, "mi-interp");
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index 29a437c14f26..fc0d8218ba73 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -58,6 +58,7 @@ class mi_interp final : public interp
   void on_inferior_removed (inferior *inf) override;
   void on_record_changed (inferior *inf, int started, const char *method,
 			  const char *format) override;
+  void on_target_resumed (ptid_t ptid) override;
 
   /* MI's output channels */
   mi_console_file *out;
diff --git a/gdb/thread.c b/gdb/thread.c
index b7b5d9fdd993..7f7f035b5ab3 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -845,13 +845,22 @@ set_running_thread (struct thread_info *tp, bool running)
   return started;
 }
 
+/* Notify interpreters and observers that the target was resumed.  */
+
+static void
+notify_target_resumed (ptid_t ptid)
+{
+  interps_notify_target_resumed (ptid);
+  gdb::observers::target_resumed.notify (ptid);
+}
+
 /* See gdbthread.h.  */
 
 void
 thread_info::set_running (bool running)
 {
   if (set_running_thread (this, running))
-    gdb::observers::target_resumed.notify (this->ptid);
+    notify_target_resumed (this->ptid);
 }
 
 void
@@ -868,7 +877,7 @@ set_running (process_stratum_target *targ, ptid_t ptid, bool running)
       any_started = true;
 
   if (any_started)
-    gdb::observers::target_resumed.notify (ptid);
+    notify_target_resumed (ptid);
 }
 
 void
@@ -916,7 +925,7 @@ finish_thread_state (process_stratum_target *targ, ptid_t ptid)
       any_started = true;
 
   if (any_started)
-    gdb::observers::target_resumed.notify (ptid);
+    notify_target_resumed (ptid);
 }
 
 /* See gdbthread.h.  */
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 19/30] gdb: add interp::on_solib_loaded method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (17 preceding siblings ...)
  2023-05-02 20:49 ` [PATCH 18/30] gdb: add interp::on_target_resumed method Simon Marchi
@ 2023-05-02 20:49 ` Simon Marchi
  2023-05-02 20:50 ` [PATCH 20/30] gdb: add interp::on_solib_unloaded method Simon Marchi
                   ` (12 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:49 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same idea as previous patches, but for solib_loaded

Change-Id: I85edb0a4b377f4b2c39ffccf31cb75f38bae0f55
---
 gdb/interps.c      |  8 ++++++++
 gdb/interps.h      |  7 +++++++
 gdb/mi/mi-interp.c | 29 +++++++++--------------------
 gdb/mi/mi-interp.h |  1 +
 gdb/solib.c        | 11 ++++++++++-
 5 files changed, 35 insertions(+), 21 deletions(-)

diff --git a/gdb/interps.c b/gdb/interps.c
index 17ea42499f95..6dde83b45e79 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -511,6 +511,14 @@ interps_notify_target_resumed (ptid_t ptid)
   interps_notify (&interp::on_target_resumed, ptid);
 }
 
+/* See interps.h.  */
+
+void
+interps_notify_solib_loaded (so_list *so)
+{
+  interps_notify (&interp::on_solib_loaded, so);
+}
+
 /* This just adds the "interpreter-exec" command.  */
 void _initialize_interpreter ();
 void
diff --git a/gdb/interps.h b/gdb/interps.h
index 0434efe40b3c..7fce025aad69 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -31,6 +31,7 @@ struct ui;
 class completion_tracker;
 struct thread_info;
 struct inferior;
+struct so_list;
 
 typedef struct interp *(*interp_factory_func) (const char *name);
 
@@ -142,6 +143,9 @@ class interp : public intrusive_list_node<interp>
   /* Notify the interpreter that the target was resumed.  */
   virtual void on_target_resumed (ptid_t ptid) {}
 
+  /* Notify the interpreter that solib SO has been loaded.  */
+  virtual void on_solib_loaded (so_list *so) {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
@@ -287,6 +291,9 @@ extern void interps_notify_record_changed (inferior *inf, int started,
 /* Notify all interpreters that the target was resumed.  */
 extern void interps_notify_target_resumed (ptid_t ptid);
 
+/* Notify all interpreters that solib SO has been loaded.  */
+extern void interps_notify_solib_loaded (so_list *so);
+
 /* well-known interpreters */
 #define INTERP_CONSOLE		"console"
 #define INTERP_MI2             "mi2"
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 5c944febf427..f0694cacfc86 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -60,7 +60,6 @@ static int mi_interp_query_hook (const char *ctlstr, va_list ap)
 static void mi_insert_notify_hooks (void);
 static void mi_remove_notify_hooks (void);
 
-static void mi_solib_loaded (struct so_list *solib);
 static void mi_solib_unloaded (struct so_list *solib);
 static void mi_about_to_proceed (void);
 static void mi_traceframe_changed (int tfnum, int tpnum);
@@ -844,30 +843,21 @@ mi_output_solib_attribs (ui_out *uiout, struct so_list *solib)
     }
 }
 
-static void
-mi_solib_loaded (struct so_list *solib)
+void
+mi_interp::on_solib_loaded (so_list *solib)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-      struct ui_out *uiout;
+  ui_out *uiout = this->interp_ui_out ();
 
-      if (mi == NULL)
-	continue;
-
-      uiout = top_level_interpreter ()->interp_ui_out ();
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  gdb_printf (this->event_channel, "library-loaded");
 
-      gdb_printf (mi->event_channel, "library-loaded");
+  ui_out_redirect_pop redir (uiout, this->event_channel);
 
-      ui_out_redirect_pop redir (uiout, mi->event_channel);
+  mi_output_solib_attribs (uiout, solib);
 
-      mi_output_solib_attribs (uiout, solib);
-
-      gdb_flush (mi->event_channel);
-    }
+  gdb_flush (this->event_channel);
 }
 
 static void
@@ -1082,7 +1072,6 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
 
-  gdb::observers::solib_loaded.attach (mi_solib_loaded, "mi-interp");
   gdb::observers::solib_unloaded.attach (mi_solib_unloaded, "mi-interp");
   gdb::observers::about_to_proceed.attach (mi_about_to_proceed, "mi-interp");
   gdb::observers::traceframe_changed.attach (mi_traceframe_changed,
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index fc0d8218ba73..62dee1cdfb5e 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -59,6 +59,7 @@ class mi_interp final : public interp
   void on_record_changed (inferior *inf, int started, const char *method,
 			  const char *format) override;
   void on_target_resumed (ptid_t ptid) override;
+  void on_solib_loaded (so_list *so) override;
 
   /* MI's output channels */
   mi_console_file *out;
diff --git a/gdb/solib.c b/gdb/solib.c
index 16147830ef2c..fc23d284b8a0 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -760,6 +760,15 @@ solib_used (const struct so_list *const known)
   return false;
 }
 
+/* Notify interpreters and observers that solib SO has been loaded.  */
+
+static void
+notify_solib_loaded (so_list *so)
+{
+  interps_notify_solib_loaded (so);
+  gdb::observers::solib_loaded.notify (so);
+}
+
 /* See solib.h.  */
 
 void
@@ -920,7 +929,7 @@ update_solib_list (int from_tty)
 
 	  /* Notify any observer that the shared object has been
 	     loaded now that we've added it to GDB's tables.  */
-	  gdb::observers::solib_loaded.notify (i);
+	  notify_solib_loaded (i);
 	}
 
       /* If a library was not found, issue an appropriate warning
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 20/30] gdb: add interp::on_solib_unloaded method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (18 preceding siblings ...)
  2023-05-02 20:49 ` [PATCH 19/30] gdb: add interp::on_solib_loaded method Simon Marchi
@ 2023-05-02 20:50 ` Simon Marchi
  2023-05-02 20:50 ` [PATCH 21/30] gdb: add interp::on_about_to_proceed method Simon Marchi
                   ` (11 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:50 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same idea as previous patches, but for solib_unloaded.

Change-Id: Iad847de93f0b38b5c90679a173d3beeaed7af6c5
---
 gdb/interps.c      |  8 ++++++++
 gdb/interps.h      |  6 ++++++
 gdb/mi/mi-interp.c | 39 +++++++++++++--------------------------
 gdb/mi/mi-interp.h |  1 +
 gdb/solib.c        | 13 +++++++++++--
 5 files changed, 39 insertions(+), 28 deletions(-)

diff --git a/gdb/interps.c b/gdb/interps.c
index 6dde83b45e79..2c7fbc80b7df 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -519,6 +519,14 @@ interps_notify_solib_loaded (so_list *so)
   interps_notify (&interp::on_solib_loaded, so);
 }
 
+/* See interps.h.  */
+
+void
+interps_notify_solib_unloaded (so_list *so)
+{
+  interps_notify (&interp::on_solib_unloaded, so);
+}
+
 /* This just adds the "interpreter-exec" command.  */
 void _initialize_interpreter ();
 void
diff --git a/gdb/interps.h b/gdb/interps.h
index 7fce025aad69..3339ae3d3013 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -146,6 +146,9 @@ class interp : public intrusive_list_node<interp>
   /* Notify the interpreter that solib SO has been loaded.  */
   virtual void on_solib_loaded (so_list *so) {}
 
+  /* Notify the interpreter that solib SO has been unloaded.  */
+  virtual void on_solib_unloaded (so_list *so) {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
@@ -294,6 +297,9 @@ extern void interps_notify_target_resumed (ptid_t ptid);
 /* Notify all interpreters that solib SO has been loaded.  */
 extern void interps_notify_solib_loaded (so_list *so);
 
+/* Notify all interpreters that solib SO has been unloaded.  */
+extern void interps_notify_solib_unloaded (so_list *so);
+
 /* well-known interpreters */
 #define INTERP_CONSOLE		"console"
 #define INTERP_MI2             "mi2"
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index f0694cacfc86..8be165e21544 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -60,7 +60,6 @@ static int mi_interp_query_hook (const char *ctlstr, va_list ap)
 static void mi_insert_notify_hooks (void);
 static void mi_remove_notify_hooks (void);
 
-static void mi_solib_unloaded (struct so_list *solib);
 static void mi_about_to_proceed (void);
 static void mi_traceframe_changed (int tfnum, int tpnum);
 static void mi_tsv_created (const struct trace_state_variable *tsv);
@@ -860,36 +859,25 @@ mi_interp::on_solib_loaded (so_list *solib)
   gdb_flush (this->event_channel);
 }
 
-static void
-mi_solib_unloaded (struct so_list *solib)
+void
+mi_interp::on_solib_unloaded (so_list *solib)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-      struct ui_out *uiout;
-
-      if (mi == NULL)
-	continue;
-
-      uiout = top_level_interpreter ()->interp_ui_out ();
+  ui_out *uiout = this->interp_ui_out ();
 
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      gdb_printf (mi->event_channel, "library-unloaded");
+  gdb_printf (this->event_channel, "library-unloaded");
 
-      ui_out_redirect_pop redir (uiout, mi->event_channel);
+  ui_out_redirect_pop redir (uiout, this->event_channel);
 
-      uiout->field_string ("id", solib->so_original_name);
-      uiout->field_string ("target-name", solib->so_original_name);
-      uiout->field_string ("host-name", solib->so_name);
-      if (!gdbarch_has_global_solist (target_gdbarch ()))
-	{
-	  uiout->field_fmt ("thread-group", "i%d", current_inferior ()->num);
-	}
+  uiout->field_string ("id", solib->so_original_name);
+  uiout->field_string ("target-name", solib->so_original_name);
+  uiout->field_string ("host-name", solib->so_name);
+  if (!gdbarch_has_global_solist (target_gdbarch ()))
+    uiout->field_fmt ("thread-group", "i%d", current_inferior ()->num);
 
-      gdb_flush (mi->event_channel);
-    }
+  gdb_flush (this->event_channel);
 }
 
 /* Emit notification about the command parameter change.  */
@@ -1072,7 +1060,6 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
 
-  gdb::observers::solib_unloaded.attach (mi_solib_unloaded, "mi-interp");
   gdb::observers::about_to_proceed.attach (mi_about_to_proceed, "mi-interp");
   gdb::observers::traceframe_changed.attach (mi_traceframe_changed,
 					     "mi-interp");
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index 62dee1cdfb5e..08a47523272c 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -60,6 +60,7 @@ class mi_interp final : public interp
 			  const char *format) override;
   void on_target_resumed (ptid_t ptid) override;
   void on_solib_loaded (so_list *so) override;
+  void on_solib_unloaded (so_list *so) override;
 
   /* MI's output channels */
   mi_console_file *out;
diff --git a/gdb/solib.c b/gdb/solib.c
index fc23d284b8a0..701efa85d1a6 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -769,6 +769,15 @@ notify_solib_loaded (so_list *so)
   gdb::observers::solib_loaded.notify (so);
 }
 
+/* Notify interpreters and observers that solib SO has been unloaded.  */
+
+static void
+notify_solib_unloaded (so_list *so)
+{
+  interps_notify_solib_unloaded (so);
+  gdb::observers::solib_unloaded.notify (so);
+}
+
 /* See solib.h.  */
 
 void
@@ -869,7 +878,7 @@ update_solib_list (int from_tty)
 	{
 	  /* Notify any observer that the shared object has been
 	     unloaded before we remove it from GDB's tables.  */
-	  gdb::observers::solib_unloaded.notify (gdb);
+	  notify_solib_unloaded (gdb);
 
 	  current_program_space->deleted_solibs.push_back (gdb->so_name);
 
@@ -1237,7 +1246,7 @@ clear_solib (void)
       struct so_list *so = current_program_space->so_list;
 
       current_program_space->so_list = so->next;
-      gdb::observers::solib_unloaded.notify (so);
+      notify_solib_unloaded (so);
       current_program_space->remove_target_sections (so);
       free_so (so);
     }
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 21/30] gdb: add interp::on_about_to_proceed method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (19 preceding siblings ...)
  2023-05-02 20:50 ` [PATCH 20/30] gdb: add interp::on_solib_unloaded method Simon Marchi
@ 2023-05-02 20:50 ` Simon Marchi
  2023-05-02 20:50 ` [PATCH 22/30] gdb: add interp::on_traceframe_changed method Simon Marchi
                   ` (10 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:50 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same idea as previous patches, but for about_to_proceed.  We only need
(and want, as far as the mi_interp implementation is concerned) to
notify the interpreter that caused the proceed.

Change-Id: Id259bca10dbc3d43d46607ff7b95243a9cbe2f89
---
 gdb/infrun.c       | 12 +++++++++++-
 gdb/interps.h      |  4 ++++
 gdb/mi/mi-interp.c | 13 +++----------
 gdb/mi/mi-interp.h |  1 +
 4 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/gdb/infrun.c b/gdb/infrun.c
index aa2d34aa6b35..aeeae8b50fd8 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -2893,6 +2893,16 @@ clear_proceed_status_thread (struct thread_info *tp)
   bpstat_clear (&tp->control.stop_bpstat);
 }
 
+/* Notify the current interpreter and observers that the target is about to
+   proceed.  */
+
+static void
+notify_about_to_proceed ()
+{
+  top_level_interpreter ()->on_about_to_proceed ();
+  gdb::observers::about_to_proceed.notify ();
+}
+
 void
 clear_proceed_status (int step)
 {
@@ -2935,7 +2945,7 @@ clear_proceed_status (int step)
       inferior->control.stop_soon = NO_STOP_QUIETLY;
     }
 
-  gdb::observers::about_to_proceed.notify ();
+  notify_about_to_proceed ();
 }
 
 /* Returns true if TP is still stopped at a breakpoint that needs
diff --git a/gdb/interps.h b/gdb/interps.h
index 3339ae3d3013..a88c40581bb3 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -149,6 +149,10 @@ class interp : public intrusive_list_node<interp>
   /* Notify the interpreter that solib SO has been unloaded.  */
   virtual void on_solib_unloaded (so_list *so) {}
 
+  /* Notify the interpreter that a command it is executing is about to cause
+     the inferior to proceed.  */
+  virtual void on_about_to_proceed () {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 8be165e21544..40a1fc93b48d 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -60,7 +60,6 @@ static int mi_interp_query_hook (const char *ctlstr, va_list ap)
 static void mi_insert_notify_hooks (void);
 static void mi_remove_notify_hooks (void);
 
-static void mi_about_to_proceed (void);
 static void mi_traceframe_changed (int tfnum, int tpnum);
 static void mi_tsv_created (const struct trace_state_variable *tsv);
 static void mi_tsv_deleted (const struct trace_state_variable *tsv);
@@ -468,8 +467,8 @@ mi_interp::on_normal_stop (struct bpstat *bs, int print_frame)
   gdb_flush (this->raw_stdout);
 }
 
-static void
-mi_about_to_proceed (void)
+void
+mi_interp::on_about_to_proceed ()
 {
   /* Suppress output while calling an inferior function.  */
 
@@ -481,12 +480,7 @@ mi_about_to_proceed (void)
 	return;
     }
 
-  mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-  if (mi == nullptr)
-    return;
-
-  mi->mi_proceeded = 1;
+  this->mi_proceeded = 1;
 }
 
 /* When the element is non-zero, no MI notifications will be emitted in
@@ -1060,7 +1054,6 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
 
-  gdb::observers::about_to_proceed.attach (mi_about_to_proceed, "mi-interp");
   gdb::observers::traceframe_changed.attach (mi_traceframe_changed,
 					     "mi-interp");
   gdb::observers::tsv_created.attach (mi_tsv_created, "mi-interp");
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index 08a47523272c..2bb6840e786f 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -61,6 +61,7 @@ class mi_interp final : public interp
   void on_target_resumed (ptid_t ptid) override;
   void on_solib_loaded (so_list *so) override;
   void on_solib_unloaded (so_list *so) override;
+  void on_about_to_proceed () override;
 
   /* MI's output channels */
   mi_console_file *out;
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 22/30] gdb: add interp::on_traceframe_changed method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (20 preceding siblings ...)
  2023-05-02 20:50 ` [PATCH 21/30] gdb: add interp::on_about_to_proceed method Simon Marchi
@ 2023-05-02 20:50 ` Simon Marchi
  2023-05-02 20:50 ` [PATCH 23/30] gdb: add interp::on_tsv_created method Simon Marchi
                   ` (9 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:50 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same idea as previous patches, but for traceframe_changed.

Change-Id: Ia473f07d70d57b30aca0094d0e0585d7e0d95637
---
 gdb/interps.c      |  8 ++++++++
 gdb/interps.h      | 10 ++++++++++
 gdb/mi/mi-interp.c | 35 +++++++++++------------------------
 gdb/mi/mi-interp.h |  1 +
 gdb/observable.c   |  1 -
 gdb/observable.h   |  6 ------
 gdb/tracepoint.c   |  3 ++-
 7 files changed, 32 insertions(+), 32 deletions(-)

diff --git a/gdb/interps.c b/gdb/interps.c
index 2c7fbc80b7df..01fa44ceddcf 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -527,6 +527,14 @@ interps_notify_solib_unloaded (so_list *so)
   interps_notify (&interp::on_solib_unloaded, so);
 }
 
+/* See interps.h.  */
+
+void
+interps_notify_traceframe_changed (int tfnum, int tpnum)
+{
+  interps_notify (&interp::on_traceframe_changed, tfnum, tpnum);
+}
+
 /* This just adds the "interpreter-exec" command.  */
 void _initialize_interpreter ();
 void
diff --git a/gdb/interps.h b/gdb/interps.h
index a88c40581bb3..3b8814616964 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -153,6 +153,9 @@ class interp : public intrusive_list_node<interp>
      the inferior to proceed.  */
   virtual void on_about_to_proceed () {}
 
+  /* Notify the interpreter that the selected traceframe changed.  */
+  virtual void on_traceframe_changed (int tfnum, int tpnum) {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
@@ -304,6 +307,13 @@ extern void interps_notify_solib_loaded (so_list *so);
 /* Notify all interpreters that solib SO has been unloaded.  */
 extern void interps_notify_solib_unloaded (so_list *so);
 
+/* Notify all interpreters that the selected traceframe changed.
+
+   The trace frame is changed to TFNUM (e.g., by using the 'tfind' command).
+   If TFNUM is negative, it means gdb resumed live debugging.  The number of
+   the tracepoint associated with this traceframe is TPNUM.  */
+extern void interps_notify_traceframe_changed (int tfnum, int tpnum);
+
 /* well-known interpreters */
 #define INTERP_CONSOLE		"console"
 #define INTERP_MI2             "mi2"
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 40a1fc93b48d..832199d8cd97 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -60,7 +60,6 @@ static int mi_interp_query_hook (const char *ctlstr, va_list ap)
 static void mi_insert_notify_hooks (void);
 static void mi_remove_notify_hooks (void);
 
-static void mi_traceframe_changed (int tfnum, int tpnum);
 static void mi_tsv_created (const struct trace_state_variable *tsv);
 static void mi_tsv_deleted (const struct trace_state_variable *tsv);
 static void mi_tsv_modified (const struct trace_state_variable *tsv);
@@ -494,33 +493,23 @@ struct mi_suppress_notification mi_suppress_notification =
     0,
   };
 
-/* Emit notification on changing a traceframe.  */
-
-static void
-mi_traceframe_changed (int tfnum, int tpnum)
+void
+mi_interp::on_traceframe_changed (int tfnum, int tpnum)
 {
   if (mi_suppress_notification.traceframe)
     return;
 
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-      if (mi == NULL)
-	continue;
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      if (tfnum >= 0)
-	gdb_printf (mi->event_channel, "traceframe-changed,"
-		    "num=\"%d\",tracepoint=\"%d\"",
-		    tfnum, tpnum);
-      else
-	gdb_printf (mi->event_channel, "traceframe-changed,end");
+  if (tfnum >= 0)
+    gdb_printf (this->event_channel, "traceframe-changed,"
+		"num=\"%d\",tracepoint=\"%d\"",
+		tfnum, tpnum);
+  else
+    gdb_printf (this->event_channel, "traceframe-changed,end");
 
-      gdb_flush (mi->event_channel);
-    }
+  gdb_flush (this->event_channel);
 }
 
 /* Emit notification on creating a trace state variable.  */
@@ -1054,8 +1043,6 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
 
-  gdb::observers::traceframe_changed.attach (mi_traceframe_changed,
-					     "mi-interp");
   gdb::observers::tsv_created.attach (mi_tsv_created, "mi-interp");
   gdb::observers::tsv_deleted.attach (mi_tsv_deleted, "mi-interp");
   gdb::observers::tsv_modified.attach (mi_tsv_modified, "mi-interp");
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index 2bb6840e786f..af335df8344c 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -62,6 +62,7 @@ class mi_interp final : public interp
   void on_solib_loaded (so_list *so) override;
   void on_solib_unloaded (so_list *so) override;
   void on_about_to_proceed () override;
+  void on_traceframe_changed (int tfnum, int tpnum) override;
 
   /* MI's output channels */
   mi_console_file *out;
diff --git a/gdb/observable.c b/gdb/observable.c
index 5b78d48908b7..4e9967f5637a 100644
--- a/gdb/observable.c
+++ b/gdb/observable.c
@@ -51,7 +51,6 @@ DEFINE_OBSERVABLE (about_to_proceed);
 DEFINE_OBSERVABLE (breakpoint_created);
 DEFINE_OBSERVABLE (breakpoint_deleted);
 DEFINE_OBSERVABLE (breakpoint_modified);
-DEFINE_OBSERVABLE (traceframe_changed);
 DEFINE_OBSERVABLE (architecture_changed);
 DEFINE_OBSERVABLE (thread_ptid_changed);
 DEFINE_OBSERVABLE (inferior_added);
diff --git a/gdb/observable.h b/gdb/observable.h
index be7c6ca8dd23..ee70f2bd4dee 100644
--- a/gdb/observable.h
+++ b/gdb/observable.h
@@ -140,12 +140,6 @@ extern observable<struct breakpoint */* b */> breakpoint_deleted;
    is the modified breakpoint.  */
 extern observable<struct breakpoint */* b */> breakpoint_modified;
 
-/* The trace frame is changed to TFNUM (e.g., by using the 'tfind'
-   command).  If TFNUM is negative, it means gdb resumes live
-   debugging.  The number of the tracepoint associated with this
-   traceframe is TPNUM.  */
-extern observable<int /* tfnum */, int /* tpnum */> traceframe_changed;
-
 /* The current architecture has changed.  The argument NEWARCH is a
    pointer to the new architecture.  */
 extern observable<struct gdbarch */* newarch */> architecture_changed;
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index ffda4a6439e4..9517d144ccee 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -59,6 +59,7 @@
 #include "cli/cli-style.h"
 #include "expop.h"
 #include "gdbsupport/buildargv.h"
+#include "interps.h"
 
 #include <unistd.h>
 
@@ -2139,7 +2140,7 @@ tfind_1 (enum trace_find_type type, int num,
   set_tracepoint_num (tp ? tp->number : target_tracept);
 
   if (target_frameno != get_traceframe_number ())
-    gdb::observers::traceframe_changed.notify (target_frameno, tracepoint_number);
+    interps_notify_traceframe_changed (target_frameno, tracepoint_number);
 
   set_current_traceframe (target_frameno);
 
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 23/30] gdb: add interp::on_tsv_created method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (21 preceding siblings ...)
  2023-05-02 20:50 ` [PATCH 22/30] gdb: add interp::on_traceframe_changed method Simon Marchi
@ 2023-05-02 20:50 ` Simon Marchi
  2023-05-02 20:50 ` [PATCH 24/30] gdb: add interp::on_tsv_deleted method Simon Marchi
                   ` (8 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:50 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same idea as previous patches, but for tsv_created.

Change-Id: I9c30ecfdbd78ca015d613f43a0c0aef6c7eb32b5
---
 gdb/interps.c      |  8 ++++++++
 gdb/interps.h      |  7 +++++++
 gdb/mi/mi-interp.c | 28 ++++++++--------------------
 gdb/mi/mi-interp.h |  1 +
 gdb/observable.c   |  1 -
 gdb/observable.h   |  3 ---
 gdb/tracepoint.c   |  4 ++--
 7 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/gdb/interps.c b/gdb/interps.c
index 01fa44ceddcf..9d736fc4fcf2 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -535,6 +535,14 @@ interps_notify_traceframe_changed (int tfnum, int tpnum)
   interps_notify (&interp::on_traceframe_changed, tfnum, tpnum);
 }
 
+/* See interps.h.  */
+
+void
+interps_notify_tsv_created (const trace_state_variable *tsv)
+{
+  interps_notify (&interp::on_tsv_created, tsv);
+}
+
 /* This just adds the "interpreter-exec" command.  */
 void _initialize_interpreter ();
 void
diff --git a/gdb/interps.h b/gdb/interps.h
index 3b8814616964..de1af0708b47 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -32,6 +32,7 @@ class completion_tracker;
 struct thread_info;
 struct inferior;
 struct so_list;
+struct trace_state_variable;
 
 typedef struct interp *(*interp_factory_func) (const char *name);
 
@@ -156,6 +157,9 @@ class interp : public intrusive_list_node<interp>
   /* Notify the interpreter that the selected traceframe changed.  */
   virtual void on_traceframe_changed (int tfnum, int tpnum) {}
 
+  /* Notify the interpreter that trace state variable TSV was created.  */
+  virtual void on_tsv_created (const trace_state_variable *tsv) {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
@@ -314,6 +318,9 @@ extern void interps_notify_solib_unloaded (so_list *so);
    the tracepoint associated with this traceframe is TPNUM.  */
 extern void interps_notify_traceframe_changed (int tfnum, int tpnum);
 
+/* Notify all interpreters that trace state variable TSV was created.  */
+extern void interps_notify_tsv_created (const trace_state_variable *tsv);
+
 /* well-known interpreters */
 #define INTERP_CONSOLE		"console"
 #define INTERP_MI2             "mi2"
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 832199d8cd97..509f84d82a13 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -60,7 +60,6 @@ static int mi_interp_query_hook (const char *ctlstr, va_list ap)
 static void mi_insert_notify_hooks (void);
 static void mi_remove_notify_hooks (void);
 
-static void mi_tsv_created (const struct trace_state_variable *tsv);
 static void mi_tsv_deleted (const struct trace_state_variable *tsv);
 static void mi_tsv_modified (const struct trace_state_variable *tsv);
 static void mi_breakpoint_created (struct breakpoint *b);
@@ -512,27 +511,17 @@ mi_interp::on_traceframe_changed (int tfnum, int tpnum)
   gdb_flush (this->event_channel);
 }
 
-/* Emit notification on creating a trace state variable.  */
-
-static void
-mi_tsv_created (const struct trace_state_variable *tsv)
+void
+mi_interp::on_tsv_created (const trace_state_variable *tsv)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-      if (mi == NULL)
-	continue;
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      gdb_printf (mi->event_channel, "tsv-created,"
-		  "name=\"%s\",initial=\"%s\"",
-		  tsv->name.c_str (), plongest (tsv->initial_value));
+  gdb_printf (this->event_channel, "tsv-created,"
+	      "name=\"%s\",initial=\"%s\"",
+	      tsv->name.c_str (), plongest (tsv->initial_value));
 
-      gdb_flush (mi->event_channel);
-    }
+  gdb_flush (this->event_channel);
 }
 
 /* Emit notification on deleting a trace state variable.  */
@@ -1043,7 +1032,6 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
 
-  gdb::observers::tsv_created.attach (mi_tsv_created, "mi-interp");
   gdb::observers::tsv_deleted.attach (mi_tsv_deleted, "mi-interp");
   gdb::observers::tsv_modified.attach (mi_tsv_modified, "mi-interp");
   gdb::observers::breakpoint_created.attach (mi_breakpoint_created,
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index af335df8344c..ee4807b93f4b 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -63,6 +63,7 @@ class mi_interp final : public interp
   void on_solib_unloaded (so_list *so) override;
   void on_about_to_proceed () override;
   void on_traceframe_changed (int tfnum, int tpnum) override;
+  void on_tsv_created (const trace_state_variable *tsv) override;
 
   /* MI's output channels */
   mi_console_file *out;
diff --git a/gdb/observable.c b/gdb/observable.c
index 4e9967f5637a..0715b6eb696d 100644
--- a/gdb/observable.c
+++ b/gdb/observable.c
@@ -62,7 +62,6 @@ DEFINE_OBSERVABLE (memory_changed);
 DEFINE_OBSERVABLE (before_prompt);
 DEFINE_OBSERVABLE (gdb_datadir_changed);
 DEFINE_OBSERVABLE (command_param_changed);
-DEFINE_OBSERVABLE (tsv_created);
 DEFINE_OBSERVABLE (tsv_deleted);
 DEFINE_OBSERVABLE (tsv_modified);
 DEFINE_OBSERVABLE (inferior_call_pre);
diff --git a/gdb/observable.h b/gdb/observable.h
index ee70f2bd4dee..46a027979e75 100644
--- a/gdb/observable.h
+++ b/gdb/observable.h
@@ -190,9 +190,6 @@ extern observable<> gdb_datadir_changed;
 extern observable<const char */* param */, const char */* value */>
     command_param_changed;
 
-/* The new trace state variable TSV is created.  */
-extern observable<const struct trace_state_variable */* tsv */> tsv_created;
-
 /* The trace state variable TSV is deleted.  If TSV is NULL, all
    trace state variables are deleted.  */
 extern observable<const struct trace_state_variable */* tsv */> tsv_deleted;
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index 9517d144ccee..a32651cf5cc6 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -373,7 +373,7 @@ trace_variable_command (const char *args, int from_tty)
   tsv = create_trace_state_variable (name.c_str ());
   tsv->initial_value = initval;
 
-  gdb::observers::tsv_created.notify (tsv);
+  interps_notify_tsv_created (tsv);
 
   gdb_printf (_("Trace state variable $%s "
 		"created, with initial value %s.\n"),
@@ -3184,7 +3184,7 @@ create_tsv_from_upload (struct uploaded_tsv *utsv)
   tsv->initial_value = utsv->initial_value;
   tsv->builtin = utsv->builtin;
 
-  gdb::observers::tsv_created.notify (tsv);
+  interps_notify_tsv_created (tsv);
 
   return tsv;
 }
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 24/30] gdb: add interp::on_tsv_deleted method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (22 preceding siblings ...)
  2023-05-02 20:50 ` [PATCH 23/30] gdb: add interp::on_tsv_created method Simon Marchi
@ 2023-05-02 20:50 ` Simon Marchi
  2023-05-02 20:50 ` [PATCH 25/30] gdb: add interp::on_tsv_modified method Simon Marchi
                   ` (7 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:50 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same idea as previous patches, but for tsv_deleted.

Change-Id: I71b0502b493da7b6e293bee02aeca98de83d4b75
---
 gdb/interps.c      |  8 ++++++++
 gdb/interps.h      |  8 ++++++++
 gdb/mi/mi-interp.c | 32 ++++++++++----------------------
 gdb/mi/mi-interp.h |  1 +
 gdb/observable.c   |  1 -
 gdb/observable.h   |  4 ----
 gdb/tracepoint.c   |  4 ++--
 7 files changed, 29 insertions(+), 29 deletions(-)

diff --git a/gdb/interps.c b/gdb/interps.c
index 9d736fc4fcf2..c8d4fbd0b4da 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -543,6 +543,14 @@ interps_notify_tsv_created (const trace_state_variable *tsv)
   interps_notify (&interp::on_tsv_created, tsv);
 }
 
+/* See interps.h.  */
+
+void
+interps_notify_tsv_deleted (const trace_state_variable *tsv)
+{
+  interps_notify (&interp::on_tsv_deleted, tsv);
+}
+
 /* This just adds the "interpreter-exec" command.  */
 void _initialize_interpreter ();
 void
diff --git a/gdb/interps.h b/gdb/interps.h
index de1af0708b47..7e761375a05e 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -160,6 +160,9 @@ class interp : public intrusive_list_node<interp>
   /* Notify the interpreter that trace state variable TSV was created.  */
   virtual void on_tsv_created (const trace_state_variable *tsv) {}
 
+  /* Notify the interpreter that trace state variable TSV was deleted.  */
+  virtual void on_tsv_deleted (const trace_state_variable *tsv) {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
@@ -321,6 +324,11 @@ extern void interps_notify_traceframe_changed (int tfnum, int tpnum);
 /* Notify all interpreters that trace state variable TSV was created.  */
 extern void interps_notify_tsv_created (const trace_state_variable *tsv);
 
+/* Notify all interpreters that trace state variable TSV was deleted.
+   
+   If TSV is nullptr, it means that all trace state variables were deleted.  */
+extern void interps_notify_tsv_deleted (const trace_state_variable *tsv);
+
 /* well-known interpreters */
 #define INTERP_CONSOLE		"console"
 #define INTERP_MI2             "mi2"
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 509f84d82a13..c255630bd444 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -60,7 +60,6 @@ static int mi_interp_query_hook (const char *ctlstr, va_list ap)
 static void mi_insert_notify_hooks (void);
 static void mi_remove_notify_hooks (void);
 
-static void mi_tsv_deleted (const struct trace_state_variable *tsv);
 static void mi_tsv_modified (const struct trace_state_variable *tsv);
 static void mi_breakpoint_created (struct breakpoint *b);
 static void mi_breakpoint_deleted (struct breakpoint *b);
@@ -524,29 +523,19 @@ mi_interp::on_tsv_created (const trace_state_variable *tsv)
   gdb_flush (this->event_channel);
 }
 
-/* Emit notification on deleting a trace state variable.  */
-
-static void
-mi_tsv_deleted (const struct trace_state_variable *tsv)
+void
+mi_interp::on_tsv_deleted (const trace_state_variable *tsv)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-      if (mi == NULL)
-	continue;
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      if (tsv != NULL)
-	gdb_printf (mi->event_channel, "tsv-deleted,"
-		    "name=\"%s\"", tsv->name.c_str ());
-      else
-	gdb_printf (mi->event_channel, "tsv-deleted");
+  if (tsv != nullptr)
+    gdb_printf (this->event_channel, "tsv-deleted,name=\"%s\"",
+		tsv->name.c_str ());
+  else
+    gdb_printf (this->event_channel, "tsv-deleted");
 
-      gdb_flush (mi->event_channel);
-    }
+  gdb_flush (this->event_channel);
 }
 
 /* Emit notification on modifying a trace state variable.  */
@@ -1032,7 +1021,6 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
 
-  gdb::observers::tsv_deleted.attach (mi_tsv_deleted, "mi-interp");
   gdb::observers::tsv_modified.attach (mi_tsv_modified, "mi-interp");
   gdb::observers::breakpoint_created.attach (mi_breakpoint_created,
 					     "mi-interp");
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index ee4807b93f4b..edd5e9f1150c 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -64,6 +64,7 @@ class mi_interp final : public interp
   void on_about_to_proceed () override;
   void on_traceframe_changed (int tfnum, int tpnum) override;
   void on_tsv_created (const trace_state_variable *tsv) override;
+  void on_tsv_deleted (const trace_state_variable *tsv) override;
 
   /* MI's output channels */
   mi_console_file *out;
diff --git a/gdb/observable.c b/gdb/observable.c
index 0715b6eb696d..f70dcef3c450 100644
--- a/gdb/observable.c
+++ b/gdb/observable.c
@@ -62,7 +62,6 @@ DEFINE_OBSERVABLE (memory_changed);
 DEFINE_OBSERVABLE (before_prompt);
 DEFINE_OBSERVABLE (gdb_datadir_changed);
 DEFINE_OBSERVABLE (command_param_changed);
-DEFINE_OBSERVABLE (tsv_deleted);
 DEFINE_OBSERVABLE (tsv_modified);
 DEFINE_OBSERVABLE (inferior_call_pre);
 DEFINE_OBSERVABLE (inferior_call_post);
diff --git a/gdb/observable.h b/gdb/observable.h
index 46a027979e75..326c49ad37c0 100644
--- a/gdb/observable.h
+++ b/gdb/observable.h
@@ -190,10 +190,6 @@ extern observable<> gdb_datadir_changed;
 extern observable<const char */* param */, const char */* value */>
     command_param_changed;
 
-/* The trace state variable TSV is deleted.  If TSV is NULL, all
-   trace state variables are deleted.  */
-extern observable<const struct trace_state_variable */* tsv */> tsv_deleted;
-
 /* The trace state value TSV is modified.  */
 extern observable<const struct trace_state_variable */* tsv */> tsv_modified;
 
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index a32651cf5cc6..08bc82a3d368 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -289,7 +289,7 @@ delete_trace_state_variable (const char *name)
   for (auto it = tvariables.begin (); it != tvariables.end (); it++)
     if (it->name == name)
       {
-	gdb::observers::tsv_deleted.notify (&*it);
+	interps_notify_tsv_deleted (&*it);
 	tvariables.erase (it);
 	return;
       }
@@ -388,7 +388,7 @@ delete_trace_variable_command (const char *args, int from_tty)
       if (query (_("Delete all trace state variables? ")))
 	tvariables.clear ();
       dont_repeat ();
-      gdb::observers::tsv_deleted.notify (NULL);
+      interps_notify_tsv_deleted (nullptr);
       return;
     }
 
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 25/30] gdb: add interp::on_tsv_modified method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (23 preceding siblings ...)
  2023-05-02 20:50 ` [PATCH 24/30] gdb: add interp::on_tsv_deleted method Simon Marchi
@ 2023-05-02 20:50 ` Simon Marchi
  2023-05-02 20:50 ` [PATCH 26/30] gdb: add interp::on_breakpoint_created method Simon Marchi
                   ` (6 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:50 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same idea as previous patches, but for tsv_modified.

Change-Id: I55454a2386d5450040b3a353909b26f389a43682
---
 gdb/interps.c      |  8 ++++++++
 gdb/interps.h      |  6 ++++++
 gdb/mi/mi-interp.c | 41 ++++++++++++++---------------------------
 gdb/mi/mi-interp.h |  1 +
 gdb/observable.c   |  1 -
 gdb/observable.h   |  3 ---
 gdb/tracepoint.c   |  2 +-
 7 files changed, 30 insertions(+), 32 deletions(-)

diff --git a/gdb/interps.c b/gdb/interps.c
index c8d4fbd0b4da..c727913e4806 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -551,6 +551,14 @@ interps_notify_tsv_deleted (const trace_state_variable *tsv)
   interps_notify (&interp::on_tsv_deleted, tsv);
 }
 
+/* See interps.h.  */
+
+void
+interps_notify_tsv_modified (const trace_state_variable *tsv)
+{
+  interps_notify (&interp::on_tsv_modified, tsv);
+}
+
 /* This just adds the "interpreter-exec" command.  */
 void _initialize_interpreter ();
 void
diff --git a/gdb/interps.h b/gdb/interps.h
index 7e761375a05e..7bd57cb05ecc 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -163,6 +163,9 @@ class interp : public intrusive_list_node<interp>
   /* Notify the interpreter that trace state variable TSV was deleted.  */
   virtual void on_tsv_deleted (const trace_state_variable *tsv) {}
 
+  /* Notify the interpreter that trace state variable TSV was modified.  */
+  virtual void on_tsv_modified (const trace_state_variable *tsv) {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
@@ -329,6 +332,9 @@ extern void interps_notify_tsv_created (const trace_state_variable *tsv);
    If TSV is nullptr, it means that all trace state variables were deleted.  */
 extern void interps_notify_tsv_deleted (const trace_state_variable *tsv);
 
+/* Notify all interpreters that trace state variable TSV was modified.  */
+extern void interps_notify_tsv_modified (const trace_state_variable *tsv);
+
 /* well-known interpreters */
 #define INTERP_CONSOLE		"console"
 #define INTERP_MI2             "mi2"
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index c255630bd444..65b9bd3693a2 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -60,7 +60,6 @@ static int mi_interp_query_hook (const char *ctlstr, va_list ap)
 static void mi_insert_notify_hooks (void);
 static void mi_remove_notify_hooks (void);
 
-static void mi_tsv_modified (const struct trace_state_variable *tsv);
 static void mi_breakpoint_created (struct breakpoint *b);
 static void mi_breakpoint_deleted (struct breakpoint *b);
 static void mi_breakpoint_modified (struct breakpoint *b);
@@ -538,37 +537,26 @@ mi_interp::on_tsv_deleted (const trace_state_variable *tsv)
   gdb_flush (this->event_channel);
 }
 
-/* Emit notification on modifying a trace state variable.  */
-
-static void
-mi_tsv_modified (const struct trace_state_variable *tsv)
+void
+mi_interp::on_tsv_modified (const trace_state_variable *tsv)
 {
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-      struct ui_out *mi_uiout;
-
-      if (mi == NULL)
-	continue;
-
-      mi_uiout = top_level_interpreter ()->interp_ui_out ();
+  ui_out *mi_uiout = this->interp_ui_out ();
 
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      gdb_printf (mi->event_channel,
-		  "tsv-modified");
+  gdb_printf (this->event_channel,
+	      "tsv-modified");
 
-      ui_out_redirect_pop redir (mi_uiout, mi->event_channel);
+  ui_out_redirect_pop redir (mi_uiout, this->event_channel);
 
-      mi_uiout->field_string ("name", tsv->name);
-      mi_uiout->field_string ("initial",
-			      plongest (tsv->initial_value));
-      if (tsv->value_known)
-	mi_uiout->field_string ("current", plongest (tsv->value));
+  mi_uiout->field_string ("name", tsv->name);
+  mi_uiout->field_string ("initial",
+			  plongest (tsv->initial_value));
+  if (tsv->value_known)
+    mi_uiout->field_string ("current", plongest (tsv->value));
 
-      gdb_flush (mi->event_channel);
-    }
+  gdb_flush (this->event_channel);
 }
 
 /* Print breakpoint BP on MI's event channel.  */
@@ -1021,7 +1009,6 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
 
-  gdb::observers::tsv_modified.attach (mi_tsv_modified, "mi-interp");
   gdb::observers::breakpoint_created.attach (mi_breakpoint_created,
 					     "mi-interp");
   gdb::observers::breakpoint_deleted.attach (mi_breakpoint_deleted,
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index edd5e9f1150c..11ec5ddf3781 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -65,6 +65,7 @@ class mi_interp final : public interp
   void on_traceframe_changed (int tfnum, int tpnum) override;
   void on_tsv_created (const trace_state_variable *tsv) override;
   void on_tsv_deleted (const trace_state_variable *tsv) override;
+  void on_tsv_modified (const trace_state_variable *tsv) override;
 
   /* MI's output channels */
   mi_console_file *out;
diff --git a/gdb/observable.c b/gdb/observable.c
index f70dcef3c450..3535e69f7f54 100644
--- a/gdb/observable.c
+++ b/gdb/observable.c
@@ -62,7 +62,6 @@ DEFINE_OBSERVABLE (memory_changed);
 DEFINE_OBSERVABLE (before_prompt);
 DEFINE_OBSERVABLE (gdb_datadir_changed);
 DEFINE_OBSERVABLE (command_param_changed);
-DEFINE_OBSERVABLE (tsv_modified);
 DEFINE_OBSERVABLE (inferior_call_pre);
 DEFINE_OBSERVABLE (inferior_call_post);
 DEFINE_OBSERVABLE (register_changed);
diff --git a/gdb/observable.h b/gdb/observable.h
index 326c49ad37c0..1c7ba0a1ba67 100644
--- a/gdb/observable.h
+++ b/gdb/observable.h
@@ -190,9 +190,6 @@ extern observable<> gdb_datadir_changed;
 extern observable<const char */* param */, const char */* value */>
     command_param_changed;
 
-/* The trace state value TSV is modified.  */
-extern observable<const struct trace_state_variable */* tsv */> tsv_modified;
-
 /* An inferior function at ADDRESS is about to be called in thread
    THREAD.  */
 extern observable<ptid_t /* thread */, CORE_ADDR /* address */>
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index 08bc82a3d368..e6ef87475060 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -361,7 +361,7 @@ trace_variable_command (const char *args, int from_tty)
       if (tsv->initial_value != initval)
 	{
 	  tsv->initial_value = initval;
-	  gdb::observers::tsv_modified.notify (tsv);
+	  interps_notify_tsv_modified (tsv);
 	}
       gdb_printf (_("Trace state variable $%s "
 		    "now has initial value %s.\n"),
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 26/30] gdb: add interp::on_breakpoint_created method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (24 preceding siblings ...)
  2023-05-02 20:50 ` [PATCH 25/30] gdb: add interp::on_tsv_modified method Simon Marchi
@ 2023-05-02 20:50 ` Simon Marchi
  2023-05-02 20:50 ` [PATCH 27/30] gdb: add interp::on_breakpoint_deleted method Simon Marchi
                   ` (5 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:50 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same idea as previous patches, but for breakpoint_created.

Change-Id: I614113c924edc243590018b8fb3bf69cb62215ef
---
 gdb/breakpoint.c   | 12 +++++++++++-
 gdb/interps.c      |  8 ++++++++
 gdb/interps.h      |  6 ++++++
 gdb/mi/mi-interp.c | 28 +++++++---------------------
 gdb/mi/mi-interp.h |  1 +
 5 files changed, 33 insertions(+), 22 deletions(-)

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 30d438d06df9..a600bc7cc7fc 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -8004,6 +8004,15 @@ catchpoint::catchpoint (struct gdbarch *gdbarch, bool temp,
   pspace = current_program_space;
 }
 
+/* Notify interpreters and observers that breakpoint B was created.  */
+
+static void
+notify_breakpoint_created (breakpoint *b)
+{
+  interps_notify_breakpoint_created (b);
+  gdb::observers::breakpoint_created.notify (b);
+}
+
 breakpoint *
 install_breakpoint (int internal, std::unique_ptr<breakpoint> &&arg, int update_gll)
 {
@@ -8013,7 +8022,8 @@ install_breakpoint (int internal, std::unique_ptr<breakpoint> &&arg, int update_
     set_tracepoint_count (breakpoint_count);
   if (!internal)
     mention (b);
-  gdb::observers::breakpoint_created.notify (b);
+
+  notify_breakpoint_created (b);
 
   if (update_gll)
     update_global_location_list (UGLL_MAY_INSERT);
diff --git a/gdb/interps.c b/gdb/interps.c
index c727913e4806..f8f97513ac66 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -559,6 +559,14 @@ interps_notify_tsv_modified (const trace_state_variable *tsv)
   interps_notify (&interp::on_tsv_modified, tsv);
 }
 
+/* See interps.h.  */
+
+void
+interps_notify_breakpoint_created (breakpoint *b)
+{
+  interps_notify (&interp::on_breakpoint_created, b);
+}
+
 /* This just adds the "interpreter-exec" command.  */
 void _initialize_interpreter ();
 void
diff --git a/gdb/interps.h b/gdb/interps.h
index 7bd57cb05ecc..b1e2903e1571 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -166,6 +166,9 @@ class interp : public intrusive_list_node<interp>
   /* Notify the interpreter that trace state variable TSV was modified.  */
   virtual void on_tsv_modified (const trace_state_variable *tsv) {}
 
+  /* Notify the interpreter that breakpoint B was created.  */
+  virtual void on_breakpoint_created (breakpoint *b) {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
@@ -335,6 +338,9 @@ extern void interps_notify_tsv_deleted (const trace_state_variable *tsv);
 /* Notify all interpreters that trace state variable TSV was modified.  */
 extern void interps_notify_tsv_modified (const trace_state_variable *tsv);
 
+/* Notify all interpreters that breakpoint B was created.  */
+extern void interps_notify_breakpoint_created (breakpoint *b);
+
 /* well-known interpreters */
 #define INTERP_CONSOLE		"console"
 #define INTERP_MI2             "mi2"
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 65b9bd3693a2..d7df572546c4 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -60,7 +60,6 @@ static int mi_interp_query_hook (const char *ctlstr, va_list ap)
 static void mi_insert_notify_hooks (void);
 static void mi_remove_notify_hooks (void);
 
-static void mi_breakpoint_created (struct breakpoint *b);
 static void mi_breakpoint_deleted (struct breakpoint *b);
 static void mi_breakpoint_modified (struct breakpoint *b);
 static void mi_command_param_changed (const char *param, const char *value);
@@ -588,10 +587,8 @@ mi_print_breakpoint_for_event (struct mi_interp *mi, breakpoint *bp)
     }
 }
 
-/* Emit notification about a created breakpoint.  */
-
-static void
-mi_breakpoint_created (struct breakpoint *b)
+void
+mi_interp::on_breakpoint_created (breakpoint *b)
 {
   if (mi_suppress_notification.breakpoint)
     return;
@@ -599,22 +596,13 @@ mi_breakpoint_created (struct breakpoint *b)
   if (b->number <= 0)
     return;
 
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-      if (mi == NULL)
-	continue;
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      gdb_printf (mi->event_channel,
-		  "breakpoint-created");
-      mi_print_breakpoint_for_event (mi, b);
+  gdb_printf (this->event_channel, "breakpoint-created");
+  mi_print_breakpoint_for_event (this, b);
 
-      gdb_flush (mi->event_channel);
-    }
+  gdb_flush (this->event_channel);
 }
 
 /* Emit notification about deleted breakpoint.  */
@@ -1009,8 +997,6 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
 
-  gdb::observers::breakpoint_created.attach (mi_breakpoint_created,
-					     "mi-interp");
   gdb::observers::breakpoint_deleted.attach (mi_breakpoint_deleted,
 					     "mi-interp");
   gdb::observers::breakpoint_modified.attach (mi_breakpoint_modified,
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index 11ec5ddf3781..bbd47422e962 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -66,6 +66,7 @@ class mi_interp final : public interp
   void on_tsv_created (const trace_state_variable *tsv) override;
   void on_tsv_deleted (const trace_state_variable *tsv) override;
   void on_tsv_modified (const trace_state_variable *tsv) override;
+  void on_breakpoint_created (breakpoint *b) override;
 
   /* MI's output channels */
   mi_console_file *out;
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 27/30] gdb: add interp::on_breakpoint_deleted method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (25 preceding siblings ...)
  2023-05-02 20:50 ` [PATCH 26/30] gdb: add interp::on_breakpoint_created method Simon Marchi
@ 2023-05-02 20:50 ` Simon Marchi
  2023-05-02 20:50 ` [PATCH 28/30] gdb: add interp::on_breakpoint_modified method Simon Marchi
                   ` (4 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:50 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same idea as previous patches, but for breakpoint_deleted.

Change-Id: I59c231ce963491bb1eee1432ee1090138f09e19c
---
 gdb/breakpoint.c   | 11 ++++++++++-
 gdb/interps.c      |  8 ++++++++
 gdb/interps.h      |  6 ++++++
 gdb/mi/mi-interp.c | 27 ++++++---------------------
 gdb/mi/mi-interp.h |  1 +
 5 files changed, 31 insertions(+), 22 deletions(-)

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index a600bc7cc7fc..430e3b959ddf 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -12329,6 +12329,15 @@ strace_marker_p (struct breakpoint *b)
   return b->type == bp_static_marker_tracepoint;
 }
 
+/* Notify interpreters and observers that breakpoint B was deleted.  */
+
+static void
+notify_breakpoint_deleted (breakpoint *b)
+{
+  interps_notify_breakpoint_deleted (b);
+  gdb::observers::breakpoint_deleted.notify (b);
+}
+
 /* Delete a breakpoint and clean up all traces of it in the data
    structures.  */
 
@@ -12384,7 +12393,7 @@ delete_breakpoint (struct breakpoint *bpt)
      a problem in that process, we'll be asked to delete the half-created
      watchpoint.  In that case, don't announce the deletion.  */
   if (bpt->number)
-    gdb::observers::breakpoint_deleted.notify (bpt);
+    notify_breakpoint_deleted (bpt);
 
   if (breakpoint_chain == bpt)
     breakpoint_chain = bpt->next;
diff --git a/gdb/interps.c b/gdb/interps.c
index f8f97513ac66..dc36af64f4c4 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -567,6 +567,14 @@ interps_notify_breakpoint_created (breakpoint *b)
   interps_notify (&interp::on_breakpoint_created, b);
 }
 
+/* See interps.h.  */
+
+void
+interps_notify_breakpoint_deleted (breakpoint *b)
+{
+  interps_notify (&interp::on_breakpoint_deleted, b);
+}
+
 /* This just adds the "interpreter-exec" command.  */
 void _initialize_interpreter ();
 void
diff --git a/gdb/interps.h b/gdb/interps.h
index b1e2903e1571..0e17b14735c0 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -169,6 +169,9 @@ class interp : public intrusive_list_node<interp>
   /* Notify the interpreter that breakpoint B was created.  */
   virtual void on_breakpoint_created (breakpoint *b) {}
 
+  /* Notify the interpreter that breakpoint B was deleted.  */
+  virtual void on_breakpoint_deleted (breakpoint *b) {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
@@ -341,6 +344,9 @@ extern void interps_notify_tsv_modified (const trace_state_variable *tsv);
 /* Notify all interpreters that breakpoint B was created.  */
 extern void interps_notify_breakpoint_created (breakpoint *b);
 
+/* Notify all interpreters that breakpoint B was deleted.  */
+extern void interps_notify_breakpoint_deleted (breakpoint *b);
+
 /* well-known interpreters */
 #define INTERP_CONSOLE		"console"
 #define INTERP_MI2             "mi2"
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index d7df572546c4..334d7f9c5a82 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -60,7 +60,6 @@ static int mi_interp_query_hook (const char *ctlstr, va_list ap)
 static void mi_insert_notify_hooks (void);
 static void mi_remove_notify_hooks (void);
 
-static void mi_breakpoint_deleted (struct breakpoint *b);
 static void mi_breakpoint_modified (struct breakpoint *b);
 static void mi_command_param_changed (const char *param, const char *value);
 static void mi_memory_changed (struct inferior *inf, CORE_ADDR memaddr,
@@ -605,10 +604,8 @@ mi_interp::on_breakpoint_created (breakpoint *b)
   gdb_flush (this->event_channel);
 }
 
-/* Emit notification about deleted breakpoint.  */
-
-static void
-mi_breakpoint_deleted (struct breakpoint *b)
+void
+mi_interp::on_breakpoint_deleted (breakpoint *b)
 {
   if (mi_suppress_notification.breakpoint)
     return;
@@ -616,21 +613,11 @@ mi_breakpoint_deleted (struct breakpoint *b)
   if (b->number <= 0)
     return;
 
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-      if (mi == NULL)
-	continue;
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
-
-      gdb_printf (mi->event_channel, "breakpoint-deleted,id=\"%d\"",
-		  b->number);
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      gdb_flush (mi->event_channel);
-    }
+  gdb_printf (this->event_channel, "breakpoint-deleted,id=\"%d\"", b->number);
+  gdb_flush (this->event_channel);
 }
 
 /* Emit notification about modified breakpoint.  */
@@ -997,8 +984,6 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
 
-  gdb::observers::breakpoint_deleted.attach (mi_breakpoint_deleted,
-					     "mi-interp");
   gdb::observers::breakpoint_modified.attach (mi_breakpoint_modified,
 					      "mi-interp");
   gdb::observers::command_param_changed.attach (mi_command_param_changed,
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index bbd47422e962..61b8739b9b3c 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -67,6 +67,7 @@ class mi_interp final : public interp
   void on_tsv_deleted (const trace_state_variable *tsv) override;
   void on_tsv_modified (const trace_state_variable *tsv) override;
   void on_breakpoint_created (breakpoint *b) override;
+  void on_breakpoint_deleted (breakpoint *b) override;
 
   /* MI's output channels */
   mi_console_file *out;
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 28/30] gdb: add interp::on_breakpoint_modified method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (26 preceding siblings ...)
  2023-05-02 20:50 ` [PATCH 27/30] gdb: add interp::on_breakpoint_deleted method Simon Marchi
@ 2023-05-02 20:50 ` Simon Marchi
  2023-05-02 20:50 ` [PATCH 29/30] gdb: add interp::on_param_changed method Simon Marchi
                   ` (3 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:50 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same idea as previous patches, but for breakpoint_modified.

Change-Id: I4f0a9edea912de431e32451d74224b2022a7c328
---
 gdb/breakpoint.c      | 47 ++++++++++++++++++++++++++-----------------
 gdb/breakpoint.h      |  5 +++++
 gdb/interps.c         |  8 ++++++++
 gdb/interps.h         |  6 ++++++
 gdb/mi/mi-cmd-break.c |  2 +-
 gdb/mi/mi-interp.c    | 28 +++++++-------------------
 gdb/mi/mi-interp.h    |  1 +
 gdb/tracepoint.c      |  4 ++--
 8 files changed, 58 insertions(+), 43 deletions(-)

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 430e3b959ddf..853fe4978256 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -1002,6 +1002,15 @@ set_breakpoint_location_condition (const char *cond_string, bp_location *loc,
     error (_("Garbage '%s' follows condition"), cond_string);
 }
 
+/* See breakpoint.h.  */
+
+void
+notify_breakpoint_modified (breakpoint *b)
+{
+  interps_notify_breakpoint_modified (b);
+  gdb::observers::breakpoint_modified.notify (b);
+}
+
 void
 set_breakpoint_condition (struct breakpoint *b, const char *exp,
 			  int from_tty, bool force)
@@ -1094,7 +1103,7 @@ set_breakpoint_condition (struct breakpoint *b, const char *exp,
     }
   mark_breakpoint_modified (b);
 
-  gdb::observers::breakpoint_modified.notify (b);
+  notify_breakpoint_modified (b);
 }
 
 /* See breakpoint.h.  */
@@ -1438,7 +1447,7 @@ breakpoint_set_commands (struct breakpoint *b,
   validate_commands_for_breakpoint (b, commands.get ());
 
   b->commands = std::move (commands);
-  gdb::observers::breakpoint_modified.notify (b);
+  notify_breakpoint_modified (b);
 }
 
 /* Set the internal `silent' flag on the breakpoint.  Note that this
@@ -1452,7 +1461,7 @@ breakpoint_set_silent (struct breakpoint *b, int silent)
 
   b->silent = silent;
   if (old_silent != silent)
-    gdb::observers::breakpoint_modified.notify (b);
+    notify_breakpoint_modified (b);
 }
 
 /* See breakpoint.h.  */
@@ -1469,7 +1478,7 @@ breakpoint_set_thread (struct breakpoint *b, int thread)
 
   b->thread = thread;
   if (old_thread != thread)
-    gdb::observers::breakpoint_modified.notify (b);
+    notify_breakpoint_modified (b);
 }
 
 /* See breakpoint.h.  */
@@ -1486,7 +1495,7 @@ breakpoint_set_task (struct breakpoint *b, int task)
 
   b->task = task;
   if (old_task != task)
-    gdb::observers::breakpoint_modified.notify (b);
+    notify_breakpoint_modified (b);
 }
 
 static void
@@ -1555,7 +1564,7 @@ commands_command_1 (const char *arg, int from_tty,
 	 {
 	   validate_commands_for_breakpoint (b, cmd.get ());
 	   b->commands = cmd;
-	   gdb::observers::breakpoint_modified.notify (b);
+	   notify_breakpoint_modified (b);
 	 }
      });
 }
@@ -2893,7 +2902,7 @@ insert_bp_location (struct bp_location *bl,
 	    {
 	      /* See also: disable_breakpoints_in_shlibs.  */
 	      bl->shlib_disabled = 1;
-	      gdb::observers::breakpoint_modified.notify (bl->owner);
+	      notify_breakpoint_modified (bl->owner);
 	      if (!*disabled_breaks)
 		{
 		  gdb_printf (tmp_error_stream, 
@@ -5599,7 +5608,7 @@ bpstat_check_breakpoint_conditions (bpstat *bs, thread_info *thread)
       bs->stop = false;
       /* Increase the hit count even though we don't stop.  */
       ++(b->hit_count);
-      gdb::observers::breakpoint_modified.notify (b);
+      notify_breakpoint_modified (b);
       return;
     }
 
@@ -5762,7 +5771,7 @@ bpstat_stop_status (const address_space *aspace,
 		    b->enable_state = bp_disabled;
 		  removed_any = 1;
 		}
-	      gdb::observers::breakpoint_modified.notify (b);
+	      notify_breakpoint_modified (b);
 	      if (b->silent)
 		bs->print = false;
 	      bs->commands = b->commands;
@@ -7893,7 +7902,7 @@ disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
 	  loc->inserted = 0;
 
 	  /* This may cause duplicate notifications for the same breakpoint.  */
-	  gdb::observers::breakpoint_modified.notify (b);
+	  notify_breakpoint_modified (b);
 
 	  if (!disabled_shlib_breaks)
 	    {
@@ -7973,7 +7982,7 @@ disable_breakpoints_in_freed_objfile (struct objfile *objfile)
 	}
 
       if (bp_modified)
-	gdb::observers::breakpoint_modified.notify (b);
+	notify_breakpoint_modified (b);
     }
 }
 
@@ -11095,7 +11104,7 @@ download_tracepoint_locations (void)
       t = (struct tracepoint *) b;
       t->number_on_target = b->number;
       if (bp_location_downloaded)
-	gdb::observers::breakpoint_modified.notify (b);
+	notify_breakpoint_modified (b);
     }
 }
 
@@ -12863,7 +12872,7 @@ update_breakpoint_locations (code_breakpoint *b,
   }
 
   if (!locations_are_equal (existing_locations, b->loc))
-    gdb::observers::breakpoint_modified.notify (b);
+    notify_breakpoint_modified (b);
 }
 
 /* Find the SaL locations corresponding to the given LOCSPEC.
@@ -13111,7 +13120,7 @@ set_ignore_count (int bptnum, int count, int from_tty)
 			    "crossings of breakpoint %d."),
 			  count, bptnum);
 	  }
-	gdb::observers::breakpoint_modified.notify (b);
+	notify_breakpoint_modified (b);
 	return;
       }
 
@@ -13365,7 +13374,7 @@ enable_disable_bp_num_loc (int bp_num, int loc_num, bool enable)
     }
   update_global_location_list (UGLL_DONT_INSERT);
 
-  gdb::observers::breakpoint_modified.notify (loc->owner);
+  notify_breakpoint_modified (loc->owner);
 }
 
 /* Calculates LOC_NUM for LOC by traversing the bp_location chain of LOC's
@@ -13422,7 +13431,7 @@ enable_disable_bp_location (bp_location *loc, bool enable)
     target_disable_tracepoint (loc);
 
   update_global_location_list (UGLL_DONT_INSERT);
-  gdb::observers::breakpoint_modified.notify (loc->owner);
+  notify_breakpoint_modified (loc->owner);
 }
 
 /* Enable or disable a range of breakpoint locations.  BP_NUM is the
@@ -13467,7 +13476,7 @@ disable_breakpoint (struct breakpoint *bpt)
 
   update_global_location_list (UGLL_DONT_INSERT);
 
-  gdb::observers::breakpoint_modified.notify (bpt);
+  notify_breakpoint_modified (bpt);
 }
 
 /* Enable or disable the breakpoint(s) or breakpoint location(s)
@@ -13592,7 +13601,7 @@ enable_breakpoint_disp (struct breakpoint *bpt, enum bpdisp disposition,
   bpt->enable_count = count;
   update_global_location_list (UGLL_MAY_INSERT);
 
-  gdb::observers::breakpoint_modified.notify (bpt);
+  notify_breakpoint_modified (bpt);
 }
 
 
@@ -14063,7 +14072,7 @@ static void
 trace_pass_set_count (struct tracepoint *tp, int count, int from_tty)
 {
   tp->pass_count = count;
-  gdb::observers::breakpoint_modified.notify (tp);
+  notify_breakpoint_modified (tp);
   if (from_tty)
     gdb_printf (_("Setting tracepoint %d's passcount to %d\n"),
 		tp->number, count);
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 7c5cf3f2bef4..5cf49c4d7cce 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -1946,4 +1946,9 @@ extern void describe_other_breakpoints (struct gdbarch *,
 
 extern void enable_disable_bp_location (bp_location *loc, bool enable);
 
+
+/* Notify interpreters and observers that breakpoint B was modified.  */
+
+extern void notify_breakpoint_modified (breakpoint *b);
+
 #endif /* !defined (BREAKPOINT_H) */
diff --git a/gdb/interps.c b/gdb/interps.c
index dc36af64f4c4..d572f92f4aa0 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -575,6 +575,14 @@ interps_notify_breakpoint_deleted (breakpoint *b)
   interps_notify (&interp::on_breakpoint_deleted, b);
 }
 
+/* See interps.h.  */
+
+void
+interps_notify_breakpoint_modified (breakpoint *b)
+{
+  interps_notify (&interp::on_breakpoint_modified, b);
+}
+
 /* This just adds the "interpreter-exec" command.  */
 void _initialize_interpreter ();
 void
diff --git a/gdb/interps.h b/gdb/interps.h
index 0e17b14735c0..6fda2ba372f1 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -172,6 +172,9 @@ class interp : public intrusive_list_node<interp>
   /* Notify the interpreter that breakpoint B was deleted.  */
   virtual void on_breakpoint_deleted (breakpoint *b) {}
 
+  /* Notify the interpreter that breakpoint B was modified.  */
+  virtual void on_breakpoint_modified (breakpoint *b) {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
@@ -347,6 +350,9 @@ extern void interps_notify_breakpoint_created (breakpoint *b);
 /* Notify all interpreters that breakpoint B was deleted.  */
 extern void interps_notify_breakpoint_deleted (breakpoint *b);
 
+/* Notify all interpreters that breakpoint B was modified.  */
+extern void interps_notify_breakpoint_modified (breakpoint *b);
+
 /* well-known interpreters */
 #define INTERP_CONSOLE		"console"
 #define INTERP_MI2             "mi2"
diff --git a/gdb/mi/mi-cmd-break.c b/gdb/mi/mi-cmd-break.c
index e5432d589900..72d30a8d44e3 100644
--- a/gdb/mi/mi-cmd-break.c
+++ b/gdb/mi/mi-cmd-break.c
@@ -467,7 +467,7 @@ mi_cmd_break_passcount (const char *command, char **argv, int argc)
   if (t)
     {
       t->pass_count = p;
-      gdb::observers::breakpoint_modified.notify (t);
+      notify_breakpoint_modified (t);
     }
   else
     {
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 334d7f9c5a82..2e30b15a4862 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -60,7 +60,6 @@ static int mi_interp_query_hook (const char *ctlstr, va_list ap)
 static void mi_insert_notify_hooks (void);
 static void mi_remove_notify_hooks (void);
 
-static void mi_breakpoint_modified (struct breakpoint *b);
 static void mi_command_param_changed (const char *param, const char *value);
 static void mi_memory_changed (struct inferior *inf, CORE_ADDR memaddr,
 			       ssize_t len, const bfd_byte *myaddr);
@@ -620,10 +619,8 @@ mi_interp::on_breakpoint_deleted (breakpoint *b)
   gdb_flush (this->event_channel);
 }
 
-/* Emit notification about modified breakpoint.  */
-
-static void
-mi_breakpoint_modified (struct breakpoint *b)
+void
+mi_interp::on_breakpoint_modified (breakpoint *b)
 {
   if (mi_suppress_notification.breakpoint)
     return;
@@ -631,21 +628,12 @@ mi_breakpoint_modified (struct breakpoint *b)
   if (b->number <= 0)
     return;
 
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-
-      if (mi == NULL)
-	continue;
-
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
-      gdb_printf (mi->event_channel,
-		  "breakpoint-modified");
-      mi_print_breakpoint_for_event (mi, b);
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
+  gdb_printf (this->event_channel, "breakpoint-modified");
+  mi_print_breakpoint_for_event (this, b);
 
-      gdb_flush (mi->event_channel);
-    }
+  gdb_flush (this->event_channel);
 }
 
 static void
@@ -984,8 +972,6 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
 
-  gdb::observers::breakpoint_modified.attach (mi_breakpoint_modified,
-					      "mi-interp");
   gdb::observers::command_param_changed.attach (mi_command_param_changed,
 						"mi-interp");
   gdb::observers::memory_changed.attach (mi_memory_changed, "mi-interp");
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index 61b8739b9b3c..52cce4c7cf4c 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -68,6 +68,7 @@ class mi_interp final : public interp
   void on_tsv_modified (const trace_state_variable *tsv) override;
   void on_breakpoint_created (breakpoint *b) override;
   void on_breakpoint_deleted (breakpoint *b) override;
+  void on_breakpoint_modified (breakpoint *b) override;
 
   /* MI's output channels */
   mi_console_file *out;
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index e6ef87475060..2f4eb9c48a46 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -1639,7 +1639,7 @@ start_tracing (const char *notes)
 					  loc->gdbarch);
 
       if (bp_location_downloaded)
-	gdb::observers::breakpoint_modified.notify (b);
+	notify_breakpoint_modified (b);
     }
 
   /* Send down all the trace state variables too.  */
@@ -3138,7 +3138,7 @@ merge_uploaded_tracepoints (struct uploaded_tp **uploaded_tps)
   /* Notify 'breakpoint-modified' observer that at least one of B's
      locations was changed.  */
   for (breakpoint *b : modified_tp)
-    gdb::observers::breakpoint_modified.notify (b);
+    notify_breakpoint_modified (b);
 
   free_uploaded_tps (uploaded_tps);
 }
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 29/30] gdb: add interp::on_param_changed method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (27 preceding siblings ...)
  2023-05-02 20:50 ` [PATCH 28/30] gdb: add interp::on_breakpoint_modified method Simon Marchi
@ 2023-05-02 20:50 ` Simon Marchi
  2023-05-02 20:50 ` [PATCH 30/30] gdb: add interp::on_memory_changed method Simon Marchi
                   ` (2 subsequent siblings)
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:50 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same idea as previous patches, but for command_param_changed.

Change-Id: I7c2196343423360da05f016f8ffa871c064092bb
---
 gdb/cli/cli-setshow.c | 13 +++++++------
 gdb/interps.c         |  8 ++++++++
 gdb/interps.h         |  6 ++++++
 gdb/mi/mi-interp.c    | 34 ++++++++++------------------------
 gdb/mi/mi-interp.h    |  1 +
 gdb/observable.c      |  1 -
 gdb/observable.h      |  7 -------
 gdb/source.c          |  5 +++--
 8 files changed, 35 insertions(+), 40 deletions(-)

diff --git a/gdb/cli/cli-setshow.c b/gdb/cli/cli-setshow.c
index 07233e36a380..ecb739b94e90 100644
--- a/gdb/cli/cli-setshow.c
+++ b/gdb/cli/cli-setshow.c
@@ -21,6 +21,7 @@
 #include <ctype.h>
 #include "arch-utils.h"
 #include "observable.h"
+#include "interps.h"
 
 #include "ui-out.h"
 
@@ -521,18 +522,18 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
 	case var_string_noescape:
 	case var_filename:
 	case var_optional_filename:
-	  gdb::observers::command_param_changed.notify
+	  interps_notify_param_changed
 	    (name, c->var->get<std::string> ().c_str ());
 	  break;
 	case var_enum:
-	  gdb::observers::command_param_changed.notify
+	  interps_notify_param_changed
 	    (name, c->var->get<const char *> ());
 	  break;
 	case var_boolean:
 	  {
 	    const char *opt = c->var->get<bool> () ? "on" : "off";
 
-	    gdb::observers::command_param_changed.notify (name, opt);
+	    interps_notify_param_changed (name, opt);
 	  }
 	  break;
 	case var_auto_boolean:
@@ -540,7 +541,7 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
 	    const char *s
 	      = auto_boolean_enums[c->var->get<enum auto_boolean> ()];
 
-	    gdb::observers::command_param_changed.notify (name, s);
+	    interps_notify_param_changed (name, s);
 	  }
 	  break;
 	case var_uinteger:
@@ -548,7 +549,7 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
 	    char s[64];
 
 	    xsnprintf (s, sizeof s, "%u", c->var->get<unsigned int> ());
-	    gdb::observers::command_param_changed.notify (name, s);
+	    interps_notify_param_changed (name, s);
 	  }
 	  break;
 	case var_integer:
@@ -557,7 +558,7 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
 	    char s[64];
 
 	    xsnprintf (s, sizeof s, "%d", c->var->get<int> ());
-	    gdb::observers::command_param_changed.notify (name, s);
+	    interps_notify_param_changed (name, s);
 	  }
 	  break;
 	}
diff --git a/gdb/interps.c b/gdb/interps.c
index d572f92f4aa0..3cb89b113a3b 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -583,6 +583,14 @@ interps_notify_breakpoint_modified (breakpoint *b)
   interps_notify (&interp::on_breakpoint_modified, b);
 }
 
+/* See interps.h.  */
+
+void
+interps_notify_param_changed (const char *param, const char *value)
+{
+  interps_notify (&interp::on_param_changed, param, value);
+}
+
 /* This just adds the "interpreter-exec" command.  */
 void _initialize_interpreter ();
 void
diff --git a/gdb/interps.h b/gdb/interps.h
index 6fda2ba372f1..948b6f520df0 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -175,6 +175,9 @@ class interp : public intrusive_list_node<interp>
   /* Notify the interpreter that breakpoint B was modified.  */
   virtual void on_breakpoint_modified (breakpoint *b) {}
 
+  /* Notify the interpreter that parameter PARAM changed to VALUE.  */
+  virtual void on_param_changed (const char *param, const char *value) {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
@@ -353,6 +356,9 @@ extern void interps_notify_breakpoint_deleted (breakpoint *b);
 /* Notify all interpreters that breakpoint B was modified.  */
 extern void interps_notify_breakpoint_modified (breakpoint *b);
 
+/* Notify all interpreters that parameter PARAM changed to VALUE.  */
+extern void interps_notify_param_changed (const char *param, const char *value);
+
 /* well-known interpreters */
 #define INTERP_CONSOLE		"console"
 #define INTERP_MI2             "mi2"
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 2e30b15a4862..c6e70a779648 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -60,7 +60,6 @@ static int mi_interp_query_hook (const char *ctlstr, va_list ap)
 static void mi_insert_notify_hooks (void);
 static void mi_remove_notify_hooks (void);
 
-static void mi_command_param_changed (const char *param, const char *value);
 static void mi_memory_changed (struct inferior *inf, CORE_ADDR memaddr,
 			       ssize_t len, const bfd_byte *myaddr);
 
@@ -792,36 +791,25 @@ mi_interp::on_solib_unloaded (so_list *solib)
   gdb_flush (this->event_channel);
 }
 
-/* Emit notification about the command parameter change.  */
-
-static void
-mi_command_param_changed (const char *param, const char *value)
+void
+mi_interp::on_param_changed (const char *param, const char *value)
 {
   if (mi_suppress_notification.cmd_param_changed)
     return;
 
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-      struct ui_out *mi_uiout;
-
-      if (mi == NULL)
-	continue;
-
-      mi_uiout = top_level_interpreter ()->interp_ui_out ();
+  ui_out *mi_uiout = this->interp_ui_out ();
 
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      gdb_printf (mi->event_channel, "cmd-param-changed");
+  gdb_printf (this->event_channel, "cmd-param-changed");
 
-      ui_out_redirect_pop redir (mi_uiout, mi->event_channel);
+  ui_out_redirect_pop redir (mi_uiout, this->event_channel);
 
-      mi_uiout->field_string ("param", param);
-      mi_uiout->field_string ("value", value);
+  mi_uiout->field_string ("param", param);
+  mi_uiout->field_string ("value", value);
 
-      gdb_flush (mi->event_channel);
-    }
+  gdb_flush (this->event_channel);
 }
 
 /* Emit notification about the target memory change.  */
@@ -972,7 +960,5 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
 
-  gdb::observers::command_param_changed.attach (mi_command_param_changed,
-						"mi-interp");
   gdb::observers::memory_changed.attach (mi_memory_changed, "mi-interp");
 }
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index 52cce4c7cf4c..51f22b2ef112 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -69,6 +69,7 @@ class mi_interp final : public interp
   void on_breakpoint_created (breakpoint *b) override;
   void on_breakpoint_deleted (breakpoint *b) override;
   void on_breakpoint_modified (breakpoint *b) override;
+  void on_param_changed (const char *param, const char *value) override;
 
   /* MI's output channels */
   mi_console_file *out;
diff --git a/gdb/observable.c b/gdb/observable.c
index 3535e69f7f54..a18b863fb471 100644
--- a/gdb/observable.c
+++ b/gdb/observable.c
@@ -61,7 +61,6 @@ DEFINE_OBSERVABLE (inferior_removed);
 DEFINE_OBSERVABLE (memory_changed);
 DEFINE_OBSERVABLE (before_prompt);
 DEFINE_OBSERVABLE (gdb_datadir_changed);
-DEFINE_OBSERVABLE (command_param_changed);
 DEFINE_OBSERVABLE (inferior_call_pre);
 DEFINE_OBSERVABLE (inferior_call_post);
 DEFINE_OBSERVABLE (register_changed);
diff --git a/gdb/observable.h b/gdb/observable.h
index 1c7ba0a1ba67..f6047a239cd6 100644
--- a/gdb/observable.h
+++ b/gdb/observable.h
@@ -183,13 +183,6 @@ extern observable<const char */* current_prompt */> before_prompt;
    change.  */
 extern observable<> gdb_datadir_changed;
 
-/* The parameter of some 'set' commands in console are changed.
-   This method is called after a command 'set param value'.  PARAM
-   is the parameter of 'set' command, and VALUE is the value of
-   changed parameter.  */
-extern observable<const char */* param */, const char */* value */>
-    command_param_changed;
-
 /* An inferior function at ADDRESS is about to be called in thread
    THREAD.  */
 extern observable<ptid_t /* thread */, CORE_ADDR /* address */>
diff --git a/gdb/source.c b/gdb/source.c
index 4d297c82ea9c..d0bb3c126f3e 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -51,6 +51,7 @@
 #include "build-id.h"
 #include "debuginfod-support.h"
 #include "gdbsupport/buildargv.h"
+#include "interps.h"
 
 #define OPEN_MODE (O_RDONLY | O_BINARY)
 #define FDOPEN_MODE FOPEN_RB
@@ -462,8 +463,8 @@ directory_command (const char *dirname, int from_tty)
     }
   if (value_changed)
     {
-      gdb::observers::command_param_changed.notify ("directories",
-						    source_path.c_str ());
+      interps_notify_param_changed ("directories", source_path.c_str ());
+
       if (from_tty)
 	show_directories_1 (gdb_stdout, (char *) 0, from_tty);
     }
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 30/30] gdb: add interp::on_memory_changed method
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (28 preceding siblings ...)
  2023-05-02 20:50 ` [PATCH 29/30] gdb: add interp::on_param_changed method Simon Marchi
@ 2023-05-02 20:50 ` Simon Marchi
  2023-05-02 20:50 ` [PATCH 00/30] Make interpreters use virtual methods (instead of observers) Simon Marchi
  2023-05-23 12:43 ` [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:50 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same idea as previous patches, but for memory_changed.

Change-Id: Ic19f20c24d8a6431d4a89c5625e8ef4898f76e82
---
 gdb/corefile.c     | 13 ++++++++++-
 gdb/interps.c      |  9 +++++++
 gdb/interps.h      |  8 +++++++
 gdb/mi/mi-interp.c | 58 +++++++++++++++++-----------------------------
 gdb/mi/mi-interp.h |  2 ++
 5 files changed, 52 insertions(+), 38 deletions(-)

diff --git a/gdb/corefile.c b/gdb/corefile.c
index 5cb559000b82..1fbefd2eb8f9 100644
--- a/gdb/corefile.c
+++ b/gdb/corefile.c
@@ -33,6 +33,7 @@
 #include "observable.h"
 #include "cli/cli-utils.h"
 #include "gdbarch.h"
+#include "interps.h"
 
 /* You can have any number of hooks for `exec_file_command' command to
    call.  If there's only one hook, it is set in exec_file_display
@@ -353,6 +354,16 @@ write_memory (CORE_ADDR memaddr,
     memory_error (TARGET_XFER_E_IO, memaddr);
 }
 
+/* Notify interpreters and observers that INF's memory was changed.  */
+
+static void
+notify_memory_changed (inferior *inf, CORE_ADDR addr, ssize_t len,
+		       const bfd_byte *data)
+{
+  interps_notify_memory_changed (inf, addr, len, data);
+  gdb::observers::memory_changed.notify (inf, addr, len, data);
+}
+
 /* Same as write_memory, but notify 'memory_changed' observers.  */
 
 void
@@ -360,7 +371,7 @@ write_memory_with_notification (CORE_ADDR memaddr, const bfd_byte *myaddr,
 				ssize_t len)
 {
   write_memory (memaddr, myaddr, len);
-  gdb::observers::memory_changed.notify (current_inferior (), memaddr, len, myaddr);
+  notify_memory_changed (current_inferior (), memaddr, len, myaddr);
 }
 
 /* Store VALUE at ADDR in the inferior as a LEN-byte unsigned
diff --git a/gdb/interps.c b/gdb/interps.c
index 3cb89b113a3b..f665e86b65c7 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -591,6 +591,15 @@ interps_notify_param_changed (const char *param, const char *value)
   interps_notify (&interp::on_param_changed, param, value);
 }
 
+/* See interps.h.  */
+
+void
+interps_notify_memory_changed (inferior *inf, CORE_ADDR addr, ssize_t len,
+			       const bfd_byte *data)
+{
+  interps_notify (&interp::on_memory_changed, inf, addr, len, data);
+}
+
 /* This just adds the "interpreter-exec" command.  */
 void _initialize_interpreter ();
 void
diff --git a/gdb/interps.h b/gdb/interps.h
index 948b6f520df0..ebe078eb7394 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -178,6 +178,10 @@ class interp : public intrusive_list_node<interp>
   /* Notify the interpreter that parameter PARAM changed to VALUE.  */
   virtual void on_param_changed (const char *param, const char *value) {}
 
+  /* Notify the interpreter that inferior INF's memory was changed.  */
+  virtual void on_memory_changed (inferior *inf, CORE_ADDR addr, ssize_t len,
+				  const bfd_byte *data) {}
+
 private:
   /* The memory for this is static, it comes from literal strings (e.g. "cli").  */
   const char *m_name;
@@ -359,6 +363,10 @@ extern void interps_notify_breakpoint_modified (breakpoint *b);
 /* Notify all interpreters that parameter PARAM changed to VALUE.  */
 extern void interps_notify_param_changed (const char *param, const char *value);
 
+/* Notify all interpreters that inferior INF's memory was changed.  */
+extern void interps_notify_memory_changed (inferior *inf, CORE_ADDR addr,
+					   ssize_t len, const bfd_byte *data);
+
 /* well-known interpreters */
 #define INTERP_CONSOLE		"console"
 #define INTERP_MI2             "mi2"
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index c6e70a779648..473490be8ff5 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -60,9 +60,6 @@ static int mi_interp_query_hook (const char *ctlstr, va_list ap)
 static void mi_insert_notify_hooks (void);
 static void mi_remove_notify_hooks (void);
 
-static void mi_memory_changed (struct inferior *inf, CORE_ADDR memaddr,
-			       ssize_t len, const bfd_byte *myaddr);
-
 /* Display the MI prompt.  */
 
 static void
@@ -812,50 +809,39 @@ mi_interp::on_param_changed (const char *param, const char *value)
   gdb_flush (this->event_channel);
 }
 
-/* Emit notification about the target memory change.  */
-
-static void
-mi_memory_changed (struct inferior *inferior, CORE_ADDR memaddr,
-		   ssize_t len, const bfd_byte *myaddr)
+void
+mi_interp::on_memory_changed (inferior *inferior, CORE_ADDR memaddr,
+			      ssize_t len, const bfd_byte *myaddr)
 {
   if (mi_suppress_notification.memory)
     return;
 
-  SWITCH_THRU_ALL_UIS ()
-    {
-      struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
-      struct ui_out *mi_uiout;
-      struct obj_section *sec;
-
-      if (mi == NULL)
-	continue;
-
-      mi_uiout = top_level_interpreter ()->interp_ui_out ();
 
-      target_terminal::scoped_restore_terminal_state term_state;
-      target_terminal::ours_for_output ();
+  ui_out *mi_uiout = this->interp_ui_out ();
 
-      gdb_printf (mi->event_channel, "memory-changed");
+  target_terminal::scoped_restore_terminal_state term_state;
+  target_terminal::ours_for_output ();
 
-      ui_out_redirect_pop redir (mi_uiout, mi->event_channel);
+  gdb_printf (this->event_channel, "memory-changed");
 
-      mi_uiout->field_fmt ("thread-group", "i%d", inferior->num);
-      mi_uiout->field_core_addr ("addr", target_gdbarch (), memaddr);
-      mi_uiout->field_string ("len", hex_string (len));
+  ui_out_redirect_pop redir (mi_uiout, this->event_channel);
 
-      /* Append 'type=code' into notification if MEMADDR falls in the range of
-	 sections contain code.  */
-      sec = find_pc_section (memaddr);
-      if (sec != NULL && sec->objfile != NULL)
-	{
-	  flagword flags = bfd_section_flags (sec->the_bfd_section);
+  mi_uiout->field_fmt ("thread-group", "i%d", inferior->num);
+  mi_uiout->field_core_addr ("addr", target_gdbarch (), memaddr);
+  mi_uiout->field_string ("len", hex_string (len));
 
-	  if (flags & SEC_CODE)
-	    mi_uiout->field_string ("type", "code");
-	}
+  /* Append 'type=code' into notification if MEMADDR falls in the range of
+     sections contain code.  */
+  obj_section *sec = find_pc_section (memaddr);
+  if (sec != nullptr && sec->objfile != nullptr)
+    {
+      flagword flags = bfd_section_flags (sec->the_bfd_section);
 
-      gdb_flush (mi->event_channel);
+      if (flags & SEC_CODE)
+	mi_uiout->field_string ("type", "code");
     }
+
+  gdb_flush (this->event_channel);
 }
 
 void
@@ -959,6 +945,4 @@ _initialize_mi_interp ()
   interp_factory_register (INTERP_MI3, mi_interp_factory);
   interp_factory_register (INTERP_MI4, mi_interp_factory);
   interp_factory_register (INTERP_MI, mi_interp_factory);
-
-  gdb::observers::memory_changed.attach (mi_memory_changed, "mi-interp");
 }
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
index 51f22b2ef112..8540e3fa4fc8 100644
--- a/gdb/mi/mi-interp.h
+++ b/gdb/mi/mi-interp.h
@@ -70,6 +70,8 @@ class mi_interp final : public interp
   void on_breakpoint_deleted (breakpoint *b) override;
   void on_breakpoint_modified (breakpoint *b) override;
   void on_param_changed (const char *param, const char *value) override;
+  void on_memory_changed (inferior *inf, CORE_ADDR addr, ssize_t len,
+			  const bfd_byte *data) override;
 
   /* MI's output channels */
   mi_console_file *out;
-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 00/30] Make interpreters use virtual methods (instead of observers)
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (29 preceding siblings ...)
  2023-05-02 20:50 ` [PATCH 30/30] gdb: add interp::on_memory_changed method Simon Marchi
@ 2023-05-02 20:50 ` Simon Marchi
  2023-05-23 12:43 ` [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
  31 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-02 20:50 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi


Simon Marchi (30):
  gdb/mi: fix ^running record with multiple MI interpreters
  gdb/mi: make current_token a field of mi_interp
  gdb: add interp::on_signal_received method
  gdb: add interp::on_normal_stop method
  gdb: add interp::on_signal_exited method
  gdb: add interp::on_exited method
  gdb: add interp::on_no_history method
  gdb: add interp::on_sync_execution_done method
  gdb: add interp::on_command_error method
  gdb: add interp::on_user_selected_context_changed method
  gdb: add interp::on_new_thread method
  gdb: add interp::on_thread_exited method
  gdb: add interp::on_inferior_added method
  gdb: add interp::on_inferior_appeared method
  gdb: add interp::on_inferior_disappeared method
  gdb: add interp::on_inferior_removed method
  gdb: add interp::on_record_changed method
  gdb: add interp::on_target_resumed method
  gdb: add interp::on_solib_loaded method
  gdb: add interp::on_solib_unloaded method
  gdb: add interp::on_about_to_proceed method
  gdb: add interp::on_traceframe_changed method
  gdb: add interp::on_tsv_created method
  gdb: add interp::on_tsv_deleted method
  gdb: add interp::on_tsv_modified method
  gdb: add interp::on_breakpoint_created method
  gdb: add interp::on_breakpoint_deleted method
  gdb: add interp::on_breakpoint_modified method
  gdb: add interp::on_param_changed method
  gdb: add interp::on_memory_changed method

 gdb/breakpoint.c                             |  70 +-
 gdb/breakpoint.h                             |   5 +
 gdb/cli/cli-interp.c                         | 149 +--
 gdb/cli/cli-interp.h                         |   9 +
 gdb/cli/cli-setshow.c                        |  13 +-
 gdb/corefile.c                               |  13 +-
 gdb/inferior.c                               |  49 +-
 gdb/infrun.c                                 |  60 +-
 gdb/infrun.h                                 |  11 +
 gdb/interps.c                                | 217 +++++
 gdb/interps.h                                | 190 ++++
 gdb/main.c                                   |   2 +-
 gdb/mi/mi-cmd-break.c                        |   2 +-
 gdb/mi/mi-interp.c                           | 910 ++++++-------------
 gdb/mi/mi-interp.h                           |  39 +
 gdb/mi/mi-main.c                             |  33 +-
 gdb/mi/mi-main.h                             |   5 -
 gdb/observable.c                             |  11 -
 gdb/observable.h                             |  50 -
 gdb/record-btrace.c                          |   2 +-
 gdb/record-full.c                            |   2 +-
 gdb/record.c                                 |  12 +-
 gdb/record.h                                 |  13 +
 gdb/remote.c                                 |   5 +-
 gdb/solib.c                                  |  24 +-
 gdb/source.c                                 |   5 +-
 gdb/stack.c                                  |   8 +-
 gdb/testsuite/gdb.mi/run-with-two-mi-uis.c   |   7 +
 gdb/testsuite/gdb.mi/run-with-two-mi-uis.exp |  44 +
 gdb/testsuite/lib/mi-support.exp             |  22 +-
 gdb/thread.c                                 |  44 +-
 gdb/tracepoint.c                             |  17 +-
 32 files changed, 1099 insertions(+), 944 deletions(-)
 create mode 100644 gdb/testsuite/gdb.mi/run-with-two-mi-uis.c
 create mode 100644 gdb/testsuite/gdb.mi/run-with-two-mi-uis.exp

-- 
2.40.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 01/30] gdb/mi: fix ^running record with multiple MI interpreters
  2023-05-02 20:49 ` [PATCH 01/30] gdb/mi: fix ^running record with multiple MI interpreters Simon Marchi
@ 2023-05-03 14:42   ` Alexandra Petlanova Hajkova
  2023-05-03 15:02     ` Simon Marchi
  2023-05-29 14:53   ` Simon Marchi
  1 sibling, 1 reply; 39+ messages in thread
From: Alexandra Petlanova Hajkova @ 2023-05-03 14:42 UTC (permalink / raw)
  To: Simon Marchi; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 3070 bytes --]

On Tue, May 2, 2023 at 10:50 PM Simon Marchi via Gdb-patches <
gdb-patches@sourceware.org> wrote:

> I stumbled on the mi_proceeded and running_result_record_printed
> globals, which are shared by all MI interpreter instances (it's unlikely
> that people use multiple MI interpreter instances, but it's possible).
> After poking at it, I found this bug:
>
> 1. Start GDB in MI mode
> 2. Add a second MI interpreter with the new-ui command
> 3. Use -exec-run on the second interpreter
>
> This is the output I get on the first interpreter:
>
>     =thread-group-added,id="i1"
>     ~"Reading symbols from a.out...\n"
>     ~"New UI allocated\n"
>     (gdb)
>     =thread-group-started,id="i1",pid="94718"
>     =thread-created,id="1",group-id="i1"
>     ^running
>     *running,thread-id="all"
>
> And this is the output I get on the second intepreter:
>
>     =thread-group-added,id="i1"
>     (gdb)
>     -exec-run
>     =thread-group-started,id="i1",pid="94718"
>     =thread-created,id="1",group-id="i1"
>     *running,thread-id="all"
>
> The problem here is that the `^running` reply to the -exec-run command
> is printed on the wrong UI.  It is printed on the first one, it should
> be printed on the second (the one on which we sent the -exec-run).
>
> What happens under the hood is that captured_mi_execute_command, while
> executing a command for the second intepreter, clears the
> running_result_record_printed and mi_proceeded globals.
> mi_about_to_proceed then sets mi_proceeded.  Then, mi_on_resume_1 gets
> called for the first intepreter first.  Since the
>
>     !running_result_record_printed && mi_proceeded
>
> condition is true, it prints a ^running, and sets
> running_result_record_printed.  When mi_on_resume_1 gets called for the
> second interpreter, running_result_record_printed is already set, so
> ^running is not printed there.
>
> It took me a while to understand the relationship between these two
> variables.  I think that in the end, this is what we want to track:
>
>  1. When executing an MI command, take note if that command causes a
>     "proceed".  This is done in mi_about_to_proceed.
>  2. In mi_on_resume_1, if the command indeed caused a "proceed", we want
>     to output a ^running record.  And we want to remember that we did,
>     because...
>  3. Back in captured_mi_execute_command, if we did not output a
>     ^running, we want to output a ^done.
>
> Moving those two variables to the mi_interp struture appears to fix it.
> Only for the interpreter doing the -exec-run command does the
> running_result_record_printed flag get cleared, and therefore only or
> that one does the ^running record get printed.
>
> Add a new test for this, that does pretty much what the reproducer above
> shows.  Without the fix, the test fails because
> mi_send_resuming_command_raw never sees the ^running record.
>
> Change-Id: I63ea30e6cb61a8e1dd5ef03377e6003381a9209b
>
>
I can confirm the new test gdb.mi/run-with-two-mi-uis.exp, passes on
ppc64le.

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 01/30] gdb/mi: fix ^running record with multiple MI interpreters
  2023-05-03 14:42   ` Alexandra Petlanova Hajkova
@ 2023-05-03 15:02     ` Simon Marchi
  0 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-03 15:02 UTC (permalink / raw)
  To: Alexandra Petlanova Hajkova; +Cc: gdb-patches

> I can confirm the new test gdb.mi/run-with-two-mi-uis.exp, passes on ppc64le.

Thanks for testing.  I will add:

Tested-By: Alexandra Petlanova Hajkova <ahajkova@redhat.com>

Simon

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 02/30] gdb/mi: make current_token a field of mi_interp
  2023-05-02 20:49 ` [PATCH 02/30] gdb/mi: make current_token a field of mi_interp Simon Marchi
@ 2023-05-04 12:31   ` Alexandra Petlanova Hajkova
  0 siblings, 0 replies; 39+ messages in thread
From: Alexandra Petlanova Hajkova @ 2023-05-04 12:31 UTC (permalink / raw)
  To: Simon Marchi; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 712 bytes --]

On Tue, May 2, 2023 at 10:50 PM Simon Marchi via Gdb-patches <
gdb-patches@sourceware.org> wrote:

> Following the previous patch, I thought it would make sense to make
> current_token a field of mi_interp.  This variable contains the token of
> the currently handled MI command, like the 222 in:
>
>     222-exec-continue
>
> I didn't find any bug related to that, it's just a "that seems nicer"
> cleanup, since the current token is a fundamentally per-interp thing.
> There should be no user-visible change.
>
> Change-Id: Ib52b3c0cba4b7c9d805b432c809692a86e4945ad
>
>
I do agree the change feels nicer  and I can confirm this causes no
regressions when tested on Fedora Rawhide, ppc64le.

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 03/30] gdb: add interp::on_signal_received method
  2023-05-02 20:49 ` [PATCH 03/30] gdb: add interp::on_signal_received method Simon Marchi
@ 2023-05-04 14:38   ` Alexandra Petlanova Hajkova
  0 siblings, 0 replies; 39+ messages in thread
From: Alexandra Petlanova Hajkova @ 2023-05-04 14:38 UTC (permalink / raw)
  To: Simon Marchi; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 2572 bytes --]

On Tue, May 2, 2023 at 10:50 PM Simon Marchi via Gdb-patches <
gdb-patches@sourceware.org> wrote:

> Instead of having the interpreter code registering observers for the
> signal_received observable, add a "signal_received" virtual method to
> struct interp.  Add a interps_notify_signal_received function that loops
> over all UIs and calls the signal_received method on the interpreter.
> Finally, add a notify_signal_received function that calls
> interps_notify_signal_received and then notifies the observers.  Replace
> all existing notifications to the signal_received observers with calls
> to notify_signal_received.
>
> Before this patch, the CLI and MI code both register a signal_received
> observer.  These observer go over all UIs, and, for those that have a
> interpreter of the right kind, print the stop notifiation.
>
> After this patch, we have just one "loop over all UIs", inside
> interps_notify_signal_received.  Since the interp::on_signal_received
> method gets called once for each interpreter, the implementations only
> need to deal with the current interpreter (the "this" pointer).
>
> The motivation for this patch comes from a future patch, that makes the
> amdgpu code register an observer to print a warning after the CLI's
> signal stop message.  Since the amdgpu and the CLI code both use
> observers, the order of the two messages is not stable, unless we define
> the priority using the observer dependency system.  However, the
> approach of using virtual methods on the interpreters seems like a good
> change anyway, I think it's more straightforward and simple to
> understand than the current solution that uses observers.  We are sure
> that the amdgpu message gets printed after the CLI message, since
> observers are notified after interpreters.
>
> Keep the signal_received, even if nothing uses if, because we will be
> using it in the upcoming amdgpu patch implementing the warning described
> above.
>
> Change-Id: I4d8614bb8f6e0717f4bfc2a59abded3702f23ac4
> ---
>  gdb/cli/cli-interp.c | 17 +++--------------
>  gdb/cli/cli-interp.h |  2 ++
>  gdb/infrun.c         | 14 ++++++++++++--
>  gdb/infrun.h         |  4 ++++
>  gdb/interps.c        | 23 +++++++++++++++++++++++
>  gdb/interps.h        |  8 ++++++++
>  gdb/mi/mi-interp.c   | 20 ++++----------------
>  gdb/mi/mi-interp.h   |  2 ++
>  gdb/remote.c         |  2 +-
>  9 files changed, 59 insertions(+), 33 deletions(-)
>
> I can confirm this causes no regressions when tested on Fedora-Rawhide,
> ppc64le.
>

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 00/30] Switch interpreters to use virtual methods
  2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
                   ` (30 preceding siblings ...)
  2023-05-02 20:50 ` [PATCH 00/30] Make interpreters use virtual methods (instead of observers) Simon Marchi
@ 2023-05-23 12:43 ` Simon Marchi
  2023-05-30 19:09   ` Simon Marchi
  31 siblings, 1 reply; 39+ messages in thread
From: Simon Marchi @ 2023-05-23 12:43 UTC (permalink / raw)
  To: Simon Marchi, gdb-patches

On 5/2/23 16:49, Simon Marchi via Gdb-patches wrote:
> Interpreters currently get notified of events through observers, usually
> doing this pattern:
> 
>   SWITCH_THRU_ALL_UIS ()
>     {
>       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
> 
>       if (mi == NULL)
> 	continue;
> 
>       ...
>     }
> 
> The example here is for MI interpreters, but the CLI does the same.
> 
> This series adds virtual methods to struct interp such that interpreters
> get notified of things happening through virtual method calls instead.
> 
> The original reason for looking at that area was to fix some unstable
> ordering between a breakpoint stop message and a message output in an
> observer, related to the amd-dbgapi target.  Pedro suggested this design
> change, which solves my ordering problem indirectly, and thought it was
> a good idea as well.  The result looks much more like idiomatic C++ than
> the original.  In particular, I like that each method implementation, in
> mi-interp.c and cli-interp.c, only has to worry about the current
> ("this") interpreter, removing all those scattered SWITCH_THRU_ALL_UIS
> calls.  It also removes the dynamic_casts hidden in as_mi_interp and
> as_cli_interp_base.
> 
> The testsuite passes fine for me.  One thing I was wondering about is
> that the MI interpreter currently has this:
> 
>     static struct mi_interp *
>     find_mi_interp (void)
>     {
>       struct mi_interp *mi;
> 
>       mi = as_mi_interp (top_level_interpreter ());
>       if (mi != NULL)
>         return mi;
> 
>       mi = as_mi_interp (command_interp ());
>       if (mi != NULL)
>         return mi;
> 
>       return NULL;
>     }
> 
> So, find_mi_interp sometimes returns the command_interp, if it's an MI
> interpreter.  In my series, however, I only ever notify the top level
> interpreter, using this templated function:
> 
>     /* Helper interps_notify_* functions.  Call METHOD on the top-level interpreter
>        of all UIs.  */
> 
>     template <typename ...Args>
>     void
>     interps_notify (void (interp::*method) (Args...), Args... args)
>     {
>       SWITCH_THRU_ALL_UIS ()
>         {
>           interp *tli = top_level_interpreter ();
>           if (tli != nullptr)
>             (tli->*method) (args...);
>         }
>     }
> 
> I was wondering if I had to notify the command_interpreter at some
> point.  Butwever I was not able to find a behavior change related to
> this, caused by my series.  command_interpreter is set (temporarily) by
> interp_exec, so in order to have an MI interpreter as the command
> interpreter, you'd have to use an `interpreter-exec mi ...` command in
> the CLI.
> 
> find_mi_interp is only used in a few observers observers that react to
> target wait events (like mi_on_signal_received).  When I do, for
> instance:
> 
>   (gdb) interpreter-exec mi -exec-continue
> 
> ... then the command_interpreter is only set for the duration of the
> -exec-continue command, which does not include consuming and handling
> the target event.  Even with a synchronous target, the "wait" part is
> done outside the continue command, after coming back to the event loop,
> since 0b333c5e7d6c:
> 
>     @@ -3094,15 +3102,11 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
> 
>        discard_cleanups (old_chain);
> 
>     -  /* Wait for it to stop (if not standalone)
>     -     and in any case decode why it stopped, and act accordingly.  */
>     -  /* Do this only if we are not using the event loop, or if the target
>     -     does not support asynchronous execution.  */
>     +  /* Tell the event loop to wait for it to stop.  If the target
>     +     supports asynchronous execution, it'll do this from within
>     +     target_resume.  */
>        if (!target_can_async_p ())
>     -    {
>     -      wait_for_inferior ();
>     -      normal_stop ();
>     -    }
>     +    mark_async_event_handler (infrun_async_inferior_event_token);
>      }
> 
> This means that all the observers using find_mi_interp are called when
> we are back at the event loop, after command_interpreter has been
> reset.  And that would explain why my change looks good, despite never
> notifying the command_interpreter.
> 
> Other than that, the first patch is a bug fix, fixing a problem I
> noticed along the way.

Any thoughts on this?  Otherwise, I plan merging it by the end of the
week.

Simon

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 01/30] gdb/mi: fix ^running record with multiple MI interpreters
  2023-05-02 20:49 ` [PATCH 01/30] gdb/mi: fix ^running record with multiple MI interpreters Simon Marchi
  2023-05-03 14:42   ` Alexandra Petlanova Hajkova
@ 2023-05-29 14:53   ` Simon Marchi
  1 sibling, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-29 14:53 UTC (permalink / raw)
  To: Simon Marchi, gdb-patches

On 5/2/23 16:49, Simon Marchi via Gdb-patches wrote:
> I stumbled on the mi_proceeded and running_result_record_printed
> globals, which are shared by all MI interpreter instances (it's unlikely
> that people use multiple MI interpreter instances, but it's possible).
> After poking at it, I found this bug:
> 
> 1. Start GDB in MI mode
> 2. Add a second MI interpreter with the new-ui command
> 3. Use -exec-run on the second interpreter
> 
> This is the output I get on the first interpreter:
> 
>     =thread-group-added,id="i1"
>     ~"Reading symbols from a.out...\n"
>     ~"New UI allocated\n"
>     (gdb)
>     =thread-group-started,id="i1",pid="94718"
>     =thread-created,id="1",group-id="i1"
>     ^running
>     *running,thread-id="all"
> 
> And this is the output I get on the second intepreter:
> 
>     =thread-group-added,id="i1"
>     (gdb)
>     -exec-run
>     =thread-group-started,id="i1",pid="94718"
>     =thread-created,id="1",group-id="i1"
>     *running,thread-id="all"
> 
> The problem here is that the `^running` reply to the -exec-run command
> is printed on the wrong UI.  It is printed on the first one, it should
> be printed on the second (the one on which we sent the -exec-run).
> 
> What happens under the hood is that captured_mi_execute_command, while
> executing a command for the second intepreter, clears the
> running_result_record_printed and mi_proceeded globals.
> mi_about_to_proceed then sets mi_proceeded.  Then, mi_on_resume_1 gets
> called for the first intepreter first.  Since the
> 
>     !running_result_record_printed && mi_proceeded
> 
> condition is true, it prints a ^running, and sets
> running_result_record_printed.  When mi_on_resume_1 gets called for the
> second interpreter, running_result_record_printed is already set, so
> ^running is not printed there.
> 
> It took me a while to understand the relationship between these two
> variables.  I think that in the end, this is what we want to track:
> 
>  1. When executing an MI command, take note if that command causes a
>     "proceed".  This is done in mi_about_to_proceed.
>  2. In mi_on_resume_1, if the command indeed caused a "proceed", we want
>     to output a ^running record.  And we want to remember that we did,
>     because...
>  3. Back in captured_mi_execute_command, if we did not output a
>     ^running, we want to output a ^done.
> 
> Moving those two variables to the mi_interp struture appears to fix it.
> Only for the interpreter doing the -exec-run command does the
> running_result_record_printed flag get cleared, and therefore only or
> that one does the ^running record get printed.
> 
> Add a new test for this, that does pretty much what the reproducer above
> shows.  Without the fix, the test fails because
> mi_send_resuming_command_raw never sees the ^running record.
> 
> Change-Id: I63ea30e6cb61a8e1dd5ef03377e6003381a9209b

I pushed just this patch on its own.  The rest of the series conflicts
in non-trivial ways with new stuff in master.

Simon

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 00/30] Switch interpreters to use virtual methods
  2023-05-23 12:43 ` [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
@ 2023-05-30 19:09   ` Simon Marchi
  0 siblings, 0 replies; 39+ messages in thread
From: Simon Marchi @ 2023-05-30 19:09 UTC (permalink / raw)
  To: Simon Marchi, gdb-patches

On 5/23/23 08:43, Simon Marchi via Gdb-patches wrote:
> On 5/2/23 16:49, Simon Marchi via Gdb-patches wrote:
>> Interpreters currently get notified of events through observers, usually
>> doing this pattern:
>>
>>   SWITCH_THRU_ALL_UIS ()
>>     {
>>       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
>>
>>       if (mi == NULL)
>> 	continue;
>>
>>       ...
>>     }
>>
>> The example here is for MI interpreters, but the CLI does the same.
>>
>> This series adds virtual methods to struct interp such that interpreters
>> get notified of things happening through virtual method calls instead.
>>
>> The original reason for looking at that area was to fix some unstable
>> ordering between a breakpoint stop message and a message output in an
>> observer, related to the amd-dbgapi target.  Pedro suggested this design
>> change, which solves my ordering problem indirectly, and thought it was
>> a good idea as well.  The result looks much more like idiomatic C++ than
>> the original.  In particular, I like that each method implementation, in
>> mi-interp.c and cli-interp.c, only has to worry about the current
>> ("this") interpreter, removing all those scattered SWITCH_THRU_ALL_UIS
>> calls.  It also removes the dynamic_casts hidden in as_mi_interp and
>> as_cli_interp_base.
>>
>> The testsuite passes fine for me.  One thing I was wondering about is
>> that the MI interpreter currently has this:
>>
>>     static struct mi_interp *
>>     find_mi_interp (void)
>>     {
>>       struct mi_interp *mi;
>>
>>       mi = as_mi_interp (top_level_interpreter ());
>>       if (mi != NULL)
>>         return mi;
>>
>>       mi = as_mi_interp (command_interp ());
>>       if (mi != NULL)
>>         return mi;
>>
>>       return NULL;
>>     }
>>
>> So, find_mi_interp sometimes returns the command_interp, if it's an MI
>> interpreter.  In my series, however, I only ever notify the top level
>> interpreter, using this templated function:
>>
>>     /* Helper interps_notify_* functions.  Call METHOD on the top-level interpreter
>>        of all UIs.  */
>>
>>     template <typename ...Args>
>>     void
>>     interps_notify (void (interp::*method) (Args...), Args... args)
>>     {
>>       SWITCH_THRU_ALL_UIS ()
>>         {
>>           interp *tli = top_level_interpreter ();
>>           if (tli != nullptr)
>>             (tli->*method) (args...);
>>         }
>>     }
>>
>> I was wondering if I had to notify the command_interpreter at some
>> point.  Butwever I was not able to find a behavior change related to
>> this, caused by my series.  command_interpreter is set (temporarily) by
>> interp_exec, so in order to have an MI interpreter as the command
>> interpreter, you'd have to use an `interpreter-exec mi ...` command in
>> the CLI.
>>
>> find_mi_interp is only used in a few observers observers that react to
>> target wait events (like mi_on_signal_received).  When I do, for
>> instance:
>>
>>   (gdb) interpreter-exec mi -exec-continue
>>
>> ... then the command_interpreter is only set for the duration of the
>> -exec-continue command, which does not include consuming and handling
>> the target event.  Even with a synchronous target, the "wait" part is
>> done outside the continue command, after coming back to the event loop,
>> since 0b333c5e7d6c:
>>
>>     @@ -3094,15 +3102,11 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
>>
>>        discard_cleanups (old_chain);
>>
>>     -  /* Wait for it to stop (if not standalone)
>>     -     and in any case decode why it stopped, and act accordingly.  */
>>     -  /* Do this only if we are not using the event loop, or if the target
>>     -     does not support asynchronous execution.  */
>>     +  /* Tell the event loop to wait for it to stop.  If the target
>>     +     supports asynchronous execution, it'll do this from within
>>     +     target_resume.  */
>>        if (!target_can_async_p ())
>>     -    {
>>     -      wait_for_inferior ();
>>     -      normal_stop ();
>>     -    }
>>     +    mark_async_event_handler (infrun_async_inferior_event_token);
>>      }
>>
>> This means that all the observers using find_mi_interp are called when
>> we are back at the event loop, after command_interpreter has been
>> reset.  And that would explain why my change looks good, despite never
>> notifying the command_interpreter.
>>
>> Other than that, the first patch is a bug fix, fixing a problem I
>> noticed along the way.
> 
> Any thoughts on this?  Otherwise, I plan merging it by the end of the
> week.

I pushed this series, except patch 2 ("gdb/mi: make current_token a
field of mi_interp") which conflicts with master in a non-trivial way.
However, it is not really necessary for the rest of the series.

Simon

^ permalink raw reply	[flat|nested] 39+ messages in thread

end of thread, other threads:[~2023-05-30 19:09 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-02 20:49 [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
2023-05-02 20:49 ` [PATCH 01/30] gdb/mi: fix ^running record with multiple MI interpreters Simon Marchi
2023-05-03 14:42   ` Alexandra Petlanova Hajkova
2023-05-03 15:02     ` Simon Marchi
2023-05-29 14:53   ` Simon Marchi
2023-05-02 20:49 ` [PATCH 02/30] gdb/mi: make current_token a field of mi_interp Simon Marchi
2023-05-04 12:31   ` Alexandra Petlanova Hajkova
2023-05-02 20:49 ` [PATCH 03/30] gdb: add interp::on_signal_received method Simon Marchi
2023-05-04 14:38   ` Alexandra Petlanova Hajkova
2023-05-02 20:49 ` [PATCH 04/30] gdb: add interp::on_normal_stop method Simon Marchi
2023-05-02 20:49 ` [PATCH 05/30] gdb: add interp::on_signal_exited method Simon Marchi
2023-05-02 20:49 ` [PATCH 06/30] gdb: add interp::on_exited method Simon Marchi
2023-05-02 20:49 ` [PATCH 07/30] gdb: add interp::on_no_history method Simon Marchi
2023-05-02 20:49 ` [PATCH 08/30] gdb: add interp::on_sync_execution_done method Simon Marchi
2023-05-02 20:49 ` [PATCH 09/30] gdb: add interp::on_command_error method Simon Marchi
2023-05-02 20:49 ` [PATCH 10/30] gdb: add interp::on_user_selected_context_changed method Simon Marchi
2023-05-02 20:49 ` [PATCH 11/30] gdb: add interp::on_new_thread method Simon Marchi
2023-05-02 20:49 ` [PATCH 12/30] gdb: add interp::on_thread_exited method Simon Marchi
2023-05-02 20:49 ` [PATCH 13/30] gdb: add interp::on_inferior_added method Simon Marchi
2023-05-02 20:49 ` [PATCH 14/30] gdb: add interp::on_inferior_appeared method Simon Marchi
2023-05-02 20:49 ` [PATCH 15/30] gdb: add interp::on_inferior_disappeared method Simon Marchi
2023-05-02 20:49 ` [PATCH 16/30] gdb: add interp::on_inferior_removed method Simon Marchi
2023-05-02 20:49 ` [PATCH 17/30] gdb: add interp::on_record_changed method Simon Marchi
2023-05-02 20:49 ` [PATCH 18/30] gdb: add interp::on_target_resumed method Simon Marchi
2023-05-02 20:49 ` [PATCH 19/30] gdb: add interp::on_solib_loaded method Simon Marchi
2023-05-02 20:50 ` [PATCH 20/30] gdb: add interp::on_solib_unloaded method Simon Marchi
2023-05-02 20:50 ` [PATCH 21/30] gdb: add interp::on_about_to_proceed method Simon Marchi
2023-05-02 20:50 ` [PATCH 22/30] gdb: add interp::on_traceframe_changed method Simon Marchi
2023-05-02 20:50 ` [PATCH 23/30] gdb: add interp::on_tsv_created method Simon Marchi
2023-05-02 20:50 ` [PATCH 24/30] gdb: add interp::on_tsv_deleted method Simon Marchi
2023-05-02 20:50 ` [PATCH 25/30] gdb: add interp::on_tsv_modified method Simon Marchi
2023-05-02 20:50 ` [PATCH 26/30] gdb: add interp::on_breakpoint_created method Simon Marchi
2023-05-02 20:50 ` [PATCH 27/30] gdb: add interp::on_breakpoint_deleted method Simon Marchi
2023-05-02 20:50 ` [PATCH 28/30] gdb: add interp::on_breakpoint_modified method Simon Marchi
2023-05-02 20:50 ` [PATCH 29/30] gdb: add interp::on_param_changed method Simon Marchi
2023-05-02 20:50 ` [PATCH 30/30] gdb: add interp::on_memory_changed method Simon Marchi
2023-05-02 20:50 ` [PATCH 00/30] Make interpreters use virtual methods (instead of observers) Simon Marchi
2023-05-23 12:43 ` [PATCH 00/30] Switch interpreters to use virtual methods Simon Marchi
2023-05-30 19:09   ` Simon Marchi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).