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

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



V3 of the patch.

Validate fds before passing it to select. Deal with invalid fds
according to spec.

If fd < 0, revents = 0; if fd >= NOFILE, revents = POLLNVAL.


Wei.

---8<---
>From ad953f1e35ecee08b37215ebc9d6196edd744128 Mon Sep 17 00:00:00 2001
From: Wei Liu <wei.liu2@xxxxxxxxxx>
Date: Tue, 19 Feb 2013 12:15:03 +0000
Subject: [PATCH] mini-os: implement poll(2)

It is just a wrapper around select(2).

Signed-off-by: Wei Liu <wei.liu2@xxxxxxxxxx>
---
 extras/mini-os/include/posix/poll.h |    1 +
 extras/mini-os/lib/sys.c            |  109 ++++++++++++++++++++++++++++++++++-
 2 files changed, 109 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..46b3933 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,90 @@ out:
     return ret;
 }
 
+/* Wrap around select */
+int poll(struct pollfd _pfd[], nfds_t _nfds, int _timeout)
+{
+    int n;
+    int i, fd;
+    struct timeval _timeo, *timeo = NULL;
+    fd_set rfds, wfds, efds;
+    int max_fd = -1;
+    int saved_errno;
+
+    DEBUG("poll(");
+    dump_pollfds(_pfd, _nfds, _timeout);
+    DEBUG(")\n");
+
+    if (_timeout >= 0) {
+        /* Timeout in poll is in millisecond. */
+        _timeo.tv_sec  = _timeout / 1000;
+        _timeo.tv_usec = (_timeout % 1000) * 1000;
+        timeo = &_timeo;
+    }
+
+    FD_ZERO(&rfds);
+    FD_ZERO(&wfds);
+    FD_ZERO(&efds);
+
+    for (i = 0; i < _nfds; i++) {
+        fd = _pfd[i].fd;
+        _pfd[i].revents = 0;
+
+        /* ignore invalid fds */
+        if (fd < 0 || fd >= NOFILE)
+            continue;
+
+        /* 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;
+    }
+
+    /* don't care about the return value, but we do need errno */
+    select(max_fd+1, &rfds, &wfds, &efds, timeo);
+
+    n = 0;
+    for (i = 0; i < _nfds; i++) {
+        fd = _pfd[i].fd;
+        if (fd < 0) continue; /* revents = 0 */
+        /* according to spec, we should set revents = POLLNVAL if fd is 
invalid */
+        if (fd >= NOFILE) {
+            n++;
+            _pfd[i].revents |= POLLNVAL;
+            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, ignoring PULLHUP
+             * POLLNVAL */
+            _pfd[i].revents |= POLLERR;
+            continue;
+        }
+        if (FD_ISSET(fd, &rfds))
+            _pfd[i].revents |= POLLIN;
+        if (FD_ISSET(fd, &wfds))
+            _pfd[i].revents |= POLLOUT;
+    }
+
+    saved_errno = errno;
+    DEBUG("poll(");
+    dump_pollfds(_pfd, _nfds, _timeout);
+    DEBUG(")\n");
+    errno = saved_errno;
+
+    return n;
+}
+
 #ifdef HAVE_LWIP
 int socket(int domain, int type, int protocol)
 {
@@ -1360,7 +1468,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®.