Commit | Line | Data |
---|---|---|
b5a0ac70 | 1 | /* Event loop machinery for GDB, the GNU debugger. |
b811d2c2 | 2 | Copyright (C) 1999-2020 Free Software Foundation, Inc. |
b5a0ac70 SS |
3 | Written by Elena Zannoni <ezannoni@cygnus.com> of Cygnus Solutions. |
4 | ||
5 | This file is part of GDB. | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
a9762ec7 | 9 | the Free Software Foundation; either version 3 of the License, or |
b5a0ac70 SS |
10 | (at your option) any later version. |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
371d5dec | 18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
b5a0ac70 | 19 | |
400b5eca TT |
20 | #include "gdbsupport/common-defs.h" |
21 | #include "gdbsupport/event-loop.h" | |
409a3f64 | 22 | |
98029d02 TT |
23 | #include <chrono> |
24 | ||
b5a0ac70 | 25 | #ifdef HAVE_POLL |
409a3f64 | 26 | #if defined (HAVE_POLL_H) |
9e0b60a8 | 27 | #include <poll.h> |
409a3f64 AC |
28 | #elif defined (HAVE_SYS_POLL_H) |
29 | #include <sys/poll.h> | |
30 | #endif | |
44f45770 | 31 | #endif |
409a3f64 | 32 | |
9e0b60a8 | 33 | #include <sys/types.h> |
268a13a5 | 34 | #include "gdbsupport/gdb_sys_time.h" |
06cc9596 | 35 | #include "gdbsupport/gdb_select.h" |
c2c6d25f | 36 | |
6b01403b SM |
37 | /* See event-loop.h. */ |
38 | ||
39 | debug_event_loop_kind debug_event_loop; | |
40 | ||
371d5dec MS |
41 | /* Tell create_file_handler what events we are interested in. |
42 | This is used by the select version of the event loop. */ | |
01f69b38 DE |
43 | |
44 | #define GDB_READABLE (1<<1) | |
45 | #define GDB_WRITABLE (1<<2) | |
46 | #define GDB_EXCEPTION (1<<3) | |
47 | ||
c2c6d25f | 48 | /* Information about each file descriptor we register with the event |
371d5dec | 49 | loop. */ |
c2c6d25f | 50 | |
29363cfa SM |
51 | struct file_handler |
52 | { | |
53 | /* File descriptor. */ | |
54 | int fd; | |
55 | ||
56 | /* Events we want to monitor: POLLIN, etc. */ | |
57 | int mask; | |
58 | ||
59 | /* Events that have been seen since the last time. */ | |
60 | int ready_mask; | |
61 | ||
62 | /* Procedure to call when fd is ready. */ | |
63 | handler_func *proc; | |
64 | ||
65 | /* Argument to pass to proc. */ | |
66 | gdb_client_data client_data; | |
67 | ||
2554f6f5 SM |
68 | /* User-friendly name of this handler. Heap-allocated, owned by this.*/ |
69 | std::string *name; | |
70 | ||
6b01403b SM |
71 | /* If set, this file descriptor is used for a user interface. */ |
72 | bool is_ui; | |
73 | ||
29363cfa SM |
74 | /* Was an error detected on this fd? */ |
75 | int error; | |
76 | ||
77 | /* Next registered file descriptor. */ | |
78 | struct file_handler *next_file; | |
79 | }; | |
c2c6d25f | 80 | |
44f45770 | 81 | /* Do we use poll or select ? */ |
b5a0ac70 | 82 | #ifdef HAVE_POLL |
44f45770 EZ |
83 | #define USE_POLL 1 |
84 | #else | |
85 | #define USE_POLL 0 | |
86 | #endif /* HAVE_POLL */ | |
87 | ||
88 | static unsigned char use_poll = USE_POLL; | |
b5a0ac70 | 89 | |
011825f0 MM |
90 | #ifdef USE_WIN32API |
91 | #include <windows.h> | |
92 | #include <io.h> | |
93 | #endif | |
94 | ||
7990abcc TT |
95 | /* Gdb_notifier is just a list of file descriptors gdb is interested in. |
96 | These are the input file descriptor, and the target file | |
97 | descriptor. We have two flavors of the notifier, one for platforms | |
98 | that have the POLL function, the other for those that don't, and | |
99 | only support SELECT. Each of the elements in the gdb_notifier list is | |
100 | basically a description of what kind of events gdb is interested | |
101 | in, for each fd. */ | |
102 | ||
b5a0ac70 SS |
103 | static struct |
104 | { | |
371d5dec | 105 | /* Ptr to head of file handler list. */ |
b5a0ac70 SS |
106 | file_handler *first_file_handler; |
107 | ||
4e63d0ac PA |
108 | /* Next file handler to handle, for the select variant. To level |
109 | the fairness across event sources, we serve file handlers in a | |
110 | round-robin-like fashion. The number and order of the polled | |
111 | file handlers may change between invocations, but this is good | |
112 | enough. */ | |
113 | file_handler *next_file_handler; | |
114 | ||
44f45770 | 115 | #ifdef HAVE_POLL |
371d5dec | 116 | /* Ptr to array of pollfd structures. */ |
b5a0ac70 SS |
117 | struct pollfd *poll_fds; |
118 | ||
4e63d0ac PA |
119 | /* Next file descriptor to handle, for the poll variant. To level |
120 | the fairness across event sources, we poll the file descriptors | |
121 | in a round-robin-like fashion. The number and order of the | |
122 | polled file descriptors may change between invocations, but | |
123 | this is good enough. */ | |
124 | int next_poll_fds_index; | |
125 | ||
371d5dec | 126 | /* Timeout in milliseconds for calls to poll(). */ |
44f45770 EZ |
127 | int poll_timeout; |
128 | #endif | |
b5a0ac70 SS |
129 | |
130 | /* Masks to be used in the next call to select. | |
371d5dec | 131 | Bits are set in response to calls to create_file_handler. */ |
58a2c44a | 132 | fd_set check_masks[3]; |
b5a0ac70 | 133 | |
371d5dec | 134 | /* What file descriptors were found ready by select. */ |
58a2c44a | 135 | fd_set ready_masks[3]; |
b5a0ac70 | 136 | |
371d5dec MS |
137 | /* Number of file descriptors to monitor (for poll). */ |
138 | /* Number of valid bits (highest fd value + 1) (for select). */ | |
b5a0ac70 SS |
139 | int num_fds; |
140 | ||
371d5dec | 141 | /* Time structure for calls to select(). */ |
44f45770 | 142 | struct timeval select_timeout; |
c2c6d25f | 143 | |
371d5dec | 144 | /* Flag to tell whether the timeout should be used. */ |
c2c6d25f | 145 | int timeout_valid; |
6426a772 | 146 | } |
b5a0ac70 SS |
147 | gdb_notifier; |
148 | ||
371d5dec MS |
149 | /* Structure associated with a timer. PROC will be executed at the |
150 | first occasion after WHEN. */ | |
c2c6d25f JM |
151 | struct gdb_timer |
152 | { | |
dcb07cfa | 153 | std::chrono::steady_clock::time_point when; |
c2c6d25f JM |
154 | int timer_id; |
155 | struct gdb_timer *next; | |
371d5dec MS |
156 | timer_handler_func *proc; /* Function to call to do the work. */ |
157 | gdb_client_data client_data; /* Argument to async_handler_func. */ | |
ae462839 | 158 | }; |
c2c6d25f | 159 | |
371d5dec MS |
160 | /* List of currently active timers. It is sorted in order of |
161 | increasing timers. */ | |
c2c6d25f JM |
162 | static struct |
163 | { | |
371d5dec | 164 | /* Pointer to first in timer list. */ |
c2c6d25f JM |
165 | struct gdb_timer *first_timer; |
166 | ||
371d5dec | 167 | /* Id of the last timer created. */ |
c2c6d25f JM |
168 | int num_timers; |
169 | } | |
170 | timer_list; | |
171 | ||
50d01748 | 172 | static void create_file_handler (int fd, int mask, handler_func *proc, |
2554f6f5 | 173 | gdb_client_data client_data, |
6b01403b | 174 | std::string &&name, bool is_ui); |
50d01748 | 175 | static int gdb_wait_for_event (int); |
70b66289 PA |
176 | static int update_wait_timeout (void); |
177 | static int poll_timers (void); | |
b5a0ac70 | 178 | \f |
b5a0ac70 SS |
179 | /* Process one high level event. If nothing is ready at this time, |
180 | wait for something to happen (via gdb_wait_for_event), then process | |
11cf8741 | 181 | it. Returns >0 if something was done otherwise returns <0 (this |
e0dd0826 | 182 | can happen if there are no event sources to wait for). */ |
11cf8741 | 183 | |
99656a61 | 184 | int |
e0dd0826 | 185 | gdb_do_one_event (void) |
b5a0ac70 | 186 | { |
50d01748 PA |
187 | static int event_source_head = 0; |
188 | const int number_of_sources = 3; | |
189 | int current = 0; | |
190 | ||
70b66289 PA |
191 | /* First let's see if there are any asynchronous signal handlers |
192 | that are ready. These would be the result of invoking any of the | |
193 | signal handlers. */ | |
194 | if (invoke_async_signal_handlers ()) | |
50d01748 PA |
195 | return 1; |
196 | ||
197 | /* To level the fairness across event sources, we poll them in a | |
198 | round-robin fashion. */ | |
199 | for (current = 0; current < number_of_sources; current++) | |
11cf8741 | 200 | { |
70b66289 PA |
201 | int res; |
202 | ||
50d01748 PA |
203 | switch (event_source_head) |
204 | { | |
205 | case 0: | |
70b66289 PA |
206 | /* Are any timers that are ready? */ |
207 | res = poll_timers (); | |
50d01748 PA |
208 | break; |
209 | case 1: | |
210 | /* Are there events already waiting to be collected on the | |
211 | monitored file descriptors? */ | |
70b66289 | 212 | res = gdb_wait_for_event (0); |
50d01748 PA |
213 | break; |
214 | case 2: | |
215 | /* Are there any asynchronous event handlers ready? */ | |
70b66289 | 216 | res = check_async_event_handlers (); |
50d01748 | 217 | break; |
80bd5fab PA |
218 | default: |
219 | internal_error (__FILE__, __LINE__, | |
220 | "unexpected event_source_head %d", | |
221 | event_source_head); | |
50d01748 PA |
222 | } |
223 | ||
224 | event_source_head++; | |
225 | if (event_source_head == number_of_sources) | |
226 | event_source_head = 0; | |
7e5cd2de | 227 | |
70b66289 PA |
228 | if (res > 0) |
229 | return 1; | |
230 | } | |
7e5cd2de | 231 | |
50d01748 PA |
232 | /* Block waiting for a new event. If gdb_wait_for_event returns -1, |
233 | we should get out because this means that there are no event | |
234 | sources left. This will make the event loop stop, and the | |
235 | application exit. */ | |
7e5cd2de | 236 | |
50d01748 PA |
237 | if (gdb_wait_for_event (1) < 0) |
238 | return -1; | |
7e5cd2de | 239 | |
50d01748 PA |
240 | /* If gdb_wait_for_event has returned 1, it means that one event has |
241 | been handled. We break out of the loop. */ | |
11cf8741 JM |
242 | return 1; |
243 | } | |
244 | ||
2554f6f5 | 245 | /* See event-loop.h */ |
b5a0ac70 | 246 | |
c5aa993b | 247 | void |
2554f6f5 | 248 | add_file_handler (int fd, handler_func *proc, gdb_client_data client_data, |
6b01403b | 249 | std::string &&name, bool is_ui) |
085dd6e6 JM |
250 | { |
251 | #ifdef HAVE_POLL | |
44f45770 EZ |
252 | struct pollfd fds; |
253 | #endif | |
254 | ||
255 | if (use_poll) | |
256 | { | |
257 | #ifdef HAVE_POLL | |
371d5dec | 258 | /* Check to see if poll () is usable. If not, we'll switch to |
dda83cd7 SM |
259 | use select. This can happen on systems like |
260 | m68k-motorola-sys, `poll' cannot be used to wait for `stdin'. | |
261 | On m68k-motorola-sysv, tty's are not stream-based and not | |
262 | `poll'able. */ | |
7e5cd2de EZ |
263 | fds.fd = fd; |
264 | fds.events = POLLIN; | |
265 | if (poll (&fds, 1, 0) == 1 && (fds.revents & POLLNVAL)) | |
266 | use_poll = 0; | |
44f45770 | 267 | #else |
8e65ff28 | 268 | internal_error (__FILE__, __LINE__, |
e2e0b3e5 | 269 | _("use_poll without HAVE_POLL")); |
44f45770 EZ |
270 | #endif /* HAVE_POLL */ |
271 | } | |
272 | if (use_poll) | |
273 | { | |
274 | #ifdef HAVE_POLL | |
6b01403b SM |
275 | create_file_handler (fd, POLLIN, proc, client_data, std::move (name), |
276 | is_ui); | |
085dd6e6 | 277 | #else |
8e65ff28 | 278 | internal_error (__FILE__, __LINE__, |
e2e0b3e5 | 279 | _("use_poll without HAVE_POLL")); |
085dd6e6 | 280 | #endif |
44f45770 EZ |
281 | } |
282 | else | |
2554f6f5 | 283 | create_file_handler (fd, GDB_READABLE | GDB_EXCEPTION, |
6b01403b | 284 | proc, client_data, std::move (name), is_ui); |
085dd6e6 JM |
285 | } |
286 | ||
2554f6f5 | 287 | /* Helper for add_file_handler. |
371d5dec MS |
288 | |
289 | For the poll case, MASK is a combination (OR) of POLLIN, | |
290 | POLLRDNORM, POLLRDBAND, POLLPRI, POLLOUT, POLLWRNORM, POLLWRBAND: | |
291 | these are the events we are interested in. If any of them occurs, | |
292 | proc should be called. | |
293 | ||
294 | For the select case, MASK is a combination of READABLE, WRITABLE, | |
295 | EXCEPTION. PROC is the procedure that will be called when an event | |
296 | occurs for FD. CLIENT_DATA is the argument to pass to PROC. */ | |
297 | ||
085dd6e6 | 298 | static void |
2554f6f5 | 299 | create_file_handler (int fd, int mask, handler_func * proc, |
6b01403b SM |
300 | gdb_client_data client_data, std::string &&name, |
301 | bool is_ui) | |
b5a0ac70 SS |
302 | { |
303 | file_handler *file_ptr; | |
304 | ||
371d5dec MS |
305 | /* Do we already have a file handler for this file? (We may be |
306 | changing its associated procedure). */ | |
b5a0ac70 SS |
307 | for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL; |
308 | file_ptr = file_ptr->next_file) | |
309 | { | |
310 | if (file_ptr->fd == fd) | |
311 | break; | |
312 | } | |
313 | ||
371d5dec MS |
314 | /* It is a new file descriptor. Add it to the list. Otherwise, just |
315 | change the data associated with it. */ | |
b5a0ac70 SS |
316 | if (file_ptr == NULL) |
317 | { | |
8d749320 | 318 | file_ptr = XNEW (file_handler); |
b5a0ac70 SS |
319 | file_ptr->fd = fd; |
320 | file_ptr->ready_mask = 0; | |
321 | file_ptr->next_file = gdb_notifier.first_file_handler; | |
322 | gdb_notifier.first_file_handler = file_ptr; | |
b5a0ac70 | 323 | |
05a6c72c KS |
324 | if (use_poll) |
325 | { | |
b5a0ac70 | 326 | #ifdef HAVE_POLL |
05a6c72c KS |
327 | gdb_notifier.num_fds++; |
328 | if (gdb_notifier.poll_fds) | |
329 | gdb_notifier.poll_fds = | |
330 | (struct pollfd *) xrealloc (gdb_notifier.poll_fds, | |
331 | (gdb_notifier.num_fds | |
332 | * sizeof (struct pollfd))); | |
333 | else | |
334 | gdb_notifier.poll_fds = | |
8d749320 | 335 | XNEW (struct pollfd); |
05a6c72c KS |
336 | (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->fd = fd; |
337 | (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->events = mask; | |
338 | (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->revents = 0; | |
44f45770 | 339 | #else |
05a6c72c | 340 | internal_error (__FILE__, __LINE__, |
e2e0b3e5 | 341 | _("use_poll without HAVE_POLL")); |
44f45770 | 342 | #endif /* HAVE_POLL */ |
05a6c72c | 343 | } |
44f45770 | 344 | else |
05a6c72c KS |
345 | { |
346 | if (mask & GDB_READABLE) | |
347 | FD_SET (fd, &gdb_notifier.check_masks[0]); | |
348 | else | |
349 | FD_CLR (fd, &gdb_notifier.check_masks[0]); | |
350 | ||
351 | if (mask & GDB_WRITABLE) | |
352 | FD_SET (fd, &gdb_notifier.check_masks[1]); | |
353 | else | |
354 | FD_CLR (fd, &gdb_notifier.check_masks[1]); | |
355 | ||
356 | if (mask & GDB_EXCEPTION) | |
357 | FD_SET (fd, &gdb_notifier.check_masks[2]); | |
358 | else | |
359 | FD_CLR (fd, &gdb_notifier.check_masks[2]); | |
360 | ||
361 | if (gdb_notifier.num_fds <= fd) | |
362 | gdb_notifier.num_fds = fd + 1; | |
363 | } | |
44f45770 | 364 | } |
05a6c72c KS |
365 | |
366 | file_ptr->proc = proc; | |
367 | file_ptr->client_data = client_data; | |
368 | file_ptr->mask = mask; | |
2554f6f5 | 369 | file_ptr->name = new std::string (std::move (name)); |
6b01403b | 370 | file_ptr->is_ui = is_ui; |
b5a0ac70 SS |
371 | } |
372 | ||
4e63d0ac PA |
373 | /* Return the next file handler to handle, and advance to the next |
374 | file handler, wrapping around if the end of the list is | |
375 | reached. */ | |
376 | ||
377 | static file_handler * | |
378 | get_next_file_handler_to_handle_and_advance (void) | |
379 | { | |
380 | file_handler *curr_next; | |
381 | ||
382 | /* The first time around, this is still NULL. */ | |
383 | if (gdb_notifier.next_file_handler == NULL) | |
384 | gdb_notifier.next_file_handler = gdb_notifier.first_file_handler; | |
385 | ||
386 | curr_next = gdb_notifier.next_file_handler; | |
387 | gdb_assert (curr_next != NULL); | |
388 | ||
389 | /* Advance. */ | |
390 | gdb_notifier.next_file_handler = curr_next->next_file; | |
391 | /* Wrap around, if necessary. */ | |
392 | if (gdb_notifier.next_file_handler == NULL) | |
393 | gdb_notifier.next_file_handler = gdb_notifier.first_file_handler; | |
394 | ||
395 | return curr_next; | |
396 | } | |
397 | ||
b5a0ac70 | 398 | /* Remove the file descriptor FD from the list of monitored fd's: |
371d5dec | 399 | i.e. we don't care anymore about events on the FD. */ |
b5a0ac70 | 400 | void |
c2c6d25f | 401 | delete_file_handler (int fd) |
b5a0ac70 SS |
402 | { |
403 | file_handler *file_ptr, *prev_ptr = NULL; | |
58a2c44a EZ |
404 | int i; |
405 | #ifdef HAVE_POLL | |
406 | int j; | |
b5a0ac70 | 407 | struct pollfd *new_poll_fds; |
b5a0ac70 SS |
408 | #endif |
409 | ||
371d5dec | 410 | /* Find the entry for the given file. */ |
b5a0ac70 SS |
411 | |
412 | for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL; | |
413 | file_ptr = file_ptr->next_file) | |
414 | { | |
415 | if (file_ptr->fd == fd) | |
416 | break; | |
417 | } | |
418 | ||
419 | if (file_ptr == NULL) | |
420 | return; | |
421 | ||
44f45770 EZ |
422 | if (use_poll) |
423 | { | |
b5a0ac70 | 424 | #ifdef HAVE_POLL |
371d5dec | 425 | /* Create a new poll_fds array by copying every fd's information |
dda83cd7 | 426 | but the one we want to get rid of. */ |
b5a0ac70 | 427 | |
371d5dec MS |
428 | new_poll_fds = (struct pollfd *) |
429 | xmalloc ((gdb_notifier.num_fds - 1) * sizeof (struct pollfd)); | |
b5a0ac70 | 430 | |
44f45770 | 431 | for (i = 0, j = 0; i < gdb_notifier.num_fds; i++) |
b5a0ac70 | 432 | { |
44f45770 EZ |
433 | if ((gdb_notifier.poll_fds + i)->fd != fd) |
434 | { | |
435 | (new_poll_fds + j)->fd = (gdb_notifier.poll_fds + i)->fd; | |
436 | (new_poll_fds + j)->events = (gdb_notifier.poll_fds + i)->events; | |
3e43a32a MS |
437 | (new_poll_fds + j)->revents |
438 | = (gdb_notifier.poll_fds + i)->revents; | |
44f45770 EZ |
439 | j++; |
440 | } | |
b5a0ac70 | 441 | } |
b8c9b27d | 442 | xfree (gdb_notifier.poll_fds); |
44f45770 EZ |
443 | gdb_notifier.poll_fds = new_poll_fds; |
444 | gdb_notifier.num_fds--; | |
445 | #else | |
8e65ff28 | 446 | internal_error (__FILE__, __LINE__, |
e2e0b3e5 | 447 | _("use_poll without HAVE_POLL")); |
44f45770 | 448 | #endif /* HAVE_POLL */ |
b5a0ac70 | 449 | } |
44f45770 EZ |
450 | else |
451 | { | |
452 | if (file_ptr->mask & GDB_READABLE) | |
453 | FD_CLR (fd, &gdb_notifier.check_masks[0]); | |
454 | if (file_ptr->mask & GDB_WRITABLE) | |
455 | FD_CLR (fd, &gdb_notifier.check_masks[1]); | |
456 | if (file_ptr->mask & GDB_EXCEPTION) | |
457 | FD_CLR (fd, &gdb_notifier.check_masks[2]); | |
b5a0ac70 | 458 | |
371d5dec | 459 | /* Find current max fd. */ |
b5a0ac70 | 460 | |
44f45770 | 461 | if ((fd + 1) == gdb_notifier.num_fds) |
b5a0ac70 | 462 | { |
44f45770 EZ |
463 | gdb_notifier.num_fds--; |
464 | for (i = gdb_notifier.num_fds; i; i--) | |
465 | { | |
466 | if (FD_ISSET (i - 1, &gdb_notifier.check_masks[0]) | |
467 | || FD_ISSET (i - 1, &gdb_notifier.check_masks[1]) | |
468 | || FD_ISSET (i - 1, &gdb_notifier.check_masks[2])) | |
469 | break; | |
470 | } | |
471 | gdb_notifier.num_fds = i; | |
b5a0ac70 SS |
472 | } |
473 | } | |
b5a0ac70 | 474 | |
cff3e48b | 475 | /* Deactivate the file descriptor, by clearing its mask, |
371d5dec | 476 | so that it will not fire again. */ |
cff3e48b JM |
477 | |
478 | file_ptr->mask = 0; | |
479 | ||
4e63d0ac PA |
480 | /* If this file handler was going to be the next one to be handled, |
481 | advance to the next's next, if any. */ | |
482 | if (gdb_notifier.next_file_handler == file_ptr) | |
483 | { | |
484 | if (file_ptr->next_file == NULL | |
485 | && file_ptr == gdb_notifier.first_file_handler) | |
486 | gdb_notifier.next_file_handler = NULL; | |
487 | else | |
488 | get_next_file_handler_to_handle_and_advance (); | |
489 | } | |
490 | ||
371d5dec | 491 | /* Get rid of the file handler in the file handler list. */ |
b5a0ac70 SS |
492 | if (file_ptr == gdb_notifier.first_file_handler) |
493 | gdb_notifier.first_file_handler = file_ptr->next_file; | |
494 | else | |
495 | { | |
496 | for (prev_ptr = gdb_notifier.first_file_handler; | |
9e0b60a8 | 497 | prev_ptr->next_file != file_ptr; |
b5a0ac70 SS |
498 | prev_ptr = prev_ptr->next_file) |
499 | ; | |
500 | prev_ptr->next_file = file_ptr->next_file; | |
501 | } | |
2554f6f5 SM |
502 | |
503 | delete file_ptr->name; | |
b8c9b27d | 504 | xfree (file_ptr); |
b5a0ac70 SS |
505 | } |
506 | ||
507 | /* Handle the given event by calling the procedure associated to the | |
70b66289 PA |
508 | corresponding file handler. */ |
509 | ||
b5a0ac70 | 510 | static void |
70b66289 | 511 | handle_file_event (file_handler *file_ptr, int ready_mask) |
b5a0ac70 | 512 | { |
c2c6d25f JM |
513 | int mask; |
514 | #ifdef HAVE_POLL | |
515 | int error_mask; | |
c2c6d25f | 516 | #endif |
b5a0ac70 | 517 | |
b5a0ac70 | 518 | { |
b5a0ac70 SS |
519 | { |
520 | /* With poll, the ready_mask could have any of three events | |
371d5dec MS |
521 | set to 1: POLLHUP, POLLERR, POLLNVAL. These events |
522 | cannot be used in the requested event mask (events), but | |
523 | they can be returned in the return mask (revents). We | |
524 | need to check for those event too, and add them to the | |
525 | mask which will be passed to the handler. */ | |
b5a0ac70 SS |
526 | |
527 | /* See if the desired events (mask) match the received | |
371d5dec | 528 | events (ready_mask). */ |
b5a0ac70 | 529 | |
44f45770 | 530 | if (use_poll) |
c2c6d25f | 531 | { |
44f45770 | 532 | #ifdef HAVE_POLL |
652c71b4 AS |
533 | /* POLLHUP means EOF, but can be combined with POLLIN to |
534 | signal more data to read. */ | |
44f45770 | 535 | error_mask = POLLHUP | POLLERR | POLLNVAL; |
70b66289 | 536 | mask = ready_mask & (file_ptr->mask | error_mask); |
44f45770 | 537 | |
652c71b4 | 538 | if ((mask & (POLLERR | POLLNVAL)) != 0) |
44f45770 | 539 | { |
371d5dec MS |
540 | /* Work in progress. We may need to tell somebody |
541 | what kind of error we had. */ | |
652c71b4 | 542 | if (mask & POLLERR) |
29f2bf4f | 543 | warning (_("Error detected on fd %d"), file_ptr->fd); |
652c71b4 | 544 | if (mask & POLLNVAL) |
29f2bf4f TT |
545 | warning (_("Invalid or non-`poll'able fd %d"), |
546 | file_ptr->fd); | |
44f45770 EZ |
547 | file_ptr->error = 1; |
548 | } | |
549 | else | |
550 | file_ptr->error = 0; | |
551 | #else | |
8e65ff28 | 552 | internal_error (__FILE__, __LINE__, |
e2e0b3e5 | 553 | _("use_poll without HAVE_POLL")); |
44f45770 | 554 | #endif /* HAVE_POLL */ |
6426a772 JM |
555 | } |
556 | else | |
c2c6d25f | 557 | { |
70b66289 | 558 | if (ready_mask & GDB_EXCEPTION) |
44f45770 | 559 | { |
29f2bf4f TT |
560 | warning (_("Exception condition detected on fd %d"), |
561 | file_ptr->fd); | |
44f45770 EZ |
562 | file_ptr->error = 1; |
563 | } | |
564 | else | |
565 | file_ptr->error = 0; | |
70b66289 | 566 | mask = ready_mask & file_ptr->mask; |
c2c6d25f | 567 | } |
b5a0ac70 | 568 | |
371d5dec | 569 | /* If there was a match, then call the handler. */ |
b5a0ac70 | 570 | if (mask != 0) |
6b01403b SM |
571 | { |
572 | event_loop_ui_debug_printf (file_ptr->is_ui, | |
573 | "invoking fd file handler `%s`", | |
574 | file_ptr->name->c_str ()); | |
575 | file_ptr->proc (file_ptr->error, file_ptr->client_data); | |
576 | } | |
b5a0ac70 SS |
577 | } |
578 | } | |
579 | } | |
580 | ||
70b66289 PA |
581 | /* Wait for new events on the monitored file descriptors. Run the |
582 | event handler if the first descriptor that is detected by the poll. | |
583 | If BLOCK and if there are no events, this function will block in | |
584 | the call to poll. Return 1 if an event was handled. Return -1 if | |
585 | there are no file descriptors to monitor. Return 1 if an event was | |
586 | handled, otherwise returns 0. */ | |
587 | ||
b5a0ac70 | 588 | static int |
50d01748 | 589 | gdb_wait_for_event (int block) |
b5a0ac70 SS |
590 | { |
591 | file_handler *file_ptr; | |
0f71a2f6 | 592 | int num_found = 0; |
b5a0ac70 | 593 | |
371d5dec | 594 | /* Make sure all output is done before getting another event. */ |
c1cd3163 | 595 | flush_streams (); |
7be570e7 | 596 | |
b5a0ac70 SS |
597 | if (gdb_notifier.num_fds == 0) |
598 | return -1; | |
599 | ||
70b66289 PA |
600 | if (block) |
601 | update_wait_timeout (); | |
602 | ||
44f45770 EZ |
603 | if (use_poll) |
604 | { | |
b5a0ac70 | 605 | #ifdef HAVE_POLL |
50d01748 PA |
606 | int timeout; |
607 | ||
608 | if (block) | |
609 | timeout = gdb_notifier.timeout_valid ? gdb_notifier.poll_timeout : -1; | |
610 | else | |
611 | timeout = 0; | |
612 | ||
613 | num_found = poll (gdb_notifier.poll_fds, | |
614 | (unsigned long) gdb_notifier.num_fds, timeout); | |
44f45770 EZ |
615 | |
616 | /* Don't print anything if we get out of poll because of a | |
50d01748 | 617 | signal. */ |
44f45770 | 618 | if (num_found == -1 && errno != EINTR) |
e2e0b3e5 | 619 | perror_with_name (("poll")); |
44f45770 | 620 | #else |
8e65ff28 | 621 | internal_error (__FILE__, __LINE__, |
e2e0b3e5 | 622 | _("use_poll without HAVE_POLL")); |
44f45770 EZ |
623 | #endif /* HAVE_POLL */ |
624 | } | |
625 | else | |
c2c6d25f | 626 | { |
50d01748 | 627 | struct timeval select_timeout; |
50d01748 | 628 | struct timeval *timeout_p; |
d7f9d729 | 629 | |
50d01748 PA |
630 | if (block) |
631 | timeout_p = gdb_notifier.timeout_valid | |
632 | ? &gdb_notifier.select_timeout : NULL; | |
633 | else | |
634 | { | |
635 | memset (&select_timeout, 0, sizeof (select_timeout)); | |
636 | timeout_p = &select_timeout; | |
637 | } | |
638 | ||
44f45770 EZ |
639 | gdb_notifier.ready_masks[0] = gdb_notifier.check_masks[0]; |
640 | gdb_notifier.ready_masks[1] = gdb_notifier.check_masks[1]; | |
641 | gdb_notifier.ready_masks[2] = gdb_notifier.check_masks[2]; | |
011825f0 MM |
642 | num_found = gdb_select (gdb_notifier.num_fds, |
643 | &gdb_notifier.ready_masks[0], | |
644 | &gdb_notifier.ready_masks[1], | |
645 | &gdb_notifier.ready_masks[2], | |
50d01748 | 646 | timeout_p); |
44f45770 | 647 | |
371d5dec | 648 | /* Clear the masks after an error from select. */ |
44f45770 EZ |
649 | if (num_found == -1) |
650 | { | |
651 | FD_ZERO (&gdb_notifier.ready_masks[0]); | |
652 | FD_ZERO (&gdb_notifier.ready_masks[1]); | |
653 | FD_ZERO (&gdb_notifier.ready_masks[2]); | |
50d01748 PA |
654 | |
655 | /* Dont print anything if we got a signal, let gdb handle | |
656 | it. */ | |
44f45770 | 657 | if (errno != EINTR) |
e2e0b3e5 | 658 | perror_with_name (("select")); |
44f45770 | 659 | } |
c2c6d25f | 660 | } |
b5a0ac70 | 661 | |
4e63d0ac PA |
662 | /* Avoid looking at poll_fds[i]->revents if no event fired. */ |
663 | if (num_found <= 0) | |
664 | return 0; | |
665 | ||
70b66289 PA |
666 | /* Run event handlers. We always run just one handler and go back |
667 | to polling, in case a handler changes the notifier list. Since | |
668 | events for sources we haven't consumed yet wake poll/select | |
669 | immediately, no event is lost. */ | |
b5a0ac70 | 670 | |
4e63d0ac PA |
671 | /* To level the fairness across event descriptors, we handle them in |
672 | a round-robin-like fashion. The number and order of descriptors | |
673 | may change between invocations, but this is good enough. */ | |
44f45770 EZ |
674 | if (use_poll) |
675 | { | |
b5a0ac70 | 676 | #ifdef HAVE_POLL |
4e63d0ac PA |
677 | int i; |
678 | int mask; | |
b5a0ac70 | 679 | |
4e63d0ac PA |
680 | while (1) |
681 | { | |
682 | if (gdb_notifier.next_poll_fds_index >= gdb_notifier.num_fds) | |
683 | gdb_notifier.next_poll_fds_index = 0; | |
684 | i = gdb_notifier.next_poll_fds_index++; | |
44f45770 | 685 | |
4e63d0ac PA |
686 | gdb_assert (i < gdb_notifier.num_fds); |
687 | if ((gdb_notifier.poll_fds + i)->revents) | |
688 | break; | |
689 | } | |
70b66289 | 690 | |
4e63d0ac PA |
691 | for (file_ptr = gdb_notifier.first_file_handler; |
692 | file_ptr != NULL; | |
693 | file_ptr = file_ptr->next_file) | |
694 | { | |
695 | if (file_ptr->fd == (gdb_notifier.poll_fds + i)->fd) | |
696 | break; | |
44f45770 | 697 | } |
4e63d0ac PA |
698 | gdb_assert (file_ptr != NULL); |
699 | ||
700 | mask = (gdb_notifier.poll_fds + i)->revents; | |
701 | handle_file_event (file_ptr, mask); | |
702 | return 1; | |
44f45770 | 703 | #else |
8e65ff28 | 704 | internal_error (__FILE__, __LINE__, |
e2e0b3e5 | 705 | _("use_poll without HAVE_POLL")); |
44f45770 EZ |
706 | #endif /* HAVE_POLL */ |
707 | } | |
708 | else | |
709 | { | |
4e63d0ac PA |
710 | /* See comment about even source fairness above. */ |
711 | int mask = 0; | |
712 | ||
713 | do | |
b5a0ac70 | 714 | { |
4e63d0ac | 715 | file_ptr = get_next_file_handler_to_handle_and_advance (); |
44f45770 EZ |
716 | |
717 | if (FD_ISSET (file_ptr->fd, &gdb_notifier.ready_masks[0])) | |
718 | mask |= GDB_READABLE; | |
719 | if (FD_ISSET (file_ptr->fd, &gdb_notifier.ready_masks[1])) | |
720 | mask |= GDB_WRITABLE; | |
721 | if (FD_ISSET (file_ptr->fd, &gdb_notifier.ready_masks[2])) | |
722 | mask |= GDB_EXCEPTION; | |
b5a0ac70 | 723 | } |
4e63d0ac PA |
724 | while (mask == 0); |
725 | ||
726 | handle_file_event (file_ptr, mask); | |
727 | return 1; | |
b5a0ac70 | 728 | } |
b5a0ac70 SS |
729 | return 0; |
730 | } | |
731 | \f | |
dcb07cfa PA |
732 | /* Create a timer that will expire in MS milliseconds from now. When |
733 | the timer is ready, PROC will be executed. At creation, the timer | |
734 | is added to the timers queue. This queue is kept sorted in order | |
735 | of increasing timers. Return a handle to the timer struct. */ | |
736 | ||
c2c6d25f | 737 | int |
dcb07cfa | 738 | create_timer (int ms, timer_handler_func *proc, |
371d5dec | 739 | gdb_client_data client_data) |
c2c6d25f | 740 | { |
dcb07cfa | 741 | using namespace std::chrono; |
c2c6d25f | 742 | struct gdb_timer *timer_ptr, *timer_index, *prev_timer; |
6426a772 | 743 | |
dcb07cfa | 744 | steady_clock::time_point time_now = steady_clock::now (); |
c2c6d25f | 745 | |
dcb07cfa PA |
746 | timer_ptr = new gdb_timer (); |
747 | timer_ptr->when = time_now + milliseconds (ms); | |
c2c6d25f JM |
748 | timer_ptr->proc = proc; |
749 | timer_ptr->client_data = client_data; | |
6426a772 | 750 | timer_list.num_timers++; |
c2c6d25f JM |
751 | timer_ptr->timer_id = timer_list.num_timers; |
752 | ||
753 | /* Now add the timer to the timer queue, making sure it is sorted in | |
371d5dec | 754 | increasing order of expiration. */ |
c2c6d25f | 755 | |
6426a772 JM |
756 | for (timer_index = timer_list.first_timer; |
757 | timer_index != NULL; | |
c2c6d25f JM |
758 | timer_index = timer_index->next) |
759 | { | |
dcb07cfa | 760 | if (timer_index->when > timer_ptr->when) |
c2c6d25f JM |
761 | break; |
762 | } | |
6426a772 | 763 | |
c2c6d25f JM |
764 | if (timer_index == timer_list.first_timer) |
765 | { | |
766 | timer_ptr->next = timer_list.first_timer; | |
767 | timer_list.first_timer = timer_ptr; | |
768 | ||
769 | } | |
770 | else | |
771 | { | |
6426a772 JM |
772 | for (prev_timer = timer_list.first_timer; |
773 | prev_timer->next != timer_index; | |
c2c6d25f JM |
774 | prev_timer = prev_timer->next) |
775 | ; | |
6426a772 | 776 | |
c2c6d25f JM |
777 | prev_timer->next = timer_ptr; |
778 | timer_ptr->next = timer_index; | |
779 | } | |
780 | ||
781 | gdb_notifier.timeout_valid = 0; | |
782 | return timer_ptr->timer_id; | |
783 | } | |
784 | ||
785 | /* There is a chance that the creator of the timer wants to get rid of | |
371d5dec | 786 | it before it expires. */ |
c2c6d25f JM |
787 | void |
788 | delete_timer (int id) | |
789 | { | |
790 | struct gdb_timer *timer_ptr, *prev_timer = NULL; | |
791 | ||
371d5dec | 792 | /* Find the entry for the given timer. */ |
c2c6d25f JM |
793 | |
794 | for (timer_ptr = timer_list.first_timer; timer_ptr != NULL; | |
795 | timer_ptr = timer_ptr->next) | |
796 | { | |
797 | if (timer_ptr->timer_id == id) | |
798 | break; | |
799 | } | |
800 | ||
801 | if (timer_ptr == NULL) | |
802 | return; | |
371d5dec | 803 | /* Get rid of the timer in the timer list. */ |
c2c6d25f JM |
804 | if (timer_ptr == timer_list.first_timer) |
805 | timer_list.first_timer = timer_ptr->next; | |
806 | else | |
807 | { | |
808 | for (prev_timer = timer_list.first_timer; | |
809 | prev_timer->next != timer_ptr; | |
810 | prev_timer = prev_timer->next) | |
811 | ; | |
812 | prev_timer->next = timer_ptr->next; | |
813 | } | |
dcb07cfa | 814 | delete timer_ptr; |
c2c6d25f JM |
815 | |
816 | gdb_notifier.timeout_valid = 0; | |
817 | } | |
818 | ||
dcb07cfa PA |
819 | /* Convert a std::chrono duration to a struct timeval. */ |
820 | ||
821 | template<typename Duration> | |
822 | static struct timeval | |
823 | duration_cast_timeval (const Duration &d) | |
824 | { | |
825 | using namespace std::chrono; | |
826 | seconds sec = duration_cast<seconds> (d); | |
827 | microseconds msec = duration_cast<microseconds> (d - sec); | |
828 | ||
829 | struct timeval tv; | |
830 | tv.tv_sec = sec.count (); | |
831 | tv.tv_usec = msec.count (); | |
832 | return tv; | |
833 | } | |
834 | ||
70b66289 PA |
835 | /* Update the timeout for the select() or poll(). Returns true if the |
836 | timer has already expired, false otherwise. */ | |
6426a772 | 837 | |
70b66289 PA |
838 | static int |
839 | update_wait_timeout (void) | |
c2c6d25f | 840 | { |
2acceee2 | 841 | if (timer_list.first_timer != NULL) |
c2c6d25f | 842 | { |
dcb07cfa PA |
843 | using namespace std::chrono; |
844 | steady_clock::time_point time_now = steady_clock::now (); | |
845 | struct timeval timeout; | |
6426a772 | 846 | |
dcb07cfa | 847 | if (timer_list.first_timer->when < time_now) |
c2c6d25f | 848 | { |
70b66289 | 849 | /* It expired already. */ |
dcb07cfa PA |
850 | timeout.tv_sec = 0; |
851 | timeout.tv_usec = 0; | |
852 | } | |
853 | else | |
854 | { | |
855 | steady_clock::duration d = timer_list.first_timer->when - time_now; | |
856 | timeout = duration_cast_timeval (d); | |
c2c6d25f JM |
857 | } |
858 | ||
70b66289 | 859 | /* Update the timeout for select/ poll. */ |
44f45770 EZ |
860 | if (use_poll) |
861 | { | |
c2c6d25f | 862 | #ifdef HAVE_POLL |
dcb07cfa | 863 | gdb_notifier.poll_timeout = timeout.tv_sec * 1000; |
c2c6d25f | 864 | #else |
8e65ff28 | 865 | internal_error (__FILE__, __LINE__, |
e2e0b3e5 | 866 | _("use_poll without HAVE_POLL")); |
44f45770 EZ |
867 | #endif /* HAVE_POLL */ |
868 | } | |
869 | else | |
870 | { | |
dcb07cfa PA |
871 | gdb_notifier.select_timeout.tv_sec = timeout.tv_sec; |
872 | gdb_notifier.select_timeout.tv_usec = timeout.tv_usec; | |
44f45770 | 873 | } |
c2c6d25f | 874 | gdb_notifier.timeout_valid = 1; |
70b66289 | 875 | |
dcb07cfa | 876 | if (timer_list.first_timer->when < time_now) |
70b66289 | 877 | return 1; |
c2c6d25f | 878 | } |
6426a772 | 879 | else |
c2c6d25f | 880 | gdb_notifier.timeout_valid = 0; |
70b66289 PA |
881 | |
882 | return 0; | |
883 | } | |
884 | ||
885 | /* Check whether a timer in the timers queue is ready. If a timer is | |
886 | ready, call its handler and return. Update the timeout for the | |
887 | select() or poll() as well. Return 1 if an event was handled, | |
888 | otherwise returns 0.*/ | |
889 | ||
890 | static int | |
891 | poll_timers (void) | |
892 | { | |
893 | if (update_wait_timeout ()) | |
894 | { | |
895 | struct gdb_timer *timer_ptr = timer_list.first_timer; | |
896 | timer_handler_func *proc = timer_ptr->proc; | |
897 | gdb_client_data client_data = timer_ptr->client_data; | |
898 | ||
899 | /* Get rid of the timer from the beginning of the list. */ | |
900 | timer_list.first_timer = timer_ptr->next; | |
901 | ||
902 | /* Delete the timer before calling the callback, not after, in | |
903 | case the callback itself decides to try deleting the timer | |
904 | too. */ | |
0e05cf3a | 905 | delete timer_ptr; |
70b66289 PA |
906 | |
907 | /* Call the procedure associated with that timer. */ | |
908 | (proc) (client_data); | |
909 | ||
910 | return 1; | |
911 | } | |
912 | ||
913 | return 0; | |
c2c6d25f | 914 | } |