xref: /netbsd-src/external/gpl3/gdb.old/dist/gdbsupport/event-loop.cc (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
17d62b00eSchristos /* Event loop machinery for GDB, the GNU debugger.
2*6881a400Schristos    Copyright (C) 1999-2023 Free Software Foundation, Inc.
37d62b00eSchristos    Written by Elena Zannoni <ezannoni@cygnus.com> of Cygnus Solutions.
47d62b00eSchristos 
57d62b00eSchristos    This file is part of GDB.
67d62b00eSchristos 
77d62b00eSchristos    This program is free software; you can redistribute it and/or modify
87d62b00eSchristos    it under the terms of the GNU General Public License as published by
97d62b00eSchristos    the Free Software Foundation; either version 3 of the License, or
107d62b00eSchristos    (at your option) any later version.
117d62b00eSchristos 
127d62b00eSchristos    This program is distributed in the hope that it will be useful,
137d62b00eSchristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
147d62b00eSchristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
157d62b00eSchristos    GNU General Public License for more details.
167d62b00eSchristos 
177d62b00eSchristos    You should have received a copy of the GNU General Public License
187d62b00eSchristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
197d62b00eSchristos 
207d62b00eSchristos #include "gdbsupport/common-defs.h"
217d62b00eSchristos #include "gdbsupport/event-loop.h"
227d62b00eSchristos 
237d62b00eSchristos #include <chrono>
247d62b00eSchristos 
257d62b00eSchristos #ifdef HAVE_POLL
267d62b00eSchristos #if defined (HAVE_POLL_H)
277d62b00eSchristos #include <poll.h>
287d62b00eSchristos #elif defined (HAVE_SYS_POLL_H)
297d62b00eSchristos #include <sys/poll.h>
307d62b00eSchristos #endif
317d62b00eSchristos #endif
327d62b00eSchristos 
337d62b00eSchristos #include <sys/types.h>
347d62b00eSchristos #include "gdbsupport/gdb_sys_time.h"
357d62b00eSchristos #include "gdbsupport/gdb_select.h"
36*6881a400Schristos #include "gdbsupport/gdb_optional.h"
37*6881a400Schristos #include "gdbsupport/scope-exit.h"
38*6881a400Schristos 
39*6881a400Schristos /* See event-loop.h.  */
40*6881a400Schristos 
41*6881a400Schristos debug_event_loop_kind debug_event_loop;
427d62b00eSchristos 
437d62b00eSchristos /* Tell create_file_handler what events we are interested in.
447d62b00eSchristos    This is used by the select version of the event loop.  */
457d62b00eSchristos 
467d62b00eSchristos #define GDB_READABLE	(1<<1)
477d62b00eSchristos #define GDB_WRITABLE	(1<<2)
487d62b00eSchristos #define GDB_EXCEPTION	(1<<3)
497d62b00eSchristos 
507d62b00eSchristos /* Information about each file descriptor we register with the event
517d62b00eSchristos    loop.  */
527d62b00eSchristos 
53*6881a400Schristos struct file_handler
547d62b00eSchristos {
55*6881a400Schristos   /* File descriptor.  */
56*6881a400Schristos   int fd;
577d62b00eSchristos 
58*6881a400Schristos   /* Events we want to monitor: POLLIN, etc.  */
59*6881a400Schristos   int mask;
60*6881a400Schristos 
61*6881a400Schristos   /* Events that have been seen since the last time.  */
62*6881a400Schristos   int ready_mask;
63*6881a400Schristos 
64*6881a400Schristos   /* Procedure to call when fd is ready.  */
65*6881a400Schristos   handler_func *proc;
66*6881a400Schristos 
67*6881a400Schristos   /* Argument to pass to proc.  */
68*6881a400Schristos   gdb_client_data client_data;
69*6881a400Schristos 
70*6881a400Schristos   /* User-friendly name of this handler.  */
71*6881a400Schristos   std::string name;
72*6881a400Schristos 
73*6881a400Schristos   /* If set, this file descriptor is used for a user interface.  */
74*6881a400Schristos   bool is_ui;
75*6881a400Schristos 
76*6881a400Schristos   /* Was an error detected on this fd?  */
77*6881a400Schristos   int error;
78*6881a400Schristos 
79*6881a400Schristos   /* Next registered file descriptor.  */
80*6881a400Schristos   struct file_handler *next_file;
81*6881a400Schristos };
82*6881a400Schristos 
837d62b00eSchristos #ifdef HAVE_POLL
84*6881a400Schristos /* Do we use poll or select?  Some systems have poll, but then it's
85*6881a400Schristos    not useable with all kinds of files.  We probe that whenever a new
86*6881a400Schristos    file handler is added.  */
87*6881a400Schristos static bool use_poll = true;
88*6881a400Schristos #endif
897d62b00eSchristos 
907d62b00eSchristos #ifdef USE_WIN32API
917d62b00eSchristos #include <windows.h>
927d62b00eSchristos #include <io.h>
937d62b00eSchristos #endif
947d62b00eSchristos 
957d62b00eSchristos /* Gdb_notifier is just a list of file descriptors gdb is interested in.
967d62b00eSchristos    These are the input file descriptor, and the target file
977d62b00eSchristos    descriptor.  We have two flavors of the notifier, one for platforms
987d62b00eSchristos    that have the POLL function, the other for those that don't, and
997d62b00eSchristos    only support SELECT.  Each of the elements in the gdb_notifier list is
1007d62b00eSchristos    basically a description of what kind of events gdb is interested
1017d62b00eSchristos    in, for each fd.  */
1027d62b00eSchristos 
1037d62b00eSchristos static struct
1047d62b00eSchristos   {
1057d62b00eSchristos     /* Ptr to head of file handler list.  */
1067d62b00eSchristos     file_handler *first_file_handler;
1077d62b00eSchristos 
1087d62b00eSchristos     /* Next file handler to handle, for the select variant.  To level
1097d62b00eSchristos        the fairness across event sources, we serve file handlers in a
1107d62b00eSchristos        round-robin-like fashion.  The number and order of the polled
1117d62b00eSchristos        file handlers may change between invocations, but this is good
1127d62b00eSchristos        enough.  */
1137d62b00eSchristos     file_handler *next_file_handler;
1147d62b00eSchristos 
1157d62b00eSchristos #ifdef HAVE_POLL
1167d62b00eSchristos     /* Ptr to array of pollfd structures.  */
1177d62b00eSchristos     struct pollfd *poll_fds;
1187d62b00eSchristos 
1197d62b00eSchristos     /* Next file descriptor to handle, for the poll variant.  To level
1207d62b00eSchristos        the fairness across event sources, we poll the file descriptors
1217d62b00eSchristos        in a round-robin-like fashion.  The number and order of the
1227d62b00eSchristos        polled file descriptors may change between invocations, but
1237d62b00eSchristos        this is good enough.  */
1247d62b00eSchristos     int next_poll_fds_index;
1257d62b00eSchristos 
1267d62b00eSchristos     /* Timeout in milliseconds for calls to poll().  */
1277d62b00eSchristos     int poll_timeout;
1287d62b00eSchristos #endif
1297d62b00eSchristos 
1307d62b00eSchristos     /* Masks to be used in the next call to select.
1317d62b00eSchristos        Bits are set in response to calls to create_file_handler.  */
1327d62b00eSchristos     fd_set check_masks[3];
1337d62b00eSchristos 
1347d62b00eSchristos     /* What file descriptors were found ready by select.  */
1357d62b00eSchristos     fd_set ready_masks[3];
1367d62b00eSchristos 
1377d62b00eSchristos     /* Number of file descriptors to monitor (for poll).  */
1387d62b00eSchristos     /* Number of valid bits (highest fd value + 1) (for select).  */
1397d62b00eSchristos     int num_fds;
1407d62b00eSchristos 
1417d62b00eSchristos     /* Time structure for calls to select().  */
1427d62b00eSchristos     struct timeval select_timeout;
1437d62b00eSchristos 
1447d62b00eSchristos     /* Flag to tell whether the timeout should be used.  */
1457d62b00eSchristos     int timeout_valid;
1467d62b00eSchristos   }
1477d62b00eSchristos gdb_notifier;
1487d62b00eSchristos 
1497d62b00eSchristos /* Structure associated with a timer.  PROC will be executed at the
1507d62b00eSchristos    first occasion after WHEN.  */
1517d62b00eSchristos struct gdb_timer
1527d62b00eSchristos   {
1537d62b00eSchristos     std::chrono::steady_clock::time_point when;
1547d62b00eSchristos     int timer_id;
1557d62b00eSchristos     struct gdb_timer *next;
1567d62b00eSchristos     timer_handler_func *proc;	    /* Function to call to do the work.  */
1577d62b00eSchristos     gdb_client_data client_data;    /* Argument to async_handler_func.  */
1587d62b00eSchristos   };
1597d62b00eSchristos 
1607d62b00eSchristos /* List of currently active timers.  It is sorted in order of
1617d62b00eSchristos    increasing timers.  */
1627d62b00eSchristos static struct
1637d62b00eSchristos   {
1647d62b00eSchristos     /* Pointer to first in timer list.  */
1657d62b00eSchristos     struct gdb_timer *first_timer;
1667d62b00eSchristos 
1677d62b00eSchristos     /* Id of the last timer created.  */
1687d62b00eSchristos     int num_timers;
1697d62b00eSchristos   }
1707d62b00eSchristos timer_list;
1717d62b00eSchristos 
1727d62b00eSchristos static void create_file_handler (int fd, int mask, handler_func *proc,
173*6881a400Schristos 				 gdb_client_data client_data,
174*6881a400Schristos 				 std::string &&name, bool is_ui);
1757d62b00eSchristos static int gdb_wait_for_event (int);
1767d62b00eSchristos static int update_wait_timeout (void);
1777d62b00eSchristos static int poll_timers (void);
1787d62b00eSchristos 
1797d62b00eSchristos /* Process one high level event.  If nothing is ready at this time,
180*6881a400Schristos    wait at most MSTIMEOUT milliseconds for something to happen (via
181*6881a400Schristos    gdb_wait_for_event), then process it.  Returns >0 if something was
182*6881a400Schristos    done, <0 if there are no event sources to wait for, =0 if timeout occurred.
183*6881a400Schristos    A timeout of 0 allows to serve an already pending event, but does not
184*6881a400Schristos    wait if none found.
185*6881a400Schristos    Setting the timeout to a negative value disables it.
186*6881a400Schristos    The timeout is never used by gdb itself, it is however needed to
187*6881a400Schristos    integrate gdb event handling within Insight's GUI event loop. */
1887d62b00eSchristos 
1897d62b00eSchristos int
190*6881a400Schristos gdb_do_one_event (int mstimeout)
1917d62b00eSchristos {
1927d62b00eSchristos   static int event_source_head = 0;
1937d62b00eSchristos   const int number_of_sources = 3;
1947d62b00eSchristos   int current = 0;
1957d62b00eSchristos 
1967d62b00eSchristos   /* First let's see if there are any asynchronous signal handlers
1977d62b00eSchristos      that are ready.  These would be the result of invoking any of the
1987d62b00eSchristos      signal handlers.  */
1997d62b00eSchristos   if (invoke_async_signal_handlers ())
2007d62b00eSchristos     return 1;
2017d62b00eSchristos 
2027d62b00eSchristos   /* To level the fairness across event sources, we poll them in a
2037d62b00eSchristos      round-robin fashion.  */
2047d62b00eSchristos   for (current = 0; current < number_of_sources; current++)
2057d62b00eSchristos     {
2067d62b00eSchristos       int res;
2077d62b00eSchristos 
2087d62b00eSchristos       switch (event_source_head)
2097d62b00eSchristos 	{
2107d62b00eSchristos 	case 0:
2117d62b00eSchristos 	  /* Are any timers that are ready?  */
2127d62b00eSchristos 	  res = poll_timers ();
2137d62b00eSchristos 	  break;
2147d62b00eSchristos 	case 1:
2157d62b00eSchristos 	  /* Are there events already waiting to be collected on the
2167d62b00eSchristos 	     monitored file descriptors?  */
2177d62b00eSchristos 	  res = gdb_wait_for_event (0);
2187d62b00eSchristos 	  break;
2197d62b00eSchristos 	case 2:
2207d62b00eSchristos 	  /* Are there any asynchronous event handlers ready?  */
2217d62b00eSchristos 	  res = check_async_event_handlers ();
2227d62b00eSchristos 	  break;
2237d62b00eSchristos 	default:
224*6881a400Schristos 	  internal_error ("unexpected event_source_head %d",
2257d62b00eSchristos 			  event_source_head);
2267d62b00eSchristos 	}
2277d62b00eSchristos 
2287d62b00eSchristos       event_source_head++;
2297d62b00eSchristos       if (event_source_head == number_of_sources)
2307d62b00eSchristos 	event_source_head = 0;
2317d62b00eSchristos 
2327d62b00eSchristos       if (res > 0)
2337d62b00eSchristos 	return 1;
2347d62b00eSchristos     }
2357d62b00eSchristos 
236*6881a400Schristos   if (mstimeout == 0)
237*6881a400Schristos     return 0;	/* 0ms timeout: do not wait for an event. */
238*6881a400Schristos 
2397d62b00eSchristos   /* Block waiting for a new event.  If gdb_wait_for_event returns -1,
2407d62b00eSchristos      we should get out because this means that there are no event
2417d62b00eSchristos      sources left.  This will make the event loop stop, and the
242*6881a400Schristos      application exit.
243*6881a400Schristos      If a timeout has been given, a new timer is set accordingly
244*6881a400Schristos      to abort event wait.  It is deleted upon gdb_wait_for_event
245*6881a400Schristos      termination and thus should never be triggered.
246*6881a400Schristos      When the timeout is reached, events are not monitored again:
247*6881a400Schristos      they already have been checked in the loop above. */
2487d62b00eSchristos 
249*6881a400Schristos   gdb::optional<int> timer_id;
2507d62b00eSchristos 
251*6881a400Schristos   SCOPE_EXIT
252*6881a400Schristos     {
253*6881a400Schristos       if (timer_id.has_value ())
254*6881a400Schristos 	delete_timer (*timer_id);
255*6881a400Schristos     };
256*6881a400Schristos 
257*6881a400Schristos   if (mstimeout > 0)
258*6881a400Schristos     timer_id = create_timer (mstimeout,
259*6881a400Schristos 			     [] (gdb_client_data arg)
260*6881a400Schristos 			     {
261*6881a400Schristos 			       ((gdb::optional<int> *) arg)->reset ();
262*6881a400Schristos 			     },
263*6881a400Schristos 			     &timer_id);
264*6881a400Schristos   return gdb_wait_for_event (1);
2657d62b00eSchristos }
2667d62b00eSchristos 
267*6881a400Schristos /* See event-loop.h  */
2687d62b00eSchristos 
2697d62b00eSchristos void
270*6881a400Schristos add_file_handler (int fd, handler_func *proc, gdb_client_data client_data,
271*6881a400Schristos 		  std::string &&name, bool is_ui)
2727d62b00eSchristos {
2737d62b00eSchristos #ifdef HAVE_POLL
2747d62b00eSchristos   if (use_poll)
2757d62b00eSchristos     {
276*6881a400Schristos       struct pollfd fds;
277*6881a400Schristos 
2787d62b00eSchristos       /* Check to see if poll () is usable.  If not, we'll switch to
2797d62b00eSchristos 	 use select.  This can happen on systems like
2807d62b00eSchristos 	 m68k-motorola-sys, `poll' cannot be used to wait for `stdin'.
2817d62b00eSchristos 	 On m68k-motorola-sysv, tty's are not stream-based and not
2827d62b00eSchristos 	 `poll'able.  */
2837d62b00eSchristos       fds.fd = fd;
2847d62b00eSchristos       fds.events = POLLIN;
2857d62b00eSchristos       if (poll (&fds, 1, 0) == 1 && (fds.revents & POLLNVAL))
286*6881a400Schristos 	use_poll = false;
2877d62b00eSchristos     }
2887d62b00eSchristos   if (use_poll)
2897d62b00eSchristos     {
290*6881a400Schristos       create_file_handler (fd, POLLIN, proc, client_data, std::move (name),
291*6881a400Schristos 			   is_ui);
2927d62b00eSchristos     }
2937d62b00eSchristos   else
294*6881a400Schristos #endif /* HAVE_POLL */
2957d62b00eSchristos     create_file_handler (fd, GDB_READABLE | GDB_EXCEPTION,
296*6881a400Schristos 			 proc, client_data, std::move (name), is_ui);
2977d62b00eSchristos }
2987d62b00eSchristos 
299*6881a400Schristos /* Helper for add_file_handler.
3007d62b00eSchristos 
3017d62b00eSchristos    For the poll case, MASK is a combination (OR) of POLLIN,
3027d62b00eSchristos    POLLRDNORM, POLLRDBAND, POLLPRI, POLLOUT, POLLWRNORM, POLLWRBAND:
3037d62b00eSchristos    these are the events we are interested in.  If any of them occurs,
3047d62b00eSchristos    proc should be called.
3057d62b00eSchristos 
3067d62b00eSchristos    For the select case, MASK is a combination of READABLE, WRITABLE,
3077d62b00eSchristos    EXCEPTION.  PROC is the procedure that will be called when an event
3087d62b00eSchristos    occurs for FD.  CLIENT_DATA is the argument to pass to PROC.  */
3097d62b00eSchristos 
3107d62b00eSchristos static void
3117d62b00eSchristos create_file_handler (int fd, int mask, handler_func * proc,
312*6881a400Schristos 		     gdb_client_data client_data, std::string &&name,
313*6881a400Schristos 		     bool is_ui)
3147d62b00eSchristos {
3157d62b00eSchristos   file_handler *file_ptr;
3167d62b00eSchristos 
3177d62b00eSchristos   /* Do we already have a file handler for this file?  (We may be
3187d62b00eSchristos      changing its associated procedure).  */
3197d62b00eSchristos   for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL;
3207d62b00eSchristos        file_ptr = file_ptr->next_file)
3217d62b00eSchristos     {
3227d62b00eSchristos       if (file_ptr->fd == fd)
3237d62b00eSchristos 	break;
3247d62b00eSchristos     }
3257d62b00eSchristos 
3267d62b00eSchristos   /* It is a new file descriptor.  Add it to the list.  Otherwise, just
3277d62b00eSchristos      change the data associated with it.  */
3287d62b00eSchristos   if (file_ptr == NULL)
3297d62b00eSchristos     {
330*6881a400Schristos       file_ptr = new file_handler;
3317d62b00eSchristos       file_ptr->fd = fd;
3327d62b00eSchristos       file_ptr->ready_mask = 0;
3337d62b00eSchristos       file_ptr->next_file = gdb_notifier.first_file_handler;
3347d62b00eSchristos       gdb_notifier.first_file_handler = file_ptr;
3357d62b00eSchristos 
336*6881a400Schristos #ifdef HAVE_POLL
3377d62b00eSchristos       if (use_poll)
3387d62b00eSchristos 	{
3397d62b00eSchristos 	  gdb_notifier.num_fds++;
3407d62b00eSchristos 	  if (gdb_notifier.poll_fds)
3417d62b00eSchristos 	    gdb_notifier.poll_fds =
3427d62b00eSchristos 	      (struct pollfd *) xrealloc (gdb_notifier.poll_fds,
3437d62b00eSchristos 					  (gdb_notifier.num_fds
3447d62b00eSchristos 					   * sizeof (struct pollfd)));
3457d62b00eSchristos 	  else
3467d62b00eSchristos 	    gdb_notifier.poll_fds =
3477d62b00eSchristos 	      XNEW (struct pollfd);
3487d62b00eSchristos 	  (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->fd = fd;
3497d62b00eSchristos 	  (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->events = mask;
3507d62b00eSchristos 	  (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->revents = 0;
3517d62b00eSchristos 	}
3527d62b00eSchristos       else
353*6881a400Schristos #endif /* HAVE_POLL */
3547d62b00eSchristos 	{
3557d62b00eSchristos 	  if (mask & GDB_READABLE)
3567d62b00eSchristos 	    FD_SET (fd, &gdb_notifier.check_masks[0]);
3577d62b00eSchristos 	  else
3587d62b00eSchristos 	    FD_CLR (fd, &gdb_notifier.check_masks[0]);
3597d62b00eSchristos 
3607d62b00eSchristos 	  if (mask & GDB_WRITABLE)
3617d62b00eSchristos 	    FD_SET (fd, &gdb_notifier.check_masks[1]);
3627d62b00eSchristos 	  else
3637d62b00eSchristos 	    FD_CLR (fd, &gdb_notifier.check_masks[1]);
3647d62b00eSchristos 
3657d62b00eSchristos 	  if (mask & GDB_EXCEPTION)
3667d62b00eSchristos 	    FD_SET (fd, &gdb_notifier.check_masks[2]);
3677d62b00eSchristos 	  else
3687d62b00eSchristos 	    FD_CLR (fd, &gdb_notifier.check_masks[2]);
3697d62b00eSchristos 
3707d62b00eSchristos 	  if (gdb_notifier.num_fds <= fd)
3717d62b00eSchristos 	    gdb_notifier.num_fds = fd + 1;
3727d62b00eSchristos 	}
3737d62b00eSchristos     }
3747d62b00eSchristos 
3757d62b00eSchristos   file_ptr->proc = proc;
3767d62b00eSchristos   file_ptr->client_data = client_data;
3777d62b00eSchristos   file_ptr->mask = mask;
378*6881a400Schristos   file_ptr->name = std::move (name);
379*6881a400Schristos   file_ptr->is_ui = is_ui;
3807d62b00eSchristos }
3817d62b00eSchristos 
3827d62b00eSchristos /* Return the next file handler to handle, and advance to the next
3837d62b00eSchristos    file handler, wrapping around if the end of the list is
3847d62b00eSchristos    reached.  */
3857d62b00eSchristos 
3867d62b00eSchristos static file_handler *
3877d62b00eSchristos get_next_file_handler_to_handle_and_advance (void)
3887d62b00eSchristos {
3897d62b00eSchristos   file_handler *curr_next;
3907d62b00eSchristos 
3917d62b00eSchristos   /* The first time around, this is still NULL.  */
3927d62b00eSchristos   if (gdb_notifier.next_file_handler == NULL)
3937d62b00eSchristos     gdb_notifier.next_file_handler = gdb_notifier.first_file_handler;
3947d62b00eSchristos 
3957d62b00eSchristos   curr_next = gdb_notifier.next_file_handler;
3967d62b00eSchristos   gdb_assert (curr_next != NULL);
3977d62b00eSchristos 
3987d62b00eSchristos   /* Advance.  */
3997d62b00eSchristos   gdb_notifier.next_file_handler = curr_next->next_file;
4007d62b00eSchristos   /* Wrap around, if necessary.  */
4017d62b00eSchristos   if (gdb_notifier.next_file_handler == NULL)
4027d62b00eSchristos     gdb_notifier.next_file_handler = gdb_notifier.first_file_handler;
4037d62b00eSchristos 
4047d62b00eSchristos   return curr_next;
4057d62b00eSchristos }
4067d62b00eSchristos 
4077d62b00eSchristos /* Remove the file descriptor FD from the list of monitored fd's:
4087d62b00eSchristos    i.e. we don't care anymore about events on the FD.  */
4097d62b00eSchristos void
4107d62b00eSchristos delete_file_handler (int fd)
4117d62b00eSchristos {
4127d62b00eSchristos   file_handler *file_ptr, *prev_ptr = NULL;
4137d62b00eSchristos   int i;
4147d62b00eSchristos 
4157d62b00eSchristos   /* Find the entry for the given file.  */
4167d62b00eSchristos 
4177d62b00eSchristos   for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL;
4187d62b00eSchristos        file_ptr = file_ptr->next_file)
4197d62b00eSchristos     {
4207d62b00eSchristos       if (file_ptr->fd == fd)
4217d62b00eSchristos 	break;
4227d62b00eSchristos     }
4237d62b00eSchristos 
4247d62b00eSchristos   if (file_ptr == NULL)
4257d62b00eSchristos     return;
4267d62b00eSchristos 
427*6881a400Schristos #ifdef HAVE_POLL
4287d62b00eSchristos   if (use_poll)
4297d62b00eSchristos     {
430*6881a400Schristos       int j;
431*6881a400Schristos       struct pollfd *new_poll_fds;
432*6881a400Schristos 
4337d62b00eSchristos       /* Create a new poll_fds array by copying every fd's information
4347d62b00eSchristos 	 but the one we want to get rid of.  */
4357d62b00eSchristos 
4367d62b00eSchristos       new_poll_fds = (struct pollfd *)
4377d62b00eSchristos 	xmalloc ((gdb_notifier.num_fds - 1) * sizeof (struct pollfd));
4387d62b00eSchristos 
4397d62b00eSchristos       for (i = 0, j = 0; i < gdb_notifier.num_fds; i++)
4407d62b00eSchristos 	{
4417d62b00eSchristos 	  if ((gdb_notifier.poll_fds + i)->fd != fd)
4427d62b00eSchristos 	    {
4437d62b00eSchristos 	      (new_poll_fds + j)->fd = (gdb_notifier.poll_fds + i)->fd;
4447d62b00eSchristos 	      (new_poll_fds + j)->events = (gdb_notifier.poll_fds + i)->events;
4457d62b00eSchristos 	      (new_poll_fds + j)->revents
4467d62b00eSchristos 		= (gdb_notifier.poll_fds + i)->revents;
4477d62b00eSchristos 	      j++;
4487d62b00eSchristos 	    }
4497d62b00eSchristos 	}
4507d62b00eSchristos       xfree (gdb_notifier.poll_fds);
4517d62b00eSchristos       gdb_notifier.poll_fds = new_poll_fds;
4527d62b00eSchristos       gdb_notifier.num_fds--;
4537d62b00eSchristos     }
4547d62b00eSchristos   else
455*6881a400Schristos #endif /* HAVE_POLL */
4567d62b00eSchristos     {
4577d62b00eSchristos       if (file_ptr->mask & GDB_READABLE)
4587d62b00eSchristos 	FD_CLR (fd, &gdb_notifier.check_masks[0]);
4597d62b00eSchristos       if (file_ptr->mask & GDB_WRITABLE)
4607d62b00eSchristos 	FD_CLR (fd, &gdb_notifier.check_masks[1]);
4617d62b00eSchristos       if (file_ptr->mask & GDB_EXCEPTION)
4627d62b00eSchristos 	FD_CLR (fd, &gdb_notifier.check_masks[2]);
4637d62b00eSchristos 
4647d62b00eSchristos       /* Find current max fd.  */
4657d62b00eSchristos 
4667d62b00eSchristos       if ((fd + 1) == gdb_notifier.num_fds)
4677d62b00eSchristos 	{
4687d62b00eSchristos 	  gdb_notifier.num_fds--;
4697d62b00eSchristos 	  for (i = gdb_notifier.num_fds; i; i--)
4707d62b00eSchristos 	    {
4717d62b00eSchristos 	      if (FD_ISSET (i - 1, &gdb_notifier.check_masks[0])
4727d62b00eSchristos 		  || FD_ISSET (i - 1, &gdb_notifier.check_masks[1])
4737d62b00eSchristos 		  || FD_ISSET (i - 1, &gdb_notifier.check_masks[2]))
4747d62b00eSchristos 		break;
4757d62b00eSchristos 	    }
4767d62b00eSchristos 	  gdb_notifier.num_fds = i;
4777d62b00eSchristos 	}
4787d62b00eSchristos     }
4797d62b00eSchristos 
4807d62b00eSchristos   /* Deactivate the file descriptor, by clearing its mask,
4817d62b00eSchristos      so that it will not fire again.  */
4827d62b00eSchristos 
4837d62b00eSchristos   file_ptr->mask = 0;
4847d62b00eSchristos 
4857d62b00eSchristos   /* If this file handler was going to be the next one to be handled,
4867d62b00eSchristos      advance to the next's next, if any.  */
4877d62b00eSchristos   if (gdb_notifier.next_file_handler == file_ptr)
4887d62b00eSchristos     {
4897d62b00eSchristos       if (file_ptr->next_file == NULL
4907d62b00eSchristos 	  && file_ptr == gdb_notifier.first_file_handler)
4917d62b00eSchristos 	gdb_notifier.next_file_handler = NULL;
4927d62b00eSchristos       else
4937d62b00eSchristos 	get_next_file_handler_to_handle_and_advance ();
4947d62b00eSchristos     }
4957d62b00eSchristos 
4967d62b00eSchristos   /* Get rid of the file handler in the file handler list.  */
4977d62b00eSchristos   if (file_ptr == gdb_notifier.first_file_handler)
4987d62b00eSchristos     gdb_notifier.first_file_handler = file_ptr->next_file;
4997d62b00eSchristos   else
5007d62b00eSchristos     {
5017d62b00eSchristos       for (prev_ptr = gdb_notifier.first_file_handler;
5027d62b00eSchristos 	   prev_ptr->next_file != file_ptr;
5037d62b00eSchristos 	   prev_ptr = prev_ptr->next_file)
5047d62b00eSchristos 	;
5057d62b00eSchristos       prev_ptr->next_file = file_ptr->next_file;
5067d62b00eSchristos     }
507*6881a400Schristos 
508*6881a400Schristos   delete file_ptr;
5097d62b00eSchristos }
5107d62b00eSchristos 
5117d62b00eSchristos /* Handle the given event by calling the procedure associated to the
5127d62b00eSchristos    corresponding file handler.  */
5137d62b00eSchristos 
5147d62b00eSchristos static void
5157d62b00eSchristos handle_file_event (file_handler *file_ptr, int ready_mask)
5167d62b00eSchristos {
5177d62b00eSchristos   int mask;
518*6881a400Schristos 
519*6881a400Schristos   /* See if the desired events (mask) match the received events
520*6881a400Schristos      (ready_mask).  */
521*6881a400Schristos 
5227d62b00eSchristos #ifdef HAVE_POLL
5237d62b00eSchristos   if (use_poll)
5247d62b00eSchristos     {
525*6881a400Schristos       int error_mask;
526*6881a400Schristos 
527*6881a400Schristos       /* With poll, the ready_mask could have any of three events set
528*6881a400Schristos 	 to 1: POLLHUP, POLLERR, POLLNVAL.  These events cannot be
529*6881a400Schristos 	 used in the requested event mask (events), but they can be
530*6881a400Schristos 	 returned in the return mask (revents).  We need to check for
531*6881a400Schristos 	 those event too, and add them to the mask which will be
532*6881a400Schristos 	 passed to the handler.  */
533*6881a400Schristos 
5347d62b00eSchristos       /* POLLHUP means EOF, but can be combined with POLLIN to
5357d62b00eSchristos 	 signal more data to read.  */
5367d62b00eSchristos       error_mask = POLLHUP | POLLERR | POLLNVAL;
5377d62b00eSchristos       mask = ready_mask & (file_ptr->mask | error_mask);
5387d62b00eSchristos 
5397d62b00eSchristos       if ((mask & (POLLERR | POLLNVAL)) != 0)
5407d62b00eSchristos 	{
5417d62b00eSchristos 	  /* Work in progress.  We may need to tell somebody
5427d62b00eSchristos 	     what kind of error we had.  */
5437d62b00eSchristos 	  if (mask & POLLERR)
5447d62b00eSchristos 	    warning (_("Error detected on fd %d"), file_ptr->fd);
5457d62b00eSchristos 	  if (mask & POLLNVAL)
5467d62b00eSchristos 	    warning (_("Invalid or non-`poll'able fd %d"),
5477d62b00eSchristos 		     file_ptr->fd);
5487d62b00eSchristos 	  file_ptr->error = 1;
5497d62b00eSchristos 	}
5507d62b00eSchristos       else
5517d62b00eSchristos 	file_ptr->error = 0;
5527d62b00eSchristos     }
5537d62b00eSchristos   else
554*6881a400Schristos #endif /* HAVE_POLL */
5557d62b00eSchristos     {
5567d62b00eSchristos       if (ready_mask & GDB_EXCEPTION)
5577d62b00eSchristos 	{
5587d62b00eSchristos 	  warning (_("Exception condition detected on fd %d"),
5597d62b00eSchristos 		   file_ptr->fd);
5607d62b00eSchristos 	  file_ptr->error = 1;
5617d62b00eSchristos 	}
5627d62b00eSchristos       else
5637d62b00eSchristos 	file_ptr->error = 0;
5647d62b00eSchristos       mask = ready_mask & file_ptr->mask;
5657d62b00eSchristos     }
5667d62b00eSchristos 
5677d62b00eSchristos   /* If there was a match, then call the handler.  */
5687d62b00eSchristos   if (mask != 0)
569*6881a400Schristos     {
570*6881a400Schristos       event_loop_ui_debug_printf (file_ptr->is_ui,
571*6881a400Schristos 				  "invoking fd file handler `%s`",
572*6881a400Schristos 				  file_ptr->name.c_str ());
573*6881a400Schristos       file_ptr->proc (file_ptr->error, file_ptr->client_data);
5747d62b00eSchristos     }
5757d62b00eSchristos }
5767d62b00eSchristos 
5777d62b00eSchristos /* Wait for new events on the monitored file descriptors.  Run the
5787d62b00eSchristos    event handler if the first descriptor that is detected by the poll.
5797d62b00eSchristos    If BLOCK and if there are no events, this function will block in
5807d62b00eSchristos    the call to poll.  Return 1 if an event was handled.  Return -1 if
5817d62b00eSchristos    there are no file descriptors to monitor.  Return 1 if an event was
5827d62b00eSchristos    handled, otherwise returns 0.  */
5837d62b00eSchristos 
5847d62b00eSchristos static int
5857d62b00eSchristos gdb_wait_for_event (int block)
5867d62b00eSchristos {
5877d62b00eSchristos   file_handler *file_ptr;
5887d62b00eSchristos   int num_found = 0;
5897d62b00eSchristos 
5907d62b00eSchristos   /* Make sure all output is done before getting another event.  */
5917d62b00eSchristos   flush_streams ();
5927d62b00eSchristos 
5937d62b00eSchristos   if (gdb_notifier.num_fds == 0)
5947d62b00eSchristos     return -1;
5957d62b00eSchristos 
5967d62b00eSchristos   if (block)
5977d62b00eSchristos     update_wait_timeout ();
5987d62b00eSchristos 
599*6881a400Schristos #ifdef HAVE_POLL
6007d62b00eSchristos   if (use_poll)
6017d62b00eSchristos     {
6027d62b00eSchristos       int timeout;
6037d62b00eSchristos 
6047d62b00eSchristos       if (block)
6057d62b00eSchristos 	timeout = gdb_notifier.timeout_valid ? gdb_notifier.poll_timeout : -1;
6067d62b00eSchristos       else
6077d62b00eSchristos 	timeout = 0;
6087d62b00eSchristos 
6097d62b00eSchristos       num_found = poll (gdb_notifier.poll_fds,
6107d62b00eSchristos 			(unsigned long) gdb_notifier.num_fds, timeout);
6117d62b00eSchristos 
6127d62b00eSchristos       /* Don't print anything if we get out of poll because of a
6137d62b00eSchristos 	 signal.  */
6147d62b00eSchristos       if (num_found == -1 && errno != EINTR)
6157d62b00eSchristos 	perror_with_name (("poll"));
6167d62b00eSchristos     }
6177d62b00eSchristos   else
618*6881a400Schristos #endif /* HAVE_POLL */
6197d62b00eSchristos     {
6207d62b00eSchristos       struct timeval select_timeout;
6217d62b00eSchristos       struct timeval *timeout_p;
6227d62b00eSchristos 
6237d62b00eSchristos       if (block)
6247d62b00eSchristos 	timeout_p = gdb_notifier.timeout_valid
6257d62b00eSchristos 	  ? &gdb_notifier.select_timeout : NULL;
6267d62b00eSchristos       else
6277d62b00eSchristos 	{
6287d62b00eSchristos 	  memset (&select_timeout, 0, sizeof (select_timeout));
6297d62b00eSchristos 	  timeout_p = &select_timeout;
6307d62b00eSchristos 	}
6317d62b00eSchristos 
6327d62b00eSchristos       gdb_notifier.ready_masks[0] = gdb_notifier.check_masks[0];
6337d62b00eSchristos       gdb_notifier.ready_masks[1] = gdb_notifier.check_masks[1];
6347d62b00eSchristos       gdb_notifier.ready_masks[2] = gdb_notifier.check_masks[2];
6357d62b00eSchristos       num_found = gdb_select (gdb_notifier.num_fds,
6367d62b00eSchristos 			      &gdb_notifier.ready_masks[0],
6377d62b00eSchristos 			      &gdb_notifier.ready_masks[1],
6387d62b00eSchristos 			      &gdb_notifier.ready_masks[2],
6397d62b00eSchristos 			      timeout_p);
6407d62b00eSchristos 
6417d62b00eSchristos       /* Clear the masks after an error from select.  */
6427d62b00eSchristos       if (num_found == -1)
6437d62b00eSchristos 	{
6447d62b00eSchristos 	  FD_ZERO (&gdb_notifier.ready_masks[0]);
6457d62b00eSchristos 	  FD_ZERO (&gdb_notifier.ready_masks[1]);
6467d62b00eSchristos 	  FD_ZERO (&gdb_notifier.ready_masks[2]);
6477d62b00eSchristos 
6487d62b00eSchristos 	  /* Dont print anything if we got a signal, let gdb handle
6497d62b00eSchristos 	     it.  */
6507d62b00eSchristos 	  if (errno != EINTR)
6517d62b00eSchristos 	    perror_with_name (("select"));
6527d62b00eSchristos 	}
6537d62b00eSchristos     }
6547d62b00eSchristos 
6557d62b00eSchristos   /* Avoid looking at poll_fds[i]->revents if no event fired.  */
6567d62b00eSchristos   if (num_found <= 0)
6577d62b00eSchristos     return 0;
6587d62b00eSchristos 
6597d62b00eSchristos   /* Run event handlers.  We always run just one handler and go back
6607d62b00eSchristos      to polling, in case a handler changes the notifier list.  Since
6617d62b00eSchristos      events for sources we haven't consumed yet wake poll/select
6627d62b00eSchristos      immediately, no event is lost.  */
6637d62b00eSchristos 
6647d62b00eSchristos   /* To level the fairness across event descriptors, we handle them in
6657d62b00eSchristos      a round-robin-like fashion.  The number and order of descriptors
6667d62b00eSchristos      may change between invocations, but this is good enough.  */
667*6881a400Schristos #ifdef HAVE_POLL
6687d62b00eSchristos   if (use_poll)
6697d62b00eSchristos     {
6707d62b00eSchristos       int i;
6717d62b00eSchristos       int mask;
6727d62b00eSchristos 
6737d62b00eSchristos       while (1)
6747d62b00eSchristos 	{
6757d62b00eSchristos 	  if (gdb_notifier.next_poll_fds_index >= gdb_notifier.num_fds)
6767d62b00eSchristos 	    gdb_notifier.next_poll_fds_index = 0;
6777d62b00eSchristos 	  i = gdb_notifier.next_poll_fds_index++;
6787d62b00eSchristos 
6797d62b00eSchristos 	  gdb_assert (i < gdb_notifier.num_fds);
6807d62b00eSchristos 	  if ((gdb_notifier.poll_fds + i)->revents)
6817d62b00eSchristos 	    break;
6827d62b00eSchristos 	}
6837d62b00eSchristos 
6847d62b00eSchristos       for (file_ptr = gdb_notifier.first_file_handler;
6857d62b00eSchristos 	   file_ptr != NULL;
6867d62b00eSchristos 	   file_ptr = file_ptr->next_file)
6877d62b00eSchristos 	{
6887d62b00eSchristos 	  if (file_ptr->fd == (gdb_notifier.poll_fds + i)->fd)
6897d62b00eSchristos 	    break;
6907d62b00eSchristos 	}
6917d62b00eSchristos       gdb_assert (file_ptr != NULL);
6927d62b00eSchristos 
6937d62b00eSchristos       mask = (gdb_notifier.poll_fds + i)->revents;
6947d62b00eSchristos       handle_file_event (file_ptr, mask);
6957d62b00eSchristos       return 1;
6967d62b00eSchristos     }
6977d62b00eSchristos   else
698*6881a400Schristos #endif /* HAVE_POLL */
6997d62b00eSchristos     {
7007d62b00eSchristos       /* See comment about even source fairness above.  */
7017d62b00eSchristos       int mask = 0;
7027d62b00eSchristos 
7037d62b00eSchristos       do
7047d62b00eSchristos 	{
7057d62b00eSchristos 	  file_ptr = get_next_file_handler_to_handle_and_advance ();
7067d62b00eSchristos 
7077d62b00eSchristos 	  if (FD_ISSET (file_ptr->fd, &gdb_notifier.ready_masks[0]))
7087d62b00eSchristos 	    mask |= GDB_READABLE;
7097d62b00eSchristos 	  if (FD_ISSET (file_ptr->fd, &gdb_notifier.ready_masks[1]))
7107d62b00eSchristos 	    mask |= GDB_WRITABLE;
7117d62b00eSchristos 	  if (FD_ISSET (file_ptr->fd, &gdb_notifier.ready_masks[2]))
7127d62b00eSchristos 	    mask |= GDB_EXCEPTION;
7137d62b00eSchristos 	}
7147d62b00eSchristos       while (mask == 0);
7157d62b00eSchristos 
7167d62b00eSchristos       handle_file_event (file_ptr, mask);
7177d62b00eSchristos       return 1;
7187d62b00eSchristos     }
7197d62b00eSchristos   return 0;
7207d62b00eSchristos }
7217d62b00eSchristos 
7227d62b00eSchristos /* Create a timer that will expire in MS milliseconds from now.  When
7237d62b00eSchristos    the timer is ready, PROC will be executed.  At creation, the timer
7247d62b00eSchristos    is added to the timers queue.  This queue is kept sorted in order
7257d62b00eSchristos    of increasing timers.  Return a handle to the timer struct.  */
7267d62b00eSchristos 
7277d62b00eSchristos int
7287d62b00eSchristos create_timer (int ms, timer_handler_func *proc,
7297d62b00eSchristos 	      gdb_client_data client_data)
7307d62b00eSchristos {
7317d62b00eSchristos   using namespace std::chrono;
7327d62b00eSchristos   struct gdb_timer *timer_ptr, *timer_index, *prev_timer;
7337d62b00eSchristos 
7347d62b00eSchristos   steady_clock::time_point time_now = steady_clock::now ();
7357d62b00eSchristos 
7367d62b00eSchristos   timer_ptr = new gdb_timer ();
7377d62b00eSchristos   timer_ptr->when = time_now + milliseconds (ms);
7387d62b00eSchristos   timer_ptr->proc = proc;
7397d62b00eSchristos   timer_ptr->client_data = client_data;
7407d62b00eSchristos   timer_list.num_timers++;
7417d62b00eSchristos   timer_ptr->timer_id = timer_list.num_timers;
7427d62b00eSchristos 
7437d62b00eSchristos   /* Now add the timer to the timer queue, making sure it is sorted in
7447d62b00eSchristos      increasing order of expiration.  */
7457d62b00eSchristos 
7467d62b00eSchristos   for (timer_index = timer_list.first_timer;
7477d62b00eSchristos        timer_index != NULL;
7487d62b00eSchristos        timer_index = timer_index->next)
7497d62b00eSchristos     {
7507d62b00eSchristos       if (timer_index->when > timer_ptr->when)
7517d62b00eSchristos 	break;
7527d62b00eSchristos     }
7537d62b00eSchristos 
7547d62b00eSchristos   if (timer_index == timer_list.first_timer)
7557d62b00eSchristos     {
7567d62b00eSchristos       timer_ptr->next = timer_list.first_timer;
7577d62b00eSchristos       timer_list.first_timer = timer_ptr;
7587d62b00eSchristos 
7597d62b00eSchristos     }
7607d62b00eSchristos   else
7617d62b00eSchristos     {
7627d62b00eSchristos       for (prev_timer = timer_list.first_timer;
7637d62b00eSchristos 	   prev_timer->next != timer_index;
7647d62b00eSchristos 	   prev_timer = prev_timer->next)
7657d62b00eSchristos 	;
7667d62b00eSchristos 
7677d62b00eSchristos       prev_timer->next = timer_ptr;
7687d62b00eSchristos       timer_ptr->next = timer_index;
7697d62b00eSchristos     }
7707d62b00eSchristos 
7717d62b00eSchristos   gdb_notifier.timeout_valid = 0;
7727d62b00eSchristos   return timer_ptr->timer_id;
7737d62b00eSchristos }
7747d62b00eSchristos 
7757d62b00eSchristos /* There is a chance that the creator of the timer wants to get rid of
7767d62b00eSchristos    it before it expires.  */
7777d62b00eSchristos void
7787d62b00eSchristos delete_timer (int id)
7797d62b00eSchristos {
7807d62b00eSchristos   struct gdb_timer *timer_ptr, *prev_timer = NULL;
7817d62b00eSchristos 
7827d62b00eSchristos   /* Find the entry for the given timer.  */
7837d62b00eSchristos 
7847d62b00eSchristos   for (timer_ptr = timer_list.first_timer; timer_ptr != NULL;
7857d62b00eSchristos        timer_ptr = timer_ptr->next)
7867d62b00eSchristos     {
7877d62b00eSchristos       if (timer_ptr->timer_id == id)
7887d62b00eSchristos 	break;
7897d62b00eSchristos     }
7907d62b00eSchristos 
7917d62b00eSchristos   if (timer_ptr == NULL)
7927d62b00eSchristos     return;
7937d62b00eSchristos   /* Get rid of the timer in the timer list.  */
7947d62b00eSchristos   if (timer_ptr == timer_list.first_timer)
7957d62b00eSchristos     timer_list.first_timer = timer_ptr->next;
7967d62b00eSchristos   else
7977d62b00eSchristos     {
7987d62b00eSchristos       for (prev_timer = timer_list.first_timer;
7997d62b00eSchristos 	   prev_timer->next != timer_ptr;
8007d62b00eSchristos 	   prev_timer = prev_timer->next)
8017d62b00eSchristos 	;
8027d62b00eSchristos       prev_timer->next = timer_ptr->next;
8037d62b00eSchristos     }
8047d62b00eSchristos   delete timer_ptr;
8057d62b00eSchristos 
8067d62b00eSchristos   gdb_notifier.timeout_valid = 0;
8077d62b00eSchristos }
8087d62b00eSchristos 
8097d62b00eSchristos /* Convert a std::chrono duration to a struct timeval.  */
8107d62b00eSchristos 
8117d62b00eSchristos template<typename Duration>
8127d62b00eSchristos static struct timeval
8137d62b00eSchristos duration_cast_timeval (const Duration &d)
8147d62b00eSchristos {
8157d62b00eSchristos   using namespace std::chrono;
8167d62b00eSchristos   seconds sec = duration_cast<seconds> (d);
8177d62b00eSchristos   microseconds msec = duration_cast<microseconds> (d - sec);
8187d62b00eSchristos 
8197d62b00eSchristos   struct timeval tv;
8207d62b00eSchristos   tv.tv_sec = sec.count ();
8217d62b00eSchristos   tv.tv_usec = msec.count ();
8227d62b00eSchristos   return tv;
8237d62b00eSchristos }
8247d62b00eSchristos 
8257d62b00eSchristos /* Update the timeout for the select() or poll().  Returns true if the
8267d62b00eSchristos    timer has already expired, false otherwise.  */
8277d62b00eSchristos 
8287d62b00eSchristos static int
8297d62b00eSchristos update_wait_timeout (void)
8307d62b00eSchristos {
8317d62b00eSchristos   if (timer_list.first_timer != NULL)
8327d62b00eSchristos     {
8337d62b00eSchristos       using namespace std::chrono;
8347d62b00eSchristos       steady_clock::time_point time_now = steady_clock::now ();
8357d62b00eSchristos       struct timeval timeout;
8367d62b00eSchristos 
8377d62b00eSchristos       if (timer_list.first_timer->when < time_now)
8387d62b00eSchristos 	{
8397d62b00eSchristos 	  /* It expired already.  */
8407d62b00eSchristos 	  timeout.tv_sec = 0;
8417d62b00eSchristos 	  timeout.tv_usec = 0;
8427d62b00eSchristos 	}
8437d62b00eSchristos       else
8447d62b00eSchristos 	{
8457d62b00eSchristos 	  steady_clock::duration d = timer_list.first_timer->when - time_now;
8467d62b00eSchristos 	  timeout = duration_cast_timeval (d);
8477d62b00eSchristos 	}
8487d62b00eSchristos 
8497d62b00eSchristos       /* Update the timeout for select/ poll.  */
8507d62b00eSchristos #ifdef HAVE_POLL
851*6881a400Schristos       if (use_poll)
8527d62b00eSchristos 	gdb_notifier.poll_timeout = timeout.tv_sec * 1000;
8537d62b00eSchristos       else
854*6881a400Schristos #endif /* HAVE_POLL */
8557d62b00eSchristos 	{
8567d62b00eSchristos 	  gdb_notifier.select_timeout.tv_sec = timeout.tv_sec;
8577d62b00eSchristos 	  gdb_notifier.select_timeout.tv_usec = timeout.tv_usec;
8587d62b00eSchristos 	}
8597d62b00eSchristos       gdb_notifier.timeout_valid = 1;
8607d62b00eSchristos 
8617d62b00eSchristos       if (timer_list.first_timer->when < time_now)
8627d62b00eSchristos 	return 1;
8637d62b00eSchristos     }
8647d62b00eSchristos   else
8657d62b00eSchristos     gdb_notifier.timeout_valid = 0;
8667d62b00eSchristos 
8677d62b00eSchristos   return 0;
8687d62b00eSchristos }
8697d62b00eSchristos 
8707d62b00eSchristos /* Check whether a timer in the timers queue is ready.  If a timer is
8717d62b00eSchristos    ready, call its handler and return.  Update the timeout for the
8727d62b00eSchristos    select() or poll() as well.  Return 1 if an event was handled,
8737d62b00eSchristos    otherwise returns 0.*/
8747d62b00eSchristos 
8757d62b00eSchristos static int
8767d62b00eSchristos poll_timers (void)
8777d62b00eSchristos {
8787d62b00eSchristos   if (update_wait_timeout ())
8797d62b00eSchristos     {
8807d62b00eSchristos       struct gdb_timer *timer_ptr = timer_list.first_timer;
8817d62b00eSchristos       timer_handler_func *proc = timer_ptr->proc;
8827d62b00eSchristos       gdb_client_data client_data = timer_ptr->client_data;
8837d62b00eSchristos 
8847d62b00eSchristos       /* Get rid of the timer from the beginning of the list.  */
8857d62b00eSchristos       timer_list.first_timer = timer_ptr->next;
8867d62b00eSchristos 
8877d62b00eSchristos       /* Delete the timer before calling the callback, not after, in
8887d62b00eSchristos 	 case the callback itself decides to try deleting the timer
8897d62b00eSchristos 	 too.  */
8907d62b00eSchristos       delete timer_ptr;
8917d62b00eSchristos 
8927d62b00eSchristos       /* Call the procedure associated with that timer.  */
8937d62b00eSchristos       (proc) (client_data);
8947d62b00eSchristos 
8957d62b00eSchristos       return 1;
8967d62b00eSchristos     }
8977d62b00eSchristos 
8987d62b00eSchristos   return 0;
8997d62b00eSchristos }
900