tidied up ChangeLogs (80 character line width), added reference
[deliverable/binutils-gdb.git] / gdb / mingw-hdep.c
index 1318cfdd38e69878f91c96c6138b74b7735d7b21..bb0f50aaa46f59e17d0a59d017d11bf41df44098 100644 (file)
    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,134 @@ 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;
+      struct serial *scb;
+
+      if (!FD_ISSET (fd, readfds) && !FD_ISSET (fd, writefds))
+       continue;
+
+      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++;
+       }
+
+      /* We created at least one event handle for this fd.  Let the
+        device know we are finished with it.  */
+      scb = serial_for_fd (fd);
+      if (scb)
+       serial_done_wait_handle (scb);
+    }
+
+  return num_ready;
+}
This page took 0.02395 seconds and 4 git commands to generate.