aboutsummaryrefslogtreecommitdiffstats
path: root/extras
diff options
context:
space:
mode:
authorWei Liu <wei.liu2@citrix.com>2013-03-25 11:17:30 +0000
committerIan Campbell <ian.campbell@citrix.com>2013-04-11 15:42:39 +0100
commit1b7720cd4b7a27e3b2c4ab67641d42c2aec31964 (patch)
treebd7ffd9dcdd665415096b024708ad102d46b2e23 /extras
parentbe8d8d634d1babbf52a83cda139554e0605660c5 (diff)
downloadxen-1b7720cd4b7a27e3b2c4ab67641d42c2aec31964.tar.gz
xen-1b7720cd4b7a27e3b2c4ab67641d42c2aec31964.tar.bz2
xen-1b7720cd4b7a27e3b2c4ab67641d42c2aec31964.zip
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@citrix.com> Acked-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Diffstat (limited to 'extras')
-rw-r--r--extras/mini-os/include/posix/poll.h1
-rw-r--r--extras/mini-os/lib/sys.c117
2 files changed, 117 insertions, 1 deletions
diff --git a/extras/mini-os/include/posix/poll.h b/extras/mini-os/include/posix/poll.h
new file mode 100644
index 0000000000..06fb41ab89
--- /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 3cc334000c..cfbdc90eb9 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);