From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53077) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YQgOR-0002ps-2L for qemu-devel@nongnu.org; Wed, 25 Feb 2015 13:09:13 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YQgOP-0001lI-QS for qemu-devel@nongnu.org; Wed, 25 Feb 2015 13:09:06 -0500 From: Max Reitz Date: Wed, 25 Feb 2015 13:08:29 -0500 Message-Id: <1424887718-10800-17-git-send-email-mreitz@redhat.com> In-Reply-To: <1424887718-10800-1-git-send-email-mreitz@redhat.com> References: <1424887718-10800-1-git-send-email-mreitz@redhat.com> Subject: [Qemu-devel] [PATCH 16/25] coroutine-io: Add I/O functions with timeout List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-block@nongnu.org Cc: Kevin Wolf , Paolo Bonzini , qemu-devel@nongnu.org, Stefan Hajnoczi , Max Reitz Signed-off-by: Max Reitz --- include/qemu-common.h | 45 +++++++++++++++++++++++++++++++++++++-------- qemu-coroutine-io.c | 23 ++++++++++++++++------- 2 files changed, 53 insertions(+), 15 deletions(-) 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 { -- 2.1.0