import gdb-1999-09-13 snapshot
[platform/upstream/binutils.git] / gdb / event-loop.c
1 /* Event loop machinery for GDB, the GNU debugger.
2    Copyright 1999 Free Software Foundation, Inc.
3    Written by Elena Zannoni <ezannoni@cygnus.com> of Cygnus Solutions.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA. */
21
22 #include "defs.h"
23 #include "top.h"
24 #include "event-loop.h"
25 #ifdef HAVE_POLL
26 #include <poll.h>
27 #else
28 #include <sys/types.h>
29 #endif
30 #include <errno.h>
31 #include <setjmp.h>
32
33 /* Event queue:  
34    - the first event in the queue is the head of the queue. 
35    It will be the next to be serviced.
36    - the last event in the queue 
37
38    Events can be inserted at the front of the queue or at the end of
39    the queue.  Events will be extracted from the queue for processing
40    starting from the head.  Therefore, events inserted at the head of
41    the queue will be processed in a last in first out fashion, while
42    those inserted at the tail of the queue will be processed in a first
43    in first out manner.  All the fields are NULL if the queue is
44    empty. */
45
46 static struct
47   {
48     gdb_event *first_event;     /* First pending event */
49     gdb_event *last_event;      /* Last pending event */
50   }
51 event_queue;
52
53 /* Gdb_notifier is just a list of file descriptors gdb is interested in.
54    These are the input file descriptor, and the target file
55    descriptor. We have two flavors of the notifier, one for platforms
56    that have the POLL function, the other for those that don't, and
57    only support SELECT. Each of the elements in the gdb_notifier list is
58    basically a description of what kind of events gdb is interested
59    in, for each fd. */
60
61 /* As of 1999-04-30 only the input file descriptor is registered with the
62    event loop. */
63
64 #ifdef HAVE_POLL
65 /* Poll based implementation of the notifier. */
66
67 static struct
68   {
69     /* Ptr to head of file handler list. */
70     file_handler *first_file_handler;
71
72     /* Ptr to array of pollfd structures. */
73     struct pollfd *poll_fds;
74
75     /* Number of file descriptors to monitor. */
76     int num_fds;
77
78   }
79 gdb_notifier;
80
81 #else /* ! HAVE_POLL */
82
83 /* Select based implementation of the notifier. */
84
85 static struct
86   {
87     /* Ptr to head of file handler list. */
88     file_handler *first_file_handler;
89
90     /* Masks to be used in the next call to select.
91        Bits are set in response to calls to create_file_handler. */
92     fd_mask check_masks[3 * MASK_SIZE];
93
94     /* What file descriptors were found ready by select. */
95     fd_mask ready_masks[3 * MASK_SIZE];
96
97     /* Number of valid bits (highest fd value + 1). */
98     int num_fds;
99
100   }
101 gdb_notifier;
102
103 #endif /* HAVE_POLL */
104
105 /* All the async_signal_handlers gdb is interested in are kept onto
106    this list. */
107 static struct
108   {
109     /* Pointer to first in handler list. */
110     async_signal_handler *first_handler;
111
112     /* Pointer to last in handler list. */
113     async_signal_handler *last_handler;
114   }
115 sighandler_list;
116
117 /* Is any of the handlers ready?  Check this variable using
118    check_async_ready. This is used by process_event, to determine
119    whether or not to invoke the invoke_async_signal_handler
120    function. */
121 static int async_handler_ready = 0;
122
123 static void create_file_handler PARAMS ((int, int, handler_func *, gdb_client_data));
124 static void invoke_async_signal_handler PARAMS ((void));
125 static void handle_file_event PARAMS ((int));
126 static int gdb_wait_for_event PARAMS ((void));
127 static int gdb_do_one_event PARAMS ((void));
128 static int check_async_ready PARAMS ((void));
129 \f
130
131 /* Insert an event object into the gdb event queue at 
132    the specified position.
133    POSITION can be head or tail, with values TAIL, HEAD.
134    EVENT_PTR points to the event to be inserted into the queue.
135    The caller must allocate memory for the event. It is freed
136    after the event has ben handled.
137    Events in the queue will be processed head to tail, therefore,
138    events inserted at the head of the queue will be processed
139    as last in first out. Event appended at the tail of the queue
140    will be processed first in first out. */
141 static void
142 async_queue_event (event_ptr, position)
143      gdb_event *event_ptr;
144      queue_position position;
145 {
146   if (position == TAIL)
147     {
148       /* The event will become the new last_event. */
149
150       event_ptr->next_event = NULL;
151       if (event_queue.first_event == NULL)
152         event_queue.first_event = event_ptr;
153       else
154         event_queue.last_event->next_event = event_ptr;
155       event_queue.last_event = event_ptr;
156     }
157   else if (position == HEAD)
158     {
159       /* The event becomes the new first_event. */
160
161       event_ptr->next_event = event_queue.first_event;
162       if (event_queue.first_event == NULL)
163         event_queue.last_event = event_ptr;
164       event_queue.first_event = event_ptr;
165     }
166 }
167
168 /* Create a file event, to be enqueued in the event queue for
169    processing. The procedure associated to this event is always
170    handle_file_event, which will in turn invoke the one that was
171    associated to FD when it was registered with the event loop. */
172 gdb_event *
173 create_file_event (fd)
174      int fd;
175 {
176   gdb_event *file_event_ptr;
177
178   file_event_ptr = (gdb_event *) xmalloc (sizeof (gdb_event));
179   file_event_ptr->proc = handle_file_event;
180   file_event_ptr->fd = fd;
181   return (file_event_ptr);
182 }
183
184 /* Process one event.
185    The event can be the next one to be serviced in the event queue,
186    or an asynchronous event handler can be invoked in response to
187    the reception of a signal.
188    If an event was processed (either way), 1 is returned otherwise
189    0 is returned.   
190    Scan the queue from head to tail, processing therefore the high
191    priority events first, by invoking the associated event handler
192    procedure. */
193 static int
194 process_event ()
195 {
196   gdb_event *event_ptr, *prev_ptr;
197   event_handler_func *proc;
198   int fd;
199
200   /* First let's see if there are any asynchronous event handlers that
201      are ready. These would be the result of invoking any of the
202      signal handlers. */
203
204   if (check_async_ready ())
205     {
206       invoke_async_signal_handler ();
207       return 1;
208     }
209
210   /* Look in the event queue to find an event that is ready
211      to be processed. */
212
213   for (event_ptr = event_queue.first_event; event_ptr != NULL;
214        event_ptr = event_ptr->next_event)
215     {
216       /* Call the handler for the event. */
217
218       proc = event_ptr->proc;
219       fd = event_ptr->fd;
220
221       /* Let's get rid of the event from the event queue.  We need to
222          do this now because while processing the event, the proc
223          function could end up calling 'error' and therefore jump out
224          to the caller of this function, gdb_do_one_event. In that
225          case, we would have on the event queue an event wich has been
226          processed, but not deleted. */
227
228       if (event_queue.first_event == event_ptr)
229         {
230           event_queue.first_event = event_ptr->next_event;
231           if (event_ptr->next_event == NULL)
232             event_queue.last_event = NULL;
233         }
234       else
235         {
236           prev_ptr = event_queue.first_event;
237           while (prev_ptr->next_event != event_ptr)
238             prev_ptr = prev_ptr->next_event;
239
240           prev_ptr->next_event = event_ptr->next_event;
241           if (event_ptr->next_event == NULL)
242             event_queue.last_event = prev_ptr;
243         }
244       free ((char *) event_ptr);
245
246       /* Now call the procedure associted with the event. */
247       (*proc) (fd);
248       return 1;
249     }
250
251   /* this is the case if there are no event on the event queue. */
252   return 0;
253 }
254
255 /* Process one high level event.  If nothing is ready at this time,
256    wait for something to happen (via gdb_wait_for_event), then process
257    it.  Returns 1 if something was done otherwise returns 0 (this can
258    happen if there are no event sources to wait for). */
259 static int
260 gdb_do_one_event ()
261 {
262   int result = 0;
263
264   while (1)
265     {
266       if (!SET_TOP_LEVEL ())
267         {
268           /* Any events already waiting in the queue? */
269           if (process_event ())
270             {
271               result = 1;
272               break;
273             }
274
275           /* Wait for a new event.  If gdb_wait_for_event returns -1,
276              we should get out because this means that there are no
277              event sources left. This will make the event loop stop,
278              and the application exit. */
279
280           result = gdb_wait_for_event ();
281           if (result < 0)
282             {
283               result = 0;
284               break;
285             }
286
287           /* Handle any new events occurred while waiting. */
288           if (process_event ())
289             {
290               result = 1;
291               break;
292             }
293
294           /* If gdb_wait_for_event has returned 1, it means that one
295              event has been handled. We break out of the loop. */
296           if (result)
297             break;
298         }                       /* end of if !set_top_level */
299       else
300         {
301           /* FIXME: this should really be a call to a hook that is
302              interface specific, because interfaces can display the
303              prompt in their own way. */
304           display_gdb_prompt (0);
305           /* Maybe better to set a flag to be checked somewhere as to
306              whether display the prompt or not. */
307         }
308     }
309   return result;
310 }
311 \f
312
313 /* Start up the event loop. This is the entry point to the event loop
314    from the command loop. */
315 void
316 start_event_loop ()
317 {
318   /* Loop until there is something to do. This is the entry point to
319      the event loop engine. gdb_do_one_event will process one event
320      for each invocation.  It always returns 1, unless there are no
321      more event sources registered. In this case it returns 0.  */
322   while (gdb_do_one_event () != 0)
323     ;
324
325   /* We are done with the event loop. There are no more event sources
326      to listen to.  So we exit GDB. */
327   return;
328 }
329 \f
330
331
332 /* Wrapper function for create_file_handler, so that the caller
333    doesn't have to know implementation details about the use of poll
334    vs. select. */
335 void
336 add_file_handler (fd, proc, client_data)
337      int fd;
338      void (*proc) (void);
339      gdb_client_data client_data;
340 {
341 #ifdef HAVE_POLL
342   create_file_handler (fd, POLLIN, (handler_func *) proc, client_data);
343 #else
344   create_file_handler (fd, GDB_READABLE, (handler_func *) proc, client_data);
345 #endif
346 }
347
348 /* Add a file handler/descriptor to the list of descriptors we are
349    interested in.  
350    FD is the file descriptor for the file/stream to be listened to.  
351    For the poll case, MASK is a combination (OR) of
352    POLLIN, POLLRDNORM, POLLRDBAND, POLLPRI, POLLOUT, POLLWRNORM,
353    POLLWRBAND: these are the events we are interested in. If any of them 
354    occurs, proc should be called.
355    For the select case, MASK is a combination of READABLE, WRITABLE, EXCEPTION.
356    PROC is the procedure that will be called when an event occurs for
357    FD.  CLIENT_DATA is the argument to pass to PROC. */
358 static void
359 create_file_handler (fd, mask, proc, client_data)
360      int fd;
361      int mask;
362      handler_func *proc;
363      gdb_client_data client_data;
364 {
365   file_handler *file_ptr;
366
367 #ifndef HAVE_POLL
368   int index, bit;
369 #endif
370
371   /* Do we already have a file handler for this file? (We may be
372      changing its associated procedure). */
373   for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL;
374        file_ptr = file_ptr->next_file)
375     {
376       if (file_ptr->fd == fd)
377         break;
378     }
379
380   /* It is a new file descriptor. */
381   if (file_ptr == NULL)
382     {
383       file_ptr = (file_handler *) xmalloc (sizeof (file_handler));
384       file_ptr->fd = fd;
385       file_ptr->ready_mask = 0;
386       file_ptr->next_file = gdb_notifier.first_file_handler;
387       gdb_notifier.first_file_handler = file_ptr;
388     }
389   file_ptr->proc = proc;
390   file_ptr->client_data = client_data;
391   file_ptr->mask = mask;
392
393 #ifdef HAVE_POLL
394
395   gdb_notifier.num_fds++;
396   if (gdb_notifier.poll_fds)
397     gdb_notifier.poll_fds =
398       (struct pollfd *) realloc (gdb_notifier.poll_fds,
399                            (gdb_notifier.num_fds) * sizeof (struct pollfd));
400   else
401     gdb_notifier.poll_fds =
402       (struct pollfd *) xmalloc (sizeof (struct pollfd));
403   (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->fd = fd;
404   (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->events = mask;
405   (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->revents = 0;
406
407 #else /* ! HAVE_POLL */
408
409   index = fd / (NBBY * sizeof (fd_mask));
410   bit = 1 << (fd % (NBBY * sizeof (fd_mask)));
411
412   if (mask & GDB_READABLE)
413     gdb_notifier.check_masks[index] |= bit;
414   else
415     gdb_notifier.check_masks[index] &= ~bit;
416
417   if (mask & GDB_WRITABLE)
418     (gdb_notifier.check_masks + MASK_SIZE)[index] |= bit;
419   else
420     (gdb_notifier.check_masks + MASK_SIZE)[index] &= ~bit;
421
422   if (mask & GDB_EXCEPTION)
423     (gdb_notifier.check_masks + 2 * (MASK_SIZE))[index] |= bit;
424   else
425     (gdb_notifier.check_masks + 2 * (MASK_SIZE))[index] &= ~bit;
426
427   if (gdb_notifier.num_fds <= fd)
428     gdb_notifier.num_fds = fd + 1;
429
430 #endif /* HAVE_POLL */
431 }
432
433 /* Remove the file descriptor FD from the list of monitored fd's: 
434    i.e. we don't care anymore about events on the FD. */
435 void
436 delete_file_handler (fd)
437      int fd;
438 {
439   file_handler *file_ptr, *prev_ptr = NULL;
440   int i, j;
441   struct pollfd *new_poll_fds;
442 #ifndef HAVE_POLL
443   int index, bit;
444   unsigned long flags;
445 #endif
446
447   /* Find the entry for the given file. */
448
449   for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL;
450        file_ptr = file_ptr->next_file)
451     {
452       if (file_ptr->fd == fd)
453         break;
454     }
455
456   if (file_ptr == NULL)
457     return;
458
459 #ifdef HAVE_POLL
460   /* Create a new poll_fds array by copying every fd's information but the
461      one we want to get rid of. */
462
463   new_poll_fds =
464     (struct pollfd *) xmalloc ((gdb_notifier.num_fds - 1) * sizeof (struct pollfd));
465
466   for (i = 0, j = 0; i < gdb_notifier.num_fds; i++)
467     {
468       if ((gdb_notifier.poll_fds + i)->fd != fd)
469         {
470           (new_poll_fds + j)->fd = (gdb_notifier.poll_fds + i)->fd;
471           (new_poll_fds + j)->events = (gdb_notifier.poll_fds + i)->events;
472           (new_poll_fds + j)->revents = (gdb_notifier.poll_fds + i)->revents;
473           j++;
474         }
475     }
476   free (gdb_notifier.poll_fds);
477   gdb_notifier.poll_fds = new_poll_fds;
478   gdb_notifier.num_fds--;
479
480 #else /* ! HAVE_POLL */
481
482   index = fd / (NBBY * sizeof (fd_mask));
483   bit = 1 << (fd % (NBBY * sizeof (fd_mask)));
484
485   if (file_ptr->mask & GDB_READABLE)
486     gdb_notifier.check_masks[index] &= ~bit;
487   if (file_ptr->mask & GDB_WRITABLE)
488     (gdb_notifier.check_masks + MASK_SIZE)[index] &= ~bit;
489   if (file_ptr->mask & GDB_EXCEPTION)
490     (gdb_notifier.check_masks + 2 * (MASK_SIZE))[index] &= ~bit;
491
492   /* Find current max fd. */
493
494   if ((fd + 1) == gdb_notifier.num_fds)
495     {
496       for (gdb_notifier.num_fds = 0; index >= 0; index--)
497         {
498           flags = gdb_notifier.check_masks[index]
499             | (gdb_notifier.check_masks + MASK_SIZE)[index]
500             | (gdb_notifier.check_masks + 2 * (MASK_SIZE))[index];
501           if (flags)
502             {
503               for (i = (NBBY * sizeof (fd_mask)); i > 0; i--)
504                 {
505                   if (flags & (((unsigned long) 1) << (i - 1)))
506                     break;
507                 }
508               gdb_notifier.num_fds = index * (NBBY * sizeof (fd_mask)) + i;
509               break;
510             }
511         }
512     }
513 #endif /* HAVE_POLL */
514
515   /* Deactivate the file descriptor, by clearing its mask, 
516      so that it will not fire again. */
517
518   file_ptr->mask = 0;
519
520   /* Get rid of the file handler in the file handler list. */
521   if (file_ptr == gdb_notifier.first_file_handler)
522     gdb_notifier.first_file_handler = file_ptr->next_file;
523   else
524     {
525       for (prev_ptr = gdb_notifier.first_file_handler;
526            prev_ptr->next_file != file_ptr;
527            prev_ptr = prev_ptr->next_file)
528         ;
529       prev_ptr->next_file = file_ptr->next_file;
530     }
531   free ((char *) file_ptr);
532 }
533
534 /* Handle the given event by calling the procedure associated to the
535    corresponding file handler.  Called by process_event indirectly,
536    through event_ptr->proc.  EVENT_FILE_DESC is file descriptor of the
537    event in the front of the event queue. */
538 static void
539 handle_file_event (event_file_desc)
540      int event_file_desc;
541 {
542   file_handler *file_ptr;
543   int mask, error_mask;
544
545   /* Search the file handler list to find one that matches the fd in
546      the event. */
547   for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL;
548        file_ptr = file_ptr->next_file)
549     {
550       if (file_ptr->fd == event_file_desc)
551         {
552           /* With poll, the ready_mask could have any of three events
553              set to 1: POLLHUP, POLLERR, POLLNVAL. These events cannot
554              be used in the requested event mask (events), but they
555              can be returned in the return mask (revents). We need to
556              check for those event too, and add them to the mask which
557              will be passed to the handler. */
558
559           /* See if the desired events (mask) match the received
560              events (ready_mask). */
561
562 #ifdef HAVE_POLL
563           error_mask = POLLHUP | POLLERR | POLLNVAL;
564           mask = (file_ptr->ready_mask & file_ptr->mask) |
565             (file_ptr->ready_mask & error_mask);
566
567 #else /* ! HAVE_POLL */
568           mask = file_ptr->ready_mask & file_ptr->mask;
569 #endif /* HAVE_POLL */
570
571           /* Clear the received events for next time around. */
572           file_ptr->ready_mask = 0;
573
574           /* If there was a match, then call the handler. */
575           if (mask != 0)
576             (*file_ptr->proc) (file_ptr->client_data);
577           break;
578         }
579     }
580 }
581
582 /* Called by gdb_do_one_event to wait for new events on the 
583    monitored file descriptors. Queue file events as they are 
584    detected by the poll. 
585    If there are no events, this function will block in the 
586    call to poll.
587    Return -1 if there are no files descriptors to monitor, 
588    otherwise return 0. */
589 static int
590 gdb_wait_for_event ()
591 {
592   file_handler *file_ptr;
593   gdb_event *file_event_ptr;
594   int num_found = 0;
595   int i;
596
597 #ifndef HAVE_POLL
598   int mask, bit, index;
599 #endif
600
601   /* Make sure all output is done before getting another event. */
602   gdb_flush (gdb_stdout);
603   gdb_flush (gdb_stderr);
604
605   if (gdb_notifier.num_fds == 0)
606     return -1;
607
608 #ifdef HAVE_POLL
609   num_found =
610     poll (gdb_notifier.poll_fds, (unsigned long) gdb_notifier.num_fds, -1);
611
612 #else /* ! HAVE_POLL */
613   memcpy (gdb_notifier.ready_masks,
614           gdb_notifier.check_masks,
615           3 * MASK_SIZE * sizeof (fd_mask));
616   num_found = select (gdb_notifier.num_fds,
617                       (SELECT_MASK *) & gdb_notifier.ready_masks[0],
618                       (SELECT_MASK *) & gdb_notifier.ready_masks[MASK_SIZE],
619                   (SELECT_MASK *) & gdb_notifier.ready_masks[2 * MASK_SIZE],
620                       NULL);
621
622   /* Clear the masks after an error from select. */
623   if (num_found == -1)
624     memset (gdb_notifier.ready_masks,
625             0, 3 * MASK_SIZE * sizeof (fd_mask));
626
627 #endif /* HAVE_POLL */
628
629   /* Enqueue all detected file events. */
630
631 #ifdef HAVE_POLL
632
633   for (i = 0; (i < gdb_notifier.num_fds) && (num_found > 0); i++)
634     {
635       if ((gdb_notifier.poll_fds + i)->revents)
636         num_found--;
637       else
638         continue;
639
640       for (file_ptr = gdb_notifier.first_file_handler;
641            file_ptr != NULL;
642            file_ptr = file_ptr->next_file)
643         {
644           if (file_ptr->fd == (gdb_notifier.poll_fds + i)->fd)
645             break;
646         }
647
648       if (file_ptr)
649         {
650           /* Enqueue an event only if this is still a new event for
651              this fd. */
652           if (file_ptr->ready_mask == 0)
653             {
654               file_event_ptr = create_file_event (file_ptr->fd);
655               async_queue_event (file_event_ptr, TAIL);
656             }
657         }
658
659       file_ptr->ready_mask = (gdb_notifier.poll_fds + i)->revents;
660     }
661
662 #else /* ! HAVE_POLL */
663   for (file_ptr = gdb_notifier.first_file_handler;
664        (file_ptr != NULL) && (num_found > 0);
665        file_ptr = file_ptr->next_file)
666     {
667       index = file_ptr->fd / (NBBY * sizeof (fd_mask));
668       bit = 1 << (file_ptr->fd % (NBBY * sizeof (fd_mask)));
669       mask = 0;
670
671       if (gdb_notifier.ready_masks[index] & bit)
672         mask |= GDB_READABLE;
673       if ((gdb_notifier.ready_masks + MASK_SIZE)[index] & bit)
674         mask |= GDB_WRITABLE;
675       if ((gdb_notifier.ready_masks + 2 * (MASK_SIZE))[index] & bit)
676         mask |= GDB_EXCEPTION;
677
678       if (!mask)
679         continue;
680       else
681         num_found--;
682
683       /* Enqueue an event only if this is still a new event for
684          this fd. */
685
686       if (file_ptr->ready_mask == 0)
687         {
688           file_event_ptr = create_file_event (file_ptr->fd);
689           async_queue_event (file_event_ptr, TAIL);
690         }
691       file_ptr->ready_mask = mask;
692     }
693 #endif /* HAVE_POLL */
694
695   return 0;
696 }
697 \f
698
699 /* Create an asynchronous handler, allocating memory for it. 
700    Return a pointer to the newly created handler.
701    This pointer will be used to invoke the handler by 
702    invoke_async_signal_handler.
703    PROC is the function to call with CLIENT_DATA argument 
704    whenever the handler is invoked. */
705 async_signal_handler *
706 create_async_signal_handler (proc, client_data)
707      handler_func *proc;
708      gdb_client_data client_data;
709 {
710   async_signal_handler *async_handler_ptr;
711
712   async_handler_ptr =
713     (async_signal_handler *) xmalloc (sizeof (async_signal_handler));
714   async_handler_ptr->ready = 0;
715   async_handler_ptr->next_handler = NULL;
716   async_handler_ptr->proc = proc;
717   async_handler_ptr->client_data = client_data;
718   if (sighandler_list.first_handler == NULL)
719     sighandler_list.first_handler = async_handler_ptr;
720   else
721     sighandler_list.last_handler->next_handler = async_handler_ptr;
722   sighandler_list.last_handler = async_handler_ptr;
723   return async_handler_ptr;
724 }
725
726 /* Mark the handler (ASYNC_HANDLER_PTR) as ready. This information will
727    be used when the handlers are invoked, after we have waited for
728    some event.  The caller of this function is the interrupt handler
729    associated with a signal. */
730 void
731 mark_async_signal_handler (async_handler_ptr)
732      async_signal_handler *async_handler_ptr;
733 {
734   ((async_signal_handler *) async_handler_ptr)->ready = 1;
735   async_handler_ready = 1;
736 }
737
738 /* Call all the handlers that are ready. */
739 static void
740 invoke_async_signal_handler ()
741 {
742   async_signal_handler *async_handler_ptr;
743
744   if (async_handler_ready == 0)
745     return;
746   async_handler_ready = 0;
747
748   /* Invoke ready handlers. */
749
750   while (1)
751     {
752       for (async_handler_ptr = sighandler_list.first_handler;
753            async_handler_ptr != NULL;
754            async_handler_ptr = async_handler_ptr->next_handler)
755         {
756           if (async_handler_ptr->ready)
757             break;
758         }
759       if (async_handler_ptr == NULL)
760         break;
761       async_handler_ptr->ready = 0;
762       (*async_handler_ptr->proc) (async_handler_ptr->client_data);
763     }
764
765   return;
766 }
767
768 /* Delete an asynchronous handler (ASYNC_HANDLER_PTR). 
769    Free the space allocated for it.  */
770 void
771 delete_async_signal_handler (async_handler_ptr)
772      async_signal_handler **async_handler_ptr;
773 {
774   async_signal_handler *prev_ptr;
775
776   if (sighandler_list.first_handler == (*async_handler_ptr))
777     {
778       sighandler_list.first_handler = (*async_handler_ptr)->next_handler;
779       if (sighandler_list.first_handler == NULL)
780         sighandler_list.last_handler = NULL;
781     }
782   else
783     {
784       prev_ptr = sighandler_list.first_handler;
785       while (prev_ptr->next_handler != (*async_handler_ptr) && prev_ptr)
786         prev_ptr = prev_ptr->next_handler;
787       prev_ptr->next_handler = (*async_handler_ptr)->next_handler;
788       if (sighandler_list.last_handler == (*async_handler_ptr))
789         sighandler_list.last_handler = prev_ptr;
790     }
791   free ((char *) (*async_handler_ptr));
792   (*async_handler_ptr) = NULL;
793 }
794
795 /* Is it necessary to call invoke_async_signal_handler? */
796 static int
797 check_async_ready ()
798 {
799   return async_handler_ready;
800 }