@@ -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 */
279274typedef 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
298280typedef 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}
771705static 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
965851typedef 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