]> Git Repo - binutils.git/blob - gdb/async-event.c
gdb: remove SYMBOL_CLASS macro, add getter
[binutils.git] / gdb / async-event.c
1 /* Async events for the GDB event loop.
2    Copyright (C) 1999-2022 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   /* User-friendly name of this handler.  */
51   const char *name;
52 };
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.  */
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;
65
66   /* Pointer to next handler.  */
67   struct async_event_handler *next_handler;
68
69   /* Function to call to do the work.  */
70   async_event_handler_func *proc;
71
72   /* Argument to PROC.  */
73   gdb_client_data client_data;
74
75   /* User-friendly name of this handler.  */
76   const char *name;
77 };
78
79 /* All the async_signal_handlers gdb is interested in are kept onto
80    this list.  */
81 static struct
82 {
83   /* Pointer to first in handler list.  */
84   async_signal_handler *first_handler;
85
86   /* Pointer to last in handler list.  */
87   async_signal_handler *last_handler;
88 }
89 sighandler_list;
90
91 /* All the async_event_handlers gdb is interested in are kept onto
92    this list.  */
93 static struct
94 {
95   /* Pointer to first in handler list.  */
96   async_event_handler *first_handler;
97
98   /* Pointer to last in handler list.  */
99   async_event_handler *last_handler;
100 }
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),
123                     async_signals_handler, NULL, "async-signals");
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,
136                              gdb_client_data client_data,
137                              const char *name)
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;
146   async_handler_ptr->name = name;
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
160 mark_async_signal_handler (async_signal_handler *async_handler_ptr)
161 {
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
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 {
186   event_loop_debug_printf ("clearing async signal handler `%s`",
187                            async_handler_ptr->name);
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;
231       event_loop_debug_printf ("invoking async signal handler `%s`",
232                                async_handler_ptr->name);
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
266 /* See async-event.h.  */
267
268 async_event_handler *
269 create_async_event_handler (async_event_handler_func *proc,
270                             gdb_client_data client_data,
271                             const char *name)
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;
280   h->name = name;
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 {
296   event_loop_debug_printf ("marking async event handler `%s`",
297                            async_handler_ptr->name);
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 {
306   event_loop_debug_printf ("clearing async event handler `%s`",
307                            async_handler_ptr->name);
308   async_handler_ptr->ready = 0;
309 }
310
311 /* See event-loop.h.  */
312
313 bool
314 async_event_handler_marked (async_event_handler *handler)
315 {
316   return handler->ready;
317 }
318
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         {
333           event_loop_debug_printf ("invoking async event handler `%s`",
334                                    async_handler_ptr->name);
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 }
This page took 0.044477 seconds and 4 git commands to generate.