aboutsummaryrefslogtreecommitdiff
path: root/qemu-coroutine-io.c
diff options
context:
space:
mode:
Diffstat (limited to 'qemu-coroutine-io.c')
-rw-r--r--qemu-coroutine-io.c82
1 files changed, 25 insertions, 57 deletions
diff --git a/qemu-coroutine-io.c b/qemu-coroutine-io.c
index 0461a9aae6..6693c7824b 100644
--- a/qemu-coroutine-io.c
+++ b/qemu-coroutine-io.c
@@ -27,71 +27,39 @@
#include "qemu-coroutine.h"
#include "iov.h"
-int coroutine_fn qemu_co_recvv(int sockfd, struct iovec *iov,
- int len, int iov_offset)
+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)
{
- int total = 0;
- int ret;
- while (len) {
- ret = iov_recv(sockfd, iov, iov_offset + total, len);
- if (ret < 0) {
+ size_t done = 0;
+ ssize_t ret;
+ while (done < bytes) {
+ ret = iov_send_recv(sockfd, iov,
+ offset + done, bytes - done, do_send);
+ if (ret > 0) {
+ done += ret;
+ } else if (ret < 0) {
if (errno == EAGAIN) {
qemu_coroutine_yield();
- continue;
- }
- if (total == 0) {
- total = -1;
- }
- break;
- }
- if (ret == 0) {
- break;
- }
- total += ret, len -= ret;
- }
-
- return total;
-}
-
-int coroutine_fn qemu_co_sendv(int sockfd, struct iovec *iov,
- int len, int iov_offset)
-{
- int total = 0;
- int ret;
- while (len) {
- ret = iov_send(sockfd, iov, iov_offset + total, len);
- if (ret < 0) {
- if (errno == EAGAIN) {
- qemu_coroutine_yield();
- continue;
- }
- if (total == 0) {
- total = -1;
+ } else if (done == 0) {
+ return -1;
+ } else {
+ break;
}
+ } else if (ret == 0 && !do_send) {
+ /* write (send) should never return 0.
+ * read (recv) returns 0 for end-of-file (-data).
+ * In both cases there's little point retrying,
+ * but we do for write anyway, just in case */
break;
}
- total += ret, len -= ret;
}
-
- return total;
+ return done;
}
-int coroutine_fn qemu_co_recv(int sockfd, void *buf, int len)
+ssize_t coroutine_fn
+qemu_co_send_recv(int sockfd, void *buf, size_t bytes, bool do_send)
{
- struct iovec iov;
-
- iov.iov_base = buf;
- iov.iov_len = len;
-
- return qemu_co_recvv(sockfd, &iov, len, 0);
-}
-
-int coroutine_fn qemu_co_send(int sockfd, void *buf, int len)
-{
- struct iovec iov;
-
- iov.iov_base = buf;
- iov.iov_len = len;
-
- return qemu_co_sendv(sockfd, &iov, len, 0);
+ struct iovec iov = { .iov_base = buf, .iov_len = bytes };
+ return qemu_co_sendv_recvv(sockfd, &iov, 1, 0, bytes, do_send);
}