+2008-08-12 Pedro Alves <pedro@codesourcery.com>
+
+ Add no-ack mode to the remote protocol --- optionally stop ACKing
+ packets and responses when we have a reliable communication
+ medium.
+
+ Based on Apple's GDB, by Jason Molenda <jmolenda@apple.com>
+
+ * remote.c (struct remote_state): Add noack_mode field.
+ (PACKET_QStartNoAckMode): New.
+ (remote_start_remote): Don't any outstanding packet here.
+ (remote_open_1): Clear noack_mode. Ack any outstanding packet
+ here. Activate noack mode if requested.
+ (remote_protocol_features): Add QStartNoAckMode.
+ (remote_open_1):
+ (putpkt_binary): Don't send ack in noack mode.
+ (read_frame): Don't recompute the checksum in noack mode.
+ (getpkt_sane): Skip sending ack if in noack mode.
+ (_initialize_remote): Add set/show remote noack mode.
+ * NEWS: Note the new features.
+
2008-08-11 Kevin Buettner <kevinb@redhat.com>
* rs6000-tdep.c (BL_MASK, BL_INSTRUCTION, BL_DISPLACEMENT_MASK):
qSearch:memory:
Search memory for a sequence of bytes.
+QStartNoAckMode
+ Turn off `+'/`-' protocol acknowledgments to permit more efficient
+ operation over reliable transport links. Use of this packet is
+ controlled by the `set remote noack-packet' command.
+
* Removed remote protocol undocumented extension
An undocumented extension to the remote protocol's `S' stop reply
gdbserver executable to debug both 32-bit and 64-bit programs.
(This requires gdbserver itself to be built as a 64-bit executable.)
+ - gdbserver uses the new noack protocol mode for TCP connections to
+ reduce communications latency, if also supported and enabled in GDB.
+
* Python scripting
GDB now has support for scripting using Python. Whether this is
+2008-08-12 Sandra Loosemore <sandra@codesourcery.com>
+
+ * gdb.texinfo (Remote Configuration): Document set remote noack-packet.
+ (Remote Protocol): Add Packet Acknowledgment to menu.
+ (Overview): Mention +/- can be disabled, and point to new section
+ where this is discussed in detail.
+ (General Query Packets): Document QStartNoAckMode packet, and
+ corresponding qSupported reply.
+ (Packet Acknowledgment): New section.
+
2008-08-11 Sandra Loosemore <sandra@codesourcery.com>
Pedro Alves <pedro@codesourcery.com>
@item @code{hostio-unlink-packet}
@tab @code{vFile:unlink}
@tab @code{remote delete}
+
+@item @code{noack-packet}
+@tab @code{QStartNoAckMode}
+@tab Packet acknowledgment
@end multitable
@node Remote Stub
You can control the timeout used while waiting for a packet, in the MIPS
remote protocol, with the @code{set timeout @var{seconds}} command. The
default is 5 seconds. Similarly, you can control the timeout used while
-waiting for an acknowledgement of a packet with the @code{set
+waiting for an acknowledgment of a packet with the @code{set
retransmit-timeout @var{seconds}} command. The default is 3 seconds.
You can inspect both values with @code{show timeout} and @code{show
retransmit-timeout}. (These commands are @emph{only} available when
* Tracepoint Packets::
* Host I/O Packets::
* Interrupts::
+* Packet Acknowledgment::
* Examples::
* File-I/O Remote Protocol Extension::
* Library List Format::
has never output @var{sequence-id}s. Stubs that handle packets added
since @value{GDBN} 5.0 must not accept @var{sequence-id}.
-@cindex acknowledgment, for @value{GDBN} remote
When either the host or the target machine receives a packet, the first
response expected is an acknowledgment: either @samp{+} (to indicate
the package was received correctly) or @samp{-} (to request
@end smallexample
@noindent
+The @samp{+}/@samp{-} acknowledgments can be disabled
+once a connection is established.
+@xref{Packet Acknowledgment}, for details.
+
The host (@value{GDBN}) sends @var{command}s, and the target (the
debugging stub incorporated in your program) sends a @var{response}. In
the case of step and continue @var{command}s, the response is only sent
An empty reply indicates that @samp{qSearch:memory} is not recognized.
@end table
+@item QStartNoAckMode
+@cindex @samp{QStartNoAckMode} packet
+@anchor{QStartNoAckMode}
+Request that the remote stub disable the normal @samp{+}/@samp{-}
+protocol acknowledgments (@pxref{Packet Acknowledgment}).
+
+Reply:
+@table @samp
+@item OK
+The stub has switched to no-acknowledgment mode.
+@value{GDBN} acknowledges this reponse,
+but neither the stub nor @value{GDBN} shall send or expect further
+@samp{+}/@samp{-} acknowledgments in the current connection.
+@item
+An empty reply indicates that the stub does not support no-acknowledgment mode.
+@end table
+
@item qSupported @r{[}:@var{gdbfeature} @r{[};@var{gdbfeature}@r{]}@dots{} @r{]}
@cindex supported packets, remote query
@cindex features of the remote protocol
@tab @samp{-}
@tab Yes
+@item @samp{QStartNoAckMode}
+@tab No
+@tab @samp{-}
+@tab Yes
+
@end multitable
These are the currently defined stub features, in more detail:
The remote stub understands the @samp{QPassSignals} packet
(@pxref{QPassSignals}).
+@item QStartNoAckMode
+The remote stub understands the @samp{QStartNoAckMode} packet and
+prefers to operate in no-acknowledgment mode. @xref{Packet Acknowledgment}.
+
@end table
@item qSymbol::
of successfully stopping the program. Interrupts received while the
program is stopped will be discarded.
+@node Packet Acknowledgment
+@section Packet Acknowledgment
+
+@cindex acknowledgment, for @value{GDBN} remote
+@cindex packet acknowledgment, for @value{GDBN} remote
+By default, when either the host or the target machine receives a packet,
+the first response expected is an acknowledgment: either @samp{+} (to indicate
+the package was received correctly) or @samp{-} (to request retransmission).
+This mechanism allows the @value{GDBN} remote protocol to operate over
+unreliable transport mechanisms, such as a serial line.
+
+In cases where the transport mechanism is itself reliable (such as a pipe or
+TCP connection), the @samp{+}/@samp{-} acknowledgments are redundant.
+It may be desirable to disable them in that case to reduce communication
+overhead, or for other reasons. This can be accomplished by means of the
+@samp{QStartNoAckMode} packet; @pxref{QStartNoAckMode}.
+
+When in no-acknowledgment mode, neither the stub nor @value{GDBN} shall send or
+expect @samp{+}/@samp{-} protocol acknowledgments. The packet
+and response format still includes the normal checksum, as described in
+@ref{Overview}, but the checksum may be ignored by the receiver.
+
+If the stub supports @samp{QStartNoAckMode} and prefers to operate in
+no-acknowledgment mode, it should report that to @value{GDBN}
+by including @samp{QStartNoAckMode+} in its response to @samp{qSupported};
+@pxref{qSupported}.
+If @value{GDBN} also supports @samp{QStartNoAckMode} and it has not been
+disabled via the @code{set remote noack-packet off} command
+(@pxref{Remote Configuration}),
+@value{GDBN} may then send a @samp{QStartNoAckMode} packet to the stub.
+Only then may the stub actually turn off packet acknowledgments.
+@value{GDBN} sends a final @samp{+} acknowledgment of the stub's @samp{OK}
+response, which can be safely ignored by the stub.
+
+Note that @code{set remote noack-packet} command only affects negotiation
+between @value{GDBN} and the stub when subsequent connections are made;
+it does not affect the protocol acknowledgment state for any current
+connection.
+Since @samp{+}/@samp{-} acknowledgments are enabled by default when a
+new connection is established,
+there is also no protocol request to re-enable the acknowledgments
+for the current connection, once disabled.
+
+
@node Examples
@section Examples
+2008-08-12 Pedro Alves <pedro@codesourcery.com>
+
+ * remote-utils.c (noack_mode, transport_is_reliable): New globals.
+ (remote_open): Set or clear transport_is_reliable.
+ (putpkt_binary): Don't expect acks in noack mode.
+ (getpkt): Don't send ack/nac in noack mode.
+ * server.c (handle_general_set): Handle QStartNoAckMode.
+ (handle_query): If connected by tcp pass QStartNoAckMode+ in
+ qSupported.
+ (main): Reset noack_mode on every connection.
+ * server.h (noack_mode): Declare.
+
2008-08-07 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
* Makefile.in (GDBREPLAY_OBS): New variable.
extern int using_threads;
extern int debug_threads;
+/* If true, then GDB has requested noack mode. */
+int noack_mode = 0;
+/* If true, then we tell GDB to use noack mode by default. */
+int transport_is_reliable = 0;
+
#ifdef USE_WIN32API
# define read(fd, buf, len) recv (fd, (char *) buf, len, 0)
# define write(fd, buf, len) send (fd, (char *) buf, len, 0)
fprintf (stderr, "Remote debugging using %s\n", name);
#endif /* USE_WIN32API */
+
+ transport_is_reliable = 0;
}
else
{
/* Convert IP address to string. */
fprintf (stderr, "Remote debugging from host %s\n",
inet_ntoa (sockaddr.sin_addr));
+
+ transport_is_reliable = 1;
}
#if defined(F_SETFL) && defined (FASYNC)
return -1;
}
+ if (noack_mode)
+ {
+ /* Don't expect an ack then. */
+ if (remote_debug)
+ {
+ fprintf (stderr, "putpkt (\"%s\"); [noack mode]\n", buf2);
+ fflush (stderr);
+ }
+ break;
+ }
+
if (remote_debug)
{
fprintf (stderr, "putpkt (\"%s\"); [looking for ack]\n", buf2);
if (csum == (c1 << 4) + c2)
break;
+ if (noack_mode)
+ {
+ fprintf (stderr, "Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s [no-ack-mode, Bad medium?]\n",
+ (c1 << 4) + c2, csum, buf);
+ /* Not much we can do, GDB wasn't expecting an ack/nac. */
+ break;
+ }
+
fprintf (stderr, "Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n",
(c1 << 4) + c2, csum, buf);
write (remote_desc, "-", 1);
}
- if (remote_debug)
+ if (!noack_mode)
{
- fprintf (stderr, "getpkt (\"%s\"); [sending ack] \n", buf);
- fflush (stderr);
- }
+ if (remote_debug)
+ {
+ fprintf (stderr, "getpkt (\"%s\"); [sending ack] \n", buf);
+ fflush (stderr);
+ }
- write (remote_desc, "+", 1);
+ write (remote_desc, "+", 1);
- if (remote_debug)
- {
- fprintf (stderr, "[sent ack]\n");
- fflush (stderr);
+ if (remote_debug)
+ {
+ fprintf (stderr, "[sent ack]\n");
+ fflush (stderr);
+ }
}
return bp - buf;
return;
}
+ if (strcmp (own_buf, "QStartNoAckMode") == 0)
+ {
+ if (remote_debug)
+ {
+ fprintf (stderr, "[noack mode enabled]\n");
+ fflush (stderr);
+ }
+
+ noack_mode = 1;
+ write_ok (own_buf);
+ return;
+ }
+
/* Otherwise we didn't know what packet it was. Say we didn't
understand it. */
own_buf[0] = 0;
qXfer:feature:read at all, we will never be re-queried. */
strcat (own_buf, ";qXfer:features:read+");
+ if (transport_is_reliable)
+ strcat (own_buf, ";QStartNoAckMode+");
return;
}
while (1)
{
+ noack_mode = 0;
remote_open (port);
restart:
extern int remote_debug;
extern int all_symbols_looked_up;
+extern int noack_mode;
+extern int transport_is_reliable;
int putpkt (char *buf);
int putpkt_binary (char *buf, int len);
skip calling getpkt. This flag is set when BUF contains a
stop reply packet and the target is not waiting. */
int cached_wait_status;
+
+ /* True, if in no ack mode. That is, neither GDB nor the stub will
+ expect acks from each other. The connection is assumed to be
+ reliable. */
+ int noack_mode;
};
/* This data could be associated with a target, but we do not always
PACKET_qSearch_memory,
PACKET_vAttach,
PACKET_vRun,
+ PACKET_QStartNoAckMode,
PACKET_MAX
};
immediate_quit++; /* Allow user to interrupt it. */
- /* Ack any packet which the remote side has already sent. */
- serial_write (remote_desc, "+", 1);
-
/* Check whether the target is running now. */
putpkt ("?");
getpkt (&rs->buf, &rs->buf_size, 0);
PACKET_qXfer_spu_write },
{ "QPassSignals", PACKET_DISABLE, remote_supported_packet,
PACKET_QPassSignals },
+ { "QStartNoAckMode", PACKET_DISABLE, remote_supported_packet,
+ PACKET_QStartNoAckMode },
};
static void
remote_open_1 (char *name, int from_tty, struct target_ops *target, int extended_p)
{
struct remote_state *rs = get_remote_state ();
+ struct packet_config *noack_config;
+
if (name == 0)
error (_("To open a remote debug connection, you need to specify what\n"
"serial device is attached to the remote system\n"
remote_query_supported or as they are needed. */
init_all_packet_configs ();
rs->explicit_packet_size = 0;
+ rs->noack_mode = 0;
general_thread = not_sent_ptid;
continue_thread = not_sent_ptid;
use_threadinfo_query = 1;
use_threadextra_query = 1;
+ /* Ack any packet which the remote side has already sent. */
+ serial_write (remote_desc, "+", 1);
+
/* The first packet we send to the target is the optional "supported
packets" request. If the target can answer this, it will tell us
which later probes to skip. */
remote_query_supported ();
+ /* Next, we possibly activate noack mode.
+
+ If the QStartNoAckMode packet configuration is set to AUTO,
+ enable noack mode if the stub reported a wish for it with
+ qSupported.
+
+ If set to TRUE, then enable noack mode even if the stub didn't
+ report it in qSupported. If the stub doesn't reply OK, the
+ session ends with an error.
+
+ If FALSE, then don't activate noack mode, regardless of what the
+ stub claimed should be the default with qSupported. */
+
+ noack_config = &remote_protocol_packets[PACKET_QStartNoAckMode];
+
+ if (noack_config->detect == AUTO_BOOLEAN_TRUE
+ || (noack_config->detect == AUTO_BOOLEAN_AUTO
+ && noack_config->support == PACKET_ENABLE))
+ {
+ putpkt ("QStartNoAckMode");
+ getpkt (&rs->buf, &rs->buf_size, 0);
+ if (packet_ok (rs->buf, noack_config) == PACKET_OK)
+ rs->noack_mode = 1;
+ }
+
/* Next, if the target can specify a description, read it. We do
this before anything involving memory or registers. */
target_find_description ();
if (serial_write (remote_desc, buf2, p - buf2))
perror_with_name (_("putpkt: write failed"));
+ /* If this is a no acks version of the remote protocol, send the
+ packet and move on. */
+ if (rs->noack_mode)
+ break;
+
/* Read until either a timeout occurs (-2) or '+' is read. */
while (1)
{
}
#endif
}
+ return 0;
}
/* Come here after finding the start of a frame when we expected an
long bc;
int c;
char *buf = *buf_p;
+ struct remote_state *rs = get_remote_state ();
csum = 0;
bc = 0;
return -1;
}
+ /* Don't recompute the checksum; with no ack packets we
+ don't have any way to indicate a packet retransmission
+ is necessary. */
+ if (rs->noack_mode)
+ return bc;
+
pktcsum = (fromhex (check_0) << 4) | fromhex (check_1);
if (csum == pktcsum)
return bc;
fputstrn_unfiltered (*buf, val, 0, gdb_stdlog);
fprintf_unfiltered (gdb_stdlog, "\n");
}
- serial_write (remote_desc, "+", 1);
+
+ /* Skip the ack char if we're in no-ack mode. */
+ if (!rs->noack_mode)
+ serial_write (remote_desc, "+", 1);
return val;
}
/* Try the whole thing again. */
retry:
- serial_write (remote_desc, "-", 1);
+ /* Skip the nack char if we're in no-ack mode. */
+ if (!rs->noack_mode)
+ serial_write (remote_desc, "-", 1);
}
/* We have tried hard enough, and just can't receive the packet.
Give up. */
printf_unfiltered (_("Ignoring packet error, continuing...\n"));
- serial_write (remote_desc, "+", 1);
+
+ /* Skip the ack char if we're in no-ack mode. */
+ if (!rs->noack_mode)
+ serial_write (remote_desc, "+", 1);
return -1;
}
\f
add_packet_config_cmd (&remote_protocol_packets[PACKET_vRun],
"vRun", "run", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_QStartNoAckMode],
+ "QStartNoAckMode", "noack", 0);
+
/* Keep the old ``set remote Z-packet ...'' working. Each individual
Z sub-packet has its own set and show commands, but users may
have sets to this variable in their .gdbinit files (or in their