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