xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/async-event.c (revision f8cf1a9151c7af1cb0bd8b09c13c66bca599c027)
1 /* Async events for the GDB event loop.
2    Copyright (C) 1999-2023 Free Software Foundation, Inc.
3 
4    This file is part of GDB.
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18 
19 #include "defs.h"
20 #include "async-event.h"
21 
22 #include "ser-event.h"
23 #include "top.h"
24 
25 /* PROC is a function to be invoked when the READY flag is set.  This
26    happens when there has been a signal and the corresponding signal
27    handler has 'triggered' this async_signal_handler for execution.
28    The actual work to be done in response to a signal will be carried
29    out by PROC at a later time, within process_event.  This provides a
30    deferred execution of signal handlers.
31 
32    Async_init_signals takes care of setting up such an
33    async_signal_handler for each interesting signal.  */
34 
35 struct async_signal_handler
36 {
37   /* If ready, call this handler  from the main event loop, using
38      invoke_async_handler.  */
39   int ready;
40 
41   /* Pointer to next handler.  */
42   struct async_signal_handler *next_handler;
43 
44   /* Function to call to do the work.  */
45   sig_handler_func *proc;
46 
47   /* Argument to PROC.  */
48   gdb_client_data client_data;
49 
50   /* User-friendly name of this handler.  */
51   const char *name;
52 };
53 
54 /* PROC is a function to be invoked when the READY flag is set.  This
55    happens when the event has been marked with
56    MARK_ASYNC_EVENT_HANDLER.  The actual work to be done in response
57    to an event will be carried out by PROC at a later time, within
58    process_event.  This provides a deferred execution of event
59    handlers.  */
60 struct async_event_handler
61 {
62   /* If ready, call this handler from the main event loop, using
63      invoke_event_handler.  */
64   int ready;
65 
66   /* Pointer to next handler.  */
67   struct async_event_handler *next_handler;
68 
69   /* Function to call to do the work.  */
70   async_event_handler_func *proc;
71 
72   /* Argument to PROC.  */
73   gdb_client_data client_data;
74 
75   /* User-friendly name of this handler.  */
76   const char *name;
77 };
78 
79 /* All the async_signal_handlers gdb is interested in are kept onto
80    this list.  */
81 static struct
82 {
83   /* Pointer to first in handler list.  */
84   async_signal_handler *first_handler;
85 
86   /* Pointer to last in handler list.  */
87   async_signal_handler *last_handler;
88 }
89 sighandler_list;
90 
91 /* All the async_event_handlers gdb is interested in are kept onto
92    this list.  */
93 static struct
94 {
95   /* Pointer to first in handler list.  */
96   async_event_handler *first_handler;
97 
98   /* Pointer to last in handler list.  */
99   async_event_handler *last_handler;
100 }
101 async_event_handler_list;
102 
103 
104 /* This event is signalled whenever an asynchronous handler needs to
105    defer an action to the event loop.  */
106 static struct serial_event *async_signal_handlers_serial_event;
107 
108 /* Callback registered with ASYNC_SIGNAL_HANDLERS_SERIAL_EVENT.  */
109 
110 static void
111 async_signals_handler (int error, gdb_client_data client_data)
112 {
113   /* Do nothing.  Handlers are run by invoke_async_signal_handlers
114      from instead.  */
115 }
116 
117 void
118 initialize_async_signal_handlers (void)
119 {
120   async_signal_handlers_serial_event = make_serial_event ();
121 
122   add_file_handler (serial_event_fd (async_signal_handlers_serial_event),
123 		    async_signals_handler, NULL, "async-signals");
124 }
125 
126 
127 
128 /* Create an asynchronous handler, allocating memory for it.
129    Return a pointer to the newly created handler.
130    This pointer will be used to invoke the handler by
131    invoke_async_signal_handler.
132    PROC is the function to call with CLIENT_DATA argument
133    whenever the handler is invoked.  */
134 async_signal_handler *
135 create_async_signal_handler (sig_handler_func * proc,
136 			     gdb_client_data client_data,
137 			     const char *name)
138 {
139   async_signal_handler *async_handler_ptr;
140 
141   async_handler_ptr = XNEW (async_signal_handler);
142   async_handler_ptr->ready = 0;
143   async_handler_ptr->next_handler = NULL;
144   async_handler_ptr->proc = proc;
145   async_handler_ptr->client_data = client_data;
146   async_handler_ptr->name = name;
147   if (sighandler_list.first_handler == NULL)
148     sighandler_list.first_handler = async_handler_ptr;
149   else
150     sighandler_list.last_handler->next_handler = async_handler_ptr;
151   sighandler_list.last_handler = async_handler_ptr;
152   return async_handler_ptr;
153 }
154 
155 /* Mark the handler (ASYNC_HANDLER_PTR) as ready.  This information
156    will be used when the handlers are invoked, after we have waited
157    for some event.  The caller of this function is the interrupt
158    handler associated with a signal.  */
159 void
160 mark_async_signal_handler (async_signal_handler *async_handler_ptr)
161 {
162   if (debug_event_loop != debug_event_loop_kind::OFF)
163     {
164       /* This is called by signal handlers, so we print it "by hand" using
165 	 the async-signal-safe methods.  */
166       const char head[] = ("[event-loop] mark_async_signal_handler: marking"
167 			   "async signal handler `");
168       gdb_stdlog->write_async_safe (head, strlen (head));
169 
170       gdb_stdlog->write_async_safe (async_handler_ptr->name,
171 				    strlen (async_handler_ptr->name));
172 
173       const char tail[] = "`\n";
174       gdb_stdlog->write_async_safe (tail, strlen (tail));
175     }
176 
177   async_handler_ptr->ready = 1;
178   serial_event_set (async_signal_handlers_serial_event);
179 }
180 
181 /* See event-loop.h.  */
182 
183 void
184 clear_async_signal_handler (async_signal_handler *async_handler_ptr)
185 {
186   event_loop_debug_printf ("clearing async signal handler `%s`",
187 			   async_handler_ptr->name);
188   async_handler_ptr->ready = 0;
189 }
190 
191 /* See event-loop.h.  */
192 
193 int
194 async_signal_handler_is_marked (async_signal_handler *async_handler_ptr)
195 {
196   return async_handler_ptr->ready;
197 }
198 
199 /* Call all the handlers that are ready.  Returns true if any was
200    indeed ready.  */
201 
202 int
203 invoke_async_signal_handlers (void)
204 {
205   async_signal_handler *async_handler_ptr;
206   int any_ready = 0;
207 
208   /* We're going to handle all pending signals, so no need to wake up
209      the event loop again the next time around.  Note this must be
210      cleared _before_ calling the callbacks, to avoid races.  */
211   serial_event_clear (async_signal_handlers_serial_event);
212 
213   /* Invoke all ready handlers.  */
214 
215   while (1)
216     {
217       for (async_handler_ptr = sighandler_list.first_handler;
218 	   async_handler_ptr != NULL;
219 	   async_handler_ptr = async_handler_ptr->next_handler)
220 	{
221 	  if (async_handler_ptr->ready)
222 	    break;
223 	}
224       if (async_handler_ptr == NULL)
225 	break;
226       any_ready = 1;
227       async_handler_ptr->ready = 0;
228       /* Async signal handlers have no connection to whichever was the
229 	 current UI, and thus always run on the main one.  */
230       current_ui = main_ui;
231       event_loop_debug_printf ("invoking async signal handler `%s`",
232 			       async_handler_ptr->name);
233       (*async_handler_ptr->proc) (async_handler_ptr->client_data);
234     }
235 
236   return any_ready;
237 }
238 
239 /* Delete an asynchronous handler (ASYNC_HANDLER_PTR).
240    Free the space allocated for it.  */
241 void
242 delete_async_signal_handler (async_signal_handler ** async_handler_ptr)
243 {
244   async_signal_handler *prev_ptr;
245 
246   if (sighandler_list.first_handler == (*async_handler_ptr))
247     {
248       sighandler_list.first_handler = (*async_handler_ptr)->next_handler;
249       if (sighandler_list.first_handler == NULL)
250 	sighandler_list.last_handler = NULL;
251     }
252   else
253     {
254       prev_ptr = sighandler_list.first_handler;
255       while (prev_ptr && prev_ptr->next_handler != (*async_handler_ptr))
256 	prev_ptr = prev_ptr->next_handler;
257       gdb_assert (prev_ptr);
258       prev_ptr->next_handler = (*async_handler_ptr)->next_handler;
259       if (sighandler_list.last_handler == (*async_handler_ptr))
260 	sighandler_list.last_handler = prev_ptr;
261     }
262   xfree ((*async_handler_ptr));
263   (*async_handler_ptr) = NULL;
264 }
265 
266 /* See async-event.h.  */
267 
268 async_event_handler *
269 create_async_event_handler (async_event_handler_func *proc,
270 			    gdb_client_data client_data,
271 			    const char *name)
272 {
273   async_event_handler *h;
274 
275   h = XNEW (struct async_event_handler);
276   h->ready = 0;
277   h->next_handler = NULL;
278   h->proc = proc;
279   h->client_data = client_data;
280   h->name = name;
281   if (async_event_handler_list.first_handler == NULL)
282     async_event_handler_list.first_handler = h;
283   else
284     async_event_handler_list.last_handler->next_handler = h;
285   async_event_handler_list.last_handler = h;
286   return h;
287 }
288 
289 /* Mark the handler (ASYNC_HANDLER_PTR) as ready.  This information
290    will be used by gdb_do_one_event.  The caller will be whoever
291    created the event source, and wants to signal that the event is
292    ready to be handled.  */
293 void
294 mark_async_event_handler (async_event_handler *async_handler_ptr)
295 {
296   event_loop_debug_printf ("marking async event handler `%s` "
297 			   "(previous state was %d)",
298 			   async_handler_ptr->name,
299 			   async_handler_ptr->ready);
300   async_handler_ptr->ready = 1;
301 }
302 
303 /* See event-loop.h.  */
304 
305 void
306 clear_async_event_handler (async_event_handler *async_handler_ptr)
307 {
308   event_loop_debug_printf ("clearing async event handler `%s`",
309 			   async_handler_ptr->name);
310   async_handler_ptr->ready = 0;
311 }
312 
313 /* See event-loop.h.  */
314 
315 bool
316 async_event_handler_marked (async_event_handler *handler)
317 {
318   return handler->ready;
319 }
320 
321 /* Check if asynchronous event handlers are ready, and call the
322    handler function for one that is.  */
323 
324 int
325 check_async_event_handlers ()
326 {
327   async_event_handler *async_handler_ptr;
328 
329   for (async_handler_ptr = async_event_handler_list.first_handler;
330        async_handler_ptr != NULL;
331        async_handler_ptr = async_handler_ptr->next_handler)
332     {
333       if (async_handler_ptr->ready)
334 	{
335 	  event_loop_debug_printf ("invoking async event handler `%s`",
336 				   async_handler_ptr->name);
337 	  (*async_handler_ptr->proc) (async_handler_ptr->client_data);
338 	  return 1;
339 	}
340     }
341 
342   return 0;
343 }
344 
345 /* Delete an asynchronous handler (ASYNC_HANDLER_PTR).
346    Free the space allocated for it.  */
347 void
348 delete_async_event_handler (async_event_handler **async_handler_ptr)
349 {
350   async_event_handler *prev_ptr;
351 
352   if (async_event_handler_list.first_handler == *async_handler_ptr)
353     {
354       async_event_handler_list.first_handler
355 	= (*async_handler_ptr)->next_handler;
356       if (async_event_handler_list.first_handler == NULL)
357 	async_event_handler_list.last_handler = NULL;
358     }
359   else
360     {
361       prev_ptr = async_event_handler_list.first_handler;
362       while (prev_ptr && prev_ptr->next_handler != *async_handler_ptr)
363 	prev_ptr = prev_ptr->next_handler;
364       gdb_assert (prev_ptr);
365       prev_ptr->next_handler = (*async_handler_ptr)->next_handler;
366       if (async_event_handler_list.last_handler == (*async_handler_ptr))
367 	async_event_handler_list.last_handler = prev_ptr;
368     }
369   xfree (*async_handler_ptr);
370   *async_handler_ptr = NULL;
371 }
372