return 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;
+}
+
/**
* Get the amount of buffer space available and enable notifications if needed.
*/
static inline int fast_get_data_ready(struct libxenvchan *ctrl, size_t request)
{
- int ready = rd_prod(ctrl) - rd_cons(ctrl);
+ int ready = raw_get_data_ready(ctrl);
if (ready >= request)
return ready;
/* We plan to consume all data; please tell us if you send more */
* will not get notified even though the actual amount of data ready is
* above request. Reread rd_prod to cover this case.
*/
- return rd_prod(ctrl) - rd_cons(ctrl);
+ return raw_get_data_ready(ctrl);
}
int libxenvchan_data_ready(struct libxenvchan *ctrl)
* when it changes
*/
request_notify(ctrl, VCHAN_NOTIFY_WRITE);
- return rd_prod(ctrl) - rd_cons(ctrl);
+ return raw_get_data_ready(ctrl);
+}
+
+/**
+ * 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;
}
/**
*/
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));
+ int ready = raw_get_buffer_space(ctrl);
if (ready >= request)
return ready;
/* We plan to fill the buffer; please tell us when you've read it */
* 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));
+ return raw_get_buffer_space(ctrl);
}
int libxenvchan_buffer_space(struct libxenvchan *ctrl)
* when it changes
*/
request_notify(ctrl, VCHAN_NOTIFY_READ);
- return wr_ring_size(ctrl) - (wr_prod(ctrl) - wr_cons(ctrl));
+ return raw_get_buffer_space(ctrl);
}
int libxenvchan_wait(struct libxenvchan *ctrl)
/**
* returns -1 on error, or size on success
+ *
+ * caller must have checked that enough space is available
*/
static int do_send(struct libxenvchan *ctrl, const void *data, size_t size)
{
}
}
+/**
+ * returns -1 on error, or size on success
+ *
+ * caller must have checked that enough data is available
+ */
static int do_recv(struct libxenvchan *ctrl, void *data, size_t size)
{
int real_idx = rd_cons(ctrl) & (rd_ring_size(ctrl) - 1);