xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/async-event.c (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
17d62b00eSchristos /* Async events for the GDB event loop.
2*6881a400Schristos    Copyright (C) 1999-2023 Free Software Foundation, Inc.
37d62b00eSchristos 
47d62b00eSchristos    This file is part of GDB.
57d62b00eSchristos 
67d62b00eSchristos    This program is free software; you can redistribute it and/or modify
77d62b00eSchristos    it under the terms of the GNU General Public License as published by
87d62b00eSchristos    the Free Software Foundation; either version 3 of the License, or
97d62b00eSchristos    (at your option) any later version.
107d62b00eSchristos 
117d62b00eSchristos    This program is distributed in the hope that it will be useful,
127d62b00eSchristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
137d62b00eSchristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
147d62b00eSchristos    GNU General Public License for more details.
157d62b00eSchristos 
167d62b00eSchristos    You should have received a copy of the GNU General Public License
177d62b00eSchristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
187d62b00eSchristos 
197d62b00eSchristos #include "defs.h"
207d62b00eSchristos #include "async-event.h"
217d62b00eSchristos 
227d62b00eSchristos #include "ser-event.h"
237d62b00eSchristos #include "top.h"
247d62b00eSchristos 
257d62b00eSchristos /* PROC is a function to be invoked when the READY flag is set.  This
267d62b00eSchristos    happens when there has been a signal and the corresponding signal
277d62b00eSchristos    handler has 'triggered' this async_signal_handler for execution.
287d62b00eSchristos    The actual work to be done in response to a signal will be carried
297d62b00eSchristos    out by PROC at a later time, within process_event.  This provides a
307d62b00eSchristos    deferred execution of signal handlers.
317d62b00eSchristos 
327d62b00eSchristos    Async_init_signals takes care of setting up such an
337d62b00eSchristos    async_signal_handler for each interesting signal.  */
347d62b00eSchristos 
357d62b00eSchristos struct async_signal_handler
367d62b00eSchristos {
377d62b00eSchristos   /* If ready, call this handler  from the main event loop, using
387d62b00eSchristos      invoke_async_handler.  */
397d62b00eSchristos   int ready;
407d62b00eSchristos 
417d62b00eSchristos   /* Pointer to next handler.  */
427d62b00eSchristos   struct async_signal_handler *next_handler;
437d62b00eSchristos 
447d62b00eSchristos   /* Function to call to do the work.  */
457d62b00eSchristos   sig_handler_func *proc;
467d62b00eSchristos 
477d62b00eSchristos   /* Argument to PROC.  */
487d62b00eSchristos   gdb_client_data client_data;
49*6881a400Schristos 
50*6881a400Schristos   /* User-friendly name of this handler.  */
51*6881a400Schristos   const char *name;
527d62b00eSchristos };
537d62b00eSchristos 
547d62b00eSchristos /* PROC is a function to be invoked when the READY flag is set.  This
557d62b00eSchristos    happens when the event has been marked with
567d62b00eSchristos    MARK_ASYNC_EVENT_HANDLER.  The actual work to be done in response
577d62b00eSchristos    to an event will be carried out by PROC at a later time, within
587d62b00eSchristos    process_event.  This provides a deferred execution of event
597d62b00eSchristos    handlers.  */
607d62b00eSchristos struct async_event_handler
617d62b00eSchristos {
627d62b00eSchristos   /* If ready, call this handler from the main event loop, using
637d62b00eSchristos      invoke_event_handler.  */
647d62b00eSchristos   int ready;
657d62b00eSchristos 
667d62b00eSchristos   /* Pointer to next handler.  */
677d62b00eSchristos   struct async_event_handler *next_handler;
687d62b00eSchristos 
697d62b00eSchristos   /* Function to call to do the work.  */
707d62b00eSchristos   async_event_handler_func *proc;
717d62b00eSchristos 
727d62b00eSchristos   /* Argument to PROC.  */
737d62b00eSchristos   gdb_client_data client_data;
74*6881a400Schristos 
75*6881a400Schristos   /* User-friendly name of this handler.  */
76*6881a400Schristos   const char *name;
777d62b00eSchristos };
787d62b00eSchristos 
797d62b00eSchristos /* All the async_signal_handlers gdb is interested in are kept onto
807d62b00eSchristos    this list.  */
817d62b00eSchristos static struct
827d62b00eSchristos {
837d62b00eSchristos   /* Pointer to first in handler list.  */
847d62b00eSchristos   async_signal_handler *first_handler;
857d62b00eSchristos 
867d62b00eSchristos   /* Pointer to last in handler list.  */
877d62b00eSchristos   async_signal_handler *last_handler;
887d62b00eSchristos }
897d62b00eSchristos sighandler_list;
907d62b00eSchristos 
917d62b00eSchristos /* All the async_event_handlers gdb is interested in are kept onto
927d62b00eSchristos    this list.  */
937d62b00eSchristos static struct
947d62b00eSchristos {
957d62b00eSchristos   /* Pointer to first in handler list.  */
967d62b00eSchristos   async_event_handler *first_handler;
977d62b00eSchristos 
987d62b00eSchristos   /* Pointer to last in handler list.  */
997d62b00eSchristos   async_event_handler *last_handler;
1007d62b00eSchristos }
1017d62b00eSchristos async_event_handler_list;
1027d62b00eSchristos 
1037d62b00eSchristos 
1047d62b00eSchristos /* This event is signalled whenever an asynchronous handler needs to
1057d62b00eSchristos    defer an action to the event loop.  */
1067d62b00eSchristos static struct serial_event *async_signal_handlers_serial_event;
1077d62b00eSchristos 
1087d62b00eSchristos /* Callback registered with ASYNC_SIGNAL_HANDLERS_SERIAL_EVENT.  */
1097d62b00eSchristos 
1107d62b00eSchristos static void
1117d62b00eSchristos async_signals_handler (int error, gdb_client_data client_data)
1127d62b00eSchristos {
1137d62b00eSchristos   /* Do nothing.  Handlers are run by invoke_async_signal_handlers
1147d62b00eSchristos      from instead.  */
1157d62b00eSchristos }
1167d62b00eSchristos 
1177d62b00eSchristos void
1187d62b00eSchristos initialize_async_signal_handlers (void)
1197d62b00eSchristos {
1207d62b00eSchristos   async_signal_handlers_serial_event = make_serial_event ();
1217d62b00eSchristos 
1227d62b00eSchristos   add_file_handler (serial_event_fd (async_signal_handlers_serial_event),
123*6881a400Schristos 		    async_signals_handler, NULL, "async-signals");
1247d62b00eSchristos }
1257d62b00eSchristos 
1267d62b00eSchristos 
1277d62b00eSchristos 
1287d62b00eSchristos /* Create an asynchronous handler, allocating memory for it.
1297d62b00eSchristos    Return a pointer to the newly created handler.
1307d62b00eSchristos    This pointer will be used to invoke the handler by
1317d62b00eSchristos    invoke_async_signal_handler.
1327d62b00eSchristos    PROC is the function to call with CLIENT_DATA argument
1337d62b00eSchristos    whenever the handler is invoked.  */
1347d62b00eSchristos async_signal_handler *
1357d62b00eSchristos create_async_signal_handler (sig_handler_func * proc,
136*6881a400Schristos 			     gdb_client_data client_data,
137*6881a400Schristos 			     const char *name)
1387d62b00eSchristos {
1397d62b00eSchristos   async_signal_handler *async_handler_ptr;
1407d62b00eSchristos 
1417d62b00eSchristos   async_handler_ptr = XNEW (async_signal_handler);
1427d62b00eSchristos   async_handler_ptr->ready = 0;
1437d62b00eSchristos   async_handler_ptr->next_handler = NULL;
1447d62b00eSchristos   async_handler_ptr->proc = proc;
1457d62b00eSchristos   async_handler_ptr->client_data = client_data;
146*6881a400Schristos   async_handler_ptr->name = name;
1477d62b00eSchristos   if (sighandler_list.first_handler == NULL)
1487d62b00eSchristos     sighandler_list.first_handler = async_handler_ptr;
1497d62b00eSchristos   else
1507d62b00eSchristos     sighandler_list.last_handler->next_handler = async_handler_ptr;
1517d62b00eSchristos   sighandler_list.last_handler = async_handler_ptr;
1527d62b00eSchristos   return async_handler_ptr;
1537d62b00eSchristos }
1547d62b00eSchristos 
1557d62b00eSchristos /* Mark the handler (ASYNC_HANDLER_PTR) as ready.  This information
1567d62b00eSchristos    will be used when the handlers are invoked, after we have waited
1577d62b00eSchristos    for some event.  The caller of this function is the interrupt
1587d62b00eSchristos    handler associated with a signal.  */
1597d62b00eSchristos void
1607d62b00eSchristos mark_async_signal_handler (async_signal_handler *async_handler_ptr)
1617d62b00eSchristos {
162*6881a400Schristos   if (debug_event_loop != debug_event_loop_kind::OFF)
163*6881a400Schristos     {
164*6881a400Schristos       /* This is called by signal handlers, so we print it "by hand" using
165*6881a400Schristos 	 the async-signal-safe methods.  */
166*6881a400Schristos       const char head[] = ("[event-loop] mark_async_signal_handler: marking"
167*6881a400Schristos 			   "async signal handler `");
168*6881a400Schristos       gdb_stdlog->write_async_safe (head, strlen (head));
169*6881a400Schristos 
170*6881a400Schristos       gdb_stdlog->write_async_safe (async_handler_ptr->name,
171*6881a400Schristos 				    strlen (async_handler_ptr->name));
172*6881a400Schristos 
173*6881a400Schristos       const char tail[] = "`\n";
174*6881a400Schristos       gdb_stdlog->write_async_safe (tail, strlen (tail));
175*6881a400Schristos     }
176*6881a400Schristos 
1777d62b00eSchristos   async_handler_ptr->ready = 1;
1787d62b00eSchristos   serial_event_set (async_signal_handlers_serial_event);
1797d62b00eSchristos }
1807d62b00eSchristos 
1817d62b00eSchristos /* See event-loop.h.  */
1827d62b00eSchristos 
1837d62b00eSchristos void
1847d62b00eSchristos clear_async_signal_handler (async_signal_handler *async_handler_ptr)
1857d62b00eSchristos {
186*6881a400Schristos   event_loop_debug_printf ("clearing async signal handler `%s`",
187*6881a400Schristos 			   async_handler_ptr->name);
1887d62b00eSchristos   async_handler_ptr->ready = 0;
1897d62b00eSchristos }
1907d62b00eSchristos 
1917d62b00eSchristos /* See event-loop.h.  */
1927d62b00eSchristos 
1937d62b00eSchristos int
1947d62b00eSchristos async_signal_handler_is_marked (async_signal_handler *async_handler_ptr)
1957d62b00eSchristos {
1967d62b00eSchristos   return async_handler_ptr->ready;
1977d62b00eSchristos }
1987d62b00eSchristos 
1997d62b00eSchristos /* Call all the handlers that are ready.  Returns true if any was
2007d62b00eSchristos    indeed ready.  */
2017d62b00eSchristos 
2027d62b00eSchristos int
2037d62b00eSchristos invoke_async_signal_handlers (void)
2047d62b00eSchristos {
2057d62b00eSchristos   async_signal_handler *async_handler_ptr;
2067d62b00eSchristos   int any_ready = 0;
2077d62b00eSchristos 
2087d62b00eSchristos   /* We're going to handle all pending signals, so no need to wake up
2097d62b00eSchristos      the event loop again the next time around.  Note this must be
2107d62b00eSchristos      cleared _before_ calling the callbacks, to avoid races.  */
2117d62b00eSchristos   serial_event_clear (async_signal_handlers_serial_event);
2127d62b00eSchristos 
2137d62b00eSchristos   /* Invoke all ready handlers.  */
2147d62b00eSchristos 
2157d62b00eSchristos   while (1)
2167d62b00eSchristos     {
2177d62b00eSchristos       for (async_handler_ptr = sighandler_list.first_handler;
2187d62b00eSchristos 	   async_handler_ptr != NULL;
2197d62b00eSchristos 	   async_handler_ptr = async_handler_ptr->next_handler)
2207d62b00eSchristos 	{
2217d62b00eSchristos 	  if (async_handler_ptr->ready)
2227d62b00eSchristos 	    break;
2237d62b00eSchristos 	}
2247d62b00eSchristos       if (async_handler_ptr == NULL)
2257d62b00eSchristos 	break;
2267d62b00eSchristos       any_ready = 1;
2277d62b00eSchristos       async_handler_ptr->ready = 0;
2287d62b00eSchristos       /* Async signal handlers have no connection to whichever was the
2297d62b00eSchristos 	 current UI, and thus always run on the main one.  */
2307d62b00eSchristos       current_ui = main_ui;
231*6881a400Schristos       event_loop_debug_printf ("invoking async signal handler `%s`",
232*6881a400Schristos 			       async_handler_ptr->name);
2337d62b00eSchristos       (*async_handler_ptr->proc) (async_handler_ptr->client_data);
2347d62b00eSchristos     }
2357d62b00eSchristos 
2367d62b00eSchristos   return any_ready;
2377d62b00eSchristos }
2387d62b00eSchristos 
2397d62b00eSchristos /* Delete an asynchronous handler (ASYNC_HANDLER_PTR).
2407d62b00eSchristos    Free the space allocated for it.  */
2417d62b00eSchristos void
2427d62b00eSchristos delete_async_signal_handler (async_signal_handler ** async_handler_ptr)
2437d62b00eSchristos {
2447d62b00eSchristos   async_signal_handler *prev_ptr;
2457d62b00eSchristos 
2467d62b00eSchristos   if (sighandler_list.first_handler == (*async_handler_ptr))
2477d62b00eSchristos     {
2487d62b00eSchristos       sighandler_list.first_handler = (*async_handler_ptr)->next_handler;
2497d62b00eSchristos       if (sighandler_list.first_handler == NULL)
2507d62b00eSchristos 	sighandler_list.last_handler = NULL;
2517d62b00eSchristos     }
2527d62b00eSchristos   else
2537d62b00eSchristos     {
2547d62b00eSchristos       prev_ptr = sighandler_list.first_handler;
2557d62b00eSchristos       while (prev_ptr && prev_ptr->next_handler != (*async_handler_ptr))
2567d62b00eSchristos 	prev_ptr = prev_ptr->next_handler;
2577d62b00eSchristos       gdb_assert (prev_ptr);
2587d62b00eSchristos       prev_ptr->next_handler = (*async_handler_ptr)->next_handler;
2597d62b00eSchristos       if (sighandler_list.last_handler == (*async_handler_ptr))
2607d62b00eSchristos 	sighandler_list.last_handler = prev_ptr;
2617d62b00eSchristos     }
2627d62b00eSchristos   xfree ((*async_handler_ptr));
2637d62b00eSchristos   (*async_handler_ptr) = NULL;
2647d62b00eSchristos }
2657d62b00eSchristos 
266*6881a400Schristos /* See async-event.h.  */
267*6881a400Schristos 
2687d62b00eSchristos async_event_handler *
2697d62b00eSchristos create_async_event_handler (async_event_handler_func *proc,
270*6881a400Schristos 			    gdb_client_data client_data,
271*6881a400Schristos 			    const char *name)
2727d62b00eSchristos {
2737d62b00eSchristos   async_event_handler *h;
2747d62b00eSchristos 
2757d62b00eSchristos   h = XNEW (struct async_event_handler);
2767d62b00eSchristos   h->ready = 0;
2777d62b00eSchristos   h->next_handler = NULL;
2787d62b00eSchristos   h->proc = proc;
2797d62b00eSchristos   h->client_data = client_data;
280*6881a400Schristos   h->name = name;
2817d62b00eSchristos   if (async_event_handler_list.first_handler == NULL)
2827d62b00eSchristos     async_event_handler_list.first_handler = h;
2837d62b00eSchristos   else
2847d62b00eSchristos     async_event_handler_list.last_handler->next_handler = h;
2857d62b00eSchristos   async_event_handler_list.last_handler = h;
2867d62b00eSchristos   return h;
2877d62b00eSchristos }
2887d62b00eSchristos 
2897d62b00eSchristos /* Mark the handler (ASYNC_HANDLER_PTR) as ready.  This information
2907d62b00eSchristos    will be used by gdb_do_one_event.  The caller will be whoever
2917d62b00eSchristos    created the event source, and wants to signal that the event is
2927d62b00eSchristos    ready to be handled.  */
2937d62b00eSchristos void
2947d62b00eSchristos mark_async_event_handler (async_event_handler *async_handler_ptr)
2957d62b00eSchristos {
296*6881a400Schristos   event_loop_debug_printf ("marking async event handler `%s` "
297*6881a400Schristos 			   "(previous state was %d)",
298*6881a400Schristos 			   async_handler_ptr->name,
299*6881a400Schristos 			   async_handler_ptr->ready);
3007d62b00eSchristos   async_handler_ptr->ready = 1;
3017d62b00eSchristos }
3027d62b00eSchristos 
3037d62b00eSchristos /* See event-loop.h.  */
3047d62b00eSchristos 
3057d62b00eSchristos void
3067d62b00eSchristos clear_async_event_handler (async_event_handler *async_handler_ptr)
3077d62b00eSchristos {
308*6881a400Schristos   event_loop_debug_printf ("clearing async event handler `%s`",
309*6881a400Schristos 			   async_handler_ptr->name);
3107d62b00eSchristos   async_handler_ptr->ready = 0;
3117d62b00eSchristos }
3127d62b00eSchristos 
313*6881a400Schristos /* See event-loop.h.  */
314*6881a400Schristos 
315*6881a400Schristos bool
316*6881a400Schristos async_event_handler_marked (async_event_handler *handler)
317*6881a400Schristos {
318*6881a400Schristos   return handler->ready;
319*6881a400Schristos }
320*6881a400Schristos 
3217d62b00eSchristos /* Check if asynchronous event handlers are ready, and call the
3227d62b00eSchristos    handler function for one that is.  */
3237d62b00eSchristos 
3247d62b00eSchristos int
3257d62b00eSchristos check_async_event_handlers ()
3267d62b00eSchristos {
3277d62b00eSchristos   async_event_handler *async_handler_ptr;
3287d62b00eSchristos 
3297d62b00eSchristos   for (async_handler_ptr = async_event_handler_list.first_handler;
3307d62b00eSchristos        async_handler_ptr != NULL;
3317d62b00eSchristos        async_handler_ptr = async_handler_ptr->next_handler)
3327d62b00eSchristos     {
3337d62b00eSchristos       if (async_handler_ptr->ready)
3347d62b00eSchristos 	{
335*6881a400Schristos 	  event_loop_debug_printf ("invoking async event handler `%s`",
336*6881a400Schristos 				   async_handler_ptr->name);
3377d62b00eSchristos 	  (*async_handler_ptr->proc) (async_handler_ptr->client_data);
3387d62b00eSchristos 	  return 1;
3397d62b00eSchristos 	}
3407d62b00eSchristos     }
3417d62b00eSchristos 
3427d62b00eSchristos   return 0;
3437d62b00eSchristos }
3447d62b00eSchristos 
3457d62b00eSchristos /* Delete an asynchronous handler (ASYNC_HANDLER_PTR).
3467d62b00eSchristos    Free the space allocated for it.  */
3477d62b00eSchristos void
3487d62b00eSchristos delete_async_event_handler (async_event_handler **async_handler_ptr)
3497d62b00eSchristos {
3507d62b00eSchristos   async_event_handler *prev_ptr;
3517d62b00eSchristos 
3527d62b00eSchristos   if (async_event_handler_list.first_handler == *async_handler_ptr)
3537d62b00eSchristos     {
3547d62b00eSchristos       async_event_handler_list.first_handler
3557d62b00eSchristos 	= (*async_handler_ptr)->next_handler;
3567d62b00eSchristos       if (async_event_handler_list.first_handler == NULL)
3577d62b00eSchristos 	async_event_handler_list.last_handler = NULL;
3587d62b00eSchristos     }
3597d62b00eSchristos   else
3607d62b00eSchristos     {
3617d62b00eSchristos       prev_ptr = async_event_handler_list.first_handler;
3627d62b00eSchristos       while (prev_ptr && prev_ptr->next_handler != *async_handler_ptr)
3637d62b00eSchristos 	prev_ptr = prev_ptr->next_handler;
3647d62b00eSchristos       gdb_assert (prev_ptr);
3657d62b00eSchristos       prev_ptr->next_handler = (*async_handler_ptr)->next_handler;
3667d62b00eSchristos       if (async_event_handler_list.last_handler == (*async_handler_ptr))
3677d62b00eSchristos 	async_event_handler_list.last_handler = prev_ptr;
3687d62b00eSchristos     }
3697d62b00eSchristos   xfree (*async_handler_ptr);
3707d62b00eSchristos   *async_handler_ptr = NULL;
3717d62b00eSchristos }
372