예제 #1
0
파일: io.c 프로젝트: pllopis/libxenvchan
/**
 * returns -1 on error, or size on success
 */
static int do_send(struct libvchan *ctrl, const void *data, size_t size)
{
    int real_idx = wr_prod(ctrl) & (wr_ring_size(ctrl) - 1);
    int avail_contig = wr_ring_size(ctrl) - real_idx;
    if (VCHAN_DEBUG) {
        char metainfo[32];
        struct iovec iov[2];
        iov[0].iov_base = metainfo;
        iov[0].iov_len = snprintf(metainfo, 32, "vchan wr %d/%d", ctrl->other_domain_id, ctrl->device_number);
        iov[1].iov_base = (void *)data;
        iov[1].iov_len = size;
        writev(-1, iov, 2);
    }
    if (avail_contig > size)
        avail_contig = size;
    memcpy(wr_ring(ctrl) + real_idx, data, avail_contig);
    if (avail_contig < size)
    {
        // we rolled across the end of the ring
        memcpy(wr_ring(ctrl), data + avail_contig, size - avail_contig);
    }
    barrier(); // data must be in the ring prior to increment
    wr_prod(ctrl) += size;
    barrier(); // increment must happen prior to notify
    if (do_notify(ctrl) < 0)
        return -1;
    return size;
}
예제 #2
0
파일: io.c 프로젝트: CrazyXen/XEN_CODE
/**
 * Get the amount of buffer space available, and do nothing
 * about notifications
 */
static inline int raw_get_buffer_space(struct libxenvchan *ctrl)
{
	uint32_t ready = wr_ring_size(ctrl) - (wr_prod(ctrl) - wr_cons(ctrl));
	if (ready > wr_ring_size(ctrl))
		/* We have no way to return errors.  Locking up the ring is
		 * better than the alternatives. */
		return 0;
	return ready;
}
예제 #3
0
파일: io.c 프로젝트: CPFL/gxen
/**
 * Get the amount of buffer space available and enable notifications if needed.
 */
static inline int fast_get_buffer_space(struct libxenvchan *ctrl, size_t request)
{
	int ready = wr_ring_size(ctrl) - (wr_prod(ctrl) - wr_cons(ctrl));
	if (ready >= request)
		return ready;
	/* We plan to fill the buffer; please tell us when you've read it */
	request_notify(ctrl, VCHAN_NOTIFY_READ);
	/*
	 * If the reader moved wr_cons after our read but before request, we
	 * will not get notified even though the actual amount of buffer space
	 * is above request. Reread wr_cons to cover this case.
	 */
	return wr_ring_size(ctrl) - (wr_prod(ctrl) - wr_cons(ctrl));
}
예제 #4
0
파일: io.c 프로젝트: CPFL/gxen
int libxenvchan_buffer_space(struct libxenvchan *ctrl)
{
	/* Since this value is being used outside libxenvchan, request notification
	 * when it changes
	 */
	request_notify(ctrl, VCHAN_NOTIFY_READ);
	return wr_ring_size(ctrl) - (wr_prod(ctrl) - wr_cons(ctrl));
}
예제 #5
0
파일: io.c 프로젝트: CPFL/gxen
/**
 * returns -1 on error, or size on success
 */
static int do_send(struct libxenvchan *ctrl, const void *data, size_t size)
{
	int real_idx = wr_prod(ctrl) & (wr_ring_size(ctrl) - 1);
	int avail_contig = wr_ring_size(ctrl) - real_idx;
	if (avail_contig > size)
		avail_contig = size;
	xen_mb(); /* read indexes /then/ write data */
	memcpy(wr_ring(ctrl) + real_idx, data, avail_contig);
	if (avail_contig < size)
	{
		// we rolled across the end of the ring
		memcpy(wr_ring(ctrl), data + avail_contig, size - avail_contig);
	}
	xen_wmb(); /* write data /then/ notify */
	wr_prod(ctrl) += size;
	if (send_notify(ctrl, VCHAN_NOTIFY_WRITE))
		return -1;
	return size;
}
예제 #6
0
파일: io.c 프로젝트: CPFL/gxen
/**
 * returns 0 if no buffer space is available, -1 on error, or size on success
 */
int libxenvchan_send(struct libxenvchan *ctrl, const void *data, size_t size)
{
	int avail;
	while (1) {
		if (!libxenvchan_is_open(ctrl))
			return -1;
		avail = fast_get_buffer_space(ctrl, size);
		if (size <= avail)
			return do_send(ctrl, data, size);
		if (!ctrl->blocking)
			return 0;
		if (size > wr_ring_size(ctrl))
			return -1;
		if (libxenvchan_wait(ctrl))
			return -1;
	}
}
예제 #7
0
파일: io.c 프로젝트: pllopis/libxenvchan
int libvchan_buffer_space(struct libvchan *ctrl)
{
    return wr_ring_size(ctrl) - (wr_prod(ctrl) - wr_cons(ctrl));
}