Beispiel #1
0
static int do_recv(struct libvchan *ctrl, void *data, size_t size)
{
    int real_idx = rd_cons(ctrl) & (rd_ring_size(ctrl) - 1);
    int avail_contig = rd_ring_size(ctrl) - real_idx;
    if (avail_contig > size)
        avail_contig = size;
    barrier(); // data read must happen after rd_cons read
    memcpy(data, rd_ring(ctrl) + real_idx, avail_contig);
    if (avail_contig < size)
    {
        // we rolled across the end of the ring
        memcpy(data + avail_contig, rd_ring(ctrl), size - avail_contig);
    }
    rd_cons(ctrl) += size;
    if (VCHAN_DEBUG) {
        char metainfo[32];
        struct iovec iov[2];
        iov[0].iov_base = metainfo;
        iov[0].iov_len = snprintf(metainfo, 32, "vchan rd %d/%d", ctrl->other_domain_id, ctrl->device_number);
        iov[1].iov_base = data;
        iov[1].iov_len = size;
        writev(-1, iov, 2);
    }
    barrier(); // consumption must happen prior to notify of newly freed space
    if (do_notify(ctrl) < 0)
        return -1;
    return size;
}
Beispiel #2
0
/*
 * Get the amount of buffer space available, and do nothing about
 * notifications.
 */
static inline int raw_get_data_ready(struct libxenvchan *ctrl)
{
	uint32_t ready = rd_prod(ctrl) - rd_cons(ctrl);
	if (ready >= rd_ring_size(ctrl))
		/* We have no way to return errors.  Locking up the ring is
		 * better than the alternatives. */
		return 0;
	return ready;
}
Beispiel #3
0
Datei: io.c Projekt: CPFL/gxen
static int do_recv(struct libxenvchan *ctrl, void *data, size_t size)
{
	int real_idx = rd_cons(ctrl) & (rd_ring_size(ctrl) - 1);
	int avail_contig = rd_ring_size(ctrl) - real_idx;
	if (avail_contig > size)
		avail_contig = size;
	xen_rmb(); /* data read must happen /after/ rd_cons read */
	memcpy(data, rd_ring(ctrl) + real_idx, avail_contig);
	if (avail_contig < size)
	{
		// we rolled across the end of the ring
		memcpy(data + avail_contig, rd_ring(ctrl), size - avail_contig);
	}
	xen_mb(); /* consume /then/ notify */
	rd_cons(ctrl) += size;
	if (send_notify(ctrl, VCHAN_NOTIFY_READ))
		return -1;
	return size;
}
Beispiel #4
0
Datei: io.c Projekt: CPFL/gxen
/**
 * reads exactly size bytes from the vchan.
 * returns 0 if insufficient data is available, -1 on error, or size on success
 */
int libxenvchan_recv(struct libxenvchan *ctrl, void *data, size_t size)
{
	while (1) {
		int avail = fast_get_data_ready(ctrl, size);
		if (size <= avail)
			return do_recv(ctrl, data, size);
		if (!libxenvchan_is_open(ctrl))
			return -1;
		if (!ctrl->blocking)
			return 0;
		if (size > rd_ring_size(ctrl))
			return -1;
		if (libxenvchan_wait(ctrl))
			return -1;
	}
}