This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH v4 9/9] enable target-async


This enables target-async by default.

Unlike the CLI, MI chose to treat target-async specially -- setting it
changes the default behavior of commands.  So, we can't get rid of the
option.  Instead we have to make it MI-only.

The hardest part of this patch, to my surprise, was getting the MI
prompt to work properly.  It was reasonably easy, and clean, to get
close to what the test suite expects; but to fix the last remaining
failure (mi-async.exp), I had to resort to a hack.

It seems to me that the MI grammar was never updated to account for
changes implied by async.

Perhaps some future MI can dispense with the prompt entirely.

Built and regtested on x86-64 Fedora 18.

	* infrun.c (set_observer_mode): Don't set target_async_permitted.
	* linux-nat.c (linux_nat_is_async_p): Always return 1.
	(linux_nat_can_async_p): Likewise.
	* mi/mi-interp.c (thread_command_not_mi): New function.
	(mi_interpreter_prompt_p): Maybe print the MI prompt.
	(mi_execute_command_input_handler): Conditionally print prompt.
	(mi_on_resume): Check sync_execution before printing prompt.
	* mi/mi-main.c (mi_target_can_async_p): New function.
	(exec_continue): Maybe call async_disable_stdin.
	(run_one_inferior, mi_cmd_exec_run, mi_cmd_list_target_features):
	Use mi_target_can_async_p.
	(mi_execute_async_cli_command): Use mi_target_can_async_p.
	* remote.c (remote_open_1, remote_terminal_inferior)
	(remote_terminal_ours, remote_can_async_p, remote_is_async_p):
	Don't check target_async_permitted.

	* gdb.texinfo (Non-Stop Mode): Remove "set target-async 1"
	from example.
	(Background Execution): Move target-async docs...
	(Asynchronous and non-stop modes): ... here.  Rewrite to
	MI form.

	* gdb.mi/mi-cli.exp: Don't check "$async".
---
 gdb/doc/gdb.texinfo             | 29 ++++++++++---------------
 gdb/infrun.c                    |  1 -
 gdb/linux-nat.c                 | 10 ++-------
 gdb/mi/mi-interp.c              | 43 ++++++++++++++++++++++++++++++------
 gdb/mi/mi-main.c                | 26 ++++++++++++++++------
 gdb/remote.c                    | 48 +++++++++++------------------------------
 gdb/testsuite/gdb.mi/mi-cli.exp | 15 +------------
 gdb/tui/tui-interp.c            |  1 +
 8 files changed, 85 insertions(+), 88 deletions(-)

diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 44fb174..770e7cb 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -5672,9 +5672,6 @@ To enter non-stop mode, use this sequence of commands before you run
 or attach to your program:
 
 @smallexample
-# Enable the async interface.  
-set target-async 1
-
 # If using the CLI, pagination breaks non-stop.
 set pagination off
 
@@ -5744,21 +5741,6 @@ the program to report that some thread has stopped before prompting for
 another command.  In background execution, @value{GDBN} immediately gives
 a command prompt so that you can issue other commands while your program runs.
 
-You need to explicitly enable asynchronous mode before you can use
-background execution commands.  You can use these commands to
-manipulate the asynchronous mode setting:
-
-@table @code
-@kindex set target-async
-@item set target-async on
-Enable asynchronous mode.
-@item set target-async off
-Disable asynchronous mode.
-@kindex show target-async
-@item show target-async
-Show the current target-async setting.
-@end table
-
 If the target doesn't support async mode, @value{GDBN} issues an error
 message if you attempt to use the background execution commands.
 
@@ -28679,6 +28661,17 @@ frontend has started the executable or attached to the target, it can
 find if asynchronous execution is enabled using the
 @code{-list-target-features} command.
 
+@table @code
+@kindex -gdb-set target-async
+@item -gdb-set target-async on
+Enable asynchronous mode.  This mode only affects MI commands.
+@item -gdb-set target-async off
+Disable asynchronous mode.
+@kindex -gdb-show target-async
+@item -gdb-show target-async
+Show the current target-async setting.
+@end table
+
 Even if @value{GDBN} can accept a command while target is running,
 many commands that access the target do not work when the target is
 running.  Therefore, asynchronous command execution is most useful
diff --git a/gdb/infrun.c b/gdb/infrun.c
index a58b6fe..b5e81a8 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -246,7 +246,6 @@ set_observer_mode (char *args, int from_tty,
      going out we leave it that way.  */
   if (observer_mode)
     {
-      target_async_permitted = 1;
       pagination_enabled = 0;
       non_stop = non_stop_1 = 1;
     }
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index fb2dbb4..a772772 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -4499,10 +4499,7 @@ linux_trad_target (CORE_ADDR (*register_u_offset)(struct gdbarch *, int, int))
 static int
 linux_nat_is_async_p (struct target_ops *ops)
 {
-  /* NOTE: palves 2008-03-21: We're only async when the user requests
-     it explicitly with the "set target-async" command.
-     Someday, linux will always be async.  */
-  return target_async_permitted;
+  return 1;
 }
 
 /* target_can_async_p implementation.  */
@@ -4510,10 +4507,7 @@ linux_nat_is_async_p (struct target_ops *ops)
 static int
 linux_nat_can_async_p (struct target_ops *ops)
 {
-  /* NOTE: palves 2008-03-21: We're only async when the user requests
-     it explicitly with the "set target-async" command.
-     Someday, linux will always be async.  */
-  return target_async_permitted;
+  return 1;
 }
 
 static int
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 527e4f1..76db63b 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -207,11 +207,33 @@ mi_interpreter_exec (void *data, const char *command)
   return exception_none;
 }
 
+/* A thread iterator callback function that checks to see if a given
+   thread's command interpreter was not the MI interpreter.  */
+
+static int
+thread_command_not_mi (struct thread_info *thr, void *ignore)
+{
+  return thr->control.command_interp != top_level_interpreter ();
+}
+
 /* Never display the default GDB prompt in MI case.  */
 
 static int
 mi_interpreter_prompt_p (void *data)
 {
+  if (!interp_quiet_p (NULL))
+    {
+      if (!target_is_async_p ()
+	  || (!sync_execution
+	      && (!target_async_permitted
+		  || iterate_over_threads (thread_command_not_mi,
+					   NULL) == NULL)))
+	{
+	  fputs_unfiltered ("(gdb) \n", raw_stdout);
+	  gdb_flush (raw_stdout);
+	}
+    }
+
   return 0;
 }
 
@@ -308,8 +330,17 @@ mi_execute_command_input_handler (char *cmd)
 {
   mi_execute_command_wrapper (cmd);
 
-  fputs_unfiltered ("(gdb) \n", raw_stdout);
-  gdb_flush (raw_stdout);
+  /* MI generally prints a prompt after a command.  However, if target
+     is async, and a synchronous command was issued, then we will
+     print the prompt elsewhere, after printing "*running".
+     target_is_async_p checks whether the target is async;
+     sync_execution checks whether a synchronous command was
+     issued.  */
+  if (!target_is_async_p () || !sync_execution)
+    {
+      fputs_unfiltered ("(gdb) \n", raw_stdout);
+      gdb_flush (raw_stdout);
+    }
 }
 
 static void
@@ -821,10 +852,10 @@ mi_on_resume (ptid_t ptid)
       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 earler.  */
-      /* FIXME: review the use of target_is_async_p here -- is that
-	 what we want? */
-      if (!target_is_async_p ())
+	 for MI3, and may be removed even earler.  SYNC_EXECUTION is
+	 checked here because we only need to emit a prompt if a
+	 synchronous command was issued when the target is async.  */
+      if (!target_is_async_p () || sync_execution)
 	fputs_unfiltered ("(gdb) \n", raw_stdout);
     }
   gdb_flush (raw_stdout);
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index 24ac1e0..704a13b 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -106,6 +106,15 @@ static int register_changed_p (int regnum, struct regcache *,
 static void output_register (struct frame_info *, int regnum, int format,
 			     int skip_unavailable);
 
+/* A wrapper for target_can_async_p that takes the MI setting into
+   account.  */
+
+static int
+mi_target_can_async_p (void)
+{
+  return target_async_permitted && target_can_async_p ();
+}
+
 /* Command implementations.  FIXME: Is this libgdb?  No.  This is the MI
    layer that calls libgdb.  Any operation used in the below should be
    formalized.  */
@@ -262,6 +271,11 @@ exec_continue (char **argv, int argc)
     {
       struct cleanup *back_to = make_cleanup_restore_integer (&sched_multi);
 
+      /* If MI is in sync mode but the target is async, then
+	 normal_stop enabled stdin.  We undo the change here.  */
+      if (!target_async_permitted && target_can_async_p ())
+	async_disable_stdin ();
+
       if (current_context->all)
 	{
 	  sched_multi = 1;
@@ -396,8 +410,8 @@ run_one_inferior (struct inferior *inf, void *arg)
       switch_to_thread (null_ptid);
       set_current_program_space (inf->pspace);
     }
-  mi_execute_cli_command (run_cmd, target_can_async_p (),
-			  target_can_async_p () ? "&" : NULL);
+  mi_execute_cli_command (run_cmd, mi_target_can_async_p (),
+			  mi_target_can_async_p () ? "&" : NULL);
   return 0;
 }
 
@@ -451,8 +465,8 @@ mi_cmd_exec_run (char *command, char **argv, int argc)
     {
       const char *run_cmd = start_p ? "start" : "run";
 
-      mi_execute_cli_command (run_cmd, target_can_async_p (),
-			      target_can_async_p () ? "&" : NULL);
+      mi_execute_cli_command (run_cmd, mi_target_can_async_p (),
+			      mi_target_can_async_p () ? "&" : NULL);
     }
 }
 
@@ -1837,7 +1851,7 @@ mi_cmd_list_target_features (char *command, char **argv, int argc)
       struct ui_out *uiout = current_uiout;
 
       cleanup = make_cleanup_ui_out_list_begin_end (uiout, "features");      
-      if (target_can_async_p ())
+      if (mi_target_can_async_p ())
 	ui_out_field_string (uiout, NULL, "async");
       if (target_can_execute_reverse)
 	ui_out_field_string (uiout, NULL, "reverse");
@@ -2252,7 +2266,7 @@ mi_execute_async_cli_command (char *cli_command, char **argv, int argc)
   struct cleanup *old_cleanups;
   char *run;
 
-  if (target_can_async_p ())
+  if (mi_target_can_async_p ())
     run = xstrprintf ("%s %s&", cli_command, argc ? *argv : "");
   else
     run = xstrprintf ("%s %s", cli_command, argc ? *argv : "");
diff --git a/gdb/remote.c b/gdb/remote.c
index b143014..db7f7ae 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -4275,8 +4275,7 @@ remote_open_1 (char *name, int from_tty,
 	   "(e.g. /dev/ttyS0, /dev/ttya, COM1, etc.)."));
 
   /* See FIXME above.  */
-  if (!target_async_permitted)
-    wait_forever_enabled_p = 1;
+  wait_forever_enabled_p = 1;
 
   /* If we're connected to a running target, target_preopen will kill it.
      Ask this question first, before target_preopen has a chance to kill
@@ -4362,20 +4361,17 @@ remote_open_1 (char *name, int from_tty,
   rs->use_threadinfo_query = 1;
   rs->use_threadextra_query = 1;
 
-  if (target_async_permitted)
-    {
-      /* With this target we start out by owning the terminal.  */
-      remote_async_terminal_ours_p = 1;
+  /* With this target we start out by owning the terminal.  */
+  remote_async_terminal_ours_p = 1;
 
-      /* FIXME: cagney/1999-09-23: During the initial connection it is
-	 assumed that the target is already ready and able to respond to
-	 requests.  Unfortunately remote_start_remote() eventually calls
-	 wait_for_inferior() with no timeout.  wait_forever_enabled_p gets
-	 around this.  Eventually a mechanism that allows
-	 wait_for_inferior() to expect/get timeouts will be
-	 implemented.  */
-      wait_forever_enabled_p = 0;
-    }
+  /* FIXME: cagney/1999-09-23: During the initial connection it is
+     assumed that the target is already ready and able to respond to
+     requests.  Unfortunately remote_start_remote() eventually calls
+     wait_for_inferior() with no timeout.  wait_forever_enabled_p gets
+     around this.  Eventually a mechanism that allows
+     wait_for_inferior() to expect/get timeouts will be
+     implemented.  */
+  wait_forever_enabled_p = 0;
 
   /* First delete any symbols previously loaded from shared libraries.  */
   no_shared_libraries (NULL, 0);
@@ -4411,14 +4407,12 @@ remote_open_1 (char *name, int from_tty,
 	   already before throwing the exception.  */
 	if (rs->remote_desc != NULL)
 	  remote_unpush_target ();
-	if (target_async_permitted)
-	  wait_forever_enabled_p = 1;
+	wait_forever_enabled_p = 1;
 	throw_exception (ex);
       }
   }
 
-  if (target_async_permitted)
-    wait_forever_enabled_p = 1;
+  wait_forever_enabled_p = 1;
 }
 
 /* This takes a program previously attached to and detaches it.  After
@@ -5209,10 +5203,6 @@ Give up (and stop debugging it)? ")))
 static void
 remote_terminal_inferior (void)
 {
-  if (!target_async_permitted)
-    /* Nothing to do.  */
-    return;
-
   /* FIXME: cagney/1999-09-27: Make calls to target_terminal_*()
      idempotent.  The event-loop GDB talking to an asynchronous target
      with a synchronous command calls this function from both
@@ -5232,10 +5222,6 @@ remote_terminal_inferior (void)
 static void
 remote_terminal_ours (void)
 {
-  if (!target_async_permitted)
-    /* Nothing to do.  */
-    return;
-
   /* See FIXME in remote_terminal_inferior.  */
   if (remote_async_terminal_ours_p)
     return;
@@ -11622,10 +11608,6 @@ remote_can_async_p (struct target_ops *ops)
 {
   struct remote_state *rs = get_remote_state ();
 
-  if (!target_async_permitted)
-    /* We only enable async when the user specifically asks for it.  */
-    return 0;
-
   /* We're async whenever the serial device is.  */
   return serial_can_async_p (rs->remote_desc);
 }
@@ -11635,10 +11617,6 @@ remote_is_async_p (struct target_ops *ops)
 {
   struct remote_state *rs = get_remote_state ();
 
-  if (!target_async_permitted)
-    /* We only enable async when the user specifically asks for it.  */
-    return 0;
-
   /* We're async whenever the serial device is.  */
   return serial_is_async_p (rs->remote_desc);
 }
diff --git a/gdb/testsuite/gdb.mi/mi-cli.exp b/gdb/testsuite/gdb.mi/mi-cli.exp
index bee296d..08e443e 100644
--- a/gdb/testsuite/gdb.mi/mi-cli.exp
+++ b/gdb/testsuite/gdb.mi/mi-cli.exp
@@ -134,20 +134,7 @@ mi_gdb_test "500-stack-select-frame 0" \
   {500\^done} \
   "-stack-select-frame 0"
 
-# When a CLI command is entered in MI session, the respose is different in
-# sync and async modes. In sync mode normal_stop is called when current
-# interpreter is CLI. So:
-#   - print_stop_reason prints stop reason in CLI uiout, and we don't show it
-#     in MI
-#   - The stop position is printed, and appears in MI 'console' channel.
-#
-# In async mode the stop event is processed when we're back to MI interpreter,
-# so the stop reason is printed into MI uiout an.
-if {$async} {
-    set reason "end-stepping-range"
-} else {
-    set reason ""
-}
+set reason "end-stepping-range"
 
 mi_execute_to "interpreter-exec console step" $reason "callee4" "" ".*basics.c" $line_callee4_next \
     "" "check *stopped from CLI command"
diff --git a/gdb/tui/tui-interp.c b/gdb/tui/tui-interp.c
index 1095220..659f1cd 100644
--- a/gdb/tui/tui-interp.c
+++ b/gdb/tui/tui-interp.c
@@ -30,6 +30,7 @@
 #include "tui/tui.h"
 #include "tui/tui-io.h"
 #include "exceptions.h"
+#include "target.h"
 
 /* Set to 1 when the TUI mode must be activated when we first start
    gdb.  */
-- 
1.8.1.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]