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