Merge patch from JeremyF:

43-nonblock-readwritev

Nonblocking readv/writev.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1319 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/arch/x86-linux/vg_libpthread.c b/coregrind/arch/x86-linux/vg_libpthread.c
index 600d198..cbc8fad 100644
--- a/coregrind/arch/x86-linux/vg_libpthread.c
+++ b/coregrind/arch/x86-linux/vg_libpthread.c
@@ -1994,6 +1994,21 @@
    return __libc_recv(s, buf, len, flags);
 }
 
+int VGL_(readv)(int fd, const struct iovec *iov, int count)
+{
+   __my_pthread_testcancel();
+   wait_for_fd_to_be_readable_or_erring(fd);
+   __my_pthread_testcancel();
+   return my_do_syscall3(__NR_readv, fd, (unsigned)iov, count);
+}
+
+int VGL_(writev)(int fd, struct iovec *iov, int count)
+{
+   __my_pthread_testcancel();
+   wait_for_fd_to_be_writable_or_erring(fd);
+   __my_pthread_testcancel();
+   return my_do_syscall3(__NR_writev, fd, (unsigned)iov, count);
+}
 
 extern
 pid_t __libc_waitpid(pid_t pid, int *status, int options);
@@ -2666,6 +2681,25 @@
    (void)poll(&pfd, 1, -1 /* forever */);
 }
 
+static void wait_for_fd_to_be_writable_or_erring ( int fd )
+{
+   struct pollfd pfd;
+   int           res;
+
+   /* fprintf(stderr, "wait_for_fd_to_be_readable_or_erring %d\n", fd); */
+
+   /* First check to see if the fd is nonblocking, and/or invalid.  In
+      either case return immediately. */
+   res = __libc_fcntl(fd, F_GETFL, 0);
+   if (res == -1) return; /* fd is invalid somehow */
+   if (res & O_NONBLOCK) return; /* fd is nonblocking */
+
+   /* Ok, we'd better wait with poll. */
+   pfd.fd = fd;
+   pfd.events = POLLOUT | POLLERR | POLLHUP | POLLNVAL;
+   pfd.revents = 0;
+   (void)poll(&pfd, 1, -1 /* forever */);
+}
 
 /* ---------------------------------------------------------------------
    Hacky implementation of semaphores.
diff --git a/coregrind/vg_intercept.c b/coregrind/vg_intercept.c
index 402a17b..f97ad37 100644
--- a/coregrind/vg_intercept.c
+++ b/coregrind/vg_intercept.c
@@ -211,3 +211,33 @@
 }
 
 strong_alias(select, __select)
+
+/* -------------------------------- readv -------------------------------- */
+
+#include <sys/uio.h>
+
+WEAK int VGL_(readv)(int fd, const struct iovec *iov, int count)
+{
+   return my_do_syscall3(__NR_readv, fd, (unsigned)iov, count);
+}
+
+int readv (int fd, const struct iovec *iov, int count)
+{
+   return VGL_(readv)(fd, iov, count);
+}
+
+strong_alias(readv, __readv)
+
+/* -------------------------------- writev -------------------------------- */
+
+WEAK int VGL_(writev)(int fd, const struct iovec *iov, int count)
+{
+   return my_do_syscall3(__NR_writev, fd, (unsigned)iov, count);
+}
+
+int writev (int fd, const struct iovec *iov, int count)
+{
+   return VGL_(writev)(fd, iov, count);
+}
+
+strong_alias(writev, __writev)
diff --git a/coregrind/vg_libpthread.c b/coregrind/vg_libpthread.c
index 600d198..cbc8fad 100644
--- a/coregrind/vg_libpthread.c
+++ b/coregrind/vg_libpthread.c
@@ -1994,6 +1994,21 @@
    return __libc_recv(s, buf, len, flags);
 }
 
+int VGL_(readv)(int fd, const struct iovec *iov, int count)
+{
+   __my_pthread_testcancel();
+   wait_for_fd_to_be_readable_or_erring(fd);
+   __my_pthread_testcancel();
+   return my_do_syscall3(__NR_readv, fd, (unsigned)iov, count);
+}
+
+int VGL_(writev)(int fd, struct iovec *iov, int count)
+{
+   __my_pthread_testcancel();
+   wait_for_fd_to_be_writable_or_erring(fd);
+   __my_pthread_testcancel();
+   return my_do_syscall3(__NR_writev, fd, (unsigned)iov, count);
+}
 
 extern
 pid_t __libc_waitpid(pid_t pid, int *status, int options);
@@ -2666,6 +2681,25 @@
    (void)poll(&pfd, 1, -1 /* forever */);
 }
 
+static void wait_for_fd_to_be_writable_or_erring ( int fd )
+{
+   struct pollfd pfd;
+   int           res;
+
+   /* fprintf(stderr, "wait_for_fd_to_be_readable_or_erring %d\n", fd); */
+
+   /* First check to see if the fd is nonblocking, and/or invalid.  In
+      either case return immediately. */
+   res = __libc_fcntl(fd, F_GETFL, 0);
+   if (res == -1) return; /* fd is invalid somehow */
+   if (res & O_NONBLOCK) return; /* fd is nonblocking */
+
+   /* Ok, we'd better wait with poll. */
+   pfd.fd = fd;
+   pfd.events = POLLOUT | POLLERR | POLLHUP | POLLNVAL;
+   pfd.revents = 0;
+   (void)poll(&pfd, 1, -1 /* forever */);
+}
 
 /* ---------------------------------------------------------------------
    Hacky implementation of semaphores.