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