X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;ds=sidebyside;f=gdb%2Fevent-loop.c;h=2f3d5359b79baa94fc2e30b3f11c9e1aea6b0f52;hb=34d9ee9e68940274e34bf5de84f46119ecd66855;hp=dd849dfb8ff81b04e015ed1cb1ac71a0f9e51cd2;hpb=750334d7543e810f17faa353e97c1a25217b9053;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/event-loop.c b/gdb/event-loop.c index dd849dfb8f..2f3d5359b7 100644 --- a/gdb/event-loop.c +++ b/gdb/event-loop.c @@ -1,5 +1,5 @@ /* Event loop machinery for GDB, the GNU debugger. - Copyright 1999 Free Software Foundation, Inc. + Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc. Written by Elena Zannoni of Cygnus Solutions. This file is part of GDB. @@ -20,57 +20,23 @@ Boston, MA 02111-1307, USA. */ #include "defs.h" -#include "top.h" #include "event-loop.h" #include "event-top.h" + #ifdef HAVE_POLL +#if defined (HAVE_POLL_H) #include -#else -#include -#endif -#include -#include -#include - -/* Type of the mask arguments to select. */ - -#ifndef NO_FD_SET -#define SELECT_MASK fd_set -#else -#ifndef _AIX -typedef long fd_mask; -#endif -#if defined(_IBMR2) -#define SELECT_MASK void -#else -#define SELECT_MASK int -#endif -#endif - -/* Define "NBBY" (number of bits per byte) if it's not already defined. */ - -#ifndef NBBY -#define NBBY 8 -#endif - - -/* Define the number of fd_masks in an fd_set */ - -#ifndef FD_SETSIZE -#ifdef OPEN_MAX -#define FD_SETSIZE OPEN_MAX -#else -#define FD_SETSIZE 256 +#elif defined (HAVE_SYS_POLL_H) +#include #endif #endif -#if !defined(howmany) -#define howmany(x, y) (((x)+((y)-1))/(y)) -#endif -#ifndef NFDBITS -#define NFDBITS NBBY*sizeof(fd_mask) -#endif -#define MASK_SIZE howmany(FD_SETSIZE, NFDBITS) +#include +#include "gdb_string.h" +#include +#include +#include "exceptions.h" +#include "gdb_assert.h" typedef struct gdb_event gdb_event; typedef void (event_handler_func) (int); @@ -84,7 +50,7 @@ typedef void (event_handler_func) (int); ready. The procedure PROC associated with each event is always the same (handle_file_event). Its duty is to invoke the handler associated with the file descriptor whose state change generated - the event, plus doing other cleanups adn such. */ + the event, plus doing other cleanups and such. */ struct gdb_event { @@ -159,57 +125,52 @@ event_queue; /* As of 1999-04-30 only the input file descriptor is registered with the event loop. */ +/* Do we use poll or select ? */ #ifdef HAVE_POLL -/* Poll based implementation of the notifier. */ +#define USE_POLL 1 +#else +#define USE_POLL 0 +#endif /* HAVE_POLL */ + +static unsigned char use_poll = USE_POLL; + +#ifdef USE_WIN32API +#include +#include +#endif static struct { /* Ptr to head of file handler list. */ file_handler *first_file_handler; +#ifdef HAVE_POLL /* Ptr to array of pollfd structures. */ struct pollfd *poll_fds; - /* Number of file descriptors to monitor. */ - int num_fds; - /* Timeout in milliseconds for calls to poll(). */ - int timeout; - - /* Flag to tell whether the timeout value shuld be used. */ - int timeout_valid; - } -gdb_notifier; - -#else /* ! HAVE_POLL */ - -/* Select based implementation of the notifier. */ - -static struct - { - /* Ptr to head of file handler list. */ - file_handler *first_file_handler; + int poll_timeout; +#endif /* Masks to be used in the next call to select. Bits are set in response to calls to create_file_handler. */ - fd_mask check_masks[3 * MASK_SIZE]; + fd_set check_masks[3]; /* What file descriptors were found ready by select. */ - fd_mask ready_masks[3 * MASK_SIZE]; + fd_set ready_masks[3]; - /* Number of valid bits (highest fd value + 1). */ + /* Number of file descriptors to monitor. (for poll) */ + /* Number of valid bits (highest fd value + 1). (for select) */ int num_fds; /* Time structure for calls to select(). */ - struct timeval timeout; + struct timeval select_timeout; - /* Flag to tell whether the timeout struct should be used. */ + /* Flag to tell whether the timeout should be used. */ int timeout_valid; } gdb_notifier; -#endif /* HAVE_POLL */ - /* Structure associated with a timer. PROC will be executed at the first occasion after WHEN. */ struct gdb_timer @@ -246,7 +207,7 @@ static struct } sighandler_list; -/* Is any of the handlers ready? Check this variable using +/* Are any of the handlers ready? Check this variable using check_async_ready. This is used by process_event, to determine whether or not to invoke the invoke_async_signal_handler function. */ @@ -256,7 +217,6 @@ static void create_file_handler (int fd, int mask, handler_func * proc, gdb_clie static void invoke_async_signal_handler (void); static void handle_file_event (int event_file_desc); static int gdb_wait_for_event (void); -static int gdb_do_one_event (void *data); static int check_async_ready (void); static void async_queue_event (gdb_event * event_ptr, queue_position position); static gdb_event *create_file_event (int fd); @@ -375,9 +335,9 @@ process_event (void) if (event_ptr->next_event == NULL) event_queue.last_event = prev_ptr; } - free ((char *) event_ptr); + xfree (event_ptr); - /* Now call the procedure associted with the event. */ + /* Now call the procedure associated with the event. */ (*proc) (fd); return 1; } @@ -390,9 +350,9 @@ process_event (void) wait for something to happen (via gdb_wait_for_event), then process it. Returns >0 if something was done otherwise returns <0 (this can happen if there are no event sources to wait for). If an error - occures catch_errors() which calls this function returns zero. */ + occurs catch_errors() which calls this function returns zero. */ -static int +int gdb_do_one_event (void *data) { /* Any events already waiting in the queue? */ @@ -400,26 +360,26 @@ gdb_do_one_event (void *data) { return 1; } - + /* Are any timers that are ready? If so, put an event on the queue. */ poll_timers (); - + /* Wait for a new event. If gdb_wait_for_event returns -1, we should get out because this means that there are no event sources left. This will make the event loop stop, and the application exit. */ - + if (gdb_wait_for_event () < 0) { return -1; } - + /* Handle any new events occurred while waiting. */ if (process_event ()) { return 1; } - + /* If gdb_wait_for_event has returned 1, it means that one event has been handled. We break out of the loop. */ return 1; @@ -439,15 +399,30 @@ start_event_loop (void) longer any event sources registered. */ while (1) { - int result = catch_errors (gdb_do_one_event, 0, "", RETURN_MASK_ALL); - if (result < 0) + int gdb_result; + + gdb_result = catch_errors (gdb_do_one_event, 0, "", RETURN_MASK_ALL); + if (gdb_result < 0) break; - if (result == 0) + + /* If we long-jumped out of do_one_event, we probably + didn't get around to resetting the prompt, which leaves + readline in a messed-up state. Reset it here. */ + + if (gdb_result == 0) { /* FIXME: this should really be a call to a hook that is interface specific, because interfaces can display the prompt in their own way. */ display_gdb_prompt (0); + /* This call looks bizarre, but it is required. If the user + entered a command that caused an error, + after_char_processing_hook won't be called from + rl_callback_read_char_wrapper. Using a cleanup there + won't work, since we want this function to be called + after a new prompt is printed. */ + if (after_char_processing_hook) + (*after_char_processing_hook) (); /* Maybe better to set a flag to be checked somewhere as to whether display the prompt or not. */ } @@ -466,10 +441,37 @@ void add_file_handler (int fd, handler_func * proc, gdb_client_data client_data) { #ifdef HAVE_POLL - create_file_handler (fd, POLLIN, proc, client_data); + struct pollfd fds; +#endif + + if (use_poll) + { +#ifdef HAVE_POLL + /* Check to see if poll () is usable. If not, we'll switch to + use select. This can happen on systems like + m68k-motorola-sys, `poll' cannot be used to wait for `stdin'. + On m68k-motorola-sysv, tty's are not stream-based and not + `poll'able. */ + fds.fd = fd; + fds.events = POLLIN; + if (poll (&fds, 1, 0) == 1 && (fds.revents & POLLNVAL)) + use_poll = 0; #else - create_file_handler (fd, GDB_READABLE | GDB_EXCEPTION, proc, client_data); + internal_error (__FILE__, __LINE__, + _("use_poll without HAVE_POLL")); +#endif /* HAVE_POLL */ + } + 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); } /* Add a file handler/descriptor to the list of descriptors we are @@ -487,10 +489,6 @@ create_file_handler (int fd, int mask, handler_func * proc, gdb_client_data clie { file_handler *file_ptr; -#ifndef HAVE_POLL - int index, bit; -#endif - /* Do we already have a file handler for this file? (We may be changing its associated procedure). */ for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL; @@ -509,51 +507,52 @@ create_file_handler (int fd, int mask, handler_func * proc, gdb_client_data clie file_ptr->ready_mask = 0; file_ptr->next_file = gdb_notifier.first_file_handler; gdb_notifier.first_file_handler = file_ptr; -#ifdef HAVE_POLL - gdb_notifier.num_fds++; -#endif - } - file_ptr->proc = proc; - file_ptr->client_data = client_data; - file_ptr->mask = mask; + 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 /* HAVE_POLL */ + } + else + { + if (mask & GDB_READABLE) + FD_SET (fd, &gdb_notifier.check_masks[0]); + else + FD_CLR (fd, &gdb_notifier.check_masks[0]); - if (gdb_notifier.poll_fds) - gdb_notifier.poll_fds = - (struct pollfd *) realloc (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 /* ! HAVE_POLL */ - - index = fd / (NBBY * sizeof (fd_mask)); - bit = 1 << (fd % (NBBY * sizeof (fd_mask))); - - if (mask & GDB_READABLE) - gdb_notifier.check_masks[index] |= bit; - else - gdb_notifier.check_masks[index] &= ~bit; - - if (mask & GDB_WRITABLE) - (gdb_notifier.check_masks + MASK_SIZE)[index] |= bit; - else - (gdb_notifier.check_masks + MASK_SIZE)[index] &= ~bit; + 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) - (gdb_notifier.check_masks + 2 * (MASK_SIZE))[index] |= bit; - else - (gdb_notifier.check_masks + 2 * (MASK_SIZE))[index] &= ~bit; + 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; + if (gdb_notifier.num_fds <= fd) + gdb_notifier.num_fds = fd + 1; + } + } -#endif /* HAVE_POLL */ + file_ptr->proc = proc; + file_ptr->client_data = client_data; + file_ptr->mask = mask; } /* Remove the file descriptor FD from the list of monitored fd's: @@ -562,11 +561,10 @@ void delete_file_handler (int fd) { file_handler *file_ptr, *prev_ptr = NULL; - int i, j; + int i; +#ifdef HAVE_POLL + int j; struct pollfd *new_poll_fds; -#ifndef HAVE_POLL - int index, bit; - unsigned long flags; #endif /* Find the entry for the given file. */ @@ -581,61 +579,57 @@ delete_file_handler (int fd) if (file_ptr == NULL) return; + if (use_poll) + { #ifdef HAVE_POLL - /* Create a new poll_fds array by copying every fd's information but the - one we want to get rid of. */ + /* Create a new poll_fds array by copying every fd's information but the + one we want to get rid of. */ - new_poll_fds = - (struct pollfd *) xmalloc ((gdb_notifier.num_fds - 1) * sizeof (struct pollfd)); + 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) + for (i = 0, j = 0; i < gdb_notifier.num_fds; i++) { - (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++; + 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 /* HAVE_POLL */ } - free (gdb_notifier.poll_fds); - gdb_notifier.poll_fds = new_poll_fds; - gdb_notifier.num_fds--; - -#else /* ! HAVE_POLL */ - - index = fd / (NBBY * sizeof (fd_mask)); - bit = 1 << (fd % (NBBY * sizeof (fd_mask))); - - if (file_ptr->mask & GDB_READABLE) - gdb_notifier.check_masks[index] &= ~bit; - if (file_ptr->mask & GDB_WRITABLE) - (gdb_notifier.check_masks + MASK_SIZE)[index] &= ~bit; - if (file_ptr->mask & GDB_EXCEPTION) - (gdb_notifier.check_masks + 2 * (MASK_SIZE))[index] &= ~bit; + 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]); - /* Find current max fd. */ + /* Find current max fd. */ - if ((fd + 1) == gdb_notifier.num_fds) - { - for (gdb_notifier.num_fds = 0; index >= 0; index--) + if ((fd + 1) == gdb_notifier.num_fds) { - flags = gdb_notifier.check_masks[index] - | (gdb_notifier.check_masks + MASK_SIZE)[index] - | (gdb_notifier.check_masks + 2 * (MASK_SIZE))[index]; - if (flags) + gdb_notifier.num_fds--; + for (i = gdb_notifier.num_fds; i; i--) { - for (i = (NBBY * sizeof (fd_mask)); i > 0; i--) - { - if (flags & (((unsigned long) 1) << (i - 1))) - break; - } - gdb_notifier.num_fds = index * (NBBY * sizeof (fd_mask)) + i; - break; + 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; } } -#endif /* HAVE_POLL */ /* Deactivate the file descriptor, by clearing its mask, so that it will not fire again. */ @@ -653,7 +647,7 @@ delete_file_handler (int fd) ; prev_ptr->next_file = file_ptr->next_file; } - free ((char *) file_ptr); + xfree (file_ptr); } /* Handle the given event by calling the procedure associated to the @@ -687,36 +681,44 @@ handle_file_event (int event_file_desc) /* See if the desired events (mask) match the received events (ready_mask). */ + 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; + 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) - { - /* Work in progress. We may need to tell somebody what - kind of error we had. */ - 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; + if (error_mask_returned != 0) + { + /* Work in progress. We may need to tell somebody what + kind of error we had. */ + 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 /* HAVE_POLL */ } else - file_ptr->error = 0; -#else /* ! HAVE_POLL */ - if (file_ptr->ready_mask & GDB_EXCEPTION) { - printf_unfiltered ("Exception condition detected on fd %d\n", file_ptr->fd); - file_ptr->error = 1; + 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; } - else - file_ptr->error = 0; - mask = file_ptr->ready_mask & file_ptr->mask; -#endif /* HAVE_POLL */ /* Clear the received events for next time around. */ file_ptr->ready_mask = 0; @@ -729,6 +731,84 @@ handle_file_event (int event_file_desc) } } +/* Wrapper for select. This function is not yet exported from this + file because it is not sufficiently general. For example, + ser-base.c uses select to check for socket activity, and this + function does not support sockets under Windows, so we do not want + to use gdb_select in ser-base.c. */ + +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) + { + /* EXCEPTFDS is silently ignored. GDB always sets GDB_EXCEPTION + when calling add_file_handler, but there is no natural analog + under Windows. */ + /* There is no support yet for WRITEFDS. At present, this isn't + used by GDB -- but we do not want to silently ignore WRITEFDS + if something starts using it. */ + 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); + /* EVENT can only be a value in the WAIT_ABANDONED_0 range if the + HANDLES included an abandoned mutex. Since GDB doesn't use + mutexes, that should never occur. */ + gdb_assert (!(WAIT_ABANDONED_0 <= event + && event < WAIT_ABANDONED_0 + num_handles)); + if (event == WAIT_FAILED) + return -1; + if (event == WAIT_TIMEOUT) + return 0; + /* Run through the READFDS, clearing bits corresponding to descriptors + for which input is unavailable. */ + 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); + /* This handle might be ready, even though it wasn't the handle + returned by WaitForMultipleObjects. */ + if (fd_h != h && WaitForSingleObject (fd_h, 0) != WAIT_OBJECT_0) + { + FD_CLR (fd, readfds); + --num_ready; + } + } + /* We never report any descriptors available for writing or with + exceptional conditions. */ + FD_ZERO (writefds); + FD_ZERO (exceptfds); + + return num_ready; +#else + return select (n, readfds, writefds, exceptfds, timeout); +#endif +} + /* Called by gdb_do_one_event to wait for new events on the monitored file descriptors. Queue file events as they are detected by the poll. @@ -744,10 +824,6 @@ gdb_wait_for_event (void) int num_found = 0; int i; -#ifndef HAVE_POLL - int mask, bit, index; -#endif - /* Make sure all output is done before getting another event. */ gdb_flush (gdb_stdout); gdb_flush (gdb_stderr); @@ -755,104 +831,116 @@ gdb_wait_for_event (void) 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.timeout : -1); - - /* Don't print anything if we get out of poll because of a - signal. */ - if (num_found == -1 && errno != EINTR) - perror_with_name ("Poll"); - -#else /* ! HAVE_POLL */ - memcpy (gdb_notifier.ready_masks, - gdb_notifier.check_masks, - 3 * MASK_SIZE * sizeof (fd_mask)); - num_found = select (gdb_notifier.num_fds, - (SELECT_MASK *) & gdb_notifier.ready_masks[0], - (SELECT_MASK *) & gdb_notifier.ready_masks[MASK_SIZE], - (SELECT_MASK *) & gdb_notifier.ready_masks[2 * MASK_SIZE], - gdb_notifier.timeout_valid ? &gdb_notifier.timeout : NULL); - - /* Clear the masks after an error from select. */ - if (num_found == -1) + num_found = + poll (gdb_notifier.poll_fds, + (unsigned long) gdb_notifier.num_fds, + gdb_notifier.timeout_valid ? gdb_notifier.poll_timeout : -1); + + /* Don't print anything if we get out of poll because of a + signal. */ + if (num_found == -1 && errno != EINTR) + perror_with_name (("poll")); +#else + internal_error (__FILE__, __LINE__, + _("use_poll without HAVE_POLL")); +#endif /* HAVE_POLL */ + } + else { - memset (gdb_notifier.ready_masks, - 0, 3 * MASK_SIZE * sizeof (fd_mask)); - /* Dont print anything is we got a signal, let gdb handle it. */ - if (errno != EINTR) - perror_with_name ("Select"); + 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); + + /* Clear the masks after an error from select. */ + 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]); + /* Dont print anything is we got a signal, let gdb handle it. */ + if (errno != EINTR) + perror_with_name (("select")); + } } -#endif /* HAVE_POLL */ /* Enqueue all detected file events. */ + 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 (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) + { + /* Enqueue an event only if this is still a new event for + this fd. */ + 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 /* HAVE_POLL */ + } + else + { for (file_ptr = gdb_notifier.first_file_handler; - file_ptr != NULL; + (file_ptr != NULL) && (num_found > 0); file_ptr = file_ptr->next_file) { - if (file_ptr->fd == (gdb_notifier.poll_fds + i)->fd) - break; - } + 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) - { /* Enqueue an event only if this is still a new event for this fd. */ + 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; } - - file_ptr->ready_mask = (gdb_notifier.poll_fds + i)->revents; } - -#else /* ! HAVE_POLL */ - for (file_ptr = gdb_notifier.first_file_handler; - (file_ptr != NULL) && (num_found > 0); - file_ptr = file_ptr->next_file) - { - index = file_ptr->fd / (NBBY * sizeof (fd_mask)); - bit = 1 << (file_ptr->fd % (NBBY * sizeof (fd_mask))); - mask = 0; - - if (gdb_notifier.ready_masks[index] & bit) - mask |= GDB_READABLE; - if ((gdb_notifier.ready_masks + MASK_SIZE)[index] & bit) - mask |= GDB_WRITABLE; - if ((gdb_notifier.ready_masks + 2 * (MASK_SIZE))[index] & bit) - mask |= GDB_EXCEPTION; - - if (!mask) - continue; - else - num_found--; - - /* Enqueue an event only if this is still a new event for - this fd. */ - - 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; - } -#endif /* HAVE_POLL */ - return 0; } @@ -945,7 +1033,7 @@ delete_async_signal_handler (async_signal_handler ** async_handler_ptr) if (sighandler_list.last_handler == (*async_handler_ptr)) sighandler_list.last_handler = prev_ptr; } - free ((char *) (*async_handler_ptr)); + xfree ((*async_handler_ptr)); (*async_handler_ptr) = NULL; } @@ -1052,7 +1140,7 @@ delete_timer (int id) ; prev_timer->next = timer_ptr->next; } - free ((char *) timer_ptr); + xfree (timer_ptr); gdb_notifier.timeout_valid = 0; } @@ -1083,7 +1171,7 @@ handle_timer_event (int dummy) timer_ptr = timer_ptr->next; /* Call the procedure associated with that timer. */ (*saved_timer->proc) (saved_timer->client_data); - free (saved_timer); + xfree (saved_timer); } gdb_notifier.timeout_valid = 0; @@ -1114,8 +1202,11 @@ poll_timers (void) } /* Oops it expired already. Tell select / poll to return - immediately. */ - if (delta.tv_sec < 0) + immediately. (Cannot simply test if delta.tv_sec is negative + because time_t might be unsigned.) */ + 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; @@ -1131,12 +1222,20 @@ poll_timers (void) /* Now we need to update the timeout for select/ poll, because we don't want to sit there while this timer is expiring. */ + if (use_poll) + { #ifdef HAVE_POLL - gdb_notifier.timeout = delta.tv_sec * 1000; + gdb_notifier.poll_timeout = delta.tv_sec * 1000; #else - gdb_notifier.timeout.tv_sec = delta.tv_sec; - gdb_notifier.timeout.tv_usec = delta.tv_usec; -#endif + internal_error (__FILE__, __LINE__, + _("use_poll without HAVE_POLL")); +#endif /* HAVE_POLL */ + } + 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