Home | History | Annotate | Line # | Download | only in gdb
async-event.c revision 1.1.1.3
      1 /* Async events for the GDB event loop.
      2    Copyright (C) 1999-2024 Free Software Foundation, Inc.
      3 
      4    This file is part of GDB.
      5 
      6    This program is free software; you can redistribute it and/or modify
      7    it under the terms of the GNU General Public License as published by
      8    the Free Software Foundation; either version 3 of the License, or
      9    (at your option) any later version.
     10 
     11    This program is distributed in the hope that it will be useful,
     12    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14    GNU General Public License for more details.
     15 
     16    You should have received a copy of the GNU General Public License
     17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     18 
     19 #include "async-event.h"
     20 
     21 #include "ser-event.h"
     22 #include "top.h"
     23 #include "ui.h"
     24 
     25 /* PROC is a function to be invoked when the READY flag is set.  This
     26    happens when there has been a signal and the corresponding signal
     27    handler has 'triggered' this async_signal_handler for execution.
     28    The actual work to be done in response to a signal will be carried
     29    out by PROC at a later time, within process_event.  This provides a
     30    deferred execution of signal handlers.
     31 
     32    Async_init_signals takes care of setting up such an
     33    async_signal_handler for each interesting signal.  */
     34 
     35 struct async_signal_handler
     36 {
     37   /* If ready, call this handler  from the main event loop, using
     38      invoke_async_handler.  */
     39   int ready;
     40 
     41   /* Pointer to next handler.  */
     42   struct async_signal_handler *next_handler;
     43 
     44   /* Function to call to do the work.  */
     45   sig_handler_func *proc;
     46 
     47   /* Argument to PROC.  */
     48   gdb_client_data client_data;
     49 
     50   /* User-friendly name of this handler.  */
     51   const char *name;
     52 };
     53 
     54 /* PROC is a function to be invoked when the READY flag is set.  This
     55    happens when the event has been marked with
     56    MARK_ASYNC_EVENT_HANDLER.  The actual work to be done in response
     57    to an event will be carried out by PROC at a later time, within
     58    process_event.  This provides a deferred execution of event
     59    handlers.  */
     60 struct async_event_handler
     61 {
     62   /* If ready, call this handler from the main event loop, using
     63      invoke_event_handler.  */
     64   int ready;
     65 
     66   /* Pointer to next handler.  */
     67   struct async_event_handler *next_handler;
     68 
     69   /* Function to call to do the work.  */
     70   async_event_handler_func *proc;
     71 
     72   /* Argument to PROC.  */
     73   gdb_client_data client_data;
     74 
     75   /* User-friendly name of this handler.  */
     76   const char *name;
     77 };
     78 
     79 /* All the async_signal_handlers gdb is interested in are kept onto
     80    this list.  */
     81 static struct
     82 {
     83   /* Pointer to first in handler list.  */
     84   async_signal_handler *first_handler;
     85 
     86   /* Pointer to last in handler list.  */
     87   async_signal_handler *last_handler;
     88 }
     89 sighandler_list;
     90 
     91 /* All the async_event_handlers gdb is interested in are kept onto
     92    this list.  */
     93 static struct
     94 {
     95   /* Pointer to first in handler list.  */
     96   async_event_handler *first_handler;
     97 
     98   /* Pointer to last in handler list.  */
     99   async_event_handler *last_handler;
    100 }
    101 async_event_handler_list;
    102 
    103 
    104 /* This event is signalled whenever an asynchronous handler needs to
    105    defer an action to the event loop.  */
    106 static struct serial_event *async_signal_handlers_serial_event;
    107 
    108 /* Callback registered with ASYNC_SIGNAL_HANDLERS_SERIAL_EVENT.  */
    109 
    110 static void
    111 async_signals_handler (int error, gdb_client_data client_data)
    112 {
    113   /* Do nothing.  Handlers are run by invoke_async_signal_handlers
    114      from instead.  */
    115 }
    116 
    117 void
    118 initialize_async_signal_handlers (void)
    119 {
    120   async_signal_handlers_serial_event = make_serial_event ();
    121 
    122   add_file_handler (serial_event_fd (async_signal_handlers_serial_event),
    123 		    async_signals_handler, NULL, "async-signals");
    124 }
    125 
    126 
    127 
    129 /* Create an asynchronous handler, allocating memory for it.
    130    Return a pointer to the newly created handler.
    131    This pointer will be used to invoke the handler by
    132    invoke_async_signal_handler.
    133    PROC is the function to call with CLIENT_DATA argument
    134    whenever the handler is invoked.  */
    135 async_signal_handler *
    136 create_async_signal_handler (sig_handler_func * proc,
    137 			     gdb_client_data client_data,
    138 			     const char *name)
    139 {
    140   async_signal_handler *async_handler_ptr;
    141 
    142   async_handler_ptr = XNEW (async_signal_handler);
    143   async_handler_ptr->ready = 0;
    144   async_handler_ptr->next_handler = NULL;
    145   async_handler_ptr->proc = proc;
    146   async_handler_ptr->client_data = client_data;
    147   async_handler_ptr->name = name;
    148   if (sighandler_list.first_handler == NULL)
    149     sighandler_list.first_handler = async_handler_ptr;
    150   else
    151     sighandler_list.last_handler->next_handler = async_handler_ptr;
    152   sighandler_list.last_handler = async_handler_ptr;
    153   return async_handler_ptr;
    154 }
    155 
    156 /* Mark the handler (ASYNC_HANDLER_PTR) as ready.  This information
    157    will be used when the handlers are invoked, after we have waited
    158    for some event.  The caller of this function is the interrupt
    159    handler associated with a signal.  */
    160 void
    161 mark_async_signal_handler (async_signal_handler *async_handler_ptr)
    162 {
    163   if (debug_event_loop != debug_event_loop_kind::OFF)
    164     {
    165       /* This is called by signal handlers, so we print it "by hand" using
    166 	 the async-signal-safe methods.  */
    167       const char head[] = ("[event-loop] mark_async_signal_handler: marking"
    168 			   "async signal handler `");
    169       gdb_stdlog->write_async_safe (head, strlen (head));
    170 
    171       gdb_stdlog->write_async_safe (async_handler_ptr->name,
    172 				    strlen (async_handler_ptr->name));
    173 
    174       const char tail[] = "`\n";
    175       gdb_stdlog->write_async_safe (tail, strlen (tail));
    176     }
    177 
    178   async_handler_ptr->ready = 1;
    179   serial_event_set (async_signal_handlers_serial_event);
    180 }
    181 
    182 /* See event-loop.h.  */
    183 
    184 void
    185 clear_async_signal_handler (async_signal_handler *async_handler_ptr)
    186 {
    187   event_loop_debug_printf ("clearing async signal handler `%s`",
    188 			   async_handler_ptr->name);
    189   async_handler_ptr->ready = 0;
    190 }
    191 
    192 /* See event-loop.h.  */
    193 
    194 int
    195 async_signal_handler_is_marked (async_signal_handler *async_handler_ptr)
    196 {
    197   return async_handler_ptr->ready;
    198 }
    199 
    200 /* Call all the handlers that are ready.  Returns true if any was
    201    indeed ready.  */
    202 
    203 int
    204 invoke_async_signal_handlers (void)
    205 {
    206   async_signal_handler *async_handler_ptr;
    207   int any_ready = 0;
    208 
    209   /* We're going to handle all pending signals, so no need to wake up
    210      the event loop again the next time around.  Note this must be
    211      cleared _before_ calling the callbacks, to avoid races.  */
    212   serial_event_clear (async_signal_handlers_serial_event);
    213 
    214   /* Invoke all ready handlers.  */
    215 
    216   while (1)
    217     {
    218       for (async_handler_ptr = sighandler_list.first_handler;
    219 	   async_handler_ptr != NULL;
    220 	   async_handler_ptr = async_handler_ptr->next_handler)
    221 	{
    222 	  if (async_handler_ptr->ready)
    223 	    break;
    224 	}
    225       if (async_handler_ptr == NULL)
    226 	break;
    227       any_ready = 1;
    228       async_handler_ptr->ready = 0;
    229       /* Async signal handlers have no connection to whichever was the
    230 	 current UI, and thus always run on the main one.  */
    231       current_ui = main_ui;
    232       event_loop_debug_printf ("invoking async signal handler `%s`",
    233 			       async_handler_ptr->name);
    234       (*async_handler_ptr->proc) (async_handler_ptr->client_data);
    235     }
    236 
    237   return any_ready;
    238 }
    239 
    240 /* Delete an asynchronous handler (ASYNC_HANDLER_PTR).
    241    Free the space allocated for it.  */
    242 void
    243 delete_async_signal_handler (async_signal_handler ** async_handler_ptr)
    244 {
    245   async_signal_handler *prev_ptr;
    246 
    247   if (sighandler_list.first_handler == (*async_handler_ptr))
    248     {
    249       sighandler_list.first_handler = (*async_handler_ptr)->next_handler;
    250       if (sighandler_list.first_handler == NULL)
    251 	sighandler_list.last_handler = NULL;
    252     }
    253   else
    254     {
    255       prev_ptr = sighandler_list.first_handler;
    256       while (prev_ptr && prev_ptr->next_handler != (*async_handler_ptr))
    257 	prev_ptr = prev_ptr->next_handler;
    258       gdb_assert (prev_ptr);
    259       prev_ptr->next_handler = (*async_handler_ptr)->next_handler;
    260       if (sighandler_list.last_handler == (*async_handler_ptr))
    261 	sighandler_list.last_handler = prev_ptr;
    262     }
    263   xfree ((*async_handler_ptr));
    264   (*async_handler_ptr) = NULL;
    265 }
    266 
    267 /* See async-event.h.  */
    268 
    269 async_event_handler *
    270 create_async_event_handler (async_event_handler_func *proc,
    271 			    gdb_client_data client_data,
    272 			    const char *name)
    273 {
    274   async_event_handler *h;
    275 
    276   h = XNEW (struct async_event_handler);
    277   h->ready = 0;
    278   h->next_handler = NULL;
    279   h->proc = proc;
    280   h->client_data = client_data;
    281   h->name = name;
    282   if (async_event_handler_list.first_handler == NULL)
    283     async_event_handler_list.first_handler = h;
    284   else
    285     async_event_handler_list.last_handler->next_handler = h;
    286   async_event_handler_list.last_handler = h;
    287   return h;
    288 }
    289 
    290 /* Mark the handler (ASYNC_HANDLER_PTR) as ready.  This information
    291    will be used by gdb_do_one_event.  The caller will be whoever
    292    created the event source, and wants to signal that the event is
    293    ready to be handled.  */
    294 void
    295 mark_async_event_handler (async_event_handler *async_handler_ptr)
    296 {
    297   event_loop_debug_printf ("marking async event handler `%s` "
    298 			   "(previous state was %d)",
    299 			   async_handler_ptr->name,
    300 			   async_handler_ptr->ready);
    301   async_handler_ptr->ready = 1;
    302 }
    303 
    304 /* See event-loop.h.  */
    305 
    306 void
    307 clear_async_event_handler (async_event_handler *async_handler_ptr)
    308 {
    309   event_loop_debug_printf ("clearing async event handler `%s`",
    310 			   async_handler_ptr->name);
    311   async_handler_ptr->ready = 0;
    312 }
    313 
    314 /* See event-loop.h.  */
    315 
    316 bool
    317 async_event_handler_marked (async_event_handler *handler)
    318 {
    319   return handler->ready;
    320 }
    321 
    322 /* Check if asynchronous event handlers are ready, and call the
    323    handler function for one that is.  */
    324 
    325 int
    326 check_async_event_handlers ()
    327 {
    328   async_event_handler *async_handler_ptr;
    329 
    330   for (async_handler_ptr = async_event_handler_list.first_handler;
    331        async_handler_ptr != NULL;
    332        async_handler_ptr = async_handler_ptr->next_handler)
    333     {
    334       if (async_handler_ptr->ready)
    335 	{
    336 	  event_loop_debug_printf ("invoking async event handler `%s`",
    337 				   async_handler_ptr->name);
    338 	  (*async_handler_ptr->proc) (async_handler_ptr->client_data);
    339 	  return 1;
    340 	}
    341     }
    342 
    343   return 0;
    344 }
    345 
    346 /* Delete an asynchronous handler (ASYNC_HANDLER_PTR).
    347    Free the space allocated for it.  */
    348 void
    349 delete_async_event_handler (async_event_handler **async_handler_ptr)
    350 {
    351   async_event_handler *prev_ptr;
    352 
    353   if (async_event_handler_list.first_handler == *async_handler_ptr)
    354     {
    355       async_event_handler_list.first_handler
    356 	= (*async_handler_ptr)->next_handler;
    357       if (async_event_handler_list.first_handler == NULL)
    358 	async_event_handler_list.last_handler = NULL;
    359     }
    360   else
    361     {
    362       prev_ptr = async_event_handler_list.first_handler;
    363       while (prev_ptr && prev_ptr->next_handler != *async_handler_ptr)
    364 	prev_ptr = prev_ptr->next_handler;
    365       gdb_assert (prev_ptr);
    366       prev_ptr->next_handler = (*async_handler_ptr)->next_handler;
    367       if (async_event_handler_list.last_handler == (*async_handler_ptr))
    368 	async_event_handler_list.last_handler = prev_ptr;
    369     }
    370   xfree (*async_handler_ptr);
    371   *async_handler_ptr = NULL;
    372 }
    373