diff mbox

[16/25] coroutine-io: Add I/O functions with timeout

Message ID 1424887718-10800-17-git-send-email-mreitz@redhat.com
State New
Headers show

Commit Message

Max Reitz Feb. 25, 2015, 6:08 p.m. UTC
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 include/qemu-common.h | 45 +++++++++++++++++++++++++++++++++++++--------
 qemu-coroutine-io.c   | 23 ++++++++++++++++-------
 2 files changed, 53 insertions(+), 15 deletions(-)
diff mbox

Patch

diff --git a/include/qemu-common.h b/include/qemu-common.h
index 644b46d..a268ffc 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -296,23 +296,52 @@  struct qemu_work_item {
  * Receives data into a (part of) iovec from a socket,
  * yielding when there is no data in the socket.
  * The same interface as qemu_sendv_recvv(), with added yielding.
- * XXX should mark these as coroutine_fn
  */
-ssize_t qemu_co_sendv_recvv(int sockfd, struct iovec *iov, unsigned iov_cnt,
-                            size_t offset, size_t bytes, bool do_send);
+#define qemu_co_sendv_recvv(sockfd, iov, iov_cnt, offset, bytes, do_send) \
+     qemu_co_sendv_recvv_timeout(sockfd, iov, iov_cnt, offset, bytes, do_send, \
+                                 -1)
 #define qemu_co_recvv(sockfd, iov, iov_cnt, offset, bytes) \
-  qemu_co_sendv_recvv(sockfd, iov, iov_cnt, offset, bytes, false)
+    qemu_co_sendv_recvv_timeout(sockfd, iov, iov_cnt, offset, bytes, false, -1)
 #define qemu_co_sendv(sockfd, iov, iov_cnt, offset, bytes) \
-  qemu_co_sendv_recvv(sockfd, iov, iov_cnt, offset, bytes, true)
+    qemu_co_sendv_recvv_timeout(sockfd, iov, iov_cnt, offset, bytes, true, -1)
 
 /**
  * The same as above, but with just a single buffer
  */
-ssize_t qemu_co_send_recv(int sockfd, void *buf, size_t bytes, bool do_send);
+#define qemu_co_send_recv(sockfd, buf, bytes, do_send) \
+    qemu_co_send_recv_timeout(sockfd, buf, bytes, do_send, -1)
 #define qemu_co_recv(sockfd, buf, bytes) \
-  qemu_co_send_recv(sockfd, buf, bytes, false)
+    qemu_co_send_recv_timeout(sockfd, buf, bytes, false, -1)
 #define qemu_co_send(sockfd, buf, bytes) \
-  qemu_co_send_recv(sockfd, buf, bytes, true)
+    qemu_co_send_recv_timeout(sockfd, buf, bytes, true, -1)
+
+/**
+ * The same as qemu_co_sendv_recvv(), but allows you to specify a timeout in
+ * nanoseconds.
+ * XXX should mark these as coroutine_fn
+ */
+ssize_t qemu_co_sendv_recvv_timeout(int sockfd, struct iovec *iov,
+                                    unsigned iov_cnt, size_t offset,
+                                    size_t bytes, bool do_send,
+                                    int64_t timeout);
+#define qemu_co_recvv_timeout(sockfd, iov, iov_cnt, offset, bytes, timeout) \
+    qemu_co_sendv_recvv_timeout(sockfd, iov, iov_cnt, offset, bytes, false, \
+                                timeout)
+#define qemu_co_sendv_timeout(sockfd, iov, iov_cnt, offset, bytes, timeout) \
+    qemu_co_sendv_recvv_timeout(sockfd, iov, iov_cnt, offset, bytes, true, \
+                                timeout)
+
+/**
+ * The same as qemu_co_send_recv(), but allows you to specify a timeout in
+ * nanoseconds.
+ */
+ssize_t qemu_co_send_recv_timeout(int sockfd, void *buf, size_t bytes,
+                                  bool do_send, int64_t timeout);
+#define qemu_co_recv_timeout(sockfd, buf, bytes, timeout) \
+    qemu_co_send_recv_timeout(sockfd, buf, bytes, false, timeout)
+#define qemu_co_send_timeout(sockfd, buf, bytes, timeout) \
+    qemu_co_send_recv_timeout(sockfd, buf, bytes, true, timeout)
+
 
 typedef struct QEMUIOVector {
     struct iovec *iov;
diff --git a/qemu-coroutine-io.c b/qemu-coroutine-io.c
index 28dc735..f261a6e 100644
--- a/qemu-coroutine-io.c
+++ b/qemu-coroutine-io.c
@@ -28,9 +28,10 @@ 
 #include "qemu/iov.h"
 #include "qemu/main-loop.h"
 
-ssize_t coroutine_fn
-qemu_co_sendv_recvv(int sockfd, struct iovec *iov, unsigned iov_cnt,
-                    size_t offset, size_t bytes, bool do_send)
+ssize_t coroutine_fn qemu_co_sendv_recvv_timeout(int sockfd, struct iovec *iov,
+                                                 unsigned iov_cnt,
+                                                 size_t offset, size_t bytes,
+                                                 bool do_send, int64_t timeout)
 {
     size_t done = 0;
     ssize_t ret;
@@ -43,7 +44,13 @@  qemu_co_sendv_recvv(int sockfd, struct iovec *iov, unsigned iov_cnt,
         } else if (ret < 0) {
             err = socket_error();
             if (err == EAGAIN || err == EWOULDBLOCK) {
-                qemu_coroutine_yield();
+                if (timeout < 0) {
+                    qemu_coroutine_yield();
+                } else {
+                    if (co_yield_timeout(QEMU_CLOCK_REALTIME, timeout)) {
+                        return -ETIMEDOUT;
+                    }
+                }
             } else if (done == 0) {
                 return -err;
             } else {
@@ -60,11 +67,13 @@  qemu_co_sendv_recvv(int sockfd, struct iovec *iov, unsigned iov_cnt,
     return done;
 }
 
-ssize_t coroutine_fn
-qemu_co_send_recv(int sockfd, void *buf, size_t bytes, bool do_send)
+ssize_t coroutine_fn qemu_co_send_recv_timeout(int sockfd, void *buf,
+                                               size_t bytes, bool do_send,
+                                               int64_t timeout)
 {
     struct iovec iov = { .iov_base = buf, .iov_len = bytes };
-    return qemu_co_sendv_recvv(sockfd, &iov, 1, 0, bytes, do_send);
+    return qemu_co_sendv_recvv_timeout(sockfd, &iov, 1, 0, bytes, do_send,
+                                       timeout);
 }
 
 typedef struct {