[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 1/2] mini-os: implement poll(2)



It is just a wrapper around select(2). This implementation mimics Linux's
do_poll.

Signed-off-by: Wei Liu <wei.liu2@xxxxxxxxxx>
Acked-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxx>
---
 extras/mini-os/include/posix/poll.h |    1 +
 extras/mini-os/lib/sys.c            |  117 ++++++++++++++++++++++++++++++++++-
 2 files changed, 117 insertions(+), 1 deletion(-)
 create mode 100644 extras/mini-os/include/posix/poll.h

diff --git a/extras/mini-os/include/posix/poll.h 
b/extras/mini-os/include/posix/poll.h
new file mode 100644
index 0000000..06fb41a
--- /dev/null
+++ b/extras/mini-os/include/posix/poll.h
@@ -0,0 +1 @@
+#include <sys/poll.h>
diff --git a/extras/mini-os/lib/sys.c b/extras/mini-os/lib/sys.c
index 3cc3340..cfbdc90 100644
--- a/extras/mini-os/lib/sys.c
+++ b/extras/mini-os/lib/sys.c
@@ -31,6 +31,7 @@
 #include <tpm_tis.h>
 #include <xenbus.h>
 #include <xenstore.h>
+#include <poll.h>
 
 #include <sys/types.h>
 #include <sys/unistd.h>
@@ -678,6 +679,29 @@ static void dump_set(int nfds, fd_set *readfds, fd_set 
*writefds, fd_set *except
 #define dump_set(nfds, readfds, writefds, exceptfds, timeout)
 #endif
 
+#ifdef LIBC_DEBUG
+static void dump_pollfds(struct pollfd *pfd, int nfds, int timeout)
+{
+    int i, comma, fd;
+
+    printk("[");
+    comma = 0;
+    for (i = 0; i < nfds; i++) {
+        fd = pfd[i].fd;
+        if (comma)
+            printk(", ");
+        printk("%d(%c)/%02x", fd, file_types[files[fd].type],
+            pfd[i].events);
+            comma = 1;
+    }
+    printk("]");
+
+    printk(", %d, %d", nfds, timeout);
+}
+#else
+#define dump_pollfds(pfds, nfds, timeout)
+#endif
+
 /* Just poll without blocking */
 static int select_poll(int nfds, fd_set *readfds, fd_set *writefds, fd_set 
*exceptfds)
 {
@@ -983,6 +1007,98 @@ out:
     return ret;
 }
 
+/* Wrap around select */
+int poll(struct pollfd _pfd[], nfds_t _nfds, int _timeout)
+{
+    int n, ret;
+    int i, fd;
+    struct timeval _timeo, *timeo = NULL;
+    fd_set rfds, wfds, efds;
+    int max_fd = -1;
+
+    DEBUG("poll(");
+    dump_pollfds(_pfd, _nfds, _timeout);
+    DEBUG(")\n");
+
+    FD_ZERO(&rfds);
+    FD_ZERO(&wfds);
+    FD_ZERO(&efds);
+
+    n = 0;
+
+    for (i = 0; i < _nfds; i++) {
+        fd = _pfd[i].fd;
+        _pfd[i].revents = 0;
+
+        /* fd < 0, revents = 0, which is already set */
+        if (fd < 0) continue;
+
+        /* fd is invalid, revents = POLLNVAL, increment counter */
+        if (fd >= NOFILE || files[fd].type == FTYPE_NONE) {
+            n++;
+            _pfd[i].revents |= POLLNVAL;
+            continue;
+        }
+
+        /* normal case, map POLL* into readfds and writefds:
+         * POLLIN  -> readfds
+         * POLLOUT -> writefds
+         * POLL*   -> none
+         */
+        if (_pfd[i].events & POLLIN)
+            FD_SET(fd, &rfds);
+        if (_pfd[i].events & POLLOUT)
+            FD_SET(fd, &wfds);
+        /* always set exceptfds */
+        FD_SET(fd, &efds);
+        if (fd > max_fd)
+            max_fd = fd;
+    }
+
+    /* should never sleep when we already have events */
+    if (n) {
+        _timeo.tv_sec  = 0;
+        _timeo.tv_usec = 0;
+        timeo = &_timeo;
+    } else if (_timeout >= 0) {
+        /* normal case, construct _timeout, might sleep */
+        _timeo.tv_sec  = _timeout / 1000;
+        _timeo.tv_usec = (_timeout % 1000) * 1000;
+        timeo = &_timeo;
+    } else {
+        /* _timeout < 0, block forever */
+        timeo = NULL;
+    }
+
+
+    ret = select(max_fd+1, &rfds, &wfds, &efds, timeo);
+    /* error in select, just return, errno is set by select() */
+    if (ret < 0)
+        return ret;
+
+    for (i = 0; i < _nfds; i++) {
+        fd = _pfd[i].fd;
+
+        /* the revents has already been set for all error case */
+        if (fd < 0 || fd >= NOFILE || files[fd].type == FTYPE_NONE)
+            continue;
+
+        if (FD_ISSET(fd, &rfds) || FD_ISSET(fd, &wfds) || FD_ISSET(fd, &efds))
+            n++;
+        if (FD_ISSET(fd, &efds)) {
+            /* anything bad happens we set POLLERR */
+            _pfd[i].revents |= POLLERR;
+            continue;
+        }
+        if (FD_ISSET(fd, &rfds))
+            _pfd[i].revents |= POLLIN;
+        if (FD_ISSET(fd, &wfds))
+            _pfd[i].revents |= POLLOUT;
+    }
+
+    return n;
+}
+
 #ifdef HAVE_LWIP
 int socket(int domain, int type, int protocol)
 {
@@ -1360,7 +1476,6 @@ unsupported_function(int, tcgetattr, 0);
 unsupported_function(int, grantpt, -1);
 unsupported_function(int, unlockpt, -1);
 unsupported_function(char *, ptsname, NULL);
-unsupported_function(int, poll, -1);
 
 /* net/if.h */
 unsupported_function_log(unsigned int, if_nametoindex, -1);
-- 
1.7.10.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.