async-event.c revision 1.1.1.1 1 /* Async events for the GDB event loop.
2 Copyright (C) 1999-2020 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
51 /* PROC is a function to be invoked when the READY flag is set. This
52 happens when the event has been marked with
53 MARK_ASYNC_EVENT_HANDLER. The actual work to be done in response
54 to an event will be carried out by PROC at a later time, within
55 process_event. This provides a deferred execution of event
56 handlers. */
57 struct async_event_handler
58 {
59 /* If ready, call this handler from the main event loop, using
60 invoke_event_handler. */
61 int ready;
62
63 /* Pointer to next handler. */
64 struct async_event_handler *next_handler;
65
66 /* Function to call to do the work. */
67 async_event_handler_func *proc;
68
69 /* Argument to PROC. */
70 gdb_client_data client_data;
71 };
72
73 /* All the async_signal_handlers gdb is interested in are kept onto
74 this list. */
75 static struct
76 {
77 /* Pointer to first in handler list. */
78 async_signal_handler *first_handler;
79
80 /* Pointer to last in handler list. */
81 async_signal_handler *last_handler;
82 }
83 sighandler_list;
84
85 /* All the async_event_handlers gdb is interested in are kept onto
86 this list. */
87 static struct
88 {
89 /* Pointer to first in handler list. */
90 async_event_handler *first_handler;
91
92 /* Pointer to last in handler list. */
93 async_event_handler *last_handler;
94 }
95 async_event_handler_list;
96
97
98 /* This event is signalled whenever an asynchronous handler needs to
99 defer an action to the event loop. */
100 static struct serial_event *async_signal_handlers_serial_event;
101
102 /* Callback registered with ASYNC_SIGNAL_HANDLERS_SERIAL_EVENT. */
103
104 static void
105 async_signals_handler (int error, gdb_client_data client_data)
106 {
107 /* Do nothing. Handlers are run by invoke_async_signal_handlers
108 from instead. */
109 }
110
111 void
112 initialize_async_signal_handlers (void)
113 {
114 async_signal_handlers_serial_event = make_serial_event ();
115
116 add_file_handler (serial_event_fd (async_signal_handlers_serial_event),
117 async_signals_handler, NULL);
118 }
119
120
121
123 /* Create an asynchronous handler, allocating memory for it.
124 Return a pointer to the newly created handler.
125 This pointer will be used to invoke the handler by
126 invoke_async_signal_handler.
127 PROC is the function to call with CLIENT_DATA argument
128 whenever the handler is invoked. */
129 async_signal_handler *
130 create_async_signal_handler (sig_handler_func * proc,
131 gdb_client_data client_data)
132 {
133 async_signal_handler *async_handler_ptr;
134
135 async_handler_ptr = XNEW (async_signal_handler);
136 async_handler_ptr->ready = 0;
137 async_handler_ptr->next_handler = NULL;
138 async_handler_ptr->proc = proc;
139 async_handler_ptr->client_data = client_data;
140 if (sighandler_list.first_handler == NULL)
141 sighandler_list.first_handler = async_handler_ptr;
142 else
143 sighandler_list.last_handler->next_handler = async_handler_ptr;
144 sighandler_list.last_handler = async_handler_ptr;
145 return async_handler_ptr;
146 }
147
148 /* Mark the handler (ASYNC_HANDLER_PTR) as ready. This information
149 will be used when the handlers are invoked, after we have waited
150 for some event. The caller of this function is the interrupt
151 handler associated with a signal. */
152 void
153 mark_async_signal_handler (async_signal_handler * async_handler_ptr)
154 {
155 async_handler_ptr->ready = 1;
156 serial_event_set (async_signal_handlers_serial_event);
157 }
158
159 /* See event-loop.h. */
160
161 void
162 clear_async_signal_handler (async_signal_handler *async_handler_ptr)
163 {
164 async_handler_ptr->ready = 0;
165 }
166
167 /* See event-loop.h. */
168
169 int
170 async_signal_handler_is_marked (async_signal_handler *async_handler_ptr)
171 {
172 return async_handler_ptr->ready;
173 }
174
175 /* Call all the handlers that are ready. Returns true if any was
176 indeed ready. */
177
178 int
179 invoke_async_signal_handlers (void)
180 {
181 async_signal_handler *async_handler_ptr;
182 int any_ready = 0;
183
184 /* We're going to handle all pending signals, so no need to wake up
185 the event loop again the next time around. Note this must be
186 cleared _before_ calling the callbacks, to avoid races. */
187 serial_event_clear (async_signal_handlers_serial_event);
188
189 /* Invoke all ready handlers. */
190
191 while (1)
192 {
193 for (async_handler_ptr = sighandler_list.first_handler;
194 async_handler_ptr != NULL;
195 async_handler_ptr = async_handler_ptr->next_handler)
196 {
197 if (async_handler_ptr->ready)
198 break;
199 }
200 if (async_handler_ptr == NULL)
201 break;
202 any_ready = 1;
203 async_handler_ptr->ready = 0;
204 /* Async signal handlers have no connection to whichever was the
205 current UI, and thus always run on the main one. */
206 current_ui = main_ui;
207 (*async_handler_ptr->proc) (async_handler_ptr->client_data);
208 }
209
210 return any_ready;
211 }
212
213 /* Delete an asynchronous handler (ASYNC_HANDLER_PTR).
214 Free the space allocated for it. */
215 void
216 delete_async_signal_handler (async_signal_handler ** async_handler_ptr)
217 {
218 async_signal_handler *prev_ptr;
219
220 if (sighandler_list.first_handler == (*async_handler_ptr))
221 {
222 sighandler_list.first_handler = (*async_handler_ptr)->next_handler;
223 if (sighandler_list.first_handler == NULL)
224 sighandler_list.last_handler = NULL;
225 }
226 else
227 {
228 prev_ptr = sighandler_list.first_handler;
229 while (prev_ptr && prev_ptr->next_handler != (*async_handler_ptr))
230 prev_ptr = prev_ptr->next_handler;
231 gdb_assert (prev_ptr);
232 prev_ptr->next_handler = (*async_handler_ptr)->next_handler;
233 if (sighandler_list.last_handler == (*async_handler_ptr))
234 sighandler_list.last_handler = prev_ptr;
235 }
236 xfree ((*async_handler_ptr));
237 (*async_handler_ptr) = NULL;
238 }
239
240 /* Create an asynchronous event handler, allocating memory for it.
241 Return a pointer to the newly created handler. PROC is the
242 function to call with CLIENT_DATA argument whenever the handler is
243 invoked. */
244 async_event_handler *
245 create_async_event_handler (async_event_handler_func *proc,
246 gdb_client_data client_data)
247 {
248 async_event_handler *h;
249
250 h = XNEW (struct async_event_handler);
251 h->ready = 0;
252 h->next_handler = NULL;
253 h->proc = proc;
254 h->client_data = client_data;
255 if (async_event_handler_list.first_handler == NULL)
256 async_event_handler_list.first_handler = h;
257 else
258 async_event_handler_list.last_handler->next_handler = h;
259 async_event_handler_list.last_handler = h;
260 return h;
261 }
262
263 /* Mark the handler (ASYNC_HANDLER_PTR) as ready. This information
264 will be used by gdb_do_one_event. The caller will be whoever
265 created the event source, and wants to signal that the event is
266 ready to be handled. */
267 void
268 mark_async_event_handler (async_event_handler *async_handler_ptr)
269 {
270 async_handler_ptr->ready = 1;
271 }
272
273 /* See event-loop.h. */
274
275 void
276 clear_async_event_handler (async_event_handler *async_handler_ptr)
277 {
278 async_handler_ptr->ready = 0;
279 }
280
281 /* Check if asynchronous event handlers are ready, and call the
282 handler function for one that is. */
283
284 int
285 check_async_event_handlers ()
286 {
287 async_event_handler *async_handler_ptr;
288
289 for (async_handler_ptr = async_event_handler_list.first_handler;
290 async_handler_ptr != NULL;
291 async_handler_ptr = async_handler_ptr->next_handler)
292 {
293 if (async_handler_ptr->ready)
294 {
295 async_handler_ptr->ready = 0;
296 (*async_handler_ptr->proc) (async_handler_ptr->client_data);
297 return 1;
298 }
299 }
300
301 return 0;
302 }
303
304 /* Delete an asynchronous handler (ASYNC_HANDLER_PTR).
305 Free the space allocated for it. */
306 void
307 delete_async_event_handler (async_event_handler **async_handler_ptr)
308 {
309 async_event_handler *prev_ptr;
310
311 if (async_event_handler_list.first_handler == *async_handler_ptr)
312 {
313 async_event_handler_list.first_handler
314 = (*async_handler_ptr)->next_handler;
315 if (async_event_handler_list.first_handler == NULL)
316 async_event_handler_list.last_handler = NULL;
317 }
318 else
319 {
320 prev_ptr = async_event_handler_list.first_handler;
321 while (prev_ptr && prev_ptr->next_handler != *async_handler_ptr)
322 prev_ptr = prev_ptr->next_handler;
323 gdb_assert (prev_ptr);
324 prev_ptr->next_handler = (*async_handler_ptr)->next_handler;
325 if (async_event_handler_list.last_handler == (*async_handler_ptr))
326 async_event_handler_list.last_handler = prev_ptr;
327 }
328 xfree (*async_handler_ptr);
329 *async_handler_ptr = NULL;
330 }
331