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