xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/async-event.c (revision 7d62b00eb9ad855ffcd7da46b41e23feb5476fac)
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 
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 }
330