binutils-gdb/gdbserver/notif.c
Tom Tromey 919adfe840 Move gdbserver to top level
This patch moves gdbserver to the top level.

This patch is as close to a pure move as possible -- gdbserver still
builds its own variant of gnulib and gdbsupport.  Changing this will
be done in a separate patch.

[v2] Note that, per Simon's review comment, this patch changes the
tree so that gdbserver is not built for or1k or score.  This makes
sense, because there is apparently not actually a gdbserver port here.

[v3] This version of the patch also splits out some configury into a
new file, gdbserver/configure.host, so that the top-level configure
script can simply rely on it in order to decide whether gdbserver
should be built.

[v4] This version adds documentation and removes some unnecessary
top-level dependencies.

[v5] Update docs to mention "make all-gdbserver" and change how
top-level configure decides whether to build gdbserver, switching to a
single, shared script.

Tested by the buildbot.

ChangeLog
2020-02-07  Tom Tromey  <tom@tromey.com>
	    Pedro Alves  <palves@redhat.com>

	* src-release.sh (GDB_SUPPORT_DIRS): Add gdbserver.
	* gdbserver: New directory, moved from gdb/gdbserver.
	* configure.ac (host_tools): Add gdbserver.
	Only build gdbserver on certain systems.
	* Makefile.in, configure: Rebuild.
	* Makefile.def (host_modules, dependencies): Add gdbserver.
	* MAINTAINERS: Add gdbserver.

gdb/ChangeLog
2020-02-07  Tom Tromey  <tom@tromey.com>

	* README: Update gdbserver documentation.
	* gdbserver: Move to top level.
	* configure.tgt (build_gdbserver): Remove.
	* configure.ac: Remove --enable-gdbserver.
	* configure: Rebuild.
	* Makefile.in (distclean): Don't mention gdbserver.

Change-Id: I826b7565b54604711dc7a11edea0499cd51ff39e
2020-02-07 08:42:25 -07:00

154 lines
4.4 KiB
C

/* Notification to GDB.
Copyright (C) 1989-2020 Free Software Foundation, Inc.
This file is part of GDB.
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/>. */
/* Async notifications to GDB. When the state of remote target is
changed or something interesting to GDB happened, async
notifications are used to tell GDB.
Each type of notification is represented by an object
'struct notif_server', in which there is a queue for events to GDB
represented by 'struct notif_event'. GDBserver writes (by means of
'write' field) each event in the queue into the buffer and send the
contents in buffer to GDB. The contents in buffer is specified in
RSP. See more in the comments to field 'queue' of
'struct notif_server'.
Here is the workflow of sending events and managing queue:
1. At any time, when something interesting FOO happens, a object
of 'struct notif_event' or its sub-class EVENT is created for FOO.
2. Enque EVENT to the 'queue' field of 'struct notif_server' for
FOO and send corresponding notification packet to GDB if EVENT is
the first one.
#1 and #2 are done by function 'notif_push'.
3. EVENT is not deque'ed until the ack of FOO from GDB arrives.
Before ack of FOO arrives, FOO happens again, a new object of
EVENT is created and enque EVENT silently.
Once GDB has a chance to ack to FOO, it sends an ack to GDBserver,
and GDBserver repeatedly sends events to GDB and gets ack of FOO,
until queue is empty. Then, GDBserver sends 'OK' to GDB that all
queued notification events are done.
# 3 is done by function 'handle_notif_ack'. */
#include "server.h"
#include "notif.h"
static struct notif_server *notifs[] =
{
&notif_stop,
};
/* Write another event or an OK, if there are no more left, to
OWN_BUF. */
void
notif_write_event (struct notif_server *notif, char *own_buf)
{
if (!notif->queue.empty ())
{
struct notif_event *event = notif->queue.front ();
notif->write (event, own_buf);
}
else
write_ok (own_buf);
}
/* Handle the ack in buffer OWN_BUF,and packet length is PACKET_LEN.
Return 1 if the ack is handled, and return 0 if the contents
in OWN_BUF is not a ack. */
int
handle_notif_ack (char *own_buf, int packet_len)
{
size_t i;
struct notif_server *np;
for (i = 0; i < ARRAY_SIZE (notifs); i++)
{
const char *ack_name = notifs[i]->ack_name;
if (startswith (own_buf, ack_name)
&& packet_len == strlen (ack_name))
break;
}
if (i == ARRAY_SIZE (notifs))
return 0;
np = notifs[i];
/* If we're waiting for GDB to acknowledge a pending event,
consider that done. */
if (!np->queue.empty ())
{
struct notif_event *head = np->queue.front ();
np->queue.pop_front ();
if (remote_debug)
debug_printf ("%s: acking %d\n", np->ack_name,
(int) np->queue.size ());
delete head;
}
notif_write_event (np, own_buf);
return 1;
}
/* Put EVENT to the queue of NOTIF. */
void
notif_event_enque (struct notif_server *notif,
struct notif_event *event)
{
notif->queue.push_back (event);
if (remote_debug)
debug_printf ("pending events: %s %d\n", notif->notif_name,
(int) notif->queue.size ());
}
/* Push one event NEW_EVENT of notification NP into NP->queue. */
void
notif_push (struct notif_server *np, struct notif_event *new_event)
{
bool is_first_event = np->queue.empty ();
/* Something interesting. Tell GDB about it. */
notif_event_enque (np, new_event);
/* If this is the first stop reply in the queue, then inform GDB
about it, by sending a corresponding notification. */
if (is_first_event)
{
char buf[PBUFSIZ];
char *p = buf;
xsnprintf (p, PBUFSIZ, "%s:", np->notif_name);
p += strlen (p);
np->write (new_event, p);
putpkt_notif (buf);
}
}