110817bf0SDaniel P. Berrange /* 210817bf0SDaniel P. Berrange * Coroutine-aware I/O functions 310817bf0SDaniel P. Berrange * 410817bf0SDaniel P. Berrange * Copyright (C) 2009-2010 Nippon Telegraph and Telephone Corporation. 510817bf0SDaniel P. Berrange * Copyright (c) 2011, Red Hat, Inc. 610817bf0SDaniel P. Berrange * 710817bf0SDaniel P. Berrange * Permission is hereby granted, free of charge, to any person obtaining a copy 810817bf0SDaniel P. Berrange * of this software and associated documentation files (the "Software"), to deal 910817bf0SDaniel P. Berrange * in the Software without restriction, including without limitation the rights 1010817bf0SDaniel P. Berrange * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 1110817bf0SDaniel P. Berrange * copies of the Software, and to permit persons to whom the Software is 1210817bf0SDaniel P. Berrange * furnished to do so, subject to the following conditions: 1310817bf0SDaniel P. Berrange * 1410817bf0SDaniel P. Berrange * The above copyright notice and this permission notice shall be included in 1510817bf0SDaniel P. Berrange * all copies or substantial portions of the Software. 1610817bf0SDaniel P. Berrange * 1710817bf0SDaniel P. Berrange * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1810817bf0SDaniel P. Berrange * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1910817bf0SDaniel P. Berrange * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2010817bf0SDaniel P. Berrange * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2110817bf0SDaniel P. Berrange * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2210817bf0SDaniel P. Berrange * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 2310817bf0SDaniel P. Berrange * THE SOFTWARE. 2410817bf0SDaniel P. Berrange */ 25*aafd7584SPeter Maydell #include "qemu/osdep.h" 2610817bf0SDaniel P. Berrange #include "qemu-common.h" 2710817bf0SDaniel P. Berrange #include "qemu/sockets.h" 2810817bf0SDaniel P. Berrange #include "qemu/coroutine.h" 2910817bf0SDaniel P. Berrange #include "qemu/iov.h" 3010817bf0SDaniel P. Berrange #include "qemu/main-loop.h" 3110817bf0SDaniel P. Berrange 3210817bf0SDaniel P. Berrange ssize_t coroutine_fn 3310817bf0SDaniel P. Berrange qemu_co_sendv_recvv(int sockfd, struct iovec *iov, unsigned iov_cnt, 3410817bf0SDaniel P. Berrange size_t offset, size_t bytes, bool do_send) 3510817bf0SDaniel P. Berrange { 3610817bf0SDaniel P. Berrange size_t done = 0; 3710817bf0SDaniel P. Berrange ssize_t ret; 3810817bf0SDaniel P. Berrange int err; 3910817bf0SDaniel P. Berrange while (done < bytes) { 4010817bf0SDaniel P. Berrange ret = iov_send_recv(sockfd, iov, iov_cnt, 4110817bf0SDaniel P. Berrange offset + done, bytes - done, do_send); 4210817bf0SDaniel P. Berrange if (ret > 0) { 4310817bf0SDaniel P. Berrange done += ret; 4410817bf0SDaniel P. Berrange } else if (ret < 0) { 4510817bf0SDaniel P. Berrange err = socket_error(); 4610817bf0SDaniel P. Berrange if (err == EAGAIN || err == EWOULDBLOCK) { 4710817bf0SDaniel P. Berrange qemu_coroutine_yield(); 4810817bf0SDaniel P. Berrange } else if (done == 0) { 4910817bf0SDaniel P. Berrange return -err; 5010817bf0SDaniel P. Berrange } else { 5110817bf0SDaniel P. Berrange break; 5210817bf0SDaniel P. Berrange } 5310817bf0SDaniel P. Berrange } else if (ret == 0 && !do_send) { 5410817bf0SDaniel P. Berrange /* write (send) should never return 0. 5510817bf0SDaniel P. Berrange * read (recv) returns 0 for end-of-file (-data). 5610817bf0SDaniel P. Berrange * In both cases there's little point retrying, 5710817bf0SDaniel P. Berrange * but we do for write anyway, just in case */ 5810817bf0SDaniel P. Berrange break; 5910817bf0SDaniel P. Berrange } 6010817bf0SDaniel P. Berrange } 6110817bf0SDaniel P. Berrange return done; 6210817bf0SDaniel P. Berrange } 6310817bf0SDaniel P. Berrange 6410817bf0SDaniel P. Berrange ssize_t coroutine_fn 6510817bf0SDaniel P. Berrange qemu_co_send_recv(int sockfd, void *buf, size_t bytes, bool do_send) 6610817bf0SDaniel P. Berrange { 6710817bf0SDaniel P. Berrange struct iovec iov = { .iov_base = buf, .iov_len = bytes }; 6810817bf0SDaniel P. Berrange return qemu_co_sendv_recvv(sockfd, &iov, 1, 0, bytes, do_send); 6910817bf0SDaniel P. Berrange } 7010817bf0SDaniel P. Berrange 7110817bf0SDaniel P. Berrange typedef struct { 7210817bf0SDaniel P. Berrange Coroutine *co; 7310817bf0SDaniel P. Berrange int fd; 7410817bf0SDaniel P. Berrange } FDYieldUntilData; 7510817bf0SDaniel P. Berrange 7610817bf0SDaniel P. Berrange static void fd_coroutine_enter(void *opaque) 7710817bf0SDaniel P. Berrange { 7810817bf0SDaniel P. Berrange FDYieldUntilData *data = opaque; 7910817bf0SDaniel P. Berrange qemu_set_fd_handler(data->fd, NULL, NULL, NULL); 8010817bf0SDaniel P. Berrange qemu_coroutine_enter(data->co, NULL); 8110817bf0SDaniel P. Berrange } 8210817bf0SDaniel P. Berrange 8310817bf0SDaniel P. Berrange void coroutine_fn yield_until_fd_readable(int fd) 8410817bf0SDaniel P. Berrange { 8510817bf0SDaniel P. Berrange FDYieldUntilData data; 8610817bf0SDaniel P. Berrange 8710817bf0SDaniel P. Berrange assert(qemu_in_coroutine()); 8810817bf0SDaniel P. Berrange data.co = qemu_coroutine_self(); 8910817bf0SDaniel P. Berrange data.fd = fd; 9010817bf0SDaniel P. Berrange qemu_set_fd_handler(fd, fd_coroutine_enter, NULL, &data); 9110817bf0SDaniel P. Berrange qemu_coroutine_yield(); 9210817bf0SDaniel P. Berrange } 93