diff --git a/virtio-snd.c b/virtio-snd.c index ad840c0..6752756 100644 --- a/virtio-snd.c +++ b/virtio-snd.c @@ -445,14 +445,15 @@ static void virtio_snd_read_pcm_prepare(const virtio_snd_pcm_hdr_t *query, /* Control the callback to prepare the buffer */ /* TODO: add lock to avoid race condition */ - pthread_mutex_lock(&virtio_snd_mutex); + // pthread_mutex_lock(&virtio_snd_mutex); v.guest_playing = false; v.stream_id = stream_id; - pthread_mutex_unlock(&virtio_snd_mutex); + // pthread_mutex_unlock(&virtio_snd_mutex); vsnd_props[stream_id].pp.hdr.hdr.code = VIRTIO_SND_R_PCM_PREPARE; vsnd_props[stream_id].audio_host = CNFAInit(NULL, "semu-virtio-snd", virtio_snd_cb, 44100, 0, 1, 0, vsnd_props[stream_id].pp.buffer_bytes, NULL, NULL, &v); + INIT_QUEUE_HEAD(&(vsnd_props[stream_id].pcm_frames_q)); *plen = 0; fprintf(stderr, "virtio_snd_read_pcm_prepare\n"); @@ -474,10 +475,10 @@ static void virtio_snd_read_pcm_start(const virtio_snd_pcm_hdr_t *query, /* Control the callback to start playing */ /* TODO: add lock to avoid race condition */ - pthread_mutex_lock(&virtio_snd_mutex); + // pthread_mutex_lock(&virtio_snd_mutex); vsnd_props[stream_id].pp.hdr.hdr.code = VIRTIO_SND_R_PCM_START; v.guest_playing = true; - pthread_mutex_unlock(&virtio_snd_mutex); + // pthread_mutex_unlock(&virtio_snd_mutex); *plen = 0; fprintf(stderr, "virtio_snd_read_pcm_start\n"); @@ -498,10 +499,10 @@ static void virtio_snd_read_pcm_stop(const virtio_snd_pcm_hdr_t *query, /* Control the callback to stop playing */ /* TODO: add lock to avoid race condition */ - pthread_mutex_lock(&virtio_snd_mutex); + // pthread_mutex_lock(&virtio_snd_mutex); vsnd_props[stream_id].pp.hdr.hdr.code = VIRTIO_SND_R_PCM_STOP; v.guest_playing = false; - pthread_mutex_lock(&virtio_snd_mutex); + // pthread_mutex_lock(&virtio_snd_mutex); *plen = 0; fprintf(stderr, "virtio_snd_read_pcm_stop\n"); @@ -522,24 +523,24 @@ static void virtio_snd_read_pcm_release(const virtio_snd_pcm_hdr_t *query, } /* Control the callback to stop playing */ /* TODO: add lock to avoid race condition */ - pthread_mutex_lock(&virtio_snd_mutex); + // pthread_mutex_lock(&virtio_snd_mutex); v.guest_playing = false; - pthread_mutex_unlock(&virtio_snd_mutex); + // pthread_mutex_unlock(&virtio_snd_mutex); vsnd_props[stream_id].pp.hdr.hdr.code = VIRTIO_SND_R_PCM_RELEASE; CNFAClose(vsnd_props[stream_id].audio_host); /* Tear down the PCM frames. */ virtio_snd_pcm_frame_t *t = NULL; - struct queue_head frame_q = vsnd_props[stream_id].pcm_frames_q; + struct queue_head *frame_q = &(vsnd_props[stream_id].pcm_frames_q); virtio_snd_pcm_frame_t *frame = vsnd_props[stream_id].pcm_frames; - queue_for_each_entry_safe(frame, t, &frame_q, q) + queue_for_each_entry_safe(frame, t, frame_q, q) { free(frame->buf); queue_del(&frame->q); free(frame); } - assert(queue_empty(&frame_q)); + assert(queue_empty(frame_q)); *plen = 0; fprintf(stderr, "virtio_snd_read_pcm_release\n"); @@ -576,8 +577,8 @@ static void virtio_snd_cb(struct CNFADriver *dev, totalframesp += framesp; if (!playing) { - fprintf(stderr, "notplaying totalframesr: %d totalframesp: %d\n", - totalframesr, totalframesp); + /*fprintf(stderr, "notplaying totalframesr: %d totalframesp: %d\n", + totalframesr, totalframesp);*/ return; } @@ -696,7 +697,7 @@ static int virtio_snd_tx_desc_handler(virtio_snd_state_t *vsnd, uint32_t *plen) { /* Start of critical section */ - pthread_mutex_lock(&virtio_snd_mutex); + // pthread_mutex_lock(&virtio_snd_mutex); /* TODO: clarify the usage of the last descriptor. */ /* virtio-snd TX uses arbitrary number of virtqueue descriptors. @@ -709,12 +710,12 @@ static int virtio_snd_tx_desc_handler(virtio_snd_state_t *vsnd, */ virtq_desc_queue_node_t *node; struct queue_head q; - INIT_QUEUE_HEAD(&q); + assert(queue_empty(&q)); /* Collect the descriptors */ int cnt = 0; - while (true) { + for (;;) { /* The size of the `struct virtq_desc` is 4 words */ const uint32_t *desc = &vsnd->ram[queue->QueueDesc + desc_idx * 4]; @@ -738,8 +739,8 @@ static int virtio_snd_tx_desc_handler(virtio_snd_state_t *vsnd, int idx = 0; uint32_t stream_id; uintptr_t base = (uintptr_t) vsnd->ram; - struct queue_head frame_q = vsnd_props[stream_id].pcm_frames_q; - INIT_QUEUE_HEAD(&frame_q); + struct queue_head *frame_q = &(vsnd_props[stream_id].pcm_frames_q); + virtio_snd_pcm_frame_t *frame = vsnd_props[stream_id].pcm_frames; uint32_t ret_len = 0; queue_for_each_entry(node, &q, q) @@ -759,7 +760,7 @@ static int virtio_snd_tx_desc_handler(virtio_snd_state_t *vsnd, (virtio_snd_pcm_status_t *) (base + addr); response->status = VIRTIO_SND_S_OK; response->latency_bytes = ret_len; - *plen = sizeof(virtio_snd_pcm_status_t); + *plen = sizeof(*response); fprintf(stderr, "TX response\n"); goto early_continue; } @@ -768,7 +769,7 @@ static int virtio_snd_tx_desc_handler(virtio_snd_state_t *vsnd, void *buf = (void *) (base + addr); frame->buf = (void *) malloc(sizeof(frame->buf) * len); memcpy(frame->buf, buf, len); - queue_push(&frame->q, &frame_q); + queue_push(&frame->q, frame_q); ret_len += len; early_continue: @@ -786,7 +787,7 @@ static int virtio_snd_tx_desc_handler(virtio_snd_state_t *vsnd, } /* End of critical seciont. */ - pthread_mutex_unlock(&virtio_snd_mutex); + // pthread_mutex_unlock(&virtio_snd_mutex); /* TODO: remove sleep once find the root cause of infinite loop in TX. */ sleep(1); @@ -860,8 +861,10 @@ static void virtio_queue_notify_handler( vsnd->ram[queue->QueueUsed] |= ((uint32_t) new_used) << 16; /* len */ /* Send interrupt, unless VIRTQ_AVAIL_F_NO_INTERRUPT is set */ - if (!(ram[queue->QueueAvail] & 1)) + if (!(ram[queue->QueueAvail] & 1)) { + fprintf(stderr, "send interrupt\n"); vsnd->InterruptStatus |= VIRTIO_INT__USED_RING; + } } static bool virtio_snd_reg_read(virtio_snd_state_t *vsnd, @@ -1014,6 +1017,7 @@ void virtio_snd_read(hart_t *vm, uint8_t width, uint32_t *value) { + pthread_mutex_lock(&virtio_snd_mutex); switch (width) { case RV_MEM_LW: if (!virtio_snd_reg_read(vsnd, addr >> 2, value)) @@ -1024,12 +1028,13 @@ void virtio_snd_read(hart_t *vm, case RV_MEM_LHU: case RV_MEM_LH: vm_set_exception(vm, RV_EXC_LOAD_MISALIGN, vm->exc_val); - return; + break; default: vm_set_exception(vm, RV_EXC_ILLEGAL_INSN, 0); - return; + break; } + pthread_mutex_unlock(&virtio_snd_mutex); } void virtio_snd_write(hart_t *vm, virtio_snd_state_t *vsnd, @@ -1037,6 +1042,7 @@ void virtio_snd_write(hart_t *vm, uint8_t width, uint32_t value) { + pthread_mutex_lock(&virtio_snd_mutex); switch (width) { case RV_MEM_SW: if (!virtio_snd_reg_write(vsnd, addr >> 2, value)) @@ -1045,11 +1051,12 @@ void virtio_snd_write(hart_t *vm, case RV_MEM_SB: case RV_MEM_SH: vm_set_exception(vm, RV_EXC_STORE_MISALIGN, vm->exc_val); - return; + break; default: vm_set_exception(vm, RV_EXC_ILLEGAL_INSN, 0); - return; + break; } + pthread_mutex_unlock(&virtio_snd_mutex); } bool virtio_snd_init(virtio_snd_state_t *vsnd)