Beispiel #1
0
static void segdev_callback(struct segdev *dev, xport portno)
{
	struct xseg *xseg;
	struct segpriv *priv = dev->priv;
	struct xseg_private *xpriv;
	struct xseg_port *port;
	struct segdev_signal_desc *ssd;

	xseg = xsegments[portno];
	if (!xseg)
		return;
	if (priv->segno >= nr_xsegments)
		return;

	xpriv = xseg->priv;
	port = xseg_get_port(xseg, portno);
	if (!port)
		return;
	ssd = xseg_get_signal_desc(xseg, port);
	if (!ssd || !ssd->waitcue){
		return;
	}

	if (xpriv->wakeup) {
		xpriv->wakeup(portno);
	}
	return;
}
Beispiel #2
0
static struct posixfd_signal_desc * __get_signal_desc(struct xseg *xseg, xport portno)
{
	struct xseg_port *port = xseg_get_port(xseg, portno);
	if (!port)
		return NULL;
	struct posixfd_signal_desc *psd = xseg_get_signal_desc(xseg, port);
	if (!psd)
		return NULL;
	return psd;
}
Beispiel #3
0
static int posix_cancel_wait(struct xseg *xseg, uint32_t portno)
{
    struct xseg_port *port = xseg_get_port(xseg, portno);
    if (!port)
        return -1;
    struct posix_signal_desc *psd = xseg_get_signal_desc(xseg, port);
    if (!psd)
        return -1;
    psd->waitcue = 0;
    return 0;
}
Beispiel #4
0
static int segdev_cancel_wait(struct xseg *xseg, uint32_t portno)
{
	struct segdev_signal_desc *ssd; 
	struct xseg_port *port = xseg_get_port(xseg, portno);
	if (!port)
		return -1;
	ssd = xseg_get_signal_desc(xseg, port);
	if (!ssd)
		return -1;
	/* true/false value */
	ssd->waitcue = 0;
	return -0;
}
Beispiel #5
0
static int posix_signal(struct xseg *xseg, uint32_t portno)
{
    struct xseg_port *port = xseg_get_port(xseg, portno);
    if (!port)
        return -1;
    struct posix_signal_desc *psd = xseg_get_signal_desc(xseg, port);
    if (!psd)
        return -1;
    pid_t cue = (pid_t)psd->waitcue;
    if (!cue)
        //HACKY!
        return -2;

    /* FIXME: Make calls to xseg_signal() check for errors */
    return syscall(SYS_tkill, cue, SIGIO);
}
Beispiel #6
0
static int wait_reply(struct xseg *xseg, xport srcport, struct xseg_port *port,
                      struct xseg_request *expected_req)
{
    struct xseg_request *req;
    xseg_prepare_wait(xseg, srcport);
    void *psd = xseg_get_signal_desc(xseg, port);
    while (1) {
        req = xseg_receive(xseg, srcport, X_NONBLOCK);
        if (req) {
            if (req != expected_req) {
                archipelagolog("Unknown received request\n");
                xseg_put_request(xseg, req, srcport);
            } else if (!(req->state & XS_SERVED)) {
                return -1;
            } else {
                break;
            }
        }
        xseg_wait_signal(xseg, psd, 100000UL);
    }
    xseg_cancel_wait(xseg, srcport);
    return 0;
}
Beispiel #7
0
static void xseg_request_handler(void *state)
{
    BDRVArchipelagoState *s = (BDRVArchipelagoState *) state;
    void *psd = xseg_get_signal_desc(s->xseg, s->port);
    qemu_mutex_lock(&s->request_mutex);

    while (!s->stopping) {
        struct xseg_request *req;
        void *data;
        xseg_prepare_wait(s->xseg, s->srcport);
        req = xseg_receive(s->xseg, s->srcport, X_NONBLOCK);
        if (req) {
            AIORequestData *reqdata;
            ArchipelagoSegmentedRequest *segreq;
            xseg_get_req_data(s->xseg, req, (void **)&reqdata);

            switch (reqdata->op) {
            case ARCHIP_OP_READ:
                data = xseg_get_data(s->xseg, req);
                segreq = reqdata->segreq;
                segreq->count += req->serviced;

                qemu_iovec_from_buf(reqdata->aio_cb->qiov, reqdata->bufidx,
                                    data,
                                    req->serviced);

                xseg_put_request(s->xseg, req, s->srcport);

                if ((__sync_add_and_fetch(&segreq->ref, -1)) == 0) {
                    if (!segreq->failed) {
                        reqdata->aio_cb->ret = segreq->count;
                        archipelago_finish_aiocb(reqdata);
                        g_free(segreq);
                    } else {
                        g_free(segreq);
                        g_free(reqdata);
                    }
                } else {
                    g_free(reqdata);
                }
                break;
            case ARCHIP_OP_WRITE:
            case ARCHIP_OP_FLUSH:
                segreq = reqdata->segreq;
                segreq->count += req->serviced;
                xseg_put_request(s->xseg, req, s->srcport);

                if ((__sync_add_and_fetch(&segreq->ref, -1)) == 0) {
                    if (!segreq->failed) {
                        reqdata->aio_cb->ret = segreq->count;
                        archipelago_finish_aiocb(reqdata);
                        g_free(segreq);
                    } else {
                        g_free(segreq);
                        g_free(reqdata);
                    }
                } else {
                    g_free(reqdata);
                }
                break;
            case ARCHIP_OP_VOLINFO:
                s->is_signaled = true;
                qemu_cond_signal(&s->archip_cond);
                break;
            }
        } else {
            xseg_wait_signal(s->xseg, psd, 100000UL);
        }
        xseg_cancel_wait(s->xseg, s->srcport);
    }

    s->th_is_signaled = true;
    qemu_cond_signal(&s->request_cond);
    qemu_mutex_unlock(&s->request_mutex);
    qemu_thread_exit(NULL);
}