#include "defs.h"
#include "event-loop.h"
#include "event-top.h"
#include "interps.h"
#include "ui-out.h"
#ifdef HAVE_POLL
#if defined (HAVE_POLL_H)
#include <poll.h>
#elif defined (HAVE_SYS_POLL_H)
#include <sys/poll.h>
#endif
#endif
#include <sys/types.h>
#include "gdb_string.h"
#include <errno.h>
#include <sys/time.h>
#include "exceptions.h"
#include "gdb_assert.h"
typedef struct gdb_event gdb_event;
struct gdb_event
{
event_handler_func *proc;
void *data;
struct gdb_event *next_event;
};
typedef struct file_handler
{
int fd;
int mask;
int ready_mask;
handler_func *proc;
gdb_client_data client_data;
int error;
struct file_handler *next_file;
}
file_handler;
typedef struct async_signal_handler
{
int ready;
struct async_signal_handler *next_handler;
sig_handler_func *proc;
gdb_client_data client_data;
}
async_signal_handler;
static struct
{
gdb_event *first_event;
gdb_event *last_event;
}
event_queue;
#ifdef HAVE_POLL
#define USE_POLL 1
#else
#define USE_POLL 0
#endif
#undef USE_POLL
#define USE_POLL 0
static unsigned char use_poll = USE_POLL;
#ifdef USE_WIN32API
#include <windows.h>
#include <io.h>
#endif
static struct
{
file_handler *first_file_handler;
#ifdef HAVE_POLL
struct pollfd *poll_fds;
int poll_timeout;
#endif
fd_set check_masks[3];
fd_set ready_masks[3];
int num_fds;
struct timeval select_timeout;
int timeout_valid;
}
gdb_notifier;
struct gdb_timer
{
struct timeval when;
int timer_id;
struct gdb_timer *next;
timer_handler_func *proc;
gdb_client_data client_data;
}
gdb_timer;
static struct
{
struct gdb_timer *first_timer;
int num_timers;
}
timer_list;
static struct
{
async_signal_handler *first_handler;
async_signal_handler *last_handler;
}
sighandler_list;
static int async_handler_ready = 0;
static void create_file_handler (int fd, int mask, handler_func * proc, gdb_client_data client_data);
static void invoke_async_signal_handler (void);
static void handle_file_event (void *data);
static int gdb_wait_for_event (void);
static int check_async_ready (void);
void async_queue_event (gdb_event * event_ptr, queue_position position);
int sigint_taken_p(void);
static gdb_event *gdb_create_event (event_handler_func proc, void *data);
static gdb_event *create_file_event (int fd);
static int process_event (void);
static void handle_timer_event (void *dummy);
static void poll_timers (void);
void
gdb_queue_event (event_handler_func proc, void *data, queue_position position)
{
gdb_event *new_event;
new_event = gdb_create_event (proc, data);
async_queue_event (new_event, position);
}
void
async_queue_event (gdb_event * event_ptr, queue_position position)
{
if (position == TAIL)
{
event_ptr->next_event = NULL;
if (event_queue.first_event == NULL)
event_queue.first_event = event_ptr;
else
event_queue.last_event->next_event = event_ptr;
event_queue.last_event = event_ptr;
}
else if (position == HEAD)
{
event_ptr->next_event = event_queue.first_event;
if (event_queue.first_event == NULL)
event_queue.last_event = event_ptr;
event_queue.first_event = event_ptr;
}
}
static gdb_event *
gdb_create_event (event_handler_func proc, void *data)
{
gdb_event *new_event;
new_event = (gdb_event *) xmalloc (sizeof (gdb_event));
new_event->proc = proc;
new_event->data = data;
return new_event;
}
static gdb_event *
create_file_event (int fd)
{
return gdb_create_event (handle_file_event, (void *) fd);
}
void
print_event_queue ()
{
gdb_event *event_ptr;
file_handler *file_ptr;
printf ("*** Printing event queue\n");
printf (" Async status: %d\n", check_async_ready());
printf ("*** File Descriptors are: \n");
for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL;
file_ptr = file_ptr->next_file)
{
printf (" FD: %d\n", (int) file_ptr->fd);
}
printf ("*** Event queue is:\n");
for (event_ptr = event_queue.first_event; event_ptr != NULL;
event_ptr = event_ptr->next_event)
{
printf (" File Descriptor: %d, Handler: 0x%lx\n",
(int) event_ptr->data, (unsigned long) event_ptr->proc);
if ((unsigned long) event_ptr->proc == (unsigned long) handle_file_event)
{
for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL;
file_ptr = file_ptr->next_file)
{
if (file_ptr->fd == (int) event_ptr->data)
{
printf (" - File Event, handler is 0x%lx\n",
(unsigned long) file_ptr->proc);
}
}
}
}
}
static int
process_event (void)
{
gdb_event *event_ptr, *prev_ptr;
event_handler_func *proc;
void *data;
if (check_async_ready ())
{
invoke_async_signal_handler ();
return 1;
}
for (event_ptr = event_queue.first_event; event_ptr != NULL;
event_ptr = event_ptr->next_event)
{
proc = event_ptr->proc;
data = event_ptr->data;
if (event_queue.first_event == event_ptr)
{
event_queue.first_event = event_ptr->next_event;
if (event_ptr->next_event == NULL)
event_queue.last_event = NULL;
}
else
{
prev_ptr = event_queue.first_event;
while (prev_ptr->next_event != event_ptr)
prev_ptr = prev_ptr->next_event;
prev_ptr->next_event = event_ptr->next_event;
if (event_ptr->next_event == NULL)
event_queue.last_event = prev_ptr;
}
xfree (event_ptr);
(*proc) (data);
return 1;
}
return 0;
}
int
gdb_do_one_event (void *data)
{
if (process_event ())
{
return 1;
}
poll_timers ();
if (gdb_wait_for_event () < 0)
{
return -1;
}
if (process_event ())
{
return 1;
}
return 1;
}
void
start_event_loop (void)
{
while (1)
{
int gdb_result;
uiout = interp_ui_out (current_interp ());
gdb_result = catch_errors (gdb_do_one_event, 0, "", RETURN_MASK_ALL);
if (gdb_result < 0)
break;
if (gdb_result == 0)
{
display_gdb_prompt (0);
if (after_char_processing_hook)
(*after_char_processing_hook) ();
}
}
return;
}
void
add_file_handler (int fd, handler_func * proc, gdb_client_data client_data)
{
#ifdef HAVE_POLL
struct pollfd fds;
#endif
if (use_poll)
{
#ifdef HAVE_POLL
fds.fd = fd;
fds.events = POLLIN;
if (poll (&fds, 1, 0) == 1 && (fds.revents & POLLNVAL))
use_poll = 0;
#else
internal_error (__FILE__, __LINE__,
_("use_poll without HAVE_POLL"));
#endif
}
if (use_poll)
{
#ifdef HAVE_POLL
create_file_handler (fd, POLLIN, proc, client_data);
#else
internal_error (__FILE__, __LINE__,
_("use_poll without HAVE_POLL"));
#endif
}
else
create_file_handler (fd, GDB_READABLE | GDB_EXCEPTION, proc, client_data);
}
static void
create_file_handler (int fd, int mask, handler_func * proc, gdb_client_data client_data)
{
file_handler *file_ptr;
for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL;
file_ptr = file_ptr->next_file)
{
if (file_ptr->fd == fd)
break;
}
if (file_ptr == NULL)
{
file_ptr = (file_handler *) xmalloc (sizeof (file_handler));
file_ptr->fd = fd;
file_ptr->ready_mask = 0;
file_ptr->next_file = gdb_notifier.first_file_handler;
gdb_notifier.first_file_handler = file_ptr;
if (use_poll)
{
#ifdef HAVE_POLL
gdb_notifier.num_fds++;
if (gdb_notifier.poll_fds)
gdb_notifier.poll_fds =
(struct pollfd *) xrealloc (gdb_notifier.poll_fds,
(gdb_notifier.num_fds
* sizeof (struct pollfd)));
else
gdb_notifier.poll_fds =
(struct pollfd *) xmalloc (sizeof (struct pollfd));
(gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->fd = fd;
(gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->events = mask;
(gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->revents = 0;
#else
internal_error (__FILE__, __LINE__,
_("use_poll without HAVE_POLL"));
#endif
}
else
{
if (mask & GDB_READABLE)
FD_SET (fd, &gdb_notifier.check_masks[0]);
else
FD_CLR (fd, &gdb_notifier.check_masks[0]);
if (mask & GDB_WRITABLE)
FD_SET (fd, &gdb_notifier.check_masks[1]);
else
FD_CLR (fd, &gdb_notifier.check_masks[1]);
if (mask & GDB_EXCEPTION)
FD_SET (fd, &gdb_notifier.check_masks[2]);
else
FD_CLR (fd, &gdb_notifier.check_masks[2]);
if (gdb_notifier.num_fds <= fd)
gdb_notifier.num_fds = fd + 1;
}
}
file_ptr->proc = proc;
file_ptr->client_data = client_data;
file_ptr->mask = mask;
}
void
delete_file_handler (int fd)
{
file_handler *file_ptr, *prev_ptr = NULL;
int i;
#ifdef HAVE_POLL
int j;
struct pollfd *new_poll_fds;
#endif
for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL;
file_ptr = file_ptr->next_file)
{
if (file_ptr->fd == fd)
break;
}
if (file_ptr == NULL)
return;
if (use_poll)
{
#ifdef HAVE_POLL
new_poll_fds =
(struct pollfd *) xmalloc ((gdb_notifier.num_fds - 1) * sizeof (struct pollfd));
for (i = 0, j = 0; i < gdb_notifier.num_fds; i++)
{
if ((gdb_notifier.poll_fds + i)->fd != fd)
{
(new_poll_fds + j)->fd = (gdb_notifier.poll_fds + i)->fd;
(new_poll_fds + j)->events = (gdb_notifier.poll_fds + i)->events;
(new_poll_fds + j)->revents = (gdb_notifier.poll_fds + i)->revents;
j++;
}
}
xfree (gdb_notifier.poll_fds);
gdb_notifier.poll_fds = new_poll_fds;
gdb_notifier.num_fds--;
#else
internal_error (__FILE__, __LINE__,
_("use_poll without HAVE_POLL"));
#endif
}
else
{
if (file_ptr->mask & GDB_READABLE)
FD_CLR (fd, &gdb_notifier.check_masks[0]);
if (file_ptr->mask & GDB_WRITABLE)
FD_CLR (fd, &gdb_notifier.check_masks[1]);
if (file_ptr->mask & GDB_EXCEPTION)
FD_CLR (fd, &gdb_notifier.check_masks[2]);
if ((fd + 1) == gdb_notifier.num_fds)
{
gdb_notifier.num_fds--;
for (i = gdb_notifier.num_fds; i; i--)
{
if (FD_ISSET (i - 1, &gdb_notifier.check_masks[0])
|| FD_ISSET (i - 1, &gdb_notifier.check_masks[1])
|| FD_ISSET (i - 1, &gdb_notifier.check_masks[2]))
break;
}
gdb_notifier.num_fds = i;
}
}
file_ptr->mask = 0;
if (file_ptr == gdb_notifier.first_file_handler)
gdb_notifier.first_file_handler = file_ptr->next_file;
else
{
for (prev_ptr = gdb_notifier.first_file_handler;
prev_ptr->next_file != file_ptr;
prev_ptr = prev_ptr->next_file)
;
prev_ptr->next_file = file_ptr->next_file;
}
xfree (file_ptr);
}
static void
handle_file_event (void *data)
{
int event_file_desc = (int) data;
file_handler *file_ptr;
int mask;
#ifdef HAVE_POLL
int error_mask;
int error_mask_returned;
#endif
for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL;
file_ptr = file_ptr->next_file)
{
if (file_ptr->fd == event_file_desc)
{
if (use_poll)
{
#ifdef HAVE_POLL
error_mask = POLLHUP | POLLERR | POLLNVAL;
mask = (file_ptr->ready_mask & file_ptr->mask) |
(file_ptr->ready_mask & error_mask);
error_mask_returned = mask & error_mask;
if (error_mask_returned != 0)
{
if (error_mask_returned & POLLHUP)
printf_unfiltered (_("Hangup detected on fd %d\n"), file_ptr->fd);
if (error_mask_returned & POLLERR)
printf_unfiltered (_("Error detected on fd %d\n"), file_ptr->fd);
if (error_mask_returned & POLLNVAL)
printf_unfiltered (_("Invalid or non-`poll'able fd %d\n"), file_ptr->fd);
file_ptr->error = 1;
}
else
file_ptr->error = 0;
#else
internal_error (__FILE__, __LINE__,
_("use_poll without HAVE_POLL"));
#endif
}
else
{
if (file_ptr->ready_mask & GDB_EXCEPTION)
{
printf_unfiltered (_("Exception condition detected on fd %d\n"), file_ptr->fd);
file_ptr->error = 1;
}
else
file_ptr->error = 0;
mask = file_ptr->ready_mask & file_ptr->mask;
}
file_ptr->ready_mask = 0;
if (mask != 0)
(*file_ptr->proc) (file_ptr->error, file_ptr->client_data);
break;
}
}
}
static int
gdb_select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
struct timeval *timeout)
{
#ifdef USE_WIN32API
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
HANDLE h;
DWORD event;
DWORD num_handles;
int fd;
int num_ready;
num_handles = 0;
for (fd = 0; fd < n; ++fd)
{
gdb_assert (!FD_ISSET (fd, writefds));
if (FD_ISSET (fd, readfds))
{
gdb_assert (num_handles < MAXIMUM_WAIT_OBJECTS);
handles[num_handles++] = (HANDLE) _get_osfhandle (fd);
}
}
event = WaitForMultipleObjects (num_handles,
handles,
FALSE,
timeout
? (timeout->tv_sec * 1000 + timeout->tv_usec)
: INFINITE);
gdb_assert (!(WAIT_ABANDONED_0 <= event
&& event < WAIT_ABANDONED_0 + num_handles));
if (event == WAIT_FAILED)
return -1;
if (event == WAIT_TIMEOUT)
return 0;
num_ready = num_handles;
h = handles[event - WAIT_OBJECT_0];
for (fd = 0; fd < n; ++fd)
{
HANDLE fd_h;
if (!FD_ISSET (fd, readfds))
continue;
fd_h = (HANDLE) _get_osfhandle (fd);
if (fd_h != h && WaitForSingleObject (fd_h, 0) != WAIT_OBJECT_0)
{
FD_CLR (fd, readfds);
--num_ready;
}
}
FD_ZERO (writefds);
FD_ZERO (exceptfds);
return num_ready;
#else
return select (n, readfds, writefds, exceptfds, timeout);
#endif
}
static int
gdb_wait_for_event (void)
{
file_handler *file_ptr;
gdb_event *file_event_ptr;
int num_found = 0;
int i;
gdb_flush (gdb_stdout);
gdb_flush (gdb_stderr);
if (gdb_notifier.num_fds == 0)
return -1;
if (use_poll)
{
#ifdef HAVE_POLL
num_found =
poll (gdb_notifier.poll_fds,
(unsigned long) gdb_notifier.num_fds,
gdb_notifier.timeout_valid ? gdb_notifier.poll_timeout : -1);
if (num_found == -1 && errno != EINTR)
perror_with_name (("poll"));
#else
internal_error (__FILE__, __LINE__,
_("use_poll without HAVE_POLL"));
#endif
}
else
{
gdb_notifier.ready_masks[0] = gdb_notifier.check_masks[0];
gdb_notifier.ready_masks[1] = gdb_notifier.check_masks[1];
gdb_notifier.ready_masks[2] = gdb_notifier.check_masks[2];
num_found = gdb_select (gdb_notifier.num_fds,
&gdb_notifier.ready_masks[0],
&gdb_notifier.ready_masks[1],
&gdb_notifier.ready_masks[2],
gdb_notifier.timeout_valid
? &gdb_notifier.select_timeout : NULL);
if (num_found == -1)
{
FD_ZERO (&gdb_notifier.ready_masks[0]);
FD_ZERO (&gdb_notifier.ready_masks[1]);
FD_ZERO (&gdb_notifier.ready_masks[2]);
if (errno != EINTR)
perror_with_name (("select"));
}
}
if (use_poll)
{
#ifdef HAVE_POLL
for (i = 0; (i < gdb_notifier.num_fds) && (num_found > 0); i++)
{
if ((gdb_notifier.poll_fds + i)->revents)
num_found--;
else
continue;
for (file_ptr = gdb_notifier.first_file_handler;
file_ptr != NULL;
file_ptr = file_ptr->next_file)
{
if (file_ptr->fd == (gdb_notifier.poll_fds + i)->fd)
break;
}
if (file_ptr)
{
if (file_ptr->ready_mask == 0)
{
file_event_ptr = create_file_event (file_ptr->fd);
async_queue_event (file_event_ptr, TAIL);
}
}
file_ptr->ready_mask = (gdb_notifier.poll_fds + i)->revents;
}
#else
internal_error (__FILE__, __LINE__,
_("use_poll without HAVE_POLL"));
#endif
}
else
{
for (file_ptr = gdb_notifier.first_file_handler;
(file_ptr != NULL) && (num_found > 0);
file_ptr = file_ptr->next_file)
{
int mask = 0;
if (FD_ISSET (file_ptr->fd, &gdb_notifier.ready_masks[0]))
mask |= GDB_READABLE;
if (FD_ISSET (file_ptr->fd, &gdb_notifier.ready_masks[1]))
mask |= GDB_WRITABLE;
if (FD_ISSET (file_ptr->fd, &gdb_notifier.ready_masks[2]))
mask |= GDB_EXCEPTION;
if (!mask)
continue;
else
num_found--;
if (file_ptr->ready_mask == 0)
{
file_event_ptr = create_file_event (file_ptr->fd);
async_queue_event (file_event_ptr, TAIL);
}
file_ptr->ready_mask = mask;
}
}
return 0;
}
async_signal_handler *
create_async_signal_handler (sig_handler_func * proc, gdb_client_data client_data)
{
async_signal_handler *async_handler_ptr;
async_handler_ptr =
(async_signal_handler *) xmalloc (sizeof (async_signal_handler));
async_handler_ptr->ready = 0;
async_handler_ptr->next_handler = NULL;
async_handler_ptr->proc = proc;
async_handler_ptr->client_data = client_data;
if (sighandler_list.first_handler == NULL)
sighandler_list.first_handler = async_handler_ptr;
else
sighandler_list.last_handler->next_handler = async_handler_ptr;
sighandler_list.last_handler = async_handler_ptr;
return async_handler_ptr;
}
void
mark_async_signal_handler (async_signal_handler * async_handler_ptr)
{
if (async_handler_ptr == NULL)
internal_error (__FILE__, __LINE__, "Called mark_async_signal_handler with null handler.");
((async_signal_handler *) async_handler_ptr)->ready = 1;
async_handler_ready = 1;
}
void
unmark_async_signal_handler (async_signal_handler * async_handler_ptr)
{
async_handler_ptr->ready = 0;
}
static void
invoke_async_signal_handler (void)
{
async_signal_handler *async_handler_ptr;
if (async_handler_ready == 0)
return;
async_handler_ready = 0;
while (1)
{
for (async_handler_ptr = sighandler_list.first_handler;
async_handler_ptr != NULL;
async_handler_ptr = async_handler_ptr->next_handler)
{
if (async_handler_ptr->ready)
break;
}
if (async_handler_ptr == NULL)
break;
async_handler_ptr->ready = 0;
(*async_handler_ptr->proc) (async_handler_ptr->client_data);
}
return;
}
void
delete_async_signal_handler (async_signal_handler ** async_handler_ptr)
{
async_signal_handler *prev_ptr;
if (sighandler_list.first_handler == (*async_handler_ptr))
{
sighandler_list.first_handler = (*async_handler_ptr)->next_handler;
if (sighandler_list.first_handler == NULL)
sighandler_list.last_handler = NULL;
}
else
{
prev_ptr = sighandler_list.first_handler;
while (prev_ptr->next_handler != (*async_handler_ptr) && prev_ptr)
prev_ptr = prev_ptr->next_handler;
prev_ptr->next_handler = (*async_handler_ptr)->next_handler;
if (sighandler_list.last_handler == (*async_handler_ptr))
sighandler_list.last_handler = prev_ptr;
}
xfree ((*async_handler_ptr));
(*async_handler_ptr) = NULL;
}
static int
check_async_ready (void)
{
return async_handler_ready;
}
int
sigint_taken_p (void)
{
extern void *sigint_token;
if (((struct async_signal_handler *) sigint_token)->ready)
{
((struct async_signal_handler *) sigint_token)->ready = 0;
return 1;
}
else return 0;
}
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;
delta.tv_sec = milliseconds / 1000;
delta.tv_usec = (milliseconds % 1000) * 1000;
gettimeofday (&time_now, NULL);
timer_ptr = (struct gdb_timer *) xmalloc (sizeof (gdb_timer));
timer_ptr->when.tv_sec = time_now.tv_sec + delta.tv_sec;
timer_ptr->when.tv_usec = time_now.tv_usec + delta.tv_usec;
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;
for (timer_index = timer_list.first_timer;
timer_index != NULL;
timer_index = timer_index->next)
{
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;
}
void
delete_timer (int id)
{
struct gdb_timer *timer_ptr, *prev_timer = NULL;
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;
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;
}
static void
handle_timer_event (void *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;
timer_list.first_timer = timer_ptr->next;
saved_timer = timer_ptr;
timer_ptr = timer_ptr->next;
(*saved_timer->proc) (saved_timer->client_data);
xfree (saved_timer);
}
gdb_notifier.timeout_valid = 0;
}
static void
poll_timers (void)
{
struct timeval time_now, delta;
gdb_event *event_ptr;
if (timer_list.first_timer != NULL)
{
gettimeofday (&time_now, NULL);
delta.tv_sec = timer_list.first_timer->when.tv_sec - time_now.tv_sec;
delta.tv_usec = timer_list.first_timer->when.tv_usec - time_now.tv_usec;
if (delta.tv_usec < 0)
{
delta.tv_sec -= 1;
delta.tv_usec += 1000000;
}
if (timer_list.first_timer->when.tv_sec < time_now.tv_sec
|| (timer_list.first_timer->when.tv_sec == time_now.tv_sec
&& timer_list.first_timer->when.tv_usec < time_now.tv_usec))
{
delta.tv_sec = 0;
delta.tv_usec = 0;
}
if (delta.tv_sec == 0 && delta.tv_usec == 0)
{
event_ptr = (gdb_event *) xmalloc (sizeof (gdb_event));
event_ptr->proc = handle_timer_event;
event_ptr->data = (void *) timer_list.first_timer->timer_id;
async_queue_event (event_ptr, TAIL);
}
if (use_poll)
{
#ifdef HAVE_POLL
gdb_notifier.poll_timeout = delta.tv_sec * 1000;
#else
internal_error (__FILE__, __LINE__,
_("use_poll without HAVE_POLL"));
#endif
}
else
{
gdb_notifier.select_timeout.tv_sec = delta.tv_sec;
gdb_notifier.select_timeout.tv_usec = delta.tv_usec;
}
gdb_notifier.timeout_valid = 1;
}
else
gdb_notifier.timeout_valid = 0;
}