aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Tromey <tom@tromey.com>2020-04-13 12:42:59 -0600
committerTom Tromey <tromey@adacore.com>2020-04-13 14:10:04 -0600
commit93b54c8ed3644a6604c5244faddf5dae7f60a743 (patch)
tree1db8cfd6f1f7c967270b9f396622848d179235d5
parentc1cd3163d99efe4f7cbe7f228859fd93f28e06bb (diff)
downloadgdb-93b54c8ed3644a6604c5244faddf5dae7f60a743.zip
gdb-93b54c8ed3644a6604c5244faddf5dae7f60a743.tar.gz
gdb-93b54c8ed3644a6604c5244faddf5dae7f60a743.tar.bz2
Introduce async-event.[ch]
This patch splits out some gdb-specific code from event-loop, into new files async-event.[ch]. Strictly speaking this code could perhaps be put into gdbsupport/, but because gdbserver does not currently use it, it seemed better, for size reasons, to split it out. gdb/ChangeLog 2020-04-13 Tom Tromey <tom@tromey.com> * tui/tui-win.c: Include async-event.h. * remote.c: Include async-event.h. * remote-notif.c: Include async-event.h. * record-full.c: Include async-event.h. * record-btrace.c: Include async-event.h. * infrun.c: Include async-event.h. * event-top.c: Include async-event.h. * event-loop.h: Move some declarations to async-event.h. * event-loop.c: Don't include ser-event.h or top.h. Move some code to async-event.c. * async-event.h: New file. * async-event.c: New file. * Makefile.in (COMMON_SFILES): Add async-event.c. (HFILES_NO_SRCDIR): Add async-event.h.
-rw-r--r--gdb/ChangeLog17
-rw-r--r--gdb/Makefile.in2
-rw-r--r--gdb/async-event.c325
-rw-r--r--gdb/async-event.h71
-rw-r--r--gdb/event-loop.c306
-rw-r--r--gdb/event-loop.h47
-rw-r--r--gdb/event-top.c1
-rw-r--r--gdb/infrun.c1
-rw-r--r--gdb/record-btrace.c1
-rw-r--r--gdb/record-full.c1
-rw-r--r--gdb/remote-notif.c1
-rw-r--r--gdb/remote.c1
-rw-r--r--gdb/tui/tui-win.c1
13 files changed, 430 insertions, 345 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index c0b3ae7..a108cd1 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,22 @@
2020-04-13 Tom Tromey <tom@tromey.com>
+ * tui/tui-win.c: Include async-event.h.
+ * remote.c: Include async-event.h.
+ * remote-notif.c: Include async-event.h.
+ * record-full.c: Include async-event.h.
+ * record-btrace.c: Include async-event.h.
+ * infrun.c: Include async-event.h.
+ * event-top.c: Include async-event.h.
+ * event-loop.h: Move some declarations to async-event.h.
+ * event-loop.c: Don't include ser-event.h or top.h. Move some
+ code to async-event.c.
+ * async-event.h: New file.
+ * async-event.c: New file.
+ * Makefile.in (COMMON_SFILES): Add async-event.c.
+ (HFILES_NO_SRCDIR): Add async-event.h.
+
+2020-04-13 Tom Tromey <tom@tromey.com>
+
* utils.c (flush_streams): New function.
* event-loop.c (gdb_wait_for_event): Call flush_streams.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index bc3ef69..bb96998 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -955,6 +955,7 @@ COMMON_SFILES = \
alloc.c \
annotate.c \
arch-utils.c \
+ async-event.c \
auto-load.c \
auxv.c \
ax-gdb.c \
@@ -1212,6 +1213,7 @@ HFILES_NO_SRCDIR = \
arm-linux-tdep.h \
arm-nbsd-tdep.h \
arm-tdep.h \
+ async-event.h \
auto-load.h \
auxv.h \
ax.h \
diff --git a/gdb/async-event.c b/gdb/async-event.c
new file mode 100644
index 0000000..dd65c17
--- /dev/null
+++ b/gdb/async-event.c
@@ -0,0 +1,325 @@
+/* Async events for the GDB event loop.
+ Copyright (C) 1999-2019 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/>. */
+
+#include "defs.h"
+#include "async-event.h"
+
+#include "ser-event.h"
+#include "top.h"
+
+/* PROC is a function to be invoked when the READY flag is set. This
+ happens when there has been a signal and the corresponding signal
+ handler has 'triggered' this async_signal_handler for execution.
+ The actual work to be done in response to a signal will be carried
+ out by PROC at a later time, within process_event. This provides a
+ deferred execution of signal handlers.
+
+ Async_init_signals takes care of setting up such an
+ async_signal_handler for each interesting signal. */
+
+typedef struct async_signal_handler
+ {
+ int ready; /* If ready, call this handler
+ from the main event loop, using
+ invoke_async_handler. */
+ struct async_signal_handler *next_handler; /* Ptr to next handler. */
+ sig_handler_func *proc; /* Function to call to do the work. */
+ gdb_client_data client_data; /* Argument to async_handler_func. */
+ }
+async_signal_handler;
+
+/* PROC is a function to be invoked when the READY flag is set. This
+ happens when the event has been marked with
+ MARK_ASYNC_EVENT_HANDLER. The actual work to be done in response
+ to an event will be carried out by PROC at a later time, within
+ process_event. This provides a deferred execution of event
+ handlers. */
+typedef struct async_event_handler
+ {
+ /* If ready, call this handler from the main event loop, using
+ invoke_event_handler. */
+ int ready;
+
+ /* Point to next handler. */
+ struct async_event_handler *next_handler;
+
+ /* Function to call to do the work. */
+ async_event_handler_func *proc;
+
+ /* Argument to PROC. */
+ gdb_client_data client_data;
+ }
+async_event_handler;
+
+/* All the async_signal_handlers gdb is interested in are kept onto
+ this list. */
+static struct
+ {
+ /* Pointer to first in handler list. */
+ async_signal_handler *first_handler;
+
+ /* Pointer to last in handler list. */
+ async_signal_handler *last_handler;
+ }
+sighandler_list;
+
+/* All the async_event_handlers gdb is interested in are kept onto
+ this list. */
+static struct
+ {
+ /* Pointer to first in handler list. */
+ async_event_handler *first_handler;
+
+ /* Pointer to last in handler list. */
+ async_event_handler *last_handler;
+ }
+async_event_handler_list;
+
+
+/* This event is signalled whenever an asynchronous handler needs to
+ defer an action to the event loop. */
+static struct serial_event *async_signal_handlers_serial_event;
+
+/* Callback registered with ASYNC_SIGNAL_HANDLERS_SERIAL_EVENT. */
+
+static void
+async_signals_handler (int error, gdb_client_data client_data)
+{
+ /* Do nothing. Handlers are run by invoke_async_signal_handlers
+ from instead. */
+}
+
+void
+initialize_async_signal_handlers (void)
+{
+ async_signal_handlers_serial_event = make_serial_event ();
+
+ add_file_handler (serial_event_fd (async_signal_handlers_serial_event),
+ async_signals_handler, NULL);
+}
+
+
+
+/* Create an asynchronous handler, allocating memory for it.
+ Return a pointer to the newly created handler.
+ This pointer will be used to invoke the handler by
+ invoke_async_signal_handler.
+ PROC is the function to call with CLIENT_DATA argument
+ whenever the handler is invoked. */
+async_signal_handler *
+create_async_signal_handler (sig_handler_func * proc,
+ gdb_client_data client_data)
+{
+ async_signal_handler *async_handler_ptr;
+
+ async_handler_ptr = XNEW (async_signal_handler);
+ async_handler_ptr->ready = 0;
+ async_handler_ptr->next_handler = NULL;
+ async_handler_ptr->proc = proc;
+ async_handler_ptr->client_data = client_data;
+ if (sighandler_list.first_handler == NULL)
+ sighandler_list.first_handler = async_handler_ptr;
+ else
+ sighandler_list.last_handler->next_handler = async_handler_ptr;
+ sighandler_list.last_handler = async_handler_ptr;
+ return async_handler_ptr;
+}
+
+/* Mark the handler (ASYNC_HANDLER_PTR) as ready. This information
+ will be used when the handlers are invoked, after we have waited
+ for some event. The caller of this function is the interrupt
+ handler associated with a signal. */
+void
+mark_async_signal_handler (async_signal_handler * async_handler_ptr)
+{
+ async_handler_ptr->ready = 1;
+ serial_event_set (async_signal_handlers_serial_event);
+}
+
+/* See event-loop.h. */
+
+void
+clear_async_signal_handler (async_signal_handler *async_handler_ptr)
+{
+ async_handler_ptr->ready = 0;
+}
+
+/* See event-loop.h. */
+
+int
+async_signal_handler_is_marked (async_signal_handler *async_handler_ptr)
+{
+ return async_handler_ptr->ready;
+}
+
+/* Call all the handlers that are ready. Returns true if any was
+ indeed ready. */
+
+int
+invoke_async_signal_handlers (void)
+{
+ async_signal_handler *async_handler_ptr;
+ int any_ready = 0;
+
+ /* We're going to handle all pending signals, so no need to wake up
+ the event loop again the next time around. Note this must be
+ cleared _before_ calling the callbacks, to avoid races. */
+ serial_event_clear (async_signal_handlers_serial_event);
+
+ /* Invoke all ready handlers. */
+
+ while (1)
+ {
+ for (async_handler_ptr = sighandler_list.first_handler;
+ async_handler_ptr != NULL;
+ async_handler_ptr = async_handler_ptr->next_handler)
+ {
+ if (async_handler_ptr->ready)
+ break;
+ }
+ if (async_handler_ptr == NULL)
+ break;
+ any_ready = 1;
+ async_handler_ptr->ready = 0;
+ /* Async signal handlers have no connection to whichever was the
+ current UI, and thus always run on the main one. */
+ current_ui = main_ui;
+ (*async_handler_ptr->proc) (async_handler_ptr->client_data);
+ }
+
+ return any_ready;
+}
+
+/* Delete an asynchronous handler (ASYNC_HANDLER_PTR).
+ Free the space allocated for it. */
+void
+delete_async_signal_handler (async_signal_handler ** async_handler_ptr)
+{
+ async_signal_handler *prev_ptr;
+
+ if (sighandler_list.first_handler == (*async_handler_ptr))
+ {
+ sighandler_list.first_handler = (*async_handler_ptr)->next_handler;
+ if (sighandler_list.first_handler == NULL)
+ sighandler_list.last_handler = NULL;
+ }
+ else
+ {
+ prev_ptr = sighandler_list.first_handler;
+ while (prev_ptr && prev_ptr->next_handler != (*async_handler_ptr))
+ prev_ptr = prev_ptr->next_handler;
+ gdb_assert (prev_ptr);
+ prev_ptr->next_handler = (*async_handler_ptr)->next_handler;
+ if (sighandler_list.last_handler == (*async_handler_ptr))
+ sighandler_list.last_handler = prev_ptr;
+ }
+ xfree ((*async_handler_ptr));
+ (*async_handler_ptr) = NULL;
+}
+
+/* Create an asynchronous event handler, allocating memory for it.
+ Return a pointer to the newly created handler. PROC is the
+ function to call with CLIENT_DATA argument whenever the handler is
+ invoked. */
+async_event_handler *
+create_async_event_handler (async_event_handler_func *proc,
+ gdb_client_data client_data)
+{
+ async_event_handler *h;
+
+ h = XNEW (struct async_event_handler);
+ h->ready = 0;
+ h->next_handler = NULL;
+ h->proc = proc;
+ h->client_data = client_data;
+ if (async_event_handler_list.first_handler == NULL)
+ async_event_handler_list.first_handler = h;
+ else
+ async_event_handler_list.last_handler->next_handler = h;
+ async_event_handler_list.last_handler = h;
+ return h;
+}
+
+/* Mark the handler (ASYNC_HANDLER_PTR) as ready. This information
+ will be used by gdb_do_one_event. The caller will be whoever
+ created the event source, and wants to signal that the event is
+ ready to be handled. */
+void
+mark_async_event_handler (async_event_handler *async_handler_ptr)
+{
+ async_handler_ptr->ready = 1;
+}
+
+/* See event-loop.h. */
+
+void
+clear_async_event_handler (async_event_handler *async_handler_ptr)
+{
+ async_handler_ptr->ready = 0;
+}
+
+/* Check if asynchronous event handlers are ready, and call the
+ handler function for one that is. */
+
+int
+check_async_event_handlers ()
+{
+ async_event_handler *async_handler_ptr;
+
+ for (async_handler_ptr = async_event_handler_list.first_handler;
+ async_handler_ptr != NULL;
+ async_handler_ptr = async_handler_ptr->next_handler)
+ {
+ if (async_handler_ptr->ready)
+ {
+ async_handler_ptr->ready = 0;
+ (*async_handler_ptr->proc) (async_handler_ptr->client_data);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* Delete an asynchronous handler (ASYNC_HANDLER_PTR).
+ Free the space allocated for it. */
+void
+delete_async_event_handler (async_event_handler **async_handler_ptr)
+{
+ async_event_handler *prev_ptr;
+
+ if (async_event_handler_list.first_handler == *async_handler_ptr)
+ {
+ async_event_handler_list.first_handler
+ = (*async_handler_ptr)->next_handler;
+ if (async_event_handler_list.first_handler == NULL)
+ async_event_handler_list.last_handler = NULL;
+ }
+ else
+ {
+ prev_ptr = async_event_handler_list.first_handler;
+ while (prev_ptr && prev_ptr->next_handler != *async_handler_ptr)
+ prev_ptr = prev_ptr->next_handler;
+ gdb_assert (prev_ptr);
+ prev_ptr->next_handler = (*async_handler_ptr)->next_handler;
+ if (async_event_handler_list.last_handler == (*async_handler_ptr))
+ async_event_handler_list.last_handler = prev_ptr;
+ }
+ xfree (*async_handler_ptr);
+ *async_handler_ptr = NULL;
+}
diff --git a/gdb/async-event.h b/gdb/async-event.h
new file mode 100644
index 0000000..408f776
--- /dev/null
+++ b/gdb/async-event.h
@@ -0,0 +1,71 @@
+/* Async events for the GDB event loop.
+ Copyright (C) 1999-2019 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/>. */
+
+#ifndef ASYNC_EVENT_H
+#define ASYNC_EVENT_H
+
+#include "event-loop.h"
+
+struct async_signal_handler;
+struct async_event_handler;
+typedef void (sig_handler_func) (gdb_client_data);
+typedef void (async_event_handler_func) (gdb_client_data);
+
+extern struct async_signal_handler *
+ create_async_signal_handler (sig_handler_func *proc,
+ gdb_client_data client_data);
+extern void delete_async_signal_handler (struct async_signal_handler **);
+
+/* Call the handler from HANDLER the next time through the event
+ loop. */
+extern void mark_async_signal_handler (struct async_signal_handler *handler);
+
+/* Returns true if HANDLER is marked ready. */
+
+extern int
+ async_signal_handler_is_marked (struct async_signal_handler *handler);
+
+/* Mark HANDLER as NOT ready. */
+
+extern void clear_async_signal_handler (struct async_signal_handler *handler);
+
+/* Create and register an asynchronous event source in the event loop,
+ and set PROC as its callback. CLIENT_DATA is passed as argument to
+ PROC upon its invocation. Returns a pointer to an opaque structure
+ used to mark as ready and to later delete this event source from
+ the event loop. */
+extern struct async_event_handler *
+ create_async_event_handler (async_event_handler_func *proc,
+ gdb_client_data client_data);
+
+/* Remove the event source pointed by HANDLER_PTR created by
+ CREATE_ASYNC_EVENT_HANDLER from the event loop, and release it. */
+extern void
+ delete_async_event_handler (struct async_event_handler **handler_ptr);
+
+/* Call the handler from HANDLER the next time through the event
+ loop. */
+extern void mark_async_event_handler (struct async_event_handler *handler);
+
+/* Mark the handler (ASYNC_HANDLER_PTR) as NOT ready. */
+
+extern void clear_async_event_handler (struct async_event_handler *handler);
+
+extern void initialize_async_signal_handlers (void);
+
+#endif /* ASYNC_EVENT_H */
diff --git a/gdb/event-loop.c b/gdb/event-loop.c
index 4ce8899..e5347d2 100644
--- a/gdb/event-loop.c
+++ b/gdb/event-loop.c
@@ -19,8 +19,6 @@
#include "defs.h"
#include "event-loop.h"
-#include "event-top.h"
-#include "ser-event.h"
#include <chrono>
@@ -35,7 +33,6 @@
#include <sys/types.h>
#include "gdbsupport/gdb_sys_time.h"
#include "gdbsupport/gdb_select.h"
-#include "top.h"
/* Tell create_file_handler what events we are interested in.
This is used by the select version of the event loop. */
@@ -60,50 +57,6 @@ typedef struct file_handler
}
file_handler;
-/* PROC is a function to be invoked when the READY flag is set. This
- happens when there has been a signal and the corresponding signal
- handler has 'triggered' this async_signal_handler for execution.
- The actual work to be done in response to a signal will be carried
- out by PROC at a later time, within process_event. This provides a
- deferred execution of signal handlers.
-
- Async_init_signals takes care of setting up such an
- async_signal_handler for each interesting signal. */
-
-typedef struct async_signal_handler
- {
- int ready; /* If ready, call this handler
- from the main event loop, using
- invoke_async_handler. */
- struct async_signal_handler *next_handler; /* Ptr to next handler. */
- sig_handler_func *proc; /* Function to call to do the work. */
- gdb_client_data client_data; /* Argument to async_handler_func. */
- }
-async_signal_handler;
-
-/* PROC is a function to be invoked when the READY flag is set. This
- happens when the event has been marked with
- MARK_ASYNC_EVENT_HANDLER. The actual work to be done in response
- to an event will be carried out by PROC at a later time, within
- process_event. This provides a deferred execution of event
- handlers. */
-typedef struct async_event_handler
- {
- /* If ready, call this handler from the main event loop, using
- invoke_event_handler. */
- int ready;
-
- /* Point to next handler. */
- struct async_event_handler *next_handler;
-
- /* Function to call to do the work. */
- async_event_handler_func *proc;
-
- /* Argument to PROC. */
- gdb_client_data client_data;
- }
-async_event_handler;
-
/* Gdb_notifier is just a list of file descriptors gdb is interested in.
These are the input file descriptor, and the target file
descriptor. We have two flavors of the notifier, one for platforms
@@ -198,61 +151,12 @@ static struct
}
timer_list;
-/* All the async_signal_handlers gdb is interested in are kept onto
- this list. */
-static struct
- {
- /* Pointer to first in handler list. */
- async_signal_handler *first_handler;
-
- /* Pointer to last in handler list. */
- async_signal_handler *last_handler;
- }
-sighandler_list;
-
-/* All the async_event_handlers gdb is interested in are kept onto
- this list. */
-static struct
- {
- /* Pointer to first in handler list. */
- async_event_handler *first_handler;
-
- /* Pointer to last in handler list. */
- async_event_handler *last_handler;
- }
-async_event_handler_list;
-
-static int invoke_async_signal_handlers (void);
static void create_file_handler (int fd, int mask, handler_func *proc,
gdb_client_data client_data);
-static int check_async_event_handlers (void);
static int gdb_wait_for_event (int);
static int update_wait_timeout (void);
static int poll_timers (void);
-
-/* This event is signalled whenever an asynchronous handler needs to
- defer an action to the event loop. */
-static struct serial_event *async_signal_handlers_serial_event;
-
-/* Callback registered with ASYNC_SIGNAL_HANDLERS_SERIAL_EVENT. */
-
-static void
-async_signals_handler (int error, gdb_client_data client_data)
-{
- /* Do nothing. Handlers are run by invoke_async_signal_handlers
- from instead. */
-}
-
-void
-initialize_async_signal_handlers (void)
-{
- async_signal_handlers_serial_event = make_serial_event ();
-
- add_file_handler (serial_event_fd (async_signal_handlers_serial_event),
- async_signals_handler, NULL);
-}
-
/* Process one high level event. If nothing is ready at this time,
wait for something to happen (via gdb_wait_for_event), then process
it. Returns >0 if something was done otherwise returns <0 (this
@@ -800,216 +704,6 @@ gdb_wait_for_event (int block)
return 0;
}
-
-/* Create an asynchronous handler, allocating memory for it.
- Return a pointer to the newly created handler.
- This pointer will be used to invoke the handler by
- invoke_async_signal_handler.
- PROC is the function to call with CLIENT_DATA argument
- whenever the handler is invoked. */
-async_signal_handler *
-create_async_signal_handler (sig_handler_func * proc,
- gdb_client_data client_data)
-{
- async_signal_handler *async_handler_ptr;
-
- async_handler_ptr = XNEW (async_signal_handler);
- async_handler_ptr->ready = 0;
- async_handler_ptr->next_handler = NULL;
- async_handler_ptr->proc = proc;
- async_handler_ptr->client_data = client_data;
- if (sighandler_list.first_handler == NULL)
- sighandler_list.first_handler = async_handler_ptr;
- else
- sighandler_list.last_handler->next_handler = async_handler_ptr;
- sighandler_list.last_handler = async_handler_ptr;
- return async_handler_ptr;
-}
-
-/* Mark the handler (ASYNC_HANDLER_PTR) as ready. This information
- will be used when the handlers are invoked, after we have waited
- for some event. The caller of this function is the interrupt
- handler associated with a signal. */
-void
-mark_async_signal_handler (async_signal_handler * async_handler_ptr)
-{
- async_handler_ptr->ready = 1;
- serial_event_set (async_signal_handlers_serial_event);
-}
-
-/* See event-loop.h. */
-
-void
-clear_async_signal_handler (async_signal_handler *async_handler_ptr)
-{
- async_handler_ptr->ready = 0;
-}
-
-/* See event-loop.h. */
-
-int
-async_signal_handler_is_marked (async_signal_handler *async_handler_ptr)
-{
- return async_handler_ptr->ready;
-}
-
-/* Call all the handlers that are ready. Returns true if any was
- indeed ready. */
-
-static int
-invoke_async_signal_handlers (void)
-{
- async_signal_handler *async_handler_ptr;
- int any_ready = 0;
-
- /* We're going to handle all pending signals, so no need to wake up
- the event loop again the next time around. Note this must be
- cleared _before_ calling the callbacks, to avoid races. */
- serial_event_clear (async_signal_handlers_serial_event);
-
- /* Invoke all ready handlers. */
-
- while (1)
- {
- for (async_handler_ptr = sighandler_list.first_handler;
- async_handler_ptr != NULL;
- async_handler_ptr = async_handler_ptr->next_handler)
- {
- if (async_handler_ptr->ready)
- break;
- }
- if (async_handler_ptr == NULL)
- break;
- any_ready = 1;
- async_handler_ptr->ready = 0;
- /* Async signal handlers have no connection to whichever was the
- current UI, and thus always run on the main one. */
- current_ui = main_ui;
- (*async_handler_ptr->proc) (async_handler_ptr->client_data);
- }
-
- return any_ready;
-}
-
-/* Delete an asynchronous handler (ASYNC_HANDLER_PTR).
- Free the space allocated for it. */
-void
-delete_async_signal_handler (async_signal_handler ** async_handler_ptr)
-{
- async_signal_handler *prev_ptr;
-
- if (sighandler_list.first_handler == (*async_handler_ptr))
- {
- sighandler_list.first_handler = (*async_handler_ptr)->next_handler;
- if (sighandler_list.first_handler == NULL)
- sighandler_list.last_handler = NULL;
- }
- else
- {
- prev_ptr = sighandler_list.first_handler;
- while (prev_ptr && prev_ptr->next_handler != (*async_handler_ptr))
- prev_ptr = prev_ptr->next_handler;
- gdb_assert (prev_ptr);
- prev_ptr->next_handler = (*async_handler_ptr)->next_handler;
- if (sighandler_list.last_handler == (*async_handler_ptr))
- sighandler_list.last_handler = prev_ptr;
- }
- xfree ((*async_handler_ptr));
- (*async_handler_ptr) = NULL;
-}
-
-/* Create an asynchronous event handler, allocating memory for it.
- Return a pointer to the newly created handler. PROC is the
- function to call with CLIENT_DATA argument whenever the handler is
- invoked. */
-async_event_handler *
-create_async_event_handler (async_event_handler_func *proc,
- gdb_client_data client_data)
-{
- async_event_handler *h;
-
- h = XNEW (struct async_event_handler);
- h->ready = 0;
- h->next_handler = NULL;
- h->proc = proc;
- h->client_data = client_data;
- if (async_event_handler_list.first_handler == NULL)
- async_event_handler_list.first_handler = h;
- else
- async_event_handler_list.last_handler->next_handler = h;
- async_event_handler_list.last_handler = h;
- return h;
-}
-
-/* Mark the handler (ASYNC_HANDLER_PTR) as ready. This information
- will be used by gdb_do_one_event. The caller will be whoever
- created the event source, and wants to signal that the event is
- ready to be handled. */
-void
-mark_async_event_handler (async_event_handler *async_handler_ptr)
-{
- async_handler_ptr->ready = 1;
-}
-
-/* See event-loop.h. */
-
-void
-clear_async_event_handler (async_event_handler *async_handler_ptr)
-{
- async_handler_ptr->ready = 0;
-}
-
-/* Check if asynchronous event handlers are ready, and call the
- handler function for one that is. */
-
-static int
-check_async_event_handlers (void)
-{
- async_event_handler *async_handler_ptr;
-
- for (async_handler_ptr = async_event_handler_list.first_handler;
- async_handler_ptr != NULL;
- async_handler_ptr = async_handler_ptr->next_handler)
- {
- if (async_handler_ptr->ready)
- {
- async_handler_ptr->ready = 0;
- (*async_handler_ptr->proc) (async_handler_ptr->client_data);
- return 1;
- }
- }
-
- return 0;
-}
-
-/* Delete an asynchronous handler (ASYNC_HANDLER_PTR).
- Free the space allocated for it. */
-void
-delete_async_event_handler (async_event_handler **async_handler_ptr)
-{
- async_event_handler *prev_ptr;
-
- if (async_event_handler_list.first_handler == *async_handler_ptr)
- {
- async_event_handler_list.first_handler
- = (*async_handler_ptr)->next_handler;
- if (async_event_handler_list.first_handler == NULL)
- async_event_handler_list.last_handler = NULL;
- }
- else
- {
- prev_ptr = async_event_handler_list.first_handler;
- while (prev_ptr && prev_ptr->next_handler != *async_handler_ptr)
- prev_ptr = prev_ptr->next_handler;
- gdb_assert (prev_ptr);
- prev_ptr->next_handler = (*async_handler_ptr)->next_handler;
- if (async_event_handler_list.last_handler == (*async_handler_ptr))
- async_event_handler_list.last_handler = prev_ptr;
- }
- xfree (*async_handler_ptr);
- *async_handler_ptr = NULL;
-}
-
/* Create a timer that will expire in MS milliseconds from now. When
the timer is ready, PROC will be executed. At creation, the timer
is added to the timers queue. This queue is kept sorted in order
diff --git a/gdb/event-loop.h b/gdb/event-loop.h
index 52740c3..2eaaa0c 100644
--- a/gdb/event-loop.h
+++ b/gdb/event-loop.h
@@ -71,11 +71,7 @@
Corollary tasks are the creation and deletion of event sources. */
typedef void *gdb_client_data;
-struct async_signal_handler;
-struct async_event_handler;
typedef void (handler_func) (int, gdb_client_data);
-typedef void (sig_handler_func) (gdb_client_data);
-typedef void (async_event_handler_func) (gdb_client_data);
typedef void (timer_handler_func) (gdb_client_data);
/* Exported functions from event-loop.c */
@@ -84,50 +80,23 @@ extern int gdb_do_one_event (void);
extern void delete_file_handler (int fd);
extern void add_file_handler (int fd, handler_func *proc,
gdb_client_data client_data);
-extern struct async_signal_handler *
- create_async_signal_handler (sig_handler_func *proc,
- gdb_client_data client_data);
-extern void delete_async_signal_handler (struct async_signal_handler **);
extern int create_timer (int milliseconds,
timer_handler_func *proc,
gdb_client_data client_data);
extern void delete_timer (int id);
-/* Call the handler from HANDLER the next time through the event
- loop. */
-extern void mark_async_signal_handler (struct async_signal_handler *handler);
+/* Must be defined by client. */
-/* Returns true if HANDLER is marked ready. */
+extern void handle_event_loop_exception (const gdb_exception &);
-extern int
- async_signal_handler_is_marked (struct async_signal_handler *handler);
+/* Must be defined by client. Returns true if any signal handler was
+ ready. */
-/* Mark HANDLER as NOT ready. */
+extern int invoke_async_signal_handlers ();
-extern void clear_async_signal_handler (struct async_signal_handler *handler);
+/* Must be defined by client. Returns true if any event handler was
+ ready. */
-/* Create and register an asynchronous event source in the event loop,
- and set PROC as its callback. CLIENT_DATA is passed as argument to
- PROC upon its invocation. Returns a pointer to an opaque structure
- used to mark as ready and to later delete this event source from
- the event loop. */
-extern struct async_event_handler *
- create_async_event_handler (async_event_handler_func *proc,
- gdb_client_data client_data);
-
-/* Remove the event source pointed by HANDLER_PTR created by
- CREATE_ASYNC_EVENT_HANDLER from the event loop, and release it. */
-extern void
- delete_async_event_handler (struct async_event_handler **handler_ptr);
-
-/* Call the handler from HANDLER the next time through the event
- loop. */
-extern void mark_async_event_handler (struct async_event_handler *handler);
-
-/* Mark the handler (ASYNC_HANDLER_PTR) as NOT ready. */
-
-extern void clear_async_event_handler (struct async_event_handler *handler);
-
-extern void initialize_async_signal_handlers (void);
+extern int check_async_event_handlers ();
#endif /* EVENT_LOOP_H */
diff --git a/gdb/event-top.c b/gdb/event-top.c
index 965ecd5..5d7a77b 100644
--- a/gdb/event-top.c
+++ b/gdb/event-top.c
@@ -41,6 +41,7 @@
#include "ser-event.h"
#include "gdbsupport/gdb_select.h"
#include "gdbsupport/gdb-sigmask.h"
+#include "async-event.h"
/* readline include files. */
#include "readline/readline.h"
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 88105e0..fc76649 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -66,6 +66,7 @@
#include "gdbsupport/forward-scope-exit.h"
#include "gdbsupport/gdb_select.h"
#include <unordered_map>
+#include "async-event.h"
/* Prototypes for local functions */
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index d3da852..acc5f3b 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -42,6 +42,7 @@
#include <algorithm>
#include "gdbarch.h"
#include "cli/cli-style.h"
+#include "async-event.h"
static const target_info record_btrace_target_info = {
"record-btrace",
diff --git a/gdb/record-full.c b/gdb/record-full.c
index 51b7bea..4e1961a 100644
--- a/gdb/record-full.c
+++ b/gdb/record-full.c
@@ -38,6 +38,7 @@
#include "infrun.h"
#include "gdbsupport/gdb_unlinker.h"
#include "gdbsupport/byte-vector.h"
+#include "async-event.h"
#include <signal.h>
diff --git a/gdb/remote-notif.c b/gdb/remote-notif.c
index cc0011f..f41ebc3 100644
--- a/gdb/remote-notif.c
+++ b/gdb/remote-notif.c
@@ -40,6 +40,7 @@
#include "inferior.h"
#include "infrun.h"
#include "gdbcmd.h"
+#include "async-event.h"
bool notif_debug = false;
diff --git a/gdb/remote.c b/gdb/remote.c
index bfbc0bc..d4919d9 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -77,6 +77,7 @@
#include "gdbsupport/byte-vector.h"
#include <algorithm>
#include <unordered_map>
+#include "async-event.h"
/* The remote target. */
diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c
index b962e02..df7480f 100644
--- a/gdb/tui/tui-win.c
+++ b/gdb/tui/tui-win.c
@@ -35,6 +35,7 @@
#include "source.h"
#include "event-loop.h"
#include "gdbcmd.h"
+#include "async-event.h"
#include "tui/tui.h"
#include "tui/tui-io.h"