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