+/* Create an asynchronous event handler, allocating memory for it.
+ Return a pointer to the newly created handler. PROC is the
+ function to call with CLIENT_DATA argument whenever the handler is
+ invoked. */
+async_event_handler *
+create_async_event_handler (async_event_handler_func *proc,
+ gdb_client_data client_data)
+{
+ async_event_handler *h;
+
+ h = xmalloc (sizeof (*h));
+ h->ready = 0;
+ h->next_handler = NULL;
+ h->proc = proc;
+ h->client_data = client_data;
+ if (async_event_handler_list.first_handler == NULL)
+ async_event_handler_list.first_handler = h;
+ else
+ async_event_handler_list.last_handler->next_handler = h;
+ async_event_handler_list.last_handler = h;
+ return h;
+}
+
+/* Mark the handler (ASYNC_HANDLER_PTR) as ready. This information
+ will be used by gdb_do_one_event. The caller will be whoever
+ created the event source, and wants to signal that the event is
+ ready to be handled. */
+void
+mark_async_event_handler (async_event_handler *async_handler_ptr)
+{
+ async_handler_ptr->ready = 1;
+}
+
+struct async_event_handler_data
+{
+ async_event_handler_func* proc;
+ gdb_client_data client_data;
+};
+
+static void
+invoke_async_event_handler (event_data data)
+{
+ struct async_event_handler_data *hdata = data.ptr;
+ async_event_handler_func* proc = hdata->proc;
+ gdb_client_data client_data = hdata->client_data;
+
+ xfree (hdata);
+ (*proc) (client_data);
+}
+
+/* Check if any asynchronous event handlers are ready, and queue
+ events in the ready queue for any that are. */
+static void
+check_async_event_handlers (void)
+{
+ async_event_handler *async_handler_ptr;
+ struct async_event_handler_data *hdata;
+ struct gdb_event *event_ptr;
+ event_data data;
+
+ for (async_handler_ptr = async_event_handler_list.first_handler;
+ async_handler_ptr != NULL;
+ async_handler_ptr = async_handler_ptr->next_handler)
+ {
+ if (async_handler_ptr->ready)
+ {
+ async_handler_ptr->ready = 0;
+
+ hdata = xmalloc (sizeof (*hdata));
+
+ hdata->proc = async_handler_ptr->proc;
+ hdata->client_data = async_handler_ptr->client_data;
+
+ data.ptr = hdata;
+
+ event_ptr = create_event (invoke_async_event_handler, data);
+ QUEUE_enque (gdb_event_p, event_queue, event_ptr);
+ }
+ }
+}
+
+/* Delete an asynchronous handler (ASYNC_HANDLER_PTR).
+ Free the space allocated for it. */
+void
+delete_async_event_handler (async_event_handler **async_handler_ptr)
+{
+ async_event_handler *prev_ptr;
+
+ if (async_event_handler_list.first_handler == *async_handler_ptr)
+ {
+ async_event_handler_list.first_handler
+ = (*async_handler_ptr)->next_handler;
+ if (async_event_handler_list.first_handler == NULL)
+ async_event_handler_list.last_handler = NULL;
+ }
+ else
+ {
+ prev_ptr = async_event_handler_list.first_handler;
+ while (prev_ptr && prev_ptr->next_handler != *async_handler_ptr)
+ prev_ptr = prev_ptr->next_handler;
+ gdb_assert (prev_ptr);
+ prev_ptr->next_handler = (*async_handler_ptr)->next_handler;
+ if (async_event_handler_list.last_handler == (*async_handler_ptr))
+ async_event_handler_list.last_handler = prev_ptr;
+ }
+ xfree (*async_handler_ptr);
+ *async_handler_ptr = NULL;
+}
+
+/* Create a timer that will expire in MILLISECONDS from now. When the
+ timer is ready, PROC will be executed. At creation, the timer is
+ aded to the timers queue. This queue is kept sorted in order of
+ increasing timers. Return a handle to the timer struct. */
+int
+create_timer (int milliseconds, timer_handler_func * proc,
+ gdb_client_data client_data)
+{
+ struct gdb_timer *timer_ptr, *timer_index, *prev_timer;
+ struct timeval time_now, delta;
+
+ /* Compute seconds. */
+ delta.tv_sec = milliseconds / 1000;
+ /* Compute microseconds. */
+ delta.tv_usec = (milliseconds % 1000) * 1000;
+
+ gettimeofday (&time_now, NULL);
+
+ timer_ptr = (struct gdb_timer *) xmalloc (sizeof (*timer_ptr));
+ timer_ptr->when.tv_sec = time_now.tv_sec + delta.tv_sec;
+ timer_ptr->when.tv_usec = time_now.tv_usec + delta.tv_usec;
+ /* Carry? */
+ if (timer_ptr->when.tv_usec >= 1000000)
+ {
+ timer_ptr->when.tv_sec += 1;
+ timer_ptr->when.tv_usec -= 1000000;
+ }
+ timer_ptr->proc = proc;
+ timer_ptr->client_data = client_data;
+ timer_list.num_timers++;
+ timer_ptr->timer_id = timer_list.num_timers;
+
+ /* Now add the timer to the timer queue, making sure it is sorted in
+ increasing order of expiration. */
+
+ for (timer_index = timer_list.first_timer;
+ timer_index != NULL;
+ timer_index = timer_index->next)
+ {
+ /* If the seconds field is greater or if it is the same, but the
+ microsecond field is greater. */
+ if ((timer_index->when.tv_sec > timer_ptr->when.tv_sec)
+ || ((timer_index->when.tv_sec == timer_ptr->when.tv_sec)
+ && (timer_index->when.tv_usec > timer_ptr->when.tv_usec)))
+ break;
+ }
+
+ if (timer_index == timer_list.first_timer)
+ {
+ timer_ptr->next = timer_list.first_timer;
+ timer_list.first_timer = timer_ptr;
+
+ }
+ else
+ {
+ for (prev_timer = timer_list.first_timer;
+ prev_timer->next != timer_index;
+ prev_timer = prev_timer->next)
+ ;
+
+ prev_timer->next = timer_ptr;
+ timer_ptr->next = timer_index;
+ }
+
+ gdb_notifier.timeout_valid = 0;
+ return timer_ptr->timer_id;
+}
+
+/* There is a chance that the creator of the timer wants to get rid of
+ it before it expires. */
+void
+delete_timer (int id)
+{
+ struct gdb_timer *timer_ptr, *prev_timer = NULL;
+
+ /* Find the entry for the given timer. */
+
+ for (timer_ptr = timer_list.first_timer; timer_ptr != NULL;
+ timer_ptr = timer_ptr->next)
+ {
+ if (timer_ptr->timer_id == id)
+ break;
+ }
+
+ if (timer_ptr == NULL)
+ return;
+ /* Get rid of the timer in the timer list. */
+ if (timer_ptr == timer_list.first_timer)
+ timer_list.first_timer = timer_ptr->next;
+ else
+ {
+ for (prev_timer = timer_list.first_timer;
+ prev_timer->next != timer_ptr;
+ prev_timer = prev_timer->next)
+ ;
+ prev_timer->next = timer_ptr->next;
+ }
+ xfree (timer_ptr);
+
+ gdb_notifier.timeout_valid = 0;
+}
+
+/* When a timer event is put on the event queue, it will be handled by
+ this function. Just call the associated procedure and delete the
+ timer event from the event queue. Repeat this for each timer that
+ has expired. */
+static void
+handle_timer_event (event_data dummy)
+{
+ struct timeval time_now;
+ struct gdb_timer *timer_ptr, *saved_timer;
+
+ gettimeofday (&time_now, NULL);
+ timer_ptr = timer_list.first_timer;
+
+ while (timer_ptr != NULL)
+ {
+ if ((timer_ptr->when.tv_sec > time_now.tv_sec)
+ || ((timer_ptr->when.tv_sec == time_now.tv_sec)
+ && (timer_ptr->when.tv_usec > time_now.tv_usec)))
+ break;
+
+ /* Get rid of the timer from the beginning of the list. */
+ timer_list.first_timer = timer_ptr->next;
+ saved_timer = timer_ptr;
+ timer_ptr = timer_ptr->next;
+ /* Call the procedure associated with that timer. */
+ (*saved_timer->proc) (saved_timer->client_data);
+ xfree (saved_timer);
+ }
+
+ gdb_notifier.timeout_valid = 0;
+}
+
+/* Check whether any timers in the timers queue are ready. If at least
+ one timer is ready, stick an event onto the event queue. Even in
+ case more than one timer is ready, one event is enough, because the
+ handle_timer_event() will go through the timers list and call the
+ procedures associated with all that have expired.l Update the
+ timeout for the select() or poll() as well. */
+static void
+poll_timers (void)