int vring_pop(VirtIODevice *vdev, Vring *vring,

              VirtQueueElement **p_elem)

{

    struct vring_desc desc;

    unsigned int i, head, found = 0, num = vring->vr.num;

    uint16_t avail_idx, last_avail_idx;

    VirtQueueElement *elem = NULL;

    int ret;



    /* If there was a fatal error then refuse operation */

    if (vring->broken) {

        ret = -EFAULT;

        goto out;

    }



    /* Check it isn't doing very strange things with descriptor numbers. */

    last_avail_idx = vring->last_avail_idx;

    avail_idx = vring->vr.avail->idx;

    barrier(); /* load indices now and not again later */



    if (unlikely((uint16_t)(avail_idx - last_avail_idx) > num)) {

        error_report("Guest moved used index from %u to %u",

                     last_avail_idx, avail_idx);

        ret = -EFAULT;

        goto out;

    }



    /* If there's nothing new since last we looked. */

    if (avail_idx == last_avail_idx) {

        ret = -EAGAIN;

        goto out;

    }



    /* Only get avail ring entries after they have been exposed by guest. */

    smp_rmb();



    /* Grab the next descriptor number they're advertising, and increment

     * the index we've seen. */

    head = vring->vr.avail->ring[last_avail_idx % num];



    elem = g_slice_new(VirtQueueElement);

    elem->index = head;

    elem->in_num = elem->out_num = 0;

    

    /* If their number is silly, that's an error. */

    if (unlikely(head >= num)) {

        error_report("Guest says index %u > %u is available", head, num);

        ret = -EFAULT;

        goto out;

    }



    if (vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) {

        vring_avail_event(&vring->vr) = vring->vr.avail->idx;

    }



    i = head;

    do {

        if (unlikely(i >= num)) {

            error_report("Desc index is %u > %u, head = %u", i, num, head);

            ret = -EFAULT;

            goto out;

        }

        if (unlikely(++found > num)) {

            error_report("Loop detected: last one at %u vq size %u head %u",

                         i, num, head);

            ret = -EFAULT;

            goto out;

        }

        desc = vring->vr.desc[i];



        /* Ensure descriptor is loaded before accessing fields */

        barrier();



        if (desc.flags & VRING_DESC_F_INDIRECT) {

            ret = get_indirect(vring, elem, &desc);

            if (ret < 0) {

                goto out;

            }

            continue;

        }



        ret = get_desc(vring, elem, &desc);

        if (ret < 0) {

            goto out;

        }



        i = desc.next;

    } while (desc.flags & VRING_DESC_F_NEXT);



    /* On success, increment avail index. */

    vring->last_avail_idx++;

    *p_elem = elem;

    return head;



out:

    assert(ret < 0);

    if (ret == -EFAULT) {

        vring->broken = true;

    }

    if (elem) {

        vring_unmap_element(elem);

        g_slice_free(VirtQueueElement, elem);

    }

    *p_elem = NULL;

    return ret;

}

int vring_pop(VirtIODevice *vdev, Vring *vring,

              VirtQueueElement **p_elem)

{

    struct vring_desc desc;

    unsigned int i, head, found = 0, num = vring->vr.num;

    uint16_t avail_idx, last_avail_idx;

    VirtQueueElement *elem = NULL;

    int ret;



    

    if (vring->broken) {

        ret = -EFAULT;

        goto out;

    }



    

    last_avail_idx = vring->last_avail_idx;

    avail_idx = vring->vr.avail->idx;

    barrier(); 



    if (unlikely((uint16_t)(avail_idx - last_avail_idx) > num)) {

        error_report("Guest moved used index from %u to %u",

                     last_avail_idx, avail_idx);

        ret = -EFAULT;

        goto out;

    }



    

    if (avail_idx == last_avail_idx) {

        ret = -EAGAIN;

        goto out;

    }



    

    smp_rmb();



    



    head = vring->vr.avail->ring[last_avail_idx % num];



    elem = g_slice_new(VirtQueueElement);

    elem->index = head;

    elem->in_num = elem->out_num = 0;

    

    

    if (unlikely(head >= num)) {

        error_report("Guest says index %u > %u is available", head, num);

        ret = -EFAULT;

        goto out;

    }



    if (vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) {

        vring_avail_event(&vring->vr) = vring->vr.avail->idx;

    }



    i = head;

    do {

        if (unlikely(i >= num)) {

            error_report("Desc index is %u > %u, head = %u", i, num, head);

            ret = -EFAULT;

            goto out;

        }

        if (unlikely(++found > num)) {

            error_report("Loop detected: last one at %u vq size %u head %u",

                         i, num, head);

            ret = -EFAULT;

            goto out;

        }

        desc = vring->vr.desc[i];



        

        barrier();



        if (desc.flags & VRING_DESC_F_INDIRECT) {

            ret = get_indirect(vring, elem, &desc);

            if (ret < 0) {

                goto out;

            }

            continue;

        }



        ret = get_desc(vring, elem, &desc);

        if (ret < 0) {

            goto out;

        }



        i = desc.next;

    } while (desc.flags & VRING_DESC_F_NEXT);



    

    vring->last_avail_idx++;

    *p_elem = elem;

    return head;



out:

    assert(ret < 0);

    if (ret == -EFAULT) {

        vring->broken = true;

    }

    if (elem) {

        vring_unmap_element(elem);

        g_slice_free(VirtQueueElement, elem);

    }

    *p_elem = NULL;

    return ret;

}

    int ret;               VirtQueueElement **p_elem)     VirtQueueElement *elem = NULL;     elem = g_slice_new(VirtQueueElement);     elem->in_num = elem->out_num = 0;     *p_elem = elem;     if (elem) {         vring_unmap_element(elem);         g_slice_free(VirtQueueElement, elem);     *p_elem = NULL;
int FUNC_0(VirtIODevice *VAR_0, Vring *VAR_1,

              VirtQueueElement **VAR_2)

{

    struct vring_desc VAR_3;

    unsigned int VAR_4, VAR_5, VAR_6 = 0, VAR_7 = VAR_1->vr.VAR_7;

    uint16_t avail_idx, last_avail_idx;

    VirtQueueElement *elem = NULL;

    int VAR_8;



    

    if (VAR_1->broken) {

        VAR_8 = -EFAULT;

        goto out;

    }



    

    last_avail_idx = VAR_1->last_avail_idx;

    avail_idx = VAR_1->vr.avail->idx;

    barrier(); 



    if (unlikely((uint16_t)(avail_idx - last_avail_idx) > VAR_7)) {

        error_report("Guest moved used index from %u to %u",

                     last_avail_idx, avail_idx);

        VAR_8 = -EFAULT;

        goto out;

    }



    

    if (avail_idx == last_avail_idx) {

        VAR_8 = -EAGAIN;

        goto out;

    }



    

    smp_rmb();



    



    VAR_5 = VAR_1->vr.avail->ring[last_avail_idx % VAR_7];



    elem = g_slice_new(VirtQueueElement);

    elem->index = VAR_5;

    elem->in_num = elem->out_num = 0;

    

    

    if (unlikely(VAR_5 >= VAR_7)) {

        error_report("Guest says index %u > %u is available", VAR_5, VAR_7);

        VAR_8 = -EFAULT;

        goto out;

    }



    if (VAR_0->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) {

        vring_avail_event(&VAR_1->vr) = VAR_1->vr.avail->idx;

    }



    VAR_4 = VAR_5;

    do {

        if (unlikely(VAR_4 >= VAR_7)) {

            error_report("Desc index is %u > %u, VAR_5 = %u", VAR_4, VAR_7, VAR_5);

            VAR_8 = -EFAULT;

            goto out;

        }

        if (unlikely(++VAR_6 > VAR_7)) {

            error_report("Loop detected: last one at %u vq size %u VAR_5 %u",

                         VAR_4, VAR_7, VAR_5);

            VAR_8 = -EFAULT;

            goto out;

        }

        VAR_3 = VAR_1->vr.VAR_3[VAR_4];



        

        barrier();



        if (VAR_3.flags & VRING_DESC_F_INDIRECT) {

            VAR_8 = get_indirect(VAR_1, elem, &VAR_3);

            if (VAR_8 < 0) {

                goto out;

            }

            continue;

        }



        VAR_8 = get_desc(VAR_1, elem, &VAR_3);

        if (VAR_8 < 0) {

            goto out;

        }



        VAR_4 = VAR_3.next;

    } while (VAR_3.flags & VRING_DESC_F_NEXT);



    

    VAR_1->last_avail_idx++;

    *VAR_2 = elem;

    return VAR_5;



out:

    assert(VAR_8 < 0);

    if (VAR_8 == -EFAULT) {

        VAR_1->broken = true;

    }

    if (elem) {

        vring_unmap_element(elem);

        g_slice_free(VirtQueueElement, elem);

    }

    *VAR_2 = NULL;

    return VAR_8;

}

int FUNC_0(VirtIODevice *VAR_0, Vring *VAR_1,
VirtQueueElement **VAR_2)
{ struct vring_desc VAR_3; unsigned int VAR_4, VAR_5, VAR_6 = 0, VAR_7 = VAR_1->vr.VAR_7; uint16_t avail_idx, last_avail_idx; VirtQueueElement *elem = NULL; int VAR_8; if (VAR_1->broken) { VAR_8 = -EFAULT; goto out; } last_avail_idx = VAR_1->last_avail_idx; avail_idx = VAR_1->vr.avail->idx; barrier(); if (unlikely((uint16_t)(avail_idx - last_avail_idx) > VAR_7)) { error_report("Guest moved used index from %u to %u",
last_avail_idx, avail_idx); VAR_8 = -EFAULT; goto out; } if (avail_idx == last_avail_idx) { VAR_8 = -EAGAIN; goto out; } smp_rmb(); VAR_5 = VAR_1->vr.avail->ring[last_avail_idx % VAR_7]; elem = g_slice_new(VirtQueueElement); elem->index = VAR_5; elem->in_num = elem->out_num = 0; if (unlikely(VAR_5 >= VAR_7)) { error_report("Guest says index %u > %u is available", VAR_5, VAR_7); VAR_8 = -EFAULT; goto out; } if (VAR_0->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) { vring_avail_event(&VAR_1->vr) = VAR_1->vr.avail->idx; } VAR_4 = VAR_5; do { if (unlikely(VAR_4 >= VAR_7)) { error_report("Desc index is %u > %u, VAR_5 = %u", VAR_4, VAR_7, VAR_5); VAR_8 = -EFAULT; goto out; } if (unlikely(++VAR_6 > VAR_7)) { error_report("Loop detected: last one at %u vq size %u VAR_5 %u",
VAR_4, VAR_7, VAR_5); VAR_8 = -EFAULT; goto out; } VAR_3 = VAR_1->vr.VAR_3[VAR_4]; barrier(); if (VAR_3.flags & VRING_DESC_F_INDIRECT) { VAR_8 = get_indirect(VAR_1, elem, &VAR_3); if (VAR_8 < 0) { goto out; } continue; } VAR_8 = get_desc(VAR_1, elem, &VAR_3); if (VAR_8 < 0) { goto out; } VAR_4 = VAR_3.next; } while (VAR_3.flags & VRING_DESC_F_NEXT); VAR_1->last_avail_idx++; *VAR_2 = elem; return VAR_5; out:
assert(VAR_8 < 0); if (VAR_8 == -EFAULT) { VAR_1->broken = true; } if (elem) { vring_unmap_element(elem); g_slice_free(VirtQueueElement, elem); } *VAR_2 = NULL; return VAR_8; }