vkr: introduce vkr_ring_control

It is used to access the control region, with iov support.

Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
Reviewed-by: Ryan Neph <ryanneph@google.com>
Reviewed-by: Yiwei Zhang <zzyiwei@chromium.org>
macos/master
Chia-I Wu 3 years ago
parent 89898ff604
commit 2a610d2708
  1. 66
      src/venus/vkr_ring.c
  2. 21
      src/venus/vkr_ring.h

@ -15,13 +15,59 @@ enum vkr_ring_status_flag {
VKR_RING_STATUS_IDLE = 1u << 0,
};
/* callers must make sure they do not seek to end-of-resource or beyond */
static const struct iovec *
seek_resource(const struct virgl_resource *res,
int base_iov_index,
size_t offset,
int *out_iov_index,
size_t *out_iov_offset)
{
const struct iovec *iov = &res->iov[base_iov_index];
assert(iov - res->iov < res->iov_count);
while (offset >= iov->iov_len) {
offset -= iov->iov_len;
iov++;
assert(iov - res->iov < res->iov_count);
}
*out_iov_index = iov - res->iov;
*out_iov_offset = offset;
return iov;
}
static void *
get_resource_pointer(const struct virgl_resource *res, int base_iov_index, size_t offset)
{
const struct iovec *iov =
seek_resource(res, base_iov_index, offset, &base_iov_index, &offset);
return (uint8_t *)iov->iov_base + offset;
}
static bool
vkr_ring_init_control(struct vkr_ring *ring, const struct vkr_ring_layout *layout)
{
struct vkr_ring_control *ctrl = &ring->control;
ctrl->head = get_resource_pointer(layout->resource, 0, layout->head.begin);
ctrl->tail = get_resource_pointer(layout->resource, 0, layout->tail.begin);
ctrl->status = get_resource_pointer(layout->resource, 0, layout->status.begin);
/* we will manage head and status, and we expect them to be 0 initially */
if (*ctrl->head || *ctrl->status)
return false;
return true;
}
static void
vkr_ring_store_head(struct vkr_ring *ring)
{
/* the renderer is expected to load the head with memory_order_acquire,
* forming a release-acquire ordering
*/
atomic_store_explicit(ring->shared.head, ring->cur, memory_order_release);
atomic_store_explicit(ring->control.head, ring->cur, memory_order_release);
}
static uint32_t
@ -30,13 +76,13 @@ vkr_ring_load_tail(const struct vkr_ring *ring)
/* the driver is expected to store the tail with memory_order_release,
* forming a release-acquire ordering
*/
return atomic_load_explicit(ring->shared.tail, memory_order_acquire);
return atomic_load_explicit(ring->control.tail, memory_order_acquire);
}
static void
vkr_ring_store_status(struct vkr_ring *ring, uint32_t status)
{
atomic_store_explicit(ring->shared.status, status, memory_order_seq_cst);
atomic_store_explicit(ring->control.status, status, memory_order_seq_cst);
}
static void
@ -69,12 +115,14 @@ vkr_ring_create(const struct vkr_ring_layout *layout,
ring->resource = layout->resource;
if (!vkr_ring_init_control(ring, layout)) {
free(ring);
return NULL;
}
uint8_t *shared = layout->resource->iov[0].iov_base;
#define ring_attach_shared(member) \
ring->shared.member = (void *)(shared + layout->member.begin)
ring_attach_shared(head);
ring_attach_shared(tail);
ring_attach_shared(status);
ring_attach_shared(buffer);
ring_attach_shared(extra);
#undef ring_attach_shared
@ -84,12 +132,6 @@ vkr_ring_create(const struct vkr_ring_layout *layout,
ring->buffer_mask = ring->buffer_size - 1;
ring->extra_size = vkr_region_size(&layout->extra);
/* we will manage head and status, and we expect them to be 0 initially */
if (*ring->shared.head || *ring->shared.status) {
free(ring);
return NULL;
}
ring->cmd = malloc(ring->buffer_size);
if (!ring->cmd) {
free(ring);

@ -22,13 +22,22 @@ struct vkr_ring_layout {
};
static_assert(ATOMIC_INT_LOCK_FREE == 2 && sizeof(atomic_uint) == 4,
"vkr_ring_shared requires lock-free 32-bit atomic_uint");
/* pointers to a ring in a virgl_resource */
struct vkr_ring_shared {
"vkr_ring_control requires lock-free 32-bit atomic_uint");
/* the control region of a ring */
struct vkr_ring_control {
/* Pointers to ring head, tail, and status.
*
* Clients increment the tail after commands are added. We increment the
* head after commands are executed. The status is updated when there is a
* status change to the ring thread.
*/
volatile atomic_uint *head;
const volatile atomic_uint *tail;
volatile atomic_uint *status;
};
struct vkr_ring_shared {
const void *buffer;
void *extra;
@ -39,7 +48,10 @@ struct vkr_ring {
vkr_object_id id;
struct list_head head;
/* ring regions */
struct virgl_resource *resource;
struct vkr_ring_control control;
struct vkr_ring_shared shared;
uint32_t buffer_size;
uint32_t buffer_mask;
@ -48,6 +60,7 @@ struct vkr_ring {
size_t extra_size;
/* ring thread */
struct virgl_context *context;
uint64_t idle_timeout;

Loading…
Cancel
Save