Skip to content

Commit 32dc951

Browse files
committed
Remove ring buffer
1 parent 2881354 commit 32dc951

File tree

1 file changed

+32
-146
lines changed

1 file changed

+32
-146
lines changed

virtio-snd.c

Lines changed: 32 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -271,29 +271,11 @@ typedef struct {
271271
uint8_t positions[VIRTIO_SND_CHMAP_MAX_SIZE];
272272
} virtio_snd_chmap_info_t;
273273

274-
/* PCM frame ring buffer */
275-
/* Adapted from DPDK ring buffer. */
276-
/* https://github.com/scylladb/dpdk/blob/master/lib/librte_ring/rte_ring.h#L147
277-
*/
278-
#define VSND_RING_SZ_MASK 0x0FFFFFFFULL /* ring size mask */
279274
typedef struct {
280-
void *buffer;
281275
pthread_cond_t readable, writable;
282276
int buf_ev_notity;
283277
pthread_mutex_t lock;
284-
struct prod {
285-
volatile uint32_t head; /* producer head */
286-
volatile uint32_t tail; /* producer tail */
287-
uint32_t size; /* Size of ring. */
288-
uint32_t mask; /* Mask (size of buffer - 1) of ring.*/
289-
} prod;
290-
struct cons {
291-
volatile uint32_t head; /* consumer head */
292-
volatile uint32_t tail; /* consumer tail */
293-
uint32_t size; /* Size of ring. */
294-
uint32_t mask; /* Mask (size of buffer - 1) of ring.*/
295-
} cons;
296-
} virtio_snd_ring_buffer_t;
278+
} virtio_snd_queue_lock_t;
297279

298280
typedef struct {
299281
int32_t guest_playing;
@@ -318,13 +300,13 @@ typedef struct {
318300
struct CNFADriver *audio_host;
319301
bool is_guest_playing;
320302

321-
// PCM frame ring buffer
322-
virtio_snd_ring_buffer_t ring;
303+
// PCM frame queue lock
304+
virtio_snd_queue_lock_t lock;
323305
// PCM frame doubly-ended queue
324306
vsnd_buf_queue_node_t buf;
325307
struct list_head buf_queue_head;
326-
// PCM frame immediate buffer;
327-
void *immediate;
308+
// PCM frame intermediate buffer;
309+
void *intermediate;
328310

329311
// playback control
330312
vsnd_stream_sel_t v;
@@ -554,23 +536,14 @@ static void virtio_snd_read_pcm_prepare(const virtio_snd_pcm_hdr_t *query,
554536
CNFAInit(NULL, "semu-virtio-snd", virtio_snd_cb, rate, 0, channels, 0,
555537
cnfa_period_frames, NULL, NULL, &props->v);
556538
uint32_t sz = props->pp.buffer_bytes;
557-
props->ring.buffer = (void *) malloc(sizeof(*props->ring.buffer) * sz);
558-
props->ring.prod.head = 0;
559-
props->ring.prod.tail = 0;
560-
props->ring.cons.head = 0;
561-
props->ring.cons.tail = 0;
562-
props->ring.prod.size = sz;
563-
props->ring.cons.size = sz;
564-
props->ring.prod.mask = sz - 1;
565-
props->ring.cons.mask = sz - 1;
566-
pthread_mutex_init(&props->ring.lock, NULL);
567-
pthread_cond_init(&props->ring.readable, NULL);
568-
pthread_cond_init(&props->ring.writable, NULL);
539+
pthread_mutex_init(&props->lock.lock, NULL);
540+
pthread_cond_init(&props->lock.readable, NULL);
541+
pthread_cond_init(&props->lock.writable, NULL);
569542
pthread_mutex_init(&props->v.ctrl_mutex, NULL);
570543
pthread_cond_init(&props->v.ctrl_cond, NULL);
571544
INIT_LIST_HEAD(&props->buf_queue_head);
572-
props->immediate =
573-
(void *) malloc(sizeof(*props->immediate) * cnfa_period_bytes);
545+
props->intermediate =
546+
(void *) malloc(sizeof(*props->intermediate) * cnfa_period_bytes);
574547
#if WRITEOUT
575548
outfile = fopen("out_deque.bin", "wb");
576549
#endif
@@ -651,11 +624,10 @@ static void virtio_snd_read_pcm_release(const virtio_snd_pcm_hdr_t *query,
651624
fclose(outfile);
652625
#endif
653626
/* Tear down the PCM ring buffer. */
654-
free(props->ring.buffer);
655-
free(props->immediate);
656-
pthread_mutex_destroy(&props->ring.lock);
657-
pthread_cond_destroy(&props->ring.readable);
658-
pthread_cond_destroy(&props->ring.writable);
627+
free(props->intermediate);
628+
pthread_mutex_destroy(&props->lock.lock);
629+
pthread_cond_destroy(&props->lock.readable);
630+
pthread_cond_destroy(&props->lock.writable);
659631
/* Tear down the PCM buffer queue */
660632
vsnd_buf_queue_node_t *tmp = NULL;
661633
vsnd_buf_queue_node_t *node;
@@ -684,54 +656,15 @@ static void __virtio_snd_frame_dequeue(short *out,
684656
uint32_t stream_id)
685657
{
686658
virtio_snd_prop_t *props = &vsnd_props[stream_id];
687-
uint32_t cons_head, prod_tail;
688-
uint32_t cons_next, entries;
689-
uint32_t mask = props->ring.cons.mask;
690659

691-
pthread_mutex_lock(&props->ring.lock);
692-
while (props->ring.buf_ev_notity < 1) {
660+
pthread_mutex_lock(&props->lock.lock);
661+
while (props->lock.buf_ev_notity < 1) {
693662
fprintf(stderr, "---wait in deque---\n");
694-
pthread_cond_wait(&props->ring.readable, &props->ring.lock);
663+
pthread_cond_wait(&props->lock.readable, &props->lock.lock);
695664
}
696665

697-
cons_head = props->ring.cons.head;
698-
prod_tail = props->ring.prod.tail;
699-
/* The subtraction is done between two unsigned 32bits value
700-
* (the result is always modulo 32 bits even if we have
701-
* cons_head > prod_tail). So 'entries' is always between 0
702-
* and size(ring)-1. */
703-
entries = prod_tail - cons_head;
704-
705-
if (n > entries)
706-
fprintf(stderr,
707-
"consumer payload length %" PRIu32
708-
" larger than entries %" PRIu32 "\n",
709-
n, entries);
710-
711-
cons_next = cons_head + n;
712-
props->ring.cons.head = cons_next;
713-
714-
/* Copy the frame to output stream */
715-
uint32_t size = props->ring.cons.size;
716-
uint32_t idx = cons_head % size;
717-
fprintf(stderr,
718-
"cons_head %" PRIu32 " cons_next %" PRIu32 " prod_tail %" PRIu32
719-
" mask %" PRIu32 " idx %" PRIu32 "\n",
720-
cons_head, cons_next, prod_tail, mask, idx);
721-
/*if (idx + n < size) {
722-
memcpy(out, props->ring.buffer + idx, n);
723-
} else {
724-
memcpy(out, props->ring.buffer + idx, size - idx);
725-
memcpy(out + (size - idx), props->ring.buffer, n - (size - idx));
726-
fprintf(stderr, "=== start %" PRIu32 " end %" PRIu32 "\n", size - idx,
727-
n - (size - idx));
728-
}*/
729-
VSND_COMPILER_BARRIER;
730-
731-
props->ring.cons.tail = cons_next;
732-
733666
uint32_t written_bytes = 0;
734-
memset(props->immediate, 0, sizeof(*props->immediate) * n);
667+
memset(props->intermediate, 0, sizeof(*props->intermediate) * n);
735668
while (!list_empty(&props->buf_queue_head) && written_bytes < n) {
736669
vsnd_buf_queue_node_t *node =
737670
list_first_entry(&props->buf_queue_head, vsnd_buf_queue_node_t, q);
@@ -747,7 +680,8 @@ static void __virtio_snd_frame_dequeue(short *out,
747680
left, actual, len, written_bytes, node->pos, node->len,
748681
node->addr);
749682

750-
memcpy(props->immediate + written_bytes, node->addr + node->pos, len);
683+
memcpy(props->intermediate + written_bytes, node->addr + node->pos,
684+
len);
751685

752686
#if WRITEOUT
753687
fwrite(node->addr + node->pos, sizeof(void), len, outfile);
@@ -762,11 +696,11 @@ static void __virtio_snd_frame_dequeue(short *out,
762696
}
763697
fprintf(stderr, "*** written %" PRIu32 " out n %" PRIu32 "\n",
764698
written_bytes, n);
765-
memcpy(out, props->immediate, written_bytes);
699+
memcpy(out, props->intermediate, written_bytes);
766700

767-
props->ring.buf_ev_notity--;
768-
pthread_cond_signal(&props->ring.writable);
769-
pthread_mutex_unlock(&props->ring.lock);
701+
props->lock.buf_ev_notity--;
702+
pthread_cond_signal(&props->lock.writable);
703+
pthread_mutex_unlock(&props->lock.lock);
770704
}
771705
static void virtio_snd_cb(struct CNFADriver *dev,
772706
short *out,
@@ -894,72 +828,24 @@ static void __virtio_snd_frame_enqueue(void *payload,
894828
uint32_t n,
895829
uint32_t stream_id)
896830
{
897-
uint32_t prod_head, cons_tail;
898-
uint32_t prod_next, free_entries;
899831
virtio_snd_prop_t *props = &vsnd_props[stream_id];
900-
uint32_t mask = props->ring.prod.mask;
901832

902-
pthread_mutex_lock(&props->ring.lock);
903-
while (props->ring.buf_ev_notity > 0) {
833+
pthread_mutex_lock(&props->lock.lock);
834+
while (props->lock.buf_ev_notity > 0) {
904835
fprintf(stderr, "---wait for enque---\n");
905-
pthread_cond_wait(&props->ring.writable, &props->ring.lock);
836+
pthread_cond_wait(&props->lock.writable, &props->lock.lock);
906837
}
907838

908-
prod_head = props->ring.prod.head;
909-
cons_tail = props->ring.cons.tail;
910-
/* The subtraction is done between two unsigned 32bits value
911-
* (the result is always modulo 32 bits even if we have
912-
* prod_head > cons_tail). So 'free_entries' is always between 0
913-
* and size(ring)-1. */
914-
free_entries = mask + cons_tail - prod_head;
915-
/*fprintf(stderr,
916-
"mask %" PRIu32 " cons_tail %" PRIu32 " prod_head %" PRIu32 "\n",
917-
mask, cons_tail, prod_head);*/
918-
919-
/* Move prod_head. */
920-
if (n > free_entries)
921-
fprintf(stderr,
922-
"producer payload length %" PRIu32
923-
" larger than free_entries %" PRIu32 "\n",
924-
n, free_entries);
925-
prod_next = prod_head + n;
926-
props->ring.prod.head = prod_next;
927-
928-
/* Write payload to ring buffer. */
929-
uint32_t size = props->ring.prod.size;
930-
uint32_t idx = prod_head % size;
931-
/*fprintf(stderr,
932-
"prod_head %" PRIu32 " prod_next %" PRIu32 " mask %" PRIu32
933-
" idx %" PRIu32 "\n",
934-
prod_head, prod_next, mask, idx);*/
935-
if (idx + n < size) {
936-
memcpy(props->ring.buffer + idx, payload, n);
937-
} else {
938-
memcpy(props->ring.buffer + idx, payload, size - idx);
939-
memcpy(props->ring.buffer, payload, n - (size - idx));
940-
}
941-
VSND_COMPILER_BARRIER;
942-
943-
/* Update prod_tail */
944-
props->ring.prod.tail = prod_next;
945-
946839
/* Add to queue */
840+
/* TODO: add description of the speciality of Linux Kernel VirtIO sound
841+
* driver */
947842
vsnd_buf_queue_node_t *node = malloc(sizeof(*node));
948843
node->addr = payload;
949844
node->len = n;
950845
node->pos = 0;
951846
list_push(&node->q, &props->buf_queue_head);
952847

953-
/*uint32_t period_bytes = props->pp.period_bytes;
954-
if (prod_next - cons_tail >= period_bytes) {
955-
fprintf(stderr,
956-
"buffer ready for %" PRIu32 " cons_tail %" PRIu32
957-
" prod_next %" PRIu32 "\n",
958-
prod_next - cons_tail, cons_tail, prod_next);
959-
props->ring.buf_ev_notity++;
960-
pthread_cond_signal(&props->ring.readable);
961-
}*/
962-
pthread_mutex_unlock(&props->ring.lock);
848+
pthread_mutex_unlock(&props->lock.lock);
963849
}
964850

965851
typedef struct {
@@ -1036,8 +922,8 @@ static int virtio_snd_tx_desc_handler(virtio_snd_state_t *vsnd,
1036922
}
1037923

1038924
virtio_snd_prop_t *props = &vsnd_props[stream_id];
1039-
props->ring.buf_ev_notity++;
1040-
pthread_cond_signal(&props->ring.readable);
925+
props->lock.buf_ev_notity++;
926+
pthread_cond_signal(&props->lock.readable);
1041927

1042928
/* Tear down the descriptor list and free space. */
1043929
virtq_desc_queue_node_t *tmp = NULL;

0 commit comments

Comments
 (0)