poll-loop: Make poll_fd_wait_event() cross-platform.
authorGurucharan Shetty <gshetty@nicira.com>
Wed, 5 Feb 2014 18:10:10 +0000 (10:10 -0800)
committerGurucharan Shetty <gshetty@nicira.com>
Tue, 11 Feb 2014 17:55:47 +0000 (09:55 -0800)
This is helpful if we want to wait either on 'fd' for POSIX or
events for Windows.

For Windows, if both 'fd' and 'wevent' is specified, we associate
that event with the 'fd' using WSAEventSelect() in poll_block().
So any 'events' on that 'fd' will wake us up from WaitForMultipleObjects().

WSAEventSelect() does not understand  POLLIN, POLLOUT etc.  Instead the
macros it understands are FD_READ, FD_ACCEPT, FD_CONNECT, FD_CLOSE etc.
So we need to make that transition.

Signed-off-by: Gurucharan Shetty <gshetty@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
lib/poll-loop.c
lib/poll-loop.h

index abd44d1..510903e 100644 (file)
@@ -81,11 +81,13 @@ find_poll_node(struct poll_loop *loop, int fd, uint32_t wevent)
  *
  * On Windows system:
  *
- *     Register 'wevent' handle for the specified 'events'.  These wevents are
- *     given to the handleMultipleObjects() to be polled.  The event
- *     registration is one-shot: only the following call to poll_block() is
- *     affected.  The event will need to be re-registered after poll_block() is
- *     called if it is to persist.
+ *     If both 'wevent' handle and 'fd' is specified, associate the 'fd' with
+ *     with that 'wevent' for 'events' (implemented in poll_block()).
+ *     In case of no 'fd' specified, wake up on any event on that 'wevent'.
+ *     These wevents are given to the WaitForMultipleObjects() to be polled.
+ *     The event registration is one-shot: only the following call to
+ *     poll_block() is affected.  The event will need to be re-registered after
+ *     poll_block() is called if it is to persist.
  *
  * ('where' is used in debug logging.  Commonly one would use poll_fd_wait() to
  * automatically provide the caller's source file and line number for
@@ -293,6 +295,16 @@ poll_block(void)
         pollfds[i] = node->pollfd;
 #ifdef _WIN32
         wevents[i] = node->wevent;
+        if (node->pollfd.fd && node->wevent) {
+            short int wsa_events = 0;
+            if (node->pollfd.events & POLLIN) {
+                wsa_events |= FD_READ | FD_ACCEPT | FD_CLOSE;
+            }
+            if (node->pollfd.events & POLLOUT) {
+                wsa_events |= FD_WRITE | FD_CONNECT | FD_CLOSE;
+            }
+            WSAEventSelect(node->pollfd.fd, node->wevent, wsa_events);
+        }
 #endif
         i++;
     }
index ae4c0c0..412bd09 100644 (file)
@@ -53,9 +53,9 @@ extern "C" {
 void poll_fd_wait_at(int fd, HANDLE wevent, short int events, const char *where);
 #ifndef _WIN32
 #define poll_fd_wait(fd, events) poll_fd_wait_at(fd, 0, events, SOURCE_LOCATOR)
-#else
-#define poll_fd_wait_event(fd, wevent, events) poll_fd_wait_at(fd, wevent, events, SOURCE_LOCATOR)
 #endif
+#define poll_fd_wait_event(fd, wevent, events)  \
+    poll_fd_wait_at(fd, wevent, events, SOURCE_LOCATOR)
 
 void poll_timer_wait_at(long long int msec, const char *where);
 #define poll_timer_wait(msec) poll_timer_wait_at(msec, SOURCE_LOCATOR)