diff options
| author | fishsoupisgood <github@madingley.org> | 2019-04-29 01:17:54 +0100 | 
|---|---|---|
| committer | fishsoupisgood <github@madingley.org> | 2019-05-27 03:43:43 +0100 | 
| commit | 3f2546b2ef55b661fd8dd69682b38992225e86f6 (patch) | |
| tree | 65ca85f13617aee1dce474596800950f266a456c /qemu-coroutine-io.c | |
| download | qemu-master.tar.gz qemu-master.tar.bz2 qemu-master.zip | |
Diffstat (limited to 'qemu-coroutine-io.c')
| -rw-r--r-- | qemu-coroutine-io.c | 91 | 
1 files changed, 91 insertions, 0 deletions
| diff --git a/qemu-coroutine-io.c b/qemu-coroutine-io.c new file mode 100644 index 00000000..28dc7351 --- /dev/null +++ b/qemu-coroutine-io.c @@ -0,0 +1,91 @@ +/* + * Coroutine-aware I/O functions + * + * Copyright (C) 2009-2010 Nippon Telegraph and Telephone Corporation. + * Copyright (c) 2011, Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "qemu-common.h" +#include "qemu/sockets.h" +#include "block/coroutine.h" +#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) +{ +    size_t done = 0; +    ssize_t ret; +    int err; +    while (done < bytes) { +        ret = iov_send_recv(sockfd, iov, iov_cnt, +                            offset + done, bytes - done, do_send); +        if (ret > 0) { +            done += ret; +        } else if (ret < 0) { +            err = socket_error(); +            if (err == EAGAIN || err == EWOULDBLOCK) { +                qemu_coroutine_yield(); +            } else if (done == 0) { +                return -err; +            } 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; +        } +    } +    return done; +} + +ssize_t coroutine_fn +qemu_co_send_recv(int sockfd, void *buf, size_t bytes, bool do_send) +{ +    struct iovec iov = { .iov_base = buf, .iov_len = bytes }; +    return qemu_co_sendv_recvv(sockfd, &iov, 1, 0, bytes, do_send); +} + +typedef struct { +    Coroutine *co; +    int fd; +} FDYieldUntilData; + +static void fd_coroutine_enter(void *opaque) +{ +    FDYieldUntilData *data = opaque; +    qemu_set_fd_handler(data->fd, NULL, NULL, NULL); +    qemu_coroutine_enter(data->co, NULL); +} + +void coroutine_fn yield_until_fd_readable(int fd) +{ +    FDYieldUntilData data; + +    assert(qemu_in_coroutine()); +    data.co = qemu_coroutine_self(); +    data.fd = fd; +    qemu_set_fd_handler(fd, fd_coroutine_enter, NULL, &data); +    qemu_coroutine_yield(); +} | 
