xref: /netbsd-src/external/gpl3/gdb.old/dist/gdbsupport/event-loop.h (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
17d62b00eSchristos /* Definitions used by the GDB event loop.
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 #ifndef EVENT_LOOP_H
217d62b00eSchristos #define EVENT_LOOP_H
227d62b00eSchristos 
237d62b00eSchristos /* An event loop listens for events from multiple event sources.  When
247d62b00eSchristos    an event arrives, it is queued and processed by calling the
257d62b00eSchristos    appropriate event handler.  The event loop then continues to listen
267d62b00eSchristos    for more events.  An event loop completes when there are no event
277d62b00eSchristos    sources to listen on.  External event sources can be plugged into
287d62b00eSchristos    the loop.
297d62b00eSchristos 
307d62b00eSchristos    There are 4 main components:
317d62b00eSchristos    - a list of file descriptors to be monitored, GDB_NOTIFIER.
327d62b00eSchristos    - a list of asynchronous event sources to be monitored,
337d62b00eSchristos      ASYNC_EVENT_HANDLER_LIST.
347d62b00eSchristos    - a list of events that have occurred, EVENT_QUEUE.
357d62b00eSchristos    - a list of signal handling functions, SIGHANDLER_LIST.
367d62b00eSchristos 
377d62b00eSchristos    GDB_NOTIFIER keeps track of the file descriptor based event
387d62b00eSchristos    sources.  ASYNC_EVENT_HANDLER_LIST keeps track of asynchronous
397d62b00eSchristos    event sources that are signalled by some component of gdb, usually
407d62b00eSchristos    a target_ops instance.  Event sources for gdb are currently the UI
417d62b00eSchristos    and the target.  Gdb communicates with the command line user
427d62b00eSchristos    interface via the readline library and usually communicates with
437d62b00eSchristos    remote targets via a serial port.  Serial ports are represented in
447d62b00eSchristos    GDB as file descriptors and select/poll calls.  For native targets
457d62b00eSchristos    instead, the communication varies across operating system debug
467d62b00eSchristos    APIs, but usually consists of calls to ptrace and waits (via
477d62b00eSchristos    signals) or calls to poll/select (via file descriptors).  In the
487d62b00eSchristos    current gdb, the code handling events related to the target resides
497d62b00eSchristos    in wait_for_inferior for synchronous targets; or, for asynchronous
507d62b00eSchristos    capable targets, by having the target register either a target
517d62b00eSchristos    controlled file descriptor and/or an asynchronous event source in
527d62b00eSchristos    the event loop, with the fetch_inferior_event function as the event
537d62b00eSchristos    callback.  In both the synchronous and asynchronous cases, usually
547d62b00eSchristos    the target event is collected through the target_wait interface.
557d62b00eSchristos    The target is free to install other event sources in the event loop
567d62b00eSchristos    if it so requires.
577d62b00eSchristos 
587d62b00eSchristos    EVENT_QUEUE keeps track of the events that have happened during the
597d62b00eSchristos    last iteration of the event loop, and need to be processed.  An
607d62b00eSchristos    event is represented by a procedure to be invoked in order to
617d62b00eSchristos    process the event.  The queue is scanned head to tail.  If the
627d62b00eSchristos    event of interest is a change of state in a file descriptor, then a
637d62b00eSchristos    call to poll or select will be made to detect it.
647d62b00eSchristos 
657d62b00eSchristos    If the events generate signals, they are also queued by special
667d62b00eSchristos    functions that are invoked through traditional signal handlers.
677d62b00eSchristos    The actions to be taken is response to such events will be executed
687d62b00eSchristos    when the SIGHANDLER_LIST is scanned, the next time through the
697d62b00eSchristos    infinite loop.
707d62b00eSchristos 
717d62b00eSchristos    Corollary tasks are the creation and deletion of event sources.  */
727d62b00eSchristos 
737d62b00eSchristos typedef void *gdb_client_data;
747d62b00eSchristos typedef void (handler_func) (int, gdb_client_data);
757d62b00eSchristos typedef void (timer_handler_func) (gdb_client_data);
767d62b00eSchristos 
777d62b00eSchristos /* Exported functions from event-loop.c */
787d62b00eSchristos 
79*6881a400Schristos extern int gdb_do_one_event (int mstimeout = -1);
807d62b00eSchristos extern void delete_file_handler (int fd);
81*6881a400Schristos 
82*6881a400Schristos /* Add a file handler/descriptor to the list of descriptors we are
83*6881a400Schristos    interested in.
84*6881a400Schristos 
85*6881a400Schristos    FD is the file descriptor for the file/stream to be listened to.
86*6881a400Schristos 
87*6881a400Schristos    NAME is a user-friendly name for the handler.
88*6881a400Schristos 
89*6881a400Schristos    If IS_UI is set, this file descriptor is used for a user interface.  */
90*6881a400Schristos 
917d62b00eSchristos extern void add_file_handler (int fd, handler_func *proc,
92*6881a400Schristos 			      gdb_client_data client_data,
93*6881a400Schristos 			      std::string &&name, bool is_ui = false);
94*6881a400Schristos 
957d62b00eSchristos extern int create_timer (int milliseconds,
967d62b00eSchristos 			 timer_handler_func *proc,
977d62b00eSchristos 			 gdb_client_data client_data);
987d62b00eSchristos extern void delete_timer (int id);
997d62b00eSchristos 
1007d62b00eSchristos /* Must be defined by client.  */
1017d62b00eSchristos 
1027d62b00eSchristos extern void handle_event_loop_exception (const gdb_exception &);
1037d62b00eSchristos 
1047d62b00eSchristos /* Must be defined by client.  Returns true if any signal handler was
1057d62b00eSchristos    ready.  */
1067d62b00eSchristos 
1077d62b00eSchristos extern int invoke_async_signal_handlers ();
1087d62b00eSchristos 
1097d62b00eSchristos /* Must be defined by client.  Returns true if any event handler was
1107d62b00eSchristos    ready.  */
1117d62b00eSchristos 
1127d62b00eSchristos extern int check_async_event_handlers ();
1137d62b00eSchristos 
114*6881a400Schristos enum class debug_event_loop_kind
115*6881a400Schristos {
116*6881a400Schristos   OFF,
117*6881a400Schristos 
118*6881a400Schristos   /* Print all event-loop related messages, except events from user-interface
119*6881a400Schristos      event sources.  */
120*6881a400Schristos   ALL_EXCEPT_UI,
121*6881a400Schristos 
122*6881a400Schristos   /* Print all event-loop related messages.  */
123*6881a400Schristos   ALL,
124*6881a400Schristos };
125*6881a400Schristos 
126*6881a400Schristos /* True if we are printing event loop debug statements.  */
127*6881a400Schristos extern debug_event_loop_kind debug_event_loop;
128*6881a400Schristos 
129*6881a400Schristos /* Print an "event loop" debug statement.  */
130*6881a400Schristos 
131*6881a400Schristos #define event_loop_debug_printf(fmt, ...) \
132*6881a400Schristos   debug_prefixed_printf_cond (debug_event_loop != debug_event_loop_kind::OFF, \
133*6881a400Schristos 			      "event-loop", fmt, ##__VA_ARGS__)
134*6881a400Schristos 
135*6881a400Schristos /* Print an "event loop" debug statement that is know to come from a UI-related
136*6881a400Schristos    event (e.g. calling the event handler for the fd of the CLI).  */
137*6881a400Schristos 
138*6881a400Schristos #define event_loop_ui_debug_printf(is_ui, fmt, ...) \
139*6881a400Schristos   do \
140*6881a400Schristos     { \
141*6881a400Schristos       if (debug_event_loop == debug_event_loop_kind::ALL \
142*6881a400Schristos 	  || (debug_event_loop == debug_event_loop_kind::ALL_EXCEPT_UI \
143*6881a400Schristos 	      && !is_ui)) \
144*6881a400Schristos 	debug_prefixed_printf ("event-loop", __func__, fmt, ##__VA_ARGS__); \
145*6881a400Schristos     } \
146*6881a400Schristos   while (0)
147*6881a400Schristos 
1487d62b00eSchristos #endif /* EVENT_LOOP_H */
149