Esempio n. 1
0
File: ssh.c Progetto: J-Liu/qemu
static void restart_coroutine(void *opaque)
{
    Coroutine *co = opaque;

    DPRINTF("co=%p", co);

    aio_co_wake(co);
}
Esempio n. 2
0
static void qio_channel_restart_write(void *opaque)
{
    QIOChannel *ioc = opaque;
    Coroutine *co = ioc->write_coroutine;

    ioc->write_coroutine = NULL;
    qio_channel_set_aio_fd_handlers(ioc);
    aio_co_wake(co);
}
Esempio n. 3
0
static void nbd_recv_coroutines_enter_all(NBDClientSession *s)
{
    int i;

    for (i = 0; i < MAX_NBD_REQUESTS; i++) {
        if (s->recv_coroutine[i]) {
            aio_co_wake(s->recv_coroutine[i]);
        }
    }
}
Esempio n. 4
0
static void nbd_recv_coroutines_wake_all(NBDClientSession *s)
{
    int i;

    for (i = 0; i < MAX_NBD_REQUESTS; i++) {
        NBDClientRequest *req = &s->requests[i];

        if (req->coroutine && req->receiving) {
            aio_co_wake(req->coroutine);
        }
    }
}
Esempio n. 5
0
static void nbd_coroutine_end(BlockDriverState *bs,
                              NBDRequest *request)
{
    NBDClientSession *s = nbd_get_client_session(bs);
    int i = HANDLE_TO_INDEX(s, request->handle);

    s->recv_coroutine[i] = NULL;
    s->in_flight--;
    qemu_co_queue_next(&s->free_sema);

    /* Kick the read_reply_co to get the next reply.  */
    if (s->read_reply_co) {
        aio_co_wake(s->read_reply_co);
    }
}
Esempio n. 6
0
static coroutine_fn void nbd_read_reply_entry(void *opaque)
{
    NBDClientSession *s = opaque;
    uint64_t i;
    int ret = 0;
    Error *local_err = NULL;

    while (!s->quit) {
        assert(s->reply.handle == 0);
        ret = nbd_receive_reply(s->ioc, &s->reply, &local_err);
        if (ret < 0) {
            error_report_err(local_err);
        }
        if (ret <= 0) {
            break;
        }

        /* There's no need for a mutex on the receive side, because the
         * handler acts as a synchronization point and ensures that only
         * one coroutine is called until the reply finishes.
         */
        i = HANDLE_TO_INDEX(s, s->reply.handle);
        if (i >= MAX_NBD_REQUESTS ||
            !s->requests[i].coroutine ||
            !s->requests[i].receiving) {
            break;
        }

        /* We're woken up again by the request itself.  Note that there
         * is no race between yielding and reentering read_reply_co.  This
         * is because:
         *
         * - if the request runs on the same AioContext, it is only
         *   entered after we yield
         *
         * - if the request runs on a different AioContext, reentering
         *   read_reply_co happens through a bottom half, which can only
         *   run after we yield.
         */
        aio_co_wake(s->requests[i].coroutine);
        qemu_coroutine_yield();
    }

    s->quit = true;
    nbd_recv_coroutines_wake_all(s);
    s->read_reply_co = NULL;
}
Esempio n. 7
0
static void nbd_co_receive_reply(NBDClientSession *s,
                                 NBDRequest *request,
                                 NBDReply *reply,
                                 QEMUIOVector *qiov)
{
    int i = HANDLE_TO_INDEX(s, request->handle);

    /* Wait until we're woken up by nbd_read_reply_entry.  */
    s->requests[i].receiving = true;
    qemu_coroutine_yield();
    s->requests[i].receiving = false;
    *reply = s->reply;
    if (reply->handle != request->handle || !s->ioc || s->quit) {
        reply->error = EIO;
    } else {
        if (qiov && reply->error == 0) {
            assert(request->len == iov_size(qiov->iov, qiov->niov));
            if (qio_channel_readv_all(s->ioc, qiov->iov, qiov->niov,
                                      NULL) < 0) {
                reply->error = EIO;
                s->quit = true;
            }
        }

        /* Tell the read handler to read another header.  */
        s->reply.handle = 0;
    }

    s->requests[i].coroutine = NULL;

    /* Kick the read_reply_co to get the next reply.  */
    if (s->read_reply_co) {
        aio_co_wake(s->read_reply_co);
    }

    qemu_co_mutex_lock(&s->send_mutex);
    s->in_flight--;
    qemu_co_queue_next(&s->free_sema);
    qemu_co_mutex_unlock(&s->send_mutex);
}