]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/async-event.c
Update copyright year range in all GDB files
[thirdparty/binutils-gdb.git] / gdb / async-event.c
CommitLineData
93b54c8e 1/* Async events for the GDB event loop.
3666a048 2 Copyright (C) 1999-2021 Free Software Foundation, Inc.
93b54c8e
TT
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
a1b68f28
SM
35struct 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;
db20ebdf
SM
49
50 /* User-friendly name of this handler. */
51 const char *name;
a1b68f28 52};
93b54c8e
TT
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. */
a1b68f28
SM
60struct async_event_handler
61{
62 /* If ready, call this handler from the main event loop, using
63 invoke_event_handler. */
64 int ready;
93b54c8e 65
a1b68f28
SM
66 /* Pointer to next handler. */
67 struct async_event_handler *next_handler;
93b54c8e 68
a1b68f28
SM
69 /* Function to call to do the work. */
70 async_event_handler_func *proc;
93b54c8e 71
a1b68f28
SM
72 /* Argument to PROC. */
73 gdb_client_data client_data;
db20ebdf
SM
74
75 /* User-friendly name of this handler. */
76 const char *name;
a1b68f28 77};
93b54c8e
TT
78
79/* All the async_signal_handlers gdb is interested in are kept onto
80 this list. */
81static struct
a1b68f28
SM
82{
83 /* Pointer to first in handler list. */
84 async_signal_handler *first_handler;
93b54c8e 85
a1b68f28
SM
86 /* Pointer to last in handler list. */
87 async_signal_handler *last_handler;
88}
93b54c8e
TT
89sighandler_list;
90
91/* All the async_event_handlers gdb is interested in are kept onto
92 this list. */
93static struct
a1b68f28
SM
94{
95 /* Pointer to first in handler list. */
96 async_event_handler *first_handler;
93b54c8e 97
a1b68f28
SM
98 /* Pointer to last in handler list. */
99 async_event_handler *last_handler;
100}
93b54c8e
TT
101async_event_handler_list;
102
103
104/* This event is signalled whenever an asynchronous handler needs to
105 defer an action to the event loop. */
106static struct serial_event *async_signal_handlers_serial_event;
107
108/* Callback registered with ASYNC_SIGNAL_HANDLERS_SERIAL_EVENT. */
109
110static void
111async_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
117void
118initialize_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),
2554f6f5 123 async_signals_handler, NULL, "async-signals");
93b54c8e
TT
124}
125
126\f
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. */
134async_signal_handler *
135create_async_signal_handler (sig_handler_func * proc,
db20ebdf
SM
136 gdb_client_data client_data,
137 const char *name)
93b54c8e
TT
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;
db20ebdf 146 async_handler_ptr->name = name;
93b54c8e
TT
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. */
159void
6b01403b 160mark_async_signal_handler (async_signal_handler *async_handler_ptr)
93b54c8e 161{
6b01403b
SM
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
93b54c8e
TT
177 async_handler_ptr->ready = 1;
178 serial_event_set (async_signal_handlers_serial_event);
179}
180
181/* See event-loop.h. */
182
183void
184clear_async_signal_handler (async_signal_handler *async_handler_ptr)
185{
6b01403b
SM
186 event_loop_debug_printf ("clearing async signal handler `%s`",
187 async_handler_ptr->name);
93b54c8e
TT
188 async_handler_ptr->ready = 0;
189}
190
191/* See event-loop.h. */
192
193int
194async_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
202int
203invoke_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;
6b01403b
SM
231 event_loop_debug_printf ("invoking async signal handler `%s`",
232 async_handler_ptr->name);
93b54c8e
TT
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. */
241void
242delete_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
db20ebdf
SM
266/* See async-event.h. */
267
93b54c8e
TT
268async_event_handler *
269create_async_event_handler (async_event_handler_func *proc,
db20ebdf
SM
270 gdb_client_data client_data,
271 const char *name)
93b54c8e
TT
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;
db20ebdf 280 h->name = name;
93b54c8e
TT
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. */
293void
294mark_async_event_handler (async_event_handler *async_handler_ptr)
295{
6b01403b
SM
296 event_loop_debug_printf ("marking async event handler `%s`",
297 async_handler_ptr->name);
93b54c8e
TT
298 async_handler_ptr->ready = 1;
299}
300
301/* See event-loop.h. */
302
303void
304clear_async_event_handler (async_event_handler *async_handler_ptr)
305{
6b01403b
SM
306 event_loop_debug_printf ("clearing async event handler `%s`",
307 async_handler_ptr->name);
93b54c8e
TT
308 async_handler_ptr->ready = 0;
309}
310
311/* Check if asynchronous event handlers are ready, and call the
312 handler function for one that is. */
313
314int
315check_async_event_handlers ()
316{
317 async_event_handler *async_handler_ptr;
318
319 for (async_handler_ptr = async_event_handler_list.first_handler;
320 async_handler_ptr != NULL;
321 async_handler_ptr = async_handler_ptr->next_handler)
322 {
323 if (async_handler_ptr->ready)
324 {
325 async_handler_ptr->ready = 0;
6b01403b
SM
326 event_loop_debug_printf ("invoking async event handler `%s`",
327 async_handler_ptr->name);
93b54c8e
TT
328 (*async_handler_ptr->proc) (async_handler_ptr->client_data);
329 return 1;
330 }
331 }
332
333 return 0;
334}
335
336/* Delete an asynchronous handler (ASYNC_HANDLER_PTR).
337 Free the space allocated for it. */
338void
339delete_async_event_handler (async_event_handler **async_handler_ptr)
340{
341 async_event_handler *prev_ptr;
342
343 if (async_event_handler_list.first_handler == *async_handler_ptr)
344 {
345 async_event_handler_list.first_handler
346 = (*async_handler_ptr)->next_handler;
347 if (async_event_handler_list.first_handler == NULL)
348 async_event_handler_list.last_handler = NULL;
349 }
350 else
351 {
352 prev_ptr = async_event_handler_list.first_handler;
353 while (prev_ptr && prev_ptr->next_handler != *async_handler_ptr)
354 prev_ptr = prev_ptr->next_handler;
355 gdb_assert (prev_ptr);
356 prev_ptr->next_handler = (*async_handler_ptr)->next_handler;
357 if (async_event_handler_list.last_handler == (*async_handler_ptr))
358 async_event_handler_list.last_handler = prev_ptr;
359 }
360 xfree (*async_handler_ptr);
361 *async_handler_ptr = NULL;
362}