Skip to content

Commit eb2e3e5

Browse files
committed
Use CV to play sound on pcm_start/pcm_stop state
1 parent f0944a3 commit eb2e3e5

File tree

1 file changed

+35
-36
lines changed

1 file changed

+35
-36
lines changed

virtio-snd.c

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -269,13 +269,15 @@ static virtio_snd_prop_t vsnd_props[VSND_DEV_CNT_MAX] = {
269269
static int vsnd_dev_cnt = 0;
270270

271271
typedef struct {
272-
bool guest_playing;
272+
int32_t guest_playing;
273273
uint32_t stream_id;
274274
} vsnd_stream_sel_t;
275275
static vsnd_stream_sel_t v;
276276

277277
static pthread_mutex_t virtio_snd_mutex = PTHREAD_MUTEX_INITIALIZER;
278+
static pthread_mutex_t virtio_snd_ctrl_mutex = PTHREAD_MUTEX_INITIALIZER;
278279
static pthread_cond_t virtio_snd_tx_cond = PTHREAD_COND_INITIALIZER;
280+
static pthread_cond_t virtio_snd_ctrl_cond = PTHREAD_COND_INITIALIZER;
279281
static int tx_ev_notify;
280282

281283
/* Forward declaration */
@@ -451,7 +453,7 @@ static void virtio_snd_read_pcm_prepare(const virtio_snd_pcm_hdr_t *query,
451453
/* Control the callback to prepare the buffer */
452454
/* TODO: add lock to avoid race condition */
453455
// pthread_mutex_lock(&virtio_snd_mutex);
454-
v.guest_playing = false;
456+
v.guest_playing = 0;
455457
v.stream_id = stream_id;
456458
// pthread_mutex_unlock(&virtio_snd_mutex);
457459
vsnd_props[stream_id].pp.hdr.hdr.code = VIRTIO_SND_R_PCM_PREPARE;
@@ -480,10 +482,9 @@ static void virtio_snd_read_pcm_start(const virtio_snd_pcm_hdr_t *query,
480482

481483
/* Control the callback to start playing */
482484
/* TODO: add lock to avoid race condition */
483-
// pthread_mutex_lock(&virtio_snd_mutex);
484485
vsnd_props[stream_id].pp.hdr.hdr.code = VIRTIO_SND_R_PCM_START;
485-
v.guest_playing = true;
486-
// pthread_mutex_unlock(&virtio_snd_mutex);
486+
v.guest_playing++;
487+
pthread_cond_signal(&virtio_snd_ctrl_cond);
487488

488489
*plen = 0;
489490
fprintf(stderr, "virtio_snd_read_pcm_start\n");
@@ -504,10 +505,9 @@ static void virtio_snd_read_pcm_stop(const virtio_snd_pcm_hdr_t *query,
504505

505506
/* Control the callback to stop playing */
506507
/* TODO: add lock to avoid race condition */
507-
// pthread_mutex_lock(&virtio_snd_mutex);
508508
vsnd_props[stream_id].pp.hdr.hdr.code = VIRTIO_SND_R_PCM_STOP;
509-
v.guest_playing = false;
510-
// pthread_mutex_lock(&virtio_snd_mutex);
509+
v.guest_playing--;
510+
pthread_cond_signal(&virtio_snd_ctrl_cond);
511511

512512
*plen = 0;
513513
fprintf(stderr, "virtio_snd_read_pcm_stop\n");
@@ -528,9 +528,8 @@ static void virtio_snd_read_pcm_release(const virtio_snd_pcm_hdr_t *query,
528528
}
529529
/* Control the callback to stop playing */
530530
/* TODO: add lock to avoid race condition */
531-
// pthread_mutex_lock(&virtio_snd_mutex);
532-
v.guest_playing = false;
533-
// pthread_mutex_unlock(&virtio_snd_mutex);
531+
v.guest_playing = 0;
532+
pthread_cond_signal(&virtio_snd_ctrl_cond);
534533

535534
vsnd_props[stream_id].pp.hdr.hdr.code = VIRTIO_SND_R_PCM_RELEASE;
536535
CNFAClose(vsnd_props[stream_id].audio_host);
@@ -577,17 +576,17 @@ static void virtio_snd_cb(struct CNFADriver *dev,
577576
memcpy(out, vsnd_props[id].buf, output_buf_sz);
578577
#endif
579578
vsnd_stream_sel_t *v_ptr = (vsnd_stream_sel_t *) dev->opaque;
580-
bool playing = v_ptr->guest_playing;
579+
580+
pthread_mutex_lock(&virtio_snd_ctrl_mutex);
581+
582+
while (v_ptr->guest_playing <= 0)
583+
pthread_cond_wait(&virtio_snd_ctrl_cond, &virtio_snd_ctrl_mutex);
584+
585+
v_ptr->guest_playing--;
581586

582587
totalframesr += framesr;
583588
totalframesp += framesp;
584589

585-
if (!playing) {
586-
/*fprintf(stderr, "notplaying totalframesr: %d totalframesp: %d\n",
587-
totalframesr, totalframesp);*/
588-
return;
589-
}
590-
591590
fprintf(stderr, "start to play\n");
592591
int channels = dev->channelsPlay;
593592
for (int i = 0; i < framesp; i++) {
@@ -602,6 +601,8 @@ static void virtio_snd_cb(struct CNFADriver *dev,
602601
*(out++) = value;
603602
}
604603
}
604+
605+
pthread_mutex_unlock(&virtio_snd_ctrl_mutex);
605606
}
606607

607608
#define VSND_DESC_CNT 3
@@ -734,7 +735,7 @@ static int virtio_snd_tx_desc_handler(virtio_snd_state_t *vsnd,
734735

735736
/* Leave the loop if next-flag is not set */
736737
if (!(desc[3] & VIRTIO_DESC_F_NEXT)) {
737-
fprintf(stderr, "index %" PRIu32 " no next flag\n", cnt);
738+
// fprintf(stderr, "index %" PRIu32 " no next flag\n", cnt);
738739
break;
739740
}
740741
}
@@ -750,21 +751,21 @@ static int virtio_snd_tx_desc_handler(virtio_snd_state_t *vsnd,
750751
{
751752
uint32_t addr = node->vq_desc.addr;
752753
uint32_t len = node->vq_desc.len;
753-
fprintf(stderr, "idx %d addr %" PRIu32 " len %" PRIu32 "\n", idx, addr,
754-
len);
754+
// fprintf(stderr, "idx %d addr %" PRIu32 " len %" PRIu32 "\n", idx,
755+
// addr, len);
755756
if (idx == 0) { // the first descriptor
756757
const virtio_snd_pcm_xfer_t *request =
757758
(virtio_snd_pcm_xfer_t *) (base + addr);
758759
stream_id = request->stream_id;
759-
fprintf(stderr, "stream_id %" PRIu32 "\n", stream_id);
760+
// fprintf(stderr, "stream_id %" PRIu32 "\n", stream_id);
760761
goto early_continue;
761762
} else if (idx == cnt - 1) { // the last descriptor
762763
virtio_snd_pcm_status_t *response =
763764
(virtio_snd_pcm_status_t *) (base + addr);
764765
response->status = VIRTIO_SND_S_OK;
765766
response->latency_bytes = ret_len;
766767
*plen = sizeof(*response);
767-
fprintf(stderr, "TX response\n");
768+
// fprintf(stderr, "TX response\n");
768769
goto early_continue;
769770
}
770771

@@ -811,8 +812,7 @@ static void virtio_queue_notify_handler(
811812
/* Check for new buffers */
812813
uint16_t new_avail = ram[queue->QueueAvail] >> 16;
813814
if (new_avail - queue->last_avail > (uint16_t) queue->QueueNum)
814-
return (fprintf(stderr, "size check fail\n"),
815-
virtio_snd_set_fail(vsnd));
815+
return virtio_snd_set_fail(vsnd);
816816

817817
if (queue->last_avail == new_avail)
818818
return;
@@ -837,7 +837,7 @@ static void virtio_queue_notify_handler(
837837
*/
838838
uint32_t len = 0;
839839
int result = handler(vsnd, queue, buffer_idx, &len);
840-
fprintf(stderr, "len: %" PRIu32 "\n", len);
840+
// fprintf(stderr, "len: %" PRIu32 "\n", len);
841841
if (result != 0)
842842
return virtio_snd_set_fail(vsnd);
843843

@@ -850,7 +850,8 @@ static void virtio_queue_notify_handler(
850850
queue->last_avail++;
851851
new_used++;
852852

853-
printf("last_avail %d new_avail %d\n", queue->last_avail, new_avail);
853+
// fprintf(stderr, "last_avail %d new_avail %d\n", queue->last_avail,
854+
// new_avail);
854855
}
855856

856857
/* Check le32 len field of struct virtq_used_elem on the spec */
@@ -859,7 +860,7 @@ static void virtio_queue_notify_handler(
859860

860861
/* Send interrupt, unless VIRTQ_AVAIL_F_NO_INTERRUPT is set */
861862
if (!(ram[queue->QueueAvail] & 1)) {
862-
fprintf(stderr, "send interrupt\n");
863+
// fprintf(stderr, "send interrupt\n");
863864
vsnd->InterruptStatus |= VIRTIO_INT__USED_RING;
864865
}
865866
}
@@ -871,20 +872,20 @@ static void *func(void *args)
871872
{
872873
virtio_snd_state_t *vsnd = (virtio_snd_state_t *) args;
873874
for (;;) {
874-
fprintf(stderr, "*** tx desc handler is called ***\n");
875+
// fprintf(stderr, "*** tx desc handler is called ***\n");
875876
pthread_mutex_lock(&virtio_snd_mutex);
876877
while (tx_ev_notify <= 0) {
877878
pthread_cond_wait(&virtio_snd_tx_cond, &virtio_snd_mutex);
878-
fprintf(stderr, "wait for cond\n");
879+
// fprintf(stderr, "wait for cond\n");
879880
}
880-
fprintf(stderr, "*** start tx critical section ***\n");
881+
// fprintf(stderr, "*** start tx critical section ***\n");
881882
tx_ev_notify--;
882-
fprintf(stderr, "*** tx desc handler ***\n");
883+
// fprintf(stderr, "*** tx desc handler ***\n");
883884
virtio_queue_notify_handler(vsnd, 2, virtio_snd_tx_desc_handler);
884-
fprintf(stderr, "*** end tx cirtical section ***\n");
885+
// fprintf(stderr, "*** end tx cirtical section ***\n");
885886
pthread_mutex_unlock(&virtio_snd_mutex);
886887
}
887-
return NULL;
888+
pthread_exit(NULL);
888889
}
889890

890891
static bool virtio_snd_reg_read(virtio_snd_state_t *vsnd,
@@ -998,10 +999,8 @@ static bool virtio_snd_reg_write(virtio_snd_state_t *vsnd,
998999
virtio_snd_desc_handler);
9991000
break;
10001001
case VSND_QUEUE_TX:
1001-
fprintf(stderr, "TX start\n");
10021002
tx_ev_notify++;
10031003
pthread_cond_signal(&virtio_snd_tx_cond);
1004-
fprintf(stderr, "TX end\n");
10051004
break;
10061005
default:
10071006
fprintf(stderr, "value %d not supported\n", value);

0 commit comments

Comments
 (0)