]>
Commit | Line | Data |
---|---|---|
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 |
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; | |
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 |
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; | |
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. */ | |
81 | static 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 |
89 | sighandler_list; |
90 | ||
91 | /* All the async_event_handlers gdb is interested in are kept onto | |
92 | this list. */ | |
93 | static 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 |
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), | |
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. */ | |
134 | async_signal_handler * | |
135 | create_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. */ | |
159 | void | |
6b01403b | 160 | mark_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 | ||
183 | void | |
184 | clear_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 | ||
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; | |
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. */ | |
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 | ||
db20ebdf SM |
266 | /* See async-event.h. */ |
267 | ||
93b54c8e TT |
268 | async_event_handler * |
269 | create_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. */ | |
293 | void | |
294 | mark_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 | ||
303 | void | |
304 | clear_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 | ||
b4b1a226 SM |
311 | /* See event-loop.h. */ |
312 | ||
313 | bool | |
314 | async_event_handler_marked (async_event_handler *handler) | |
315 | { | |
316 | return handler->ready; | |
317 | } | |
318 | ||
93b54c8e TT |
319 | /* Check if asynchronous event handlers are ready, and call the |
320 | handler function for one that is. */ | |
321 | ||
322 | int | |
323 | check_async_event_handlers () | |
324 | { | |
325 | async_event_handler *async_handler_ptr; | |
326 | ||
327 | for (async_handler_ptr = async_event_handler_list.first_handler; | |
328 | async_handler_ptr != NULL; | |
329 | async_handler_ptr = async_handler_ptr->next_handler) | |
330 | { | |
331 | if (async_handler_ptr->ready) | |
332 | { | |
6b01403b SM |
333 | event_loop_debug_printf ("invoking async event handler `%s`", |
334 | async_handler_ptr->name); | |
93b54c8e TT |
335 | (*async_handler_ptr->proc) (async_handler_ptr->client_data); |
336 | return 1; | |
337 | } | |
338 | } | |
339 | ||
340 | return 0; | |
341 | } | |
342 | ||
343 | /* Delete an asynchronous handler (ASYNC_HANDLER_PTR). | |
344 | Free the space allocated for it. */ | |
345 | void | |
346 | delete_async_event_handler (async_event_handler **async_handler_ptr) | |
347 | { | |
348 | async_event_handler *prev_ptr; | |
349 | ||
350 | if (async_event_handler_list.first_handler == *async_handler_ptr) | |
351 | { | |
352 | async_event_handler_list.first_handler | |
353 | = (*async_handler_ptr)->next_handler; | |
354 | if (async_event_handler_list.first_handler == NULL) | |
355 | async_event_handler_list.last_handler = NULL; | |
356 | } | |
357 | else | |
358 | { | |
359 | prev_ptr = async_event_handler_list.first_handler; | |
360 | while (prev_ptr && prev_ptr->next_handler != *async_handler_ptr) | |
361 | prev_ptr = prev_ptr->next_handler; | |
362 | gdb_assert (prev_ptr); | |
363 | prev_ptr->next_handler = (*async_handler_ptr)->next_handler; | |
364 | if (async_event_handler_list.last_handler == (*async_handler_ptr)) | |
365 | async_event_handler_list.last_handler = prev_ptr; | |
366 | } | |
367 | xfree (*async_handler_ptr); | |
368 | *async_handler_ptr = NULL; | |
369 | } |