diff options
author | Daniel Jacobowitz <drow@false.org> | 2006-02-10 22:01:43 +0000 |
---|---|---|
committer | Daniel Jacobowitz <drow@false.org> | 2006-02-10 22:01:43 +0000 |
commit | 0ea3f30e219bd42259f09f68bcd605bf4ed4a1ea (patch) | |
tree | 07c791175cea3abee634fa9ccec99e18031ed5cd /gdb/mingw-hdep.c | |
parent | 121ce6e53dd5751c6938ab86cbec2742702d06eb (diff) | |
download | binutils-gdb-0ea3f30e219bd42259f09f68bcd605bf4ed4a1ea.tar.gz |
* NEWS: Mention native Windows support.
* Makefile.in (gdb_select_h, ser_tcp_h): New.
(ALLDEPFILES): Add ser-mingw.c.
(event-loop.o, inflow.o, mingw-hdep.o, posix-hdep.o, ser-base.o)
(ser-tcp.o, ser-unix.o): Update.
(ser-mingw.o): New rule.
* configure: Regenerated.
* configure.ac: Add ser-mingw.o for mingw32.
* ser-mingw.c: New file.
* event-loop.c: Include "gdb_select.h".
(gdb_select): Remove, moved to mingw-hdep.c and posix-hdep.c.
* ser-base.c: Include "gdb_select.h".
(ser_base_wait_for): Use gdb_select.
* serial.c (serial_for_fd): New function.
(serial_fdopen): Try "terminal" before "hardwire". Initialize
the allocated struct serial.
(serial_wait_handle): New function.
* serial.h (serial_for_fd, serial_wait_handle): New prototypes.
(struct serial_ops) [USE_WIN32API]: Add wait_handle.
* gdb_select.h: New file.
* ser-tcp.c: Include "ser-tcp.h". Remove unused "ser-unix.h" include.
(net_close, net_read_prim, net_write_prim): Make global.
(net_open): Likewise. Pass an exception set to select. Whitespace fix.
Document why we can not use gdb_select.
(_initialize_ser_tcp) [USE_WIN32API]: Do not register TCP support here.
* ser-tcp.h: New file.
* inflow.c (gdb_has_a_terminal): Don't initialize stdin_serial here.
(handle_sigio): Use gdb_select.
(initialize_stdin_serial): New function.
* terminal.h (initialize_stdin_serial): New prototype.
* top.c (gdb_init): Call initialize_stdin_serial.
* mingw-hdep.c (gdb_select): New function, moved from gdb_select in
event-loop.c. Add exception condition support. Use serial_for_fd
and serial_wait_handle. Fix timeout handling.
* posix-hdep.c: Include "gdb_select.h".
(gdb_select): New function.
* remote-st.c (connect_command): Use gdb_select.
* ser-unix.c: Include "gdb_select.h".
(hardwire_send_break, wait_for): Use gdb_select.
Diffstat (limited to 'gdb/mingw-hdep.c')
-rw-r--r-- | gdb/mingw-hdep.c | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/gdb/mingw-hdep.c b/gdb/mingw-hdep.c index 1318cfdd38e..79b23dc2556 100644 --- a/gdb/mingw-hdep.c +++ b/gdb/mingw-hdep.c @@ -21,7 +21,10 @@ Boston, MA 02110-1301, USA. */ #include "defs.h" +#include "serial.h" +#include "gdb_assert.h" +#include "gdb_select.h" #include "gdb_string.h" #include <windows.h> @@ -69,3 +72,124 @@ safe_strerror (int errnum) return buffer; } + +/* Wrapper for select. On Windows systems, where the select interface + only works for sockets, this uses the GDB serial abstraction to + handle sockets, consoles, pipes, and serial ports. + + The arguments to this function are the same as the traditional + arguments to select on POSIX platforms. */ + +int +gdb_select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + struct timeval *timeout) +{ + static HANDLE never_handle; + HANDLE handles[MAXIMUM_WAIT_OBJECTS]; + HANDLE h; + DWORD event; + DWORD num_handles; + int fd; + int num_ready; + int indx; + + num_ready = 0; + num_handles = 0; + for (fd = 0; fd < n; ++fd) + { + HANDLE read = NULL, except = NULL; + struct serial *scb; + + /* 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 (!writefds || !FD_ISSET (fd, writefds)); + + if (!FD_ISSET (fd, readfds) + && !FD_ISSET (fd, exceptfds)) + continue; + h = (HANDLE) _get_osfhandle (fd); + + scb = serial_for_fd (fd); + if (scb) + serial_wait_handle (scb, &read, &except); + + if (read == NULL) + read = h; + if (except == NULL) + { + if (!never_handle) + never_handle = CreateEvent (0, FALSE, FALSE, 0); + + except = never_handle; + } + + if (FD_ISSET (fd, readfds)) + { + gdb_assert (num_handles < MAXIMUM_WAIT_OBJECTS); + handles[num_handles++] = read; + } + + if (FD_ISSET (fd, exceptfds)) + { + gdb_assert (num_handles < MAXIMUM_WAIT_OBJECTS); + handles[num_handles++] = except; + } + } + /* If we don't need to wait for any handles, we are done. */ + if (!num_handles) + { + if (timeout) + Sleep (timeout->tv_sec * 1000 + timeout->tv_usec / 1000); + + return 0; + } + + event = WaitForMultipleObjects (num_handles, + handles, + FALSE, + timeout + ? (timeout->tv_sec * 1000 + + timeout->tv_usec / 1000) + : 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. */ + h = handles[event - WAIT_OBJECT_0]; + for (fd = 0, indx = 0; fd < n; ++fd) + { + HANDLE fd_h; + + if (FD_ISSET (fd, readfds)) + { + fd_h = handles[indx++]; + /* 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); + else + num_ready++; + } + + if (FD_ISSET (fd, exceptfds)) + { + fd_h = handles[indx++]; + /* 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, exceptfds); + else + num_ready++; + } + } + + return num_ready; +} |