Home | History | Annotate | Line # | Download | only in gdb
async-event.c revision 1.1
      1 /* Async events for the GDB event loop.
      2    Copyright (C) 1999-2020 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 "defs.h"
     20 #include "async-event.h"
     21 
     22 #include "ser-event.h"
     23 #include "top.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 
     51 /* PROC is a function to be invoked when the READY flag is set.  This
     52    happens when the event has been marked with
     53    MARK_ASYNC_EVENT_HANDLER.  The actual work to be done in response
     54    to an event will be carried out by PROC at a later time, within
     55    process_event.  This provides a deferred execution of event
     56    handlers.  */
     57 struct async_event_handler
     58 {
     59   /* If ready, call this handler from the main event loop, using
     60      invoke_event_handler.  */
     61   int ready;
     62 
     63   /* Pointer to next handler.  */
     64   struct async_event_handler *next_handler;
     65 
     66   /* Function to call to do the work.  */
     67   async_event_handler_func *proc;
     68 
     69   /* Argument to PROC.  */
     70   gdb_client_data client_data;
     71 };
     72 
     73 /* All the async_signal_handlers gdb is interested in are kept onto
     74    this list.  */
     75 static struct
     76 {
     77   /* Pointer to first in handler list.  */
     78   async_signal_handler *first_handler;
     79 
     80   /* Pointer to last in handler list.  */
     81   async_signal_handler *last_handler;
     82 }
     83 sighandler_list;
     84 
     85 /* All the async_event_handlers gdb is interested in are kept onto
     86    this list.  */
     87 static struct
     88 {
     89   /* Pointer to first in handler list.  */
     90   async_event_handler *first_handler;
     91 
     92   /* Pointer to last in handler list.  */
     93   async_event_handler *last_handler;
     94 }
     95 async_event_handler_list;
     96 
     97 
     98 /* This event is signalled whenever an asynchronous handler needs to
     99    defer an action to the event loop.  */
    100 static struct serial_event *async_signal_handlers_serial_event;
    101 
    102 /* Callback registered with ASYNC_SIGNAL_HANDLERS_SERIAL_EVENT.  */
    103 
    104 static void
    105 async_signals_handler (int error, gdb_client_data client_data)
    106 {
    107   /* Do nothing.  Handlers are run by invoke_async_signal_handlers
    108      from instead.  */
    109 }
    110 
    111 void
    112 initialize_async_signal_handlers (void)
    113 {
    114   async_signal_handlers_serial_event = make_serial_event ();
    115 
    116   add_file_handler (serial_event_fd (async_signal_handlers_serial_event),
    117 		    async_signals_handler, NULL);
    118 }
    119 
    120 
    121 
    123 /* Create an asynchronous handler, allocating memory for it.
    124    Return a pointer to the newly created handler.
    125    This pointer will be used to invoke the handler by
    126    invoke_async_signal_handler.
    127    PROC is the function to call with CLIENT_DATA argument
    128    whenever the handler is invoked.  */
    129 async_signal_handler *
    130 create_async_signal_handler (sig_handler_func * proc,
    131 			     gdb_client_data client_data)
    132 {
    133   async_signal_handler *async_handler_ptr;
    134 
    135   async_handler_ptr = XNEW (async_signal_handler);
    136   async_handler_ptr->ready = 0;
    137   async_handler_ptr->next_handler = NULL;
    138   async_handler_ptr->proc = proc;
    139   async_handler_ptr->client_data = client_data;
    140   if (sighandler_list.first_handler == NULL)
    141     sighandler_list.first_handler = async_handler_ptr;
    142   else
    143     sighandler_list.last_handler->next_handler = async_handler_ptr;
    144   sighandler_list.last_handler = async_handler_ptr;
    145   return async_handler_ptr;
    146 }
    147 
    148 /* Mark the handler (ASYNC_HANDLER_PTR) as ready.  This information
    149    will be used when the handlers are invoked, after we have waited
    150    for some event.  The caller of this function is the interrupt
    151    handler associated with a signal.  */
    152 void
    153 mark_async_signal_handler (async_signal_handler * async_handler_ptr)
    154 {
    155   async_handler_ptr->ready = 1;
    156   serial_event_set (async_signal_handlers_serial_event);
    157 }
    158 
    159 /* See event-loop.h.  */
    160 
    161 void
    162 clear_async_signal_handler (async_signal_handler *async_handler_ptr)
    163 {
    164   async_handler_ptr->ready = 0;
    165 }
    166 
    167 /* See event-loop.h.  */
    168 
    169 int
    170 async_signal_handler_is_marked (async_signal_handler *async_handler_ptr)
    171 {
    172   return async_handler_ptr->ready;
    173 }
    174 
    175 /* Call all the handlers that are ready.  Returns true if any was
    176    indeed ready.  */
    177 
    178 int
    179 invoke_async_signal_handlers (void)
    180 {
    181   async_signal_handler *async_handler_ptr;
    182   int any_ready = 0;
    183 
    184   /* We're going to handle all pending signals, so no need to wake up
    185      the event loop again the next time around.  Note this must be
    186      cleared _before_ calling the callbacks, to avoid races.  */
    187   serial_event_clear (async_signal_handlers_serial_event);
    188 
    189   /* Invoke all ready handlers.  */
    190 
    191   while (1)
    192     {
    193       for (async_handler_ptr = sighandler_list.first_handler;
    194 	   async_handler_ptr != NULL;
    195 	   async_handler_ptr = async_handler_ptr->next_handler)
    196 	{
    197 	  if (async_handler_ptr->ready)
    198 	    break;
    199 	}
    200       if (async_handler_ptr == NULL)
    201 	break;
    202       any_ready = 1;
    203       async_handler_ptr->ready = 0;
    204       /* Async signal handlers have no connection to whichever was the
    205 	 current UI, and thus always run on the main one.  */
    206       current_ui = main_ui;
    207       (*async_handler_ptr->proc) (async_handler_ptr->client_data);
    208     }
    209 
    210   return any_ready;
    211 }
    212 
    213 /* Delete an asynchronous handler (ASYNC_HANDLER_PTR).
    214    Free the space allocated for it.  */
    215 void
    216 delete_async_signal_handler (async_signal_handler ** async_handler_ptr)
    217 {
    218   async_signal_handler *prev_ptr;
    219 
    220   if (sighandler_list.first_handler == (*async_handler_ptr))
    221     {
    222       sighandler_list.first_handler = (*async_handler_ptr)->next_handler;
    223       if (sighandler_list.first_handler == NULL)
    224 	sighandler_list.last_handler = NULL;
    225     }
    226   else
    227     {
    228       prev_ptr = sighandler_list.first_handler;
    229       while (prev_ptr && prev_ptr->next_handler != (*async_handler_ptr))
    230 	prev_ptr = prev_ptr->next_handler;
    231       gdb_assert (prev_ptr);
    232       prev_ptr->next_handler = (*async_handler_ptr)->next_handler;
    233       if (sighandler_list.last_handler == (*async_handler_ptr))
    234 	sighandler_list.last_handler = prev_ptr;
    235     }
    236   xfree ((*async_handler_ptr));
    237   (*async_handler_ptr) = NULL;
    238 }
    239 
    240 /* Create an asynchronous event handler, allocating memory for it.
    241    Return a pointer to the newly created handler.  PROC is the
    242    function to call with CLIENT_DATA argument whenever the handler is
    243    invoked.  */
    244 async_event_handler *
    245 create_async_event_handler (async_event_handler_func *proc,
    246 			    gdb_client_data client_data)
    247 {
    248   async_event_handler *h;
    249 
    250   h = XNEW (struct async_event_handler);
    251   h->ready = 0;
    252   h->next_handler = NULL;
    253   h->proc = proc;
    254   h->client_data = client_data;
    255   if (async_event_handler_list.first_handler == NULL)
    256     async_event_handler_list.first_handler = h;
    257   else
    258     async_event_handler_list.last_handler->next_handler = h;
    259   async_event_handler_list.last_handler = h;
    260   return h;
    261 }
    262 
    263 /* Mark the handler (ASYNC_HANDLER_PTR) as ready.  This information
    264    will be used by gdb_do_one_event.  The caller will be whoever
    265    created the event source, and wants to signal that the event is
    266    ready to be handled.  */
    267 void
    268 mark_async_event_handler (async_event_handler *async_handler_ptr)
    269 {
    270   async_handler_ptr->ready = 1;
    271 }
    272 
    273 /* See event-loop.h.  */
    274 
    275 void
    276 clear_async_event_handler (async_event_handler *async_handler_ptr)
    277 {
    278   async_handler_ptr->ready = 0;
    279 }
    280 
    281 /* Check if asynchronous event handlers are ready, and call the
    282    handler function for one that is.  */
    283 
    284 int
    285 check_async_event_handlers ()
    286 {
    287   async_event_handler *async_handler_ptr;
    288 
    289   for (async_handler_ptr = async_event_handler_list.first_handler;
    290        async_handler_ptr != NULL;
    291        async_handler_ptr = async_handler_ptr->next_handler)
    292     {
    293       if (async_handler_ptr->ready)
    294 	{
    295 	  async_handler_ptr->ready = 0;
    296 	  (*async_handler_ptr->proc) (async_handler_ptr->client_data);
    297 	  return 1;
    298 	}
    299     }
    300 
    301   return 0;
    302 }
    303 
    304 /* Delete an asynchronous handler (ASYNC_HANDLER_PTR).
    305    Free the space allocated for it.  */
    306 void
    307 delete_async_event_handler (async_event_handler **async_handler_ptr)
    308 {
    309   async_event_handler *prev_ptr;
    310 
    311   if (async_event_handler_list.first_handler == *async_handler_ptr)
    312     {
    313       async_event_handler_list.first_handler
    314 	= (*async_handler_ptr)->next_handler;
    315       if (async_event_handler_list.first_handler == NULL)
    316 	async_event_handler_list.last_handler = NULL;
    317     }
    318   else
    319     {
    320       prev_ptr = async_event_handler_list.first_handler;
    321       while (prev_ptr && prev_ptr->next_handler != *async_handler_ptr)
    322 	prev_ptr = prev_ptr->next_handler;
    323       gdb_assert (prev_ptr);
    324       prev_ptr->next_handler = (*async_handler_ptr)->next_handler;
    325       if (async_event_handler_list.last_handler == (*async_handler_ptr))
    326 	async_event_handler_list.last_handler = prev_ptr;
    327     }
    328   xfree (*async_handler_ptr);
    329   *async_handler_ptr = NULL;
    330 }
    331