xref: /netbsd-src/external/gpl3/gdb/dist/gdbsupport/event-loop.cc (revision 5ba1f45f2a09259cc846f20c7c5501604d633c90)
18dffb485Schristos /* Event loop machinery for GDB, the GNU debugger.
2*5ba1f45fSchristos    Copyright (C) 1999-2024 Free Software Foundation, Inc.
38dffb485Schristos    Written by Elena Zannoni <ezannoni@cygnus.com> of Cygnus Solutions.
48dffb485Schristos 
58dffb485Schristos    This file is part of GDB.
68dffb485Schristos 
78dffb485Schristos    This program is free software; you can redistribute it and/or modify
88dffb485Schristos    it under the terms of the GNU General Public License as published by
98dffb485Schristos    the Free Software Foundation; either version 3 of the License, or
108dffb485Schristos    (at your option) any later version.
118dffb485Schristos 
128dffb485Schristos    This program is distributed in the hope that it will be useful,
138dffb485Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
148dffb485Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
158dffb485Schristos    GNU General Public License for more details.
168dffb485Schristos 
178dffb485Schristos    You should have received a copy of the GNU General Public License
188dffb485Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
198dffb485Schristos 
208dffb485Schristos #include "gdbsupport/event-loop.h"
218dffb485Schristos 
228dffb485Schristos #include <chrono>
238dffb485Schristos 
248dffb485Schristos #ifdef HAVE_POLL
258dffb485Schristos #if defined (HAVE_POLL_H)
268dffb485Schristos #include <poll.h>
278dffb485Schristos #elif defined (HAVE_SYS_POLL_H)
288dffb485Schristos #include <sys/poll.h>
298dffb485Schristos #endif
308dffb485Schristos #endif
318dffb485Schristos 
328dffb485Schristos #include <sys/types.h>
338dffb485Schristos #include "gdbsupport/gdb_sys_time.h"
348dffb485Schristos #include "gdbsupport/gdb_select.h"
35*5ba1f45fSchristos #include <optional>
364b169a6bSchristos #include "gdbsupport/scope-exit.h"
374b169a6bSchristos 
384b169a6bSchristos /* See event-loop.h.  */
394b169a6bSchristos 
404b169a6bSchristos debug_event_loop_kind debug_event_loop;
418dffb485Schristos 
428dffb485Schristos /* Tell create_file_handler what events we are interested in.
438dffb485Schristos    This is used by the select version of the event loop.  */
448dffb485Schristos 
458dffb485Schristos #define GDB_READABLE	(1<<1)
468dffb485Schristos #define GDB_WRITABLE	(1<<2)
478dffb485Schristos #define GDB_EXCEPTION	(1<<3)
488dffb485Schristos 
498dffb485Schristos /* Information about each file descriptor we register with the event
508dffb485Schristos    loop.  */
518dffb485Schristos 
524b169a6bSchristos struct file_handler
538dffb485Schristos {
544b169a6bSchristos   /* File descriptor.  */
554b169a6bSchristos   int fd;
568dffb485Schristos 
574b169a6bSchristos   /* Events we want to monitor: POLLIN, etc.  */
584b169a6bSchristos   int mask;
594b169a6bSchristos 
604b169a6bSchristos   /* Events that have been seen since the last time.  */
614b169a6bSchristos   int ready_mask;
624b169a6bSchristos 
634b169a6bSchristos   /* Procedure to call when fd is ready.  */
644b169a6bSchristos   handler_func *proc;
654b169a6bSchristos 
664b169a6bSchristos   /* Argument to pass to proc.  */
674b169a6bSchristos   gdb_client_data client_data;
684b169a6bSchristos 
694b169a6bSchristos   /* User-friendly name of this handler.  */
704b169a6bSchristos   std::string name;
714b169a6bSchristos 
724b169a6bSchristos   /* If set, this file descriptor is used for a user interface.  */
734b169a6bSchristos   bool is_ui;
744b169a6bSchristos 
754b169a6bSchristos   /* Was an error detected on this fd?  */
764b169a6bSchristos   int error;
774b169a6bSchristos 
784b169a6bSchristos   /* Next registered file descriptor.  */
794b169a6bSchristos   struct file_handler *next_file;
804b169a6bSchristos };
814b169a6bSchristos 
828dffb485Schristos #ifdef HAVE_POLL
834b169a6bSchristos /* Do we use poll or select?  Some systems have poll, but then it's
844b169a6bSchristos    not useable with all kinds of files.  We probe that whenever a new
854b169a6bSchristos    file handler is added.  */
864b169a6bSchristos static bool use_poll = true;
874b169a6bSchristos #endif
888dffb485Schristos 
898dffb485Schristos #ifdef USE_WIN32API
908dffb485Schristos #include <windows.h>
918dffb485Schristos #include <io.h>
928dffb485Schristos #endif
938dffb485Schristos 
948dffb485Schristos /* Gdb_notifier is just a list of file descriptors gdb is interested in.
958dffb485Schristos    These are the input file descriptor, and the target file
968dffb485Schristos    descriptor.  We have two flavors of the notifier, one for platforms
978dffb485Schristos    that have the POLL function, the other for those that don't, and
988dffb485Schristos    only support SELECT.  Each of the elements in the gdb_notifier list is
998dffb485Schristos    basically a description of what kind of events gdb is interested
1008dffb485Schristos    in, for each fd.  */
1018dffb485Schristos 
1028dffb485Schristos static struct
1038dffb485Schristos   {
1048dffb485Schristos     /* Ptr to head of file handler list.  */
1058dffb485Schristos     file_handler *first_file_handler;
1068dffb485Schristos 
1078dffb485Schristos     /* Next file handler to handle, for the select variant.  To level
1088dffb485Schristos        the fairness across event sources, we serve file handlers in a
1098dffb485Schristos        round-robin-like fashion.  The number and order of the polled
1108dffb485Schristos        file handlers may change between invocations, but this is good
1118dffb485Schristos        enough.  */
1128dffb485Schristos     file_handler *next_file_handler;
1138dffb485Schristos 
1148dffb485Schristos #ifdef HAVE_POLL
115*5ba1f45fSchristos     /* Descriptors to poll.  */
116*5ba1f45fSchristos     std::vector<struct pollfd> poll_fds;
1178dffb485Schristos 
1188dffb485Schristos     /* Next file descriptor to handle, for the poll variant.  To level
1198dffb485Schristos        the fairness across event sources, we poll the file descriptors
1208dffb485Schristos        in a round-robin-like fashion.  The number and order of the
1218dffb485Schristos        polled file descriptors may change between invocations, but
1228dffb485Schristos        this is good enough.  */
1238dffb485Schristos     int next_poll_fds_index;
1248dffb485Schristos 
1258dffb485Schristos     /* Timeout in milliseconds for calls to poll().  */
1268dffb485Schristos     int poll_timeout;
1278dffb485Schristos #endif
1288dffb485Schristos 
1298dffb485Schristos     /* Masks to be used in the next call to select.
1308dffb485Schristos        Bits are set in response to calls to create_file_handler.  */
1318dffb485Schristos     fd_set check_masks[3];
1328dffb485Schristos 
1338dffb485Schristos     /* What file descriptors were found ready by select.  */
1348dffb485Schristos     fd_set ready_masks[3];
1358dffb485Schristos 
1368dffb485Schristos     /* Number of file descriptors to monitor (for poll).  */
1378dffb485Schristos     /* Number of valid bits (highest fd value + 1) (for select).  */
1388dffb485Schristos     int num_fds;
1398dffb485Schristos 
1408dffb485Schristos     /* Time structure for calls to select().  */
1418dffb485Schristos     struct timeval select_timeout;
1428dffb485Schristos 
1438dffb485Schristos     /* Flag to tell whether the timeout should be used.  */
1448dffb485Schristos     int timeout_valid;
1458dffb485Schristos   }
1468dffb485Schristos gdb_notifier;
1478dffb485Schristos 
1488dffb485Schristos /* Structure associated with a timer.  PROC will be executed at the
1498dffb485Schristos    first occasion after WHEN.  */
1508dffb485Schristos struct gdb_timer
1518dffb485Schristos   {
1528dffb485Schristos     std::chrono::steady_clock::time_point when;
1538dffb485Schristos     int timer_id;
1548dffb485Schristos     struct gdb_timer *next;
1558dffb485Schristos     timer_handler_func *proc;	    /* Function to call to do the work.  */
1568dffb485Schristos     gdb_client_data client_data;    /* Argument to async_handler_func.  */
1578dffb485Schristos   };
1588dffb485Schristos 
1598dffb485Schristos /* List of currently active timers.  It is sorted in order of
1608dffb485Schristos    increasing timers.  */
1618dffb485Schristos static struct
1628dffb485Schristos   {
1638dffb485Schristos     /* Pointer to first in timer list.  */
1648dffb485Schristos     struct gdb_timer *first_timer;
1658dffb485Schristos 
1668dffb485Schristos     /* Id of the last timer created.  */
1678dffb485Schristos     int num_timers;
1688dffb485Schristos   }
1698dffb485Schristos timer_list;
1708dffb485Schristos 
1718dffb485Schristos static void create_file_handler (int fd, int mask, handler_func *proc,
1724b169a6bSchristos 				 gdb_client_data client_data,
1734b169a6bSchristos 				 std::string &&name, bool is_ui);
1748dffb485Schristos static int gdb_wait_for_event (int);
1758dffb485Schristos static int update_wait_timeout (void);
1768dffb485Schristos static int poll_timers (void);
1778dffb485Schristos 
1788dffb485Schristos /* Process one high level event.  If nothing is ready at this time,
1794b169a6bSchristos    wait at most MSTIMEOUT milliseconds for something to happen (via
1804b169a6bSchristos    gdb_wait_for_event), then process it.  Returns >0 if something was
1814b169a6bSchristos    done, <0 if there are no event sources to wait for, =0 if timeout occurred.
1824b169a6bSchristos    A timeout of 0 allows to serve an already pending event, but does not
1834b169a6bSchristos    wait if none found.
1844b169a6bSchristos    Setting the timeout to a negative value disables it.
1854b169a6bSchristos    The timeout is never used by gdb itself, it is however needed to
1864b169a6bSchristos    integrate gdb event handling within Insight's GUI event loop. */
1878dffb485Schristos 
1888dffb485Schristos int
1894b169a6bSchristos gdb_do_one_event (int mstimeout)
1908dffb485Schristos {
1918dffb485Schristos   static int event_source_head = 0;
1928dffb485Schristos   const int number_of_sources = 3;
1938dffb485Schristos   int current = 0;
1948dffb485Schristos 
1958dffb485Schristos   /* First let's see if there are any asynchronous signal handlers
1968dffb485Schristos      that are ready.  These would be the result of invoking any of the
1978dffb485Schristos      signal handlers.  */
1988dffb485Schristos   if (invoke_async_signal_handlers ())
1998dffb485Schristos     return 1;
2008dffb485Schristos 
2018dffb485Schristos   /* To level the fairness across event sources, we poll them in a
2028dffb485Schristos      round-robin fashion.  */
2038dffb485Schristos   for (current = 0; current < number_of_sources; current++)
2048dffb485Schristos     {
2058dffb485Schristos       int res;
2068dffb485Schristos 
2078dffb485Schristos       switch (event_source_head)
2088dffb485Schristos 	{
2098dffb485Schristos 	case 0:
2108dffb485Schristos 	  /* Are any timers that are ready?  */
2118dffb485Schristos 	  res = poll_timers ();
2128dffb485Schristos 	  break;
2138dffb485Schristos 	case 1:
2148dffb485Schristos 	  /* Are there events already waiting to be collected on the
2158dffb485Schristos 	     monitored file descriptors?  */
2168dffb485Schristos 	  res = gdb_wait_for_event (0);
2178dffb485Schristos 	  break;
2188dffb485Schristos 	case 2:
2198dffb485Schristos 	  /* Are there any asynchronous event handlers ready?  */
2208dffb485Schristos 	  res = check_async_event_handlers ();
2218dffb485Schristos 	  break;
2228dffb485Schristos 	default:
2234b169a6bSchristos 	  internal_error ("unexpected event_source_head %d",
2248dffb485Schristos 			  event_source_head);
2258dffb485Schristos 	}
2268dffb485Schristos 
2278dffb485Schristos       event_source_head++;
2288dffb485Schristos       if (event_source_head == number_of_sources)
2298dffb485Schristos 	event_source_head = 0;
2308dffb485Schristos 
2318dffb485Schristos       if (res > 0)
2328dffb485Schristos 	return 1;
2338dffb485Schristos     }
2348dffb485Schristos 
2354b169a6bSchristos   if (mstimeout == 0)
2364b169a6bSchristos     return 0;	/* 0ms timeout: do not wait for an event. */
2374b169a6bSchristos 
2388dffb485Schristos   /* Block waiting for a new event.  If gdb_wait_for_event returns -1,
2398dffb485Schristos      we should get out because this means that there are no event
2408dffb485Schristos      sources left.  This will make the event loop stop, and the
2414b169a6bSchristos      application exit.
2424b169a6bSchristos      If a timeout has been given, a new timer is set accordingly
2434b169a6bSchristos      to abort event wait.  It is deleted upon gdb_wait_for_event
2444b169a6bSchristos      termination and thus should never be triggered.
2454b169a6bSchristos      When the timeout is reached, events are not monitored again:
2464b169a6bSchristos      they already have been checked in the loop above. */
2478dffb485Schristos 
248*5ba1f45fSchristos   std::optional<int> timer_id;
2498dffb485Schristos 
2504b169a6bSchristos   SCOPE_EXIT
2514b169a6bSchristos     {
2524b169a6bSchristos       if (timer_id.has_value ())
2534b169a6bSchristos 	delete_timer (*timer_id);
2544b169a6bSchristos     };
2554b169a6bSchristos 
2564b169a6bSchristos   if (mstimeout > 0)
2574b169a6bSchristos     timer_id = create_timer (mstimeout,
2584b169a6bSchristos 			     [] (gdb_client_data arg)
2594b169a6bSchristos 			     {
260*5ba1f45fSchristos 			       ((std::optional<int> *) arg)->reset ();
2614b169a6bSchristos 			     },
2624b169a6bSchristos 			     &timer_id);
2634b169a6bSchristos   return gdb_wait_for_event (1);
2648dffb485Schristos }
2658dffb485Schristos 
2664b169a6bSchristos /* See event-loop.h  */
2678dffb485Schristos 
2688dffb485Schristos void
2694b169a6bSchristos add_file_handler (int fd, handler_func *proc, gdb_client_data client_data,
2704b169a6bSchristos 		  std::string &&name, bool is_ui)
2718dffb485Schristos {
2728dffb485Schristos #ifdef HAVE_POLL
2738dffb485Schristos   if (use_poll)
2748dffb485Schristos     {
2754b169a6bSchristos       struct pollfd fds;
2764b169a6bSchristos 
2778dffb485Schristos       /* Check to see if poll () is usable.  If not, we'll switch to
2788dffb485Schristos 	 use select.  This can happen on systems like
2798dffb485Schristos 	 m68k-motorola-sys, `poll' cannot be used to wait for `stdin'.
2808dffb485Schristos 	 On m68k-motorola-sysv, tty's are not stream-based and not
2818dffb485Schristos 	 `poll'able.  */
2828dffb485Schristos       fds.fd = fd;
2838dffb485Schristos       fds.events = POLLIN;
2848dffb485Schristos       if (poll (&fds, 1, 0) == 1 && (fds.revents & POLLNVAL))
2854b169a6bSchristos 	use_poll = false;
2868dffb485Schristos     }
2878dffb485Schristos   if (use_poll)
2888dffb485Schristos     {
2894b169a6bSchristos       create_file_handler (fd, POLLIN, proc, client_data, std::move (name),
2904b169a6bSchristos 			   is_ui);
2918dffb485Schristos     }
2928dffb485Schristos   else
2934b169a6bSchristos #endif /* HAVE_POLL */
2948dffb485Schristos     create_file_handler (fd, GDB_READABLE | GDB_EXCEPTION,
2954b169a6bSchristos 			 proc, client_data, std::move (name), is_ui);
2968dffb485Schristos }
2978dffb485Schristos 
2984b169a6bSchristos /* Helper for add_file_handler.
2998dffb485Schristos 
3008dffb485Schristos    For the poll case, MASK is a combination (OR) of POLLIN,
3018dffb485Schristos    POLLRDNORM, POLLRDBAND, POLLPRI, POLLOUT, POLLWRNORM, POLLWRBAND:
3028dffb485Schristos    these are the events we are interested in.  If any of them occurs,
3038dffb485Schristos    proc should be called.
3048dffb485Schristos 
3058dffb485Schristos    For the select case, MASK is a combination of READABLE, WRITABLE,
3068dffb485Schristos    EXCEPTION.  PROC is the procedure that will be called when an event
3078dffb485Schristos    occurs for FD.  CLIENT_DATA is the argument to pass to PROC.  */
3088dffb485Schristos 
3098dffb485Schristos static void
3108dffb485Schristos create_file_handler (int fd, int mask, handler_func * proc,
3114b169a6bSchristos 		     gdb_client_data client_data, std::string &&name,
3124b169a6bSchristos 		     bool is_ui)
3138dffb485Schristos {
3148dffb485Schristos   file_handler *file_ptr;
3158dffb485Schristos 
3168dffb485Schristos   /* Do we already have a file handler for this file?  (We may be
3178dffb485Schristos      changing its associated procedure).  */
3188dffb485Schristos   for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL;
3198dffb485Schristos        file_ptr = file_ptr->next_file)
3208dffb485Schristos     {
3218dffb485Schristos       if (file_ptr->fd == fd)
3228dffb485Schristos 	break;
3238dffb485Schristos     }
3248dffb485Schristos 
3258dffb485Schristos   /* It is a new file descriptor.  Add it to the list.  Otherwise, just
3268dffb485Schristos      change the data associated with it.  */
3278dffb485Schristos   if (file_ptr == NULL)
3288dffb485Schristos     {
3294b169a6bSchristos       file_ptr = new file_handler;
3308dffb485Schristos       file_ptr->fd = fd;
3318dffb485Schristos       file_ptr->ready_mask = 0;
3328dffb485Schristos       file_ptr->next_file = gdb_notifier.first_file_handler;
3338dffb485Schristos       gdb_notifier.first_file_handler = file_ptr;
3348dffb485Schristos 
3354b169a6bSchristos #ifdef HAVE_POLL
3368dffb485Schristos       if (use_poll)
3378dffb485Schristos 	{
3388dffb485Schristos 	  gdb_notifier.num_fds++;
339*5ba1f45fSchristos 	  struct pollfd new_fd;
340*5ba1f45fSchristos 	  new_fd.fd = fd;
341*5ba1f45fSchristos 	  new_fd.events = mask;
342*5ba1f45fSchristos 	  new_fd.revents = 0;
343*5ba1f45fSchristos 	  gdb_notifier.poll_fds.push_back (new_fd);
3448dffb485Schristos 	}
3458dffb485Schristos       else
3464b169a6bSchristos #endif /* HAVE_POLL */
3478dffb485Schristos 	{
3488dffb485Schristos 	  if (mask & GDB_READABLE)
3498dffb485Schristos 	    FD_SET (fd, &gdb_notifier.check_masks[0]);
3508dffb485Schristos 	  else
3518dffb485Schristos 	    FD_CLR (fd, &gdb_notifier.check_masks[0]);
3528dffb485Schristos 
3538dffb485Schristos 	  if (mask & GDB_WRITABLE)
3548dffb485Schristos 	    FD_SET (fd, &gdb_notifier.check_masks[1]);
3558dffb485Schristos 	  else
3568dffb485Schristos 	    FD_CLR (fd, &gdb_notifier.check_masks[1]);
3578dffb485Schristos 
3588dffb485Schristos 	  if (mask & GDB_EXCEPTION)
3598dffb485Schristos 	    FD_SET (fd, &gdb_notifier.check_masks[2]);
3608dffb485Schristos 	  else
3618dffb485Schristos 	    FD_CLR (fd, &gdb_notifier.check_masks[2]);
3628dffb485Schristos 
3638dffb485Schristos 	  if (gdb_notifier.num_fds <= fd)
3648dffb485Schristos 	    gdb_notifier.num_fds = fd + 1;
3658dffb485Schristos 	}
3668dffb485Schristos     }
3678dffb485Schristos 
3688dffb485Schristos   file_ptr->proc = proc;
3698dffb485Schristos   file_ptr->client_data = client_data;
3708dffb485Schristos   file_ptr->mask = mask;
3714b169a6bSchristos   file_ptr->name = std::move (name);
3724b169a6bSchristos   file_ptr->is_ui = is_ui;
3738dffb485Schristos }
3748dffb485Schristos 
3758dffb485Schristos /* Return the next file handler to handle, and advance to the next
3768dffb485Schristos    file handler, wrapping around if the end of the list is
3778dffb485Schristos    reached.  */
3788dffb485Schristos 
3798dffb485Schristos static file_handler *
3808dffb485Schristos get_next_file_handler_to_handle_and_advance (void)
3818dffb485Schristos {
3828dffb485Schristos   file_handler *curr_next;
3838dffb485Schristos 
3848dffb485Schristos   /* The first time around, this is still NULL.  */
3858dffb485Schristos   if (gdb_notifier.next_file_handler == NULL)
3868dffb485Schristos     gdb_notifier.next_file_handler = gdb_notifier.first_file_handler;
3878dffb485Schristos 
3888dffb485Schristos   curr_next = gdb_notifier.next_file_handler;
3898dffb485Schristos   gdb_assert (curr_next != NULL);
3908dffb485Schristos 
3918dffb485Schristos   /* Advance.  */
3928dffb485Schristos   gdb_notifier.next_file_handler = curr_next->next_file;
3938dffb485Schristos   /* Wrap around, if necessary.  */
3948dffb485Schristos   if (gdb_notifier.next_file_handler == NULL)
3958dffb485Schristos     gdb_notifier.next_file_handler = gdb_notifier.first_file_handler;
3968dffb485Schristos 
3978dffb485Schristos   return curr_next;
3988dffb485Schristos }
3998dffb485Schristos 
4008dffb485Schristos /* Remove the file descriptor FD from the list of monitored fd's:
4018dffb485Schristos    i.e. we don't care anymore about events on the FD.  */
4028dffb485Schristos void
4038dffb485Schristos delete_file_handler (int fd)
4048dffb485Schristos {
4058dffb485Schristos   file_handler *file_ptr, *prev_ptr = NULL;
4068dffb485Schristos   int i;
4078dffb485Schristos 
4088dffb485Schristos   /* Find the entry for the given file.  */
4098dffb485Schristos 
4108dffb485Schristos   for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL;
4118dffb485Schristos        file_ptr = file_ptr->next_file)
4128dffb485Schristos     {
4138dffb485Schristos       if (file_ptr->fd == fd)
4148dffb485Schristos 	break;
4158dffb485Schristos     }
4168dffb485Schristos 
4178dffb485Schristos   if (file_ptr == NULL)
4188dffb485Schristos     return;
4198dffb485Schristos 
4204b169a6bSchristos #ifdef HAVE_POLL
4218dffb485Schristos   if (use_poll)
4228dffb485Schristos     {
423*5ba1f45fSchristos       auto iter = std::remove_if (gdb_notifier.poll_fds.begin (),
424*5ba1f45fSchristos 				  gdb_notifier.poll_fds.end (),
425*5ba1f45fSchristos 				  [=] (const pollfd &item)
4268dffb485Schristos 				  {
427*5ba1f45fSchristos 				    return item.fd == fd;
428*5ba1f45fSchristos 				  });
429*5ba1f45fSchristos       gdb_notifier.poll_fds.erase (iter, gdb_notifier.poll_fds.end());
4308dffb485Schristos       gdb_notifier.num_fds--;
4318dffb485Schristos     }
4328dffb485Schristos   else
4334b169a6bSchristos #endif /* HAVE_POLL */
4348dffb485Schristos     {
4358dffb485Schristos       if (file_ptr->mask & GDB_READABLE)
4368dffb485Schristos 	FD_CLR (fd, &gdb_notifier.check_masks[0]);
4378dffb485Schristos       if (file_ptr->mask & GDB_WRITABLE)
4388dffb485Schristos 	FD_CLR (fd, &gdb_notifier.check_masks[1]);
4398dffb485Schristos       if (file_ptr->mask & GDB_EXCEPTION)
4408dffb485Schristos 	FD_CLR (fd, &gdb_notifier.check_masks[2]);
4418dffb485Schristos 
4428dffb485Schristos       /* Find current max fd.  */
4438dffb485Schristos 
4448dffb485Schristos       if ((fd + 1) == gdb_notifier.num_fds)
4458dffb485Schristos 	{
4468dffb485Schristos 	  gdb_notifier.num_fds--;
4478dffb485Schristos 	  for (i = gdb_notifier.num_fds; i; i--)
4488dffb485Schristos 	    {
4498dffb485Schristos 	      if (FD_ISSET (i - 1, &gdb_notifier.check_masks[0])
4508dffb485Schristos 		  || FD_ISSET (i - 1, &gdb_notifier.check_masks[1])
4518dffb485Schristos 		  || FD_ISSET (i - 1, &gdb_notifier.check_masks[2]))
4528dffb485Schristos 		break;
4538dffb485Schristos 	    }
4548dffb485Schristos 	  gdb_notifier.num_fds = i;
4558dffb485Schristos 	}
4568dffb485Schristos     }
4578dffb485Schristos 
4588dffb485Schristos   /* Deactivate the file descriptor, by clearing its mask,
4598dffb485Schristos      so that it will not fire again.  */
4608dffb485Schristos 
4618dffb485Schristos   file_ptr->mask = 0;
4628dffb485Schristos 
4638dffb485Schristos   /* If this file handler was going to be the next one to be handled,
4648dffb485Schristos      advance to the next's next, if any.  */
4658dffb485Schristos   if (gdb_notifier.next_file_handler == file_ptr)
4668dffb485Schristos     {
4678dffb485Schristos       if (file_ptr->next_file == NULL
4688dffb485Schristos 	  && file_ptr == gdb_notifier.first_file_handler)
4698dffb485Schristos 	gdb_notifier.next_file_handler = NULL;
4708dffb485Schristos       else
4718dffb485Schristos 	get_next_file_handler_to_handle_and_advance ();
4728dffb485Schristos     }
4738dffb485Schristos 
4748dffb485Schristos   /* Get rid of the file handler in the file handler list.  */
4758dffb485Schristos   if (file_ptr == gdb_notifier.first_file_handler)
4768dffb485Schristos     gdb_notifier.first_file_handler = file_ptr->next_file;
4778dffb485Schristos   else
4788dffb485Schristos     {
4798dffb485Schristos       for (prev_ptr = gdb_notifier.first_file_handler;
4808dffb485Schristos 	   prev_ptr->next_file != file_ptr;
4818dffb485Schristos 	   prev_ptr = prev_ptr->next_file)
4828dffb485Schristos 	;
4838dffb485Schristos       prev_ptr->next_file = file_ptr->next_file;
4848dffb485Schristos     }
4854b169a6bSchristos 
4864b169a6bSchristos   delete file_ptr;
4878dffb485Schristos }
4888dffb485Schristos 
4898dffb485Schristos /* Handle the given event by calling the procedure associated to the
4908dffb485Schristos    corresponding file handler.  */
4918dffb485Schristos 
4928dffb485Schristos static void
4938dffb485Schristos handle_file_event (file_handler *file_ptr, int ready_mask)
4948dffb485Schristos {
4958dffb485Schristos   int mask;
4964b169a6bSchristos 
4974b169a6bSchristos   /* See if the desired events (mask) match the received events
4984b169a6bSchristos      (ready_mask).  */
4994b169a6bSchristos 
5008dffb485Schristos #ifdef HAVE_POLL
5018dffb485Schristos   if (use_poll)
5028dffb485Schristos     {
5034b169a6bSchristos       int error_mask;
5044b169a6bSchristos 
5054b169a6bSchristos       /* With poll, the ready_mask could have any of three events set
5064b169a6bSchristos 	 to 1: POLLHUP, POLLERR, POLLNVAL.  These events cannot be
5074b169a6bSchristos 	 used in the requested event mask (events), but they can be
5084b169a6bSchristos 	 returned in the return mask (revents).  We need to check for
5094b169a6bSchristos 	 those event too, and add them to the mask which will be
5104b169a6bSchristos 	 passed to the handler.  */
5114b169a6bSchristos 
5128dffb485Schristos       /* POLLHUP means EOF, but can be combined with POLLIN to
5138dffb485Schristos 	 signal more data to read.  */
5148dffb485Schristos       error_mask = POLLHUP | POLLERR | POLLNVAL;
5158dffb485Schristos       mask = ready_mask & (file_ptr->mask | error_mask);
5168dffb485Schristos 
5178dffb485Schristos       if ((mask & (POLLERR | POLLNVAL)) != 0)
5188dffb485Schristos 	{
5198dffb485Schristos 	  /* Work in progress.  We may need to tell somebody
5208dffb485Schristos 	     what kind of error we had.  */
5218dffb485Schristos 	  if (mask & POLLERR)
5228dffb485Schristos 	    warning (_("Error detected on fd %d"), file_ptr->fd);
5238dffb485Schristos 	  if (mask & POLLNVAL)
5248dffb485Schristos 	    warning (_("Invalid or non-`poll'able fd %d"),
5258dffb485Schristos 		     file_ptr->fd);
5268dffb485Schristos 	  file_ptr->error = 1;
5278dffb485Schristos 	}
5288dffb485Schristos       else
5298dffb485Schristos 	file_ptr->error = 0;
5308dffb485Schristos     }
5318dffb485Schristos   else
5324b169a6bSchristos #endif /* HAVE_POLL */
5338dffb485Schristos     {
5348dffb485Schristos       if (ready_mask & GDB_EXCEPTION)
5358dffb485Schristos 	{
5368dffb485Schristos 	  warning (_("Exception condition detected on fd %d"),
5378dffb485Schristos 		   file_ptr->fd);
5388dffb485Schristos 	  file_ptr->error = 1;
5398dffb485Schristos 	}
5408dffb485Schristos       else
5418dffb485Schristos 	file_ptr->error = 0;
5428dffb485Schristos       mask = ready_mask & file_ptr->mask;
5438dffb485Schristos     }
5448dffb485Schristos 
5458dffb485Schristos   /* If there was a match, then call the handler.  */
5468dffb485Schristos   if (mask != 0)
5474b169a6bSchristos     {
5484b169a6bSchristos       event_loop_ui_debug_printf (file_ptr->is_ui,
5494b169a6bSchristos 				  "invoking fd file handler `%s`",
5504b169a6bSchristos 				  file_ptr->name.c_str ());
5514b169a6bSchristos       file_ptr->proc (file_ptr->error, file_ptr->client_data);
5528dffb485Schristos     }
5538dffb485Schristos }
5548dffb485Schristos 
5558dffb485Schristos /* Wait for new events on the monitored file descriptors.  Run the
5568dffb485Schristos    event handler if the first descriptor that is detected by the poll.
5578dffb485Schristos    If BLOCK and if there are no events, this function will block in
5588dffb485Schristos    the call to poll.  Return 1 if an event was handled.  Return -1 if
5598dffb485Schristos    there are no file descriptors to monitor.  Return 1 if an event was
5608dffb485Schristos    handled, otherwise returns 0.  */
5618dffb485Schristos 
5628dffb485Schristos static int
5638dffb485Schristos gdb_wait_for_event (int block)
5648dffb485Schristos {
5658dffb485Schristos   file_handler *file_ptr;
5668dffb485Schristos   int num_found = 0;
5678dffb485Schristos 
5688dffb485Schristos   /* Make sure all output is done before getting another event.  */
5698dffb485Schristos   flush_streams ();
5708dffb485Schristos 
5718dffb485Schristos   if (gdb_notifier.num_fds == 0)
5728dffb485Schristos     return -1;
5738dffb485Schristos 
5748dffb485Schristos   if (block)
5758dffb485Schristos     update_wait_timeout ();
5768dffb485Schristos 
5774b169a6bSchristos #ifdef HAVE_POLL
5788dffb485Schristos   if (use_poll)
5798dffb485Schristos     {
5808dffb485Schristos       int timeout;
5818dffb485Schristos 
5828dffb485Schristos       if (block)
5838dffb485Schristos 	timeout = gdb_notifier.timeout_valid ? gdb_notifier.poll_timeout : -1;
5848dffb485Schristos       else
5858dffb485Schristos 	timeout = 0;
5868dffb485Schristos 
587*5ba1f45fSchristos       num_found = poll (gdb_notifier.poll_fds.data (),
5888dffb485Schristos 			(unsigned long) gdb_notifier.num_fds, timeout);
5898dffb485Schristos 
5908dffb485Schristos       /* Don't print anything if we get out of poll because of a
5918dffb485Schristos 	 signal.  */
5928dffb485Schristos       if (num_found == -1 && errno != EINTR)
5938dffb485Schristos 	perror_with_name (("poll"));
5948dffb485Schristos     }
5958dffb485Schristos   else
5964b169a6bSchristos #endif /* HAVE_POLL */
5978dffb485Schristos     {
5988dffb485Schristos       struct timeval select_timeout;
5998dffb485Schristos       struct timeval *timeout_p;
6008dffb485Schristos 
6018dffb485Schristos       if (block)
6028dffb485Schristos 	timeout_p = gdb_notifier.timeout_valid
6038dffb485Schristos 	  ? &gdb_notifier.select_timeout : NULL;
6048dffb485Schristos       else
6058dffb485Schristos 	{
6068dffb485Schristos 	  memset (&select_timeout, 0, sizeof (select_timeout));
6078dffb485Schristos 	  timeout_p = &select_timeout;
6088dffb485Schristos 	}
6098dffb485Schristos 
6108dffb485Schristos       gdb_notifier.ready_masks[0] = gdb_notifier.check_masks[0];
6118dffb485Schristos       gdb_notifier.ready_masks[1] = gdb_notifier.check_masks[1];
6128dffb485Schristos       gdb_notifier.ready_masks[2] = gdb_notifier.check_masks[2];
6138dffb485Schristos       num_found = gdb_select (gdb_notifier.num_fds,
6148dffb485Schristos 			      &gdb_notifier.ready_masks[0],
6158dffb485Schristos 			      &gdb_notifier.ready_masks[1],
6168dffb485Schristos 			      &gdb_notifier.ready_masks[2],
6178dffb485Schristos 			      timeout_p);
6188dffb485Schristos 
6198dffb485Schristos       /* Clear the masks after an error from select.  */
6208dffb485Schristos       if (num_found == -1)
6218dffb485Schristos 	{
6228dffb485Schristos 	  FD_ZERO (&gdb_notifier.ready_masks[0]);
6238dffb485Schristos 	  FD_ZERO (&gdb_notifier.ready_masks[1]);
6248dffb485Schristos 	  FD_ZERO (&gdb_notifier.ready_masks[2]);
6258dffb485Schristos 
6268dffb485Schristos 	  /* Dont print anything if we got a signal, let gdb handle
6278dffb485Schristos 	     it.  */
6288dffb485Schristos 	  if (errno != EINTR)
6298dffb485Schristos 	    perror_with_name (("select"));
6308dffb485Schristos 	}
6318dffb485Schristos     }
6328dffb485Schristos 
6338dffb485Schristos   /* Avoid looking at poll_fds[i]->revents if no event fired.  */
6348dffb485Schristos   if (num_found <= 0)
6358dffb485Schristos     return 0;
6368dffb485Schristos 
6378dffb485Schristos   /* Run event handlers.  We always run just one handler and go back
6388dffb485Schristos      to polling, in case a handler changes the notifier list.  Since
6398dffb485Schristos      events for sources we haven't consumed yet wake poll/select
6408dffb485Schristos      immediately, no event is lost.  */
6418dffb485Schristos 
6428dffb485Schristos   /* To level the fairness across event descriptors, we handle them in
6438dffb485Schristos      a round-robin-like fashion.  The number and order of descriptors
6448dffb485Schristos      may change between invocations, but this is good enough.  */
6454b169a6bSchristos #ifdef HAVE_POLL
6468dffb485Schristos   if (use_poll)
6478dffb485Schristos     {
6488dffb485Schristos       int i;
6498dffb485Schristos       int mask;
6508dffb485Schristos 
6518dffb485Schristos       while (1)
6528dffb485Schristos 	{
6538dffb485Schristos 	  if (gdb_notifier.next_poll_fds_index >= gdb_notifier.num_fds)
6548dffb485Schristos 	    gdb_notifier.next_poll_fds_index = 0;
6558dffb485Schristos 	  i = gdb_notifier.next_poll_fds_index++;
6568dffb485Schristos 
6578dffb485Schristos 	  gdb_assert (i < gdb_notifier.num_fds);
658*5ba1f45fSchristos 	  if (gdb_notifier.poll_fds[i].revents)
6598dffb485Schristos 	    break;
6608dffb485Schristos 	}
6618dffb485Schristos 
6628dffb485Schristos       for (file_ptr = gdb_notifier.first_file_handler;
6638dffb485Schristos 	   file_ptr != NULL;
6648dffb485Schristos 	   file_ptr = file_ptr->next_file)
6658dffb485Schristos 	{
666*5ba1f45fSchristos 	  if (file_ptr->fd == gdb_notifier.poll_fds[i].fd)
6678dffb485Schristos 	    break;
6688dffb485Schristos 	}
6698dffb485Schristos       gdb_assert (file_ptr != NULL);
6708dffb485Schristos 
671*5ba1f45fSchristos       mask = gdb_notifier.poll_fds[i].revents;
6728dffb485Schristos       handle_file_event (file_ptr, mask);
6738dffb485Schristos       return 1;
6748dffb485Schristos     }
6758dffb485Schristos   else
6764b169a6bSchristos #endif /* HAVE_POLL */
6778dffb485Schristos     {
6788dffb485Schristos       /* See comment about even source fairness above.  */
6798dffb485Schristos       int mask = 0;
6808dffb485Schristos 
6818dffb485Schristos       do
6828dffb485Schristos 	{
6838dffb485Schristos 	  file_ptr = get_next_file_handler_to_handle_and_advance ();
6848dffb485Schristos 
6858dffb485Schristos 	  if (FD_ISSET (file_ptr->fd, &gdb_notifier.ready_masks[0]))
6868dffb485Schristos 	    mask |= GDB_READABLE;
6878dffb485Schristos 	  if (FD_ISSET (file_ptr->fd, &gdb_notifier.ready_masks[1]))
6888dffb485Schristos 	    mask |= GDB_WRITABLE;
6898dffb485Schristos 	  if (FD_ISSET (file_ptr->fd, &gdb_notifier.ready_masks[2]))
6908dffb485Schristos 	    mask |= GDB_EXCEPTION;
6918dffb485Schristos 	}
6928dffb485Schristos       while (mask == 0);
6938dffb485Schristos 
6948dffb485Schristos       handle_file_event (file_ptr, mask);
6958dffb485Schristos       return 1;
6968dffb485Schristos     }
6978dffb485Schristos   return 0;
6988dffb485Schristos }
6998dffb485Schristos 
7008dffb485Schristos /* Create a timer that will expire in MS milliseconds from now.  When
7018dffb485Schristos    the timer is ready, PROC will be executed.  At creation, the timer
7028dffb485Schristos    is added to the timers queue.  This queue is kept sorted in order
7038dffb485Schristos    of increasing timers.  Return a handle to the timer struct.  */
7048dffb485Schristos 
7058dffb485Schristos int
7068dffb485Schristos create_timer (int ms, timer_handler_func *proc,
7078dffb485Schristos 	      gdb_client_data client_data)
7088dffb485Schristos {
7098dffb485Schristos   using namespace std::chrono;
7108dffb485Schristos   struct gdb_timer *timer_ptr, *timer_index, *prev_timer;
7118dffb485Schristos 
7128dffb485Schristos   steady_clock::time_point time_now = steady_clock::now ();
7138dffb485Schristos 
7148dffb485Schristos   timer_ptr = new gdb_timer ();
7158dffb485Schristos   timer_ptr->when = time_now + milliseconds (ms);
7168dffb485Schristos   timer_ptr->proc = proc;
7178dffb485Schristos   timer_ptr->client_data = client_data;
7188dffb485Schristos   timer_list.num_timers++;
7198dffb485Schristos   timer_ptr->timer_id = timer_list.num_timers;
7208dffb485Schristos 
7218dffb485Schristos   /* Now add the timer to the timer queue, making sure it is sorted in
7228dffb485Schristos      increasing order of expiration.  */
7238dffb485Schristos 
7248dffb485Schristos   for (timer_index = timer_list.first_timer;
7258dffb485Schristos        timer_index != NULL;
7268dffb485Schristos        timer_index = timer_index->next)
7278dffb485Schristos     {
7288dffb485Schristos       if (timer_index->when > timer_ptr->when)
7298dffb485Schristos 	break;
7308dffb485Schristos     }
7318dffb485Schristos 
7328dffb485Schristos   if (timer_index == timer_list.first_timer)
7338dffb485Schristos     {
7348dffb485Schristos       timer_ptr->next = timer_list.first_timer;
7358dffb485Schristos       timer_list.first_timer = timer_ptr;
7368dffb485Schristos 
7378dffb485Schristos     }
7388dffb485Schristos   else
7398dffb485Schristos     {
7408dffb485Schristos       for (prev_timer = timer_list.first_timer;
7418dffb485Schristos 	   prev_timer->next != timer_index;
7428dffb485Schristos 	   prev_timer = prev_timer->next)
7438dffb485Schristos 	;
7448dffb485Schristos 
7458dffb485Schristos       prev_timer->next = timer_ptr;
7468dffb485Schristos       timer_ptr->next = timer_index;
7478dffb485Schristos     }
7488dffb485Schristos 
7498dffb485Schristos   gdb_notifier.timeout_valid = 0;
7508dffb485Schristos   return timer_ptr->timer_id;
7518dffb485Schristos }
7528dffb485Schristos 
7538dffb485Schristos /* There is a chance that the creator of the timer wants to get rid of
7548dffb485Schristos    it before it expires.  */
7558dffb485Schristos void
7568dffb485Schristos delete_timer (int id)
7578dffb485Schristos {
7588dffb485Schristos   struct gdb_timer *timer_ptr, *prev_timer = NULL;
7598dffb485Schristos 
7608dffb485Schristos   /* Find the entry for the given timer.  */
7618dffb485Schristos 
7628dffb485Schristos   for (timer_ptr = timer_list.first_timer; timer_ptr != NULL;
7638dffb485Schristos        timer_ptr = timer_ptr->next)
7648dffb485Schristos     {
7658dffb485Schristos       if (timer_ptr->timer_id == id)
7668dffb485Schristos 	break;
7678dffb485Schristos     }
7688dffb485Schristos 
7698dffb485Schristos   if (timer_ptr == NULL)
7708dffb485Schristos     return;
7718dffb485Schristos   /* Get rid of the timer in the timer list.  */
7728dffb485Schristos   if (timer_ptr == timer_list.first_timer)
7738dffb485Schristos     timer_list.first_timer = timer_ptr->next;
7748dffb485Schristos   else
7758dffb485Schristos     {
7768dffb485Schristos       for (prev_timer = timer_list.first_timer;
7778dffb485Schristos 	   prev_timer->next != timer_ptr;
7788dffb485Schristos 	   prev_timer = prev_timer->next)
7798dffb485Schristos 	;
7808dffb485Schristos       prev_timer->next = timer_ptr->next;
7818dffb485Schristos     }
7828dffb485Schristos   delete timer_ptr;
7838dffb485Schristos 
7848dffb485Schristos   gdb_notifier.timeout_valid = 0;
7858dffb485Schristos }
7868dffb485Schristos 
7878dffb485Schristos /* Convert a std::chrono duration to a struct timeval.  */
7888dffb485Schristos 
7898dffb485Schristos template<typename Duration>
7908dffb485Schristos static struct timeval
7918dffb485Schristos duration_cast_timeval (const Duration &d)
7928dffb485Schristos {
7938dffb485Schristos   using namespace std::chrono;
7948dffb485Schristos   seconds sec = duration_cast<seconds> (d);
7958dffb485Schristos   microseconds msec = duration_cast<microseconds> (d - sec);
7968dffb485Schristos 
7978dffb485Schristos   struct timeval tv;
7988dffb485Schristos   tv.tv_sec = sec.count ();
7998dffb485Schristos   tv.tv_usec = msec.count ();
8008dffb485Schristos   return tv;
8018dffb485Schristos }
8028dffb485Schristos 
8038dffb485Schristos /* Update the timeout for the select() or poll().  Returns true if the
8048dffb485Schristos    timer has already expired, false otherwise.  */
8058dffb485Schristos 
8068dffb485Schristos static int
8078dffb485Schristos update_wait_timeout (void)
8088dffb485Schristos {
8098dffb485Schristos   if (timer_list.first_timer != NULL)
8108dffb485Schristos     {
8118dffb485Schristos       using namespace std::chrono;
8128dffb485Schristos       steady_clock::time_point time_now = steady_clock::now ();
8138dffb485Schristos       struct timeval timeout;
8148dffb485Schristos 
8158dffb485Schristos       if (timer_list.first_timer->when < time_now)
8168dffb485Schristos 	{
8178dffb485Schristos 	  /* It expired already.  */
8188dffb485Schristos 	  timeout.tv_sec = 0;
8198dffb485Schristos 	  timeout.tv_usec = 0;
8208dffb485Schristos 	}
8218dffb485Schristos       else
8228dffb485Schristos 	{
8238dffb485Schristos 	  steady_clock::duration d = timer_list.first_timer->when - time_now;
8248dffb485Schristos 	  timeout = duration_cast_timeval (d);
8258dffb485Schristos 	}
8268dffb485Schristos 
8278dffb485Schristos       /* Update the timeout for select/ poll.  */
8288dffb485Schristos #ifdef HAVE_POLL
8294b169a6bSchristos       if (use_poll)
8308dffb485Schristos 	gdb_notifier.poll_timeout = timeout.tv_sec * 1000;
8318dffb485Schristos       else
8324b169a6bSchristos #endif /* HAVE_POLL */
8338dffb485Schristos 	{
8348dffb485Schristos 	  gdb_notifier.select_timeout.tv_sec = timeout.tv_sec;
8358dffb485Schristos 	  gdb_notifier.select_timeout.tv_usec = timeout.tv_usec;
8368dffb485Schristos 	}
8378dffb485Schristos       gdb_notifier.timeout_valid = 1;
8388dffb485Schristos 
8398dffb485Schristos       if (timer_list.first_timer->when < time_now)
8408dffb485Schristos 	return 1;
8418dffb485Schristos     }
8428dffb485Schristos   else
8438dffb485Schristos     gdb_notifier.timeout_valid = 0;
8448dffb485Schristos 
8458dffb485Schristos   return 0;
8468dffb485Schristos }
8478dffb485Schristos 
8488dffb485Schristos /* Check whether a timer in the timers queue is ready.  If a timer is
8498dffb485Schristos    ready, call its handler and return.  Update the timeout for the
8508dffb485Schristos    select() or poll() as well.  Return 1 if an event was handled,
8518dffb485Schristos    otherwise returns 0.*/
8528dffb485Schristos 
8538dffb485Schristos static int
8548dffb485Schristos poll_timers (void)
8558dffb485Schristos {
8568dffb485Schristos   if (update_wait_timeout ())
8578dffb485Schristos     {
8588dffb485Schristos       struct gdb_timer *timer_ptr = timer_list.first_timer;
8598dffb485Schristos       timer_handler_func *proc = timer_ptr->proc;
8608dffb485Schristos       gdb_client_data client_data = timer_ptr->client_data;
8618dffb485Schristos 
8628dffb485Schristos       /* Get rid of the timer from the beginning of the list.  */
8638dffb485Schristos       timer_list.first_timer = timer_ptr->next;
8648dffb485Schristos 
8658dffb485Schristos       /* Delete the timer before calling the callback, not after, in
8668dffb485Schristos 	 case the callback itself decides to try deleting the timer
8678dffb485Schristos 	 too.  */
8688dffb485Schristos       delete timer_ptr;
8698dffb485Schristos 
8708dffb485Schristos       /* Call the procedure associated with that timer.  */
8718dffb485Schristos       (proc) (client_data);
8728dffb485Schristos 
8738dffb485Schristos       return 1;
8748dffb485Schristos     }
8758dffb485Schristos 
8768dffb485Schristos   return 0;
8778dffb485Schristos }
878