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