1*bbecb9d1SAndroid Build Coastguard Worker /* 2*bbecb9d1SAndroid Build Coastguard Worker * Copyright 2021 Google LLC 3*bbecb9d1SAndroid Build Coastguard Worker * SPDX-License-Identifier: MIT 4*bbecb9d1SAndroid Build Coastguard Worker */ 5*bbecb9d1SAndroid Build Coastguard Worker 6*bbecb9d1SAndroid Build Coastguard Worker #ifndef VKR_RING_H 7*bbecb9d1SAndroid Build Coastguard Worker #define VKR_RING_H 8*bbecb9d1SAndroid Build Coastguard Worker 9*bbecb9d1SAndroid Build Coastguard Worker #include "vkr_common.h" 10*bbecb9d1SAndroid Build Coastguard Worker 11*bbecb9d1SAndroid Build Coastguard Worker /* We read from the ring buffer to a temporary buffer for 12*bbecb9d1SAndroid Build Coastguard Worker * virgl_context::submit_cmd. Until that is changed, we want to put a limit 13*bbecb9d1SAndroid Build Coastguard Worker * on the size of the temporary buffer. It also makes no sense to have huge 14*bbecb9d1SAndroid Build Coastguard Worker * rings. 15*bbecb9d1SAndroid Build Coastguard Worker * 16*bbecb9d1SAndroid Build Coastguard Worker * This must not exceed UINT32_MAX because the ring head and tail are 32-bit. 17*bbecb9d1SAndroid Build Coastguard Worker */ 18*bbecb9d1SAndroid Build Coastguard Worker #define VKR_RING_BUFFER_MAX_SIZE (16u * 1024 * 1024) 19*bbecb9d1SAndroid Build Coastguard Worker 20*bbecb9d1SAndroid Build Coastguard Worker /* The layout of a ring in a virgl_resource. This is parsed and discarded by 21*bbecb9d1SAndroid Build Coastguard Worker * vkr_ring_create. 22*bbecb9d1SAndroid Build Coastguard Worker */ 23*bbecb9d1SAndroid Build Coastguard Worker struct vkr_ring_layout { 24*bbecb9d1SAndroid Build Coastguard Worker const struct vkr_resource_attachment *attachment; 25*bbecb9d1SAndroid Build Coastguard Worker 26*bbecb9d1SAndroid Build Coastguard Worker struct vkr_region head; 27*bbecb9d1SAndroid Build Coastguard Worker struct vkr_region tail; 28*bbecb9d1SAndroid Build Coastguard Worker struct vkr_region status; 29*bbecb9d1SAndroid Build Coastguard Worker struct vkr_region buffer; 30*bbecb9d1SAndroid Build Coastguard Worker struct vkr_region extra; 31*bbecb9d1SAndroid Build Coastguard Worker }; 32*bbecb9d1SAndroid Build Coastguard Worker 33*bbecb9d1SAndroid Build Coastguard Worker static_assert(ATOMIC_INT_LOCK_FREE == 2 && sizeof(atomic_uint) == 4, 34*bbecb9d1SAndroid Build Coastguard Worker "vkr_ring_control requires lock-free 32-bit atomic_uint"); 35*bbecb9d1SAndroid Build Coastguard Worker 36*bbecb9d1SAndroid Build Coastguard Worker /* the control region of a ring */ 37*bbecb9d1SAndroid Build Coastguard Worker struct vkr_ring_control { 38*bbecb9d1SAndroid Build Coastguard Worker /* Pointers to ring head, tail, and status. 39*bbecb9d1SAndroid Build Coastguard Worker * 40*bbecb9d1SAndroid Build Coastguard Worker * Clients increment the tail after commands are added. We increment the 41*bbecb9d1SAndroid Build Coastguard Worker * head after commands are executed. The status is updated when there is a 42*bbecb9d1SAndroid Build Coastguard Worker * status change to the ring thread. 43*bbecb9d1SAndroid Build Coastguard Worker */ 44*bbecb9d1SAndroid Build Coastguard Worker volatile atomic_uint *head; 45*bbecb9d1SAndroid Build Coastguard Worker const volatile atomic_uint *tail; 46*bbecb9d1SAndroid Build Coastguard Worker volatile atomic_uint *status; 47*bbecb9d1SAndroid Build Coastguard Worker }; 48*bbecb9d1SAndroid Build Coastguard Worker 49*bbecb9d1SAndroid Build Coastguard Worker /* the buffer region of a ring */ 50*bbecb9d1SAndroid Build Coastguard Worker struct vkr_ring_buffer { 51*bbecb9d1SAndroid Build Coastguard Worker /* the base of the region in the resource */ 52*bbecb9d1SAndroid Build Coastguard Worker int base_iov_index; 53*bbecb9d1SAndroid Build Coastguard Worker size_t base_iov_offset; 54*bbecb9d1SAndroid Build Coastguard Worker 55*bbecb9d1SAndroid Build Coastguard Worker uint32_t size; 56*bbecb9d1SAndroid Build Coastguard Worker uint32_t mask; 57*bbecb9d1SAndroid Build Coastguard Worker 58*bbecb9d1SAndroid Build Coastguard Worker /* The current offset in the buffer region. It is free-running and must be 59*bbecb9d1SAndroid Build Coastguard Worker * masked to be between [0, size). 60*bbecb9d1SAndroid Build Coastguard Worker */ 61*bbecb9d1SAndroid Build Coastguard Worker uint32_t cur; 62*bbecb9d1SAndroid Build Coastguard Worker 63*bbecb9d1SAndroid Build Coastguard Worker /* The current iov and iov offset in the resource. */ 64*bbecb9d1SAndroid Build Coastguard Worker const struct iovec *cur_iov; 65*bbecb9d1SAndroid Build Coastguard Worker int cur_iov_index; 66*bbecb9d1SAndroid Build Coastguard Worker size_t cur_iov_offset; 67*bbecb9d1SAndroid Build Coastguard Worker }; 68*bbecb9d1SAndroid Build Coastguard Worker 69*bbecb9d1SAndroid Build Coastguard Worker /* the extra region of a ring */ 70*bbecb9d1SAndroid Build Coastguard Worker struct vkr_ring_extra { 71*bbecb9d1SAndroid Build Coastguard Worker /* the base of the region in the resource */ 72*bbecb9d1SAndroid Build Coastguard Worker int base_iov_index; 73*bbecb9d1SAndroid Build Coastguard Worker size_t base_iov_offset; 74*bbecb9d1SAndroid Build Coastguard Worker 75*bbecb9d1SAndroid Build Coastguard Worker /* used for offset validation */ 76*bbecb9d1SAndroid Build Coastguard Worker struct vkr_region region; 77*bbecb9d1SAndroid Build Coastguard Worker 78*bbecb9d1SAndroid Build Coastguard Worker /* cache the latest offset->pointer result */ 79*bbecb9d1SAndroid Build Coastguard Worker size_t cached_offset; 80*bbecb9d1SAndroid Build Coastguard Worker volatile atomic_uint *cached_data; 81*bbecb9d1SAndroid Build Coastguard Worker }; 82*bbecb9d1SAndroid Build Coastguard Worker 83*bbecb9d1SAndroid Build Coastguard Worker struct vkr_ring { 84*bbecb9d1SAndroid Build Coastguard Worker /* used by the caller */ 85*bbecb9d1SAndroid Build Coastguard Worker vkr_object_id id; 86*bbecb9d1SAndroid Build Coastguard Worker struct list_head head; 87*bbecb9d1SAndroid Build Coastguard Worker 88*bbecb9d1SAndroid Build Coastguard Worker /* ring regions */ 89*bbecb9d1SAndroid Build Coastguard Worker const struct vkr_resource_attachment *attachment; 90*bbecb9d1SAndroid Build Coastguard Worker struct vkr_ring_control control; 91*bbecb9d1SAndroid Build Coastguard Worker struct vkr_ring_buffer buffer; 92*bbecb9d1SAndroid Build Coastguard Worker struct vkr_ring_extra extra; 93*bbecb9d1SAndroid Build Coastguard Worker 94*bbecb9d1SAndroid Build Coastguard Worker /* ring thread */ 95*bbecb9d1SAndroid Build Coastguard Worker struct virgl_context *context; 96*bbecb9d1SAndroid Build Coastguard Worker uint64_t idle_timeout; 97*bbecb9d1SAndroid Build Coastguard Worker void *cmd; 98*bbecb9d1SAndroid Build Coastguard Worker 99*bbecb9d1SAndroid Build Coastguard Worker mtx_t mutex; 100*bbecb9d1SAndroid Build Coastguard Worker cnd_t cond; 101*bbecb9d1SAndroid Build Coastguard Worker thrd_t thread; 102*bbecb9d1SAndroid Build Coastguard Worker atomic_bool started; 103*bbecb9d1SAndroid Build Coastguard Worker atomic_bool pending_notify; 104*bbecb9d1SAndroid Build Coastguard Worker }; 105*bbecb9d1SAndroid Build Coastguard Worker 106*bbecb9d1SAndroid Build Coastguard Worker struct vkr_ring * 107*bbecb9d1SAndroid Build Coastguard Worker vkr_ring_create(const struct vkr_ring_layout *layout, 108*bbecb9d1SAndroid Build Coastguard Worker struct virgl_context *ctx, 109*bbecb9d1SAndroid Build Coastguard Worker uint64_t idle_timeout); 110*bbecb9d1SAndroid Build Coastguard Worker 111*bbecb9d1SAndroid Build Coastguard Worker void 112*bbecb9d1SAndroid Build Coastguard Worker vkr_ring_destroy(struct vkr_ring *ring); 113*bbecb9d1SAndroid Build Coastguard Worker 114*bbecb9d1SAndroid Build Coastguard Worker void 115*bbecb9d1SAndroid Build Coastguard Worker vkr_ring_start(struct vkr_ring *ring); 116*bbecb9d1SAndroid Build Coastguard Worker 117*bbecb9d1SAndroid Build Coastguard Worker bool 118*bbecb9d1SAndroid Build Coastguard Worker vkr_ring_stop(struct vkr_ring *ring); 119*bbecb9d1SAndroid Build Coastguard Worker 120*bbecb9d1SAndroid Build Coastguard Worker void 121*bbecb9d1SAndroid Build Coastguard Worker vkr_ring_notify(struct vkr_ring *ring); 122*bbecb9d1SAndroid Build Coastguard Worker 123*bbecb9d1SAndroid Build Coastguard Worker bool 124*bbecb9d1SAndroid Build Coastguard Worker vkr_ring_write_extra(struct vkr_ring *ring, size_t offset, uint32_t val); 125*bbecb9d1SAndroid Build Coastguard Worker 126*bbecb9d1SAndroid Build Coastguard Worker #endif /* VKR_RING_H */ 127