| /* Async events for the GDB event loop. | 
 |    Copyright (C) 1999-2024 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 "async-event.h" | 
 |  | 
 | #include "ser-event.h" | 
 | #include "top.h" | 
 | #include "ui.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.  */ | 
 |  | 
 | struct async_signal_handler | 
 | { | 
 |   /* If ready, call this handler  from the main event loop, using | 
 |      invoke_async_handler.  */ | 
 |   int ready; | 
 |  | 
 |   /* Pointer to next handler.  */ | 
 |   struct async_signal_handler *next_handler; | 
 |  | 
 |   /* Function to call to do the work.  */ | 
 |   sig_handler_func *proc; | 
 |  | 
 |   /* Argument to PROC.  */ | 
 |   gdb_client_data client_data; | 
 |  | 
 |   /* User-friendly name of this handler.  */ | 
 |   const char *name; | 
 | }; | 
 |  | 
 | /* 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.  */ | 
 | struct async_event_handler | 
 | { | 
 |   /* If ready, call this handler from the main event loop, using | 
 |      invoke_event_handler.  */ | 
 |   int ready; | 
 |  | 
 |   /* Pointer 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; | 
 |  | 
 |   /* User-friendly name of this handler.  */ | 
 |   const char *name; | 
 | }; | 
 |  | 
 | /* 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, "async-signals"); | 
 | } | 
 |  | 
 |  | 
 |  | 
 | /* 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, | 
 | 			     const char *name) | 
 | { | 
 |   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; | 
 |   async_handler_ptr->name = name; | 
 |   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) | 
 | { | 
 |   if (debug_event_loop != debug_event_loop_kind::OFF) | 
 |     { | 
 |       /* This is called by signal handlers, so we print it "by hand" using | 
 | 	 the async-signal-safe methods.  */ | 
 |       const char head[] = ("[event-loop] mark_async_signal_handler: marking" | 
 | 			   "async signal handler `"); | 
 |       gdb_stdlog->write_async_safe (head, strlen (head)); | 
 |  | 
 |       gdb_stdlog->write_async_safe (async_handler_ptr->name, | 
 | 				    strlen (async_handler_ptr->name)); | 
 |  | 
 |       const char tail[] = "`\n"; | 
 |       gdb_stdlog->write_async_safe (tail, strlen (tail)); | 
 |     } | 
 |  | 
 |   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) | 
 | { | 
 |   event_loop_debug_printf ("clearing async signal handler `%s`", | 
 | 			   async_handler_ptr->name); | 
 |   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; | 
 |       event_loop_debug_printf ("invoking async signal handler `%s`", | 
 | 			       async_handler_ptr->name); | 
 |       (*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; | 
 | } | 
 |  | 
 | /* See async-event.h.  */ | 
 |  | 
 | async_event_handler * | 
 | create_async_event_handler (async_event_handler_func *proc, | 
 | 			    gdb_client_data client_data, | 
 | 			    const char *name) | 
 | { | 
 |   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; | 
 |   h->name = name; | 
 |   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) | 
 | { | 
 |   event_loop_debug_printf ("marking async event handler `%s` " | 
 | 			   "(previous state was %d)", | 
 | 			   async_handler_ptr->name, | 
 | 			   async_handler_ptr->ready); | 
 |   async_handler_ptr->ready = 1; | 
 | } | 
 |  | 
 | /* See event-loop.h.  */ | 
 |  | 
 | void | 
 | clear_async_event_handler (async_event_handler *async_handler_ptr) | 
 | { | 
 |   event_loop_debug_printf ("clearing async event handler `%s`", | 
 | 			   async_handler_ptr->name); | 
 |   async_handler_ptr->ready = 0; | 
 | } | 
 |  | 
 | /* See event-loop.h.  */ | 
 |  | 
 | bool | 
 | async_event_handler_marked (async_event_handler *handler) | 
 | { | 
 |   return handler->ready; | 
 | } | 
 |  | 
 | /* 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) | 
 | 	{ | 
 | 	  event_loop_debug_printf ("invoking async event handler `%s`", | 
 | 				   async_handler_ptr->name); | 
 | 	  (*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; | 
 | } |