Skip to content

Commit 7a4c8e8

Browse files
committed
Create dedicated RX enque function
1 parent 4d6aa40 commit 7a4c8e8

File tree

1 file changed

+112
-23
lines changed

1 file changed

+112
-23
lines changed

virtio-snd.c

Lines changed: 112 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,12 @@ static void virtio_queue_notify_handler(virtio_snd_state_t *vsnd,
394394
static void __virtio_snd_frame_enqueue(void *payload,
395395
uint32_t n,
396396
uint32_t stream_id);
397+
static void __virtio_snd_rx_frame_enqueue(void *payload,
398+
uint32_t n,
399+
uint32_t stream_id);
400+
static void __virtio_snd_rx_frame_dequeue(void *out,
401+
uint32_t n,
402+
uint32_t stream_id);
397403
typedef struct {
398404
struct virtq_desc vq_desc;
399405
struct list_head q;
@@ -562,11 +568,9 @@ VSND_GEN_TX_QUEUE_HANDLER(flush, 0);
562568
uintptr_t base = (uintptr_t) vsnd->ram; \
563569
uint32_t ret_len = 0; \
564570
uint8_t bad_msg_err = 0; \
565-
fprintf(stderr, "*** rx_normal cnt %d\n", cnt); \
566571
list_for_each_entry (node, &q, q) { \
567572
uint32_t addr = node->vq_desc.addr; \
568573
uint32_t len = node->vq_desc.len; \
569-
fprintf(stderr, "*** rx_normal idx %" PRIu32 "\n", len); \
570574
if (idx == 0) { /* the first descriptor */ \
571575
const virtio_snd_pcm_xfer_t *request = \
572576
(virtio_snd_pcm_xfer_t *) (base + addr); \
@@ -592,15 +596,16 @@ VSND_GEN_TX_QUEUE_HANDLER(flush, 0);
592596
(virtio_snd_pcm_status_t *) (base + addr); \
593597
response->status = \
594598
bad_msg_err ? VIRTIO_SND_S_IO_ERR : VIRTIO_SND_S_OK; \
595-
response->latency_bytes = ret_len; \
599+
response->latency_bytes = 0; \
596600
*plen = sizeof(virtio_snd_pcm_status_t) + ret_len; \
601+
fprintf(stderr, "*** rx get %" PRIu32 " bytes \n", *plen); \
597602
goto early_continue; \
598603
} \
599604
\
600605
IIF(WRITE) \
601606
(/* enqueue frames */ \
602607
void *payload = (void *) (base + addr); if (bad_msg_err == 0) \
603-
/*__virtio_snd_frame_enqueue(payload, len, stream_id);*/ \
608+
__virtio_snd_rx_frame_dequeue(payload, len, stream_id); \
604609
, /* flush queue */ \
605610
(void) stream_id; \
606611
/* Suppress unused variable warning. */) ret_len += len; \
@@ -614,8 +619,8 @@ VSND_GEN_TX_QUEUE_HANDLER(flush, 0);
614619
IIF(WRITE) \
615620
(/* enque frames */ \
616621
virtio_snd_prop_t *props = &vsnd_props[stream_id]; \
617-
props->lock.buf_ev_notity++; \
618-
pthread_cond_signal(&props->lock.readable);, /* flush queue */ \
622+
/*props->lock.buf_ev_notity++;*/ \
623+
/*pthread_cond_signal(&props->lock.readable);*/, /* flush queue */ \
619624
) \
620625
\
621626
/* Tear down the descriptor list and free space. */ \
@@ -845,6 +850,8 @@ static void virtio_snd_read_pcm_prepare(const virtio_snd_pcm_hdr_t *query,
845850
}
846851

847852
*plen = 0;
853+
854+
fprintf(stderr, "=== pcm_prepare \n");
848855
}
849856

850857
static void virtio_snd_read_pcm_start(const virtio_snd_pcm_hdr_t *query,
@@ -872,6 +879,8 @@ static void virtio_snd_read_pcm_start(const virtio_snd_pcm_hdr_t *query,
872879
}
873880

874881
*plen = 0;
882+
883+
fprintf(stderr, "=== pcm_start \n");
875884
}
876885

877886
static void virtio_snd_read_pcm_stop(const virtio_snd_pcm_hdr_t *query,
@@ -899,6 +908,8 @@ static void virtio_snd_read_pcm_stop(const virtio_snd_pcm_hdr_t *query,
899908
}
900909

901910
*plen = 0;
911+
912+
fprintf(stderr, "=== pcm_stop\n");
902913
}
903914

904915
static void virtio_snd_read_pcm_release(const virtio_snd_pcm_hdr_t *query,
@@ -996,6 +1007,42 @@ static void __virtio_snd_frame_dequeue(void *out,
9961007
pthread_mutex_unlock(&props->lock.lock);
9971008
}
9981009

1010+
static void __virtio_snd_rx_frame_dequeue(void *out,
1011+
uint32_t n,
1012+
uint32_t stream_id)
1013+
{
1014+
virtio_snd_prop_t *props = &vsnd_props[stream_id];
1015+
1016+
pthread_mutex_lock(&props->lock.lock);
1017+
while (props->lock.buf_ev_notity < 1)
1018+
pthread_cond_wait(&props->lock.readable, &props->lock.lock);
1019+
1020+
/* Get the PCM frames from queue */
1021+
uint32_t written_bytes = 0;
1022+
while (!list_empty(&props->buf_queue_head) && written_bytes < n) {
1023+
vsnd_buf_queue_node_t *node =
1024+
list_first_entry(&props->buf_queue_head, vsnd_buf_queue_node_t, q);
1025+
uint32_t left = n - written_bytes;
1026+
uint32_t actual = node->len - node->pos;
1027+
uint32_t len =
1028+
left < actual ? left : actual; /* Naive min implementation */
1029+
1030+
memcpy(props->intermediate + written_bytes, node->addr + node->pos,
1031+
len);
1032+
1033+
written_bytes += len;
1034+
node->pos += len;
1035+
if (node->pos >= node->len)
1036+
list_del(&node->q);
1037+
}
1038+
memcpy(out, props->intermediate, written_bytes);
1039+
1040+
props->lock.buf_ev_notity--;
1041+
pthread_cond_signal(&props->lock.writable);
1042+
pthread_mutex_unlock(&props->lock.lock);
1043+
}
1044+
1045+
9991046
static int virtio_snd_tx_stream_cb(const void *input,
10001047
void *output,
10011048
unsigned long frame_cnt,
@@ -1030,29 +1077,16 @@ static int virtio_snd_rx_stream_cb(const void *input,
10301077
(void) time_info;
10311078
(void) status_flags;
10321079

1080+
fprintf(stderr, "rx_stream_cb\n");
1081+
10331082
vsnd_stream_sel_t *v_ptr = (vsnd_stream_sel_t *) user_data;
10341083
uint32_t id = v_ptr->stream_id;
10351084
virtio_snd_prop_t *props = &vsnd_props[id];
10361085
int channels = props->pp.channels;
10371086
uint32_t out_buf_sz = frame_cnt * channels;
10381087
uint32_t out_buf_bytes = out_buf_sz * VSND_CNFA_FRAME_SZ;
10391088

1040-
uint32_t idx = props->buf_idx;
1041-
uint32_t sz = props->buf_sz;
1042-
uint32_t base = (idx + out_buf_bytes > sz) ? (sz - idx) : out_buf_bytes;
1043-
uint32_t left = out_buf_bytes - base;
1044-
memcpy(props->intermediate + idx, input, base);
1045-
if(left != 0)
1046-
memcpy(props->intermediate, input + base, left);
1047-
props->buf_idx = (props->buf_idx + out_buf_bytes) % sz;
1048-
// enque to list
1049-
// FIXME: create cirular queue behavior
1050-
__virtio_snd_frame_enqueue(props->intermediate + idx, out_buf_bytes, id);
1051-
fprintf(stderr, "+++ virtio_snd_rx_stream_cb"
1052-
" idx %" PRIu32
1053-
" base %" PRIu32
1054-
" left %" PRIu32 " +++\n",
1055-
idx, base, left);
1089+
__virtio_snd_rx_frame_enqueue(input, out_buf_bytes, id);
10561090

10571091
return paContinue;
10581092
}
@@ -1149,9 +1183,12 @@ static void __virtio_snd_frame_enqueue(void *payload,
11491183
virtio_snd_prop_t *props = &vsnd_props[stream_id];
11501184

11511185
pthread_mutex_lock(&props->lock.lock);
1152-
while (props->lock.buf_ev_notity > 0)
1186+
while (props->lock.buf_ev_notity > 0) {
1187+
fprintf(stderr, "buf_ev_notity %d", props->lock.buf_ev_notity);
11531188
pthread_cond_wait(&props->lock.writable, &props->lock.lock);
1189+
}
11541190

1191+
fprintf(stderr, "enque start\n");
11551192
/* Add a PCM frame to queue */
11561193
/* As stated in Linux Kernel mailing list [1], we keep the pointer
11571194
* points to the payload [2] so that we can always get up-to-date
@@ -1171,8 +1208,60 @@ static void __virtio_snd_frame_enqueue(void *payload,
11711208
list_push(&node->q, &props->buf_queue_head);
11721209

11731210
pthread_mutex_unlock(&props->lock.lock);
1211+
fprintf(stderr, "enque end\n");
1212+
}
1213+
1214+
// FIXME: create cirular queue behavior
1215+
static void __virtio_snd_rx_frame_enqueue(void *payload,
1216+
uint32_t n,
1217+
uint32_t stream_id)
1218+
{
1219+
virtio_snd_prop_t *props = &vsnd_props[stream_id];
1220+
1221+
pthread_mutex_lock(&props->lock.lock);
1222+
while (props->lock.buf_ev_notity > 0) {
1223+
fprintf(stderr, "buf_ev_notity %d", props->lock.buf_ev_notity);
1224+
pthread_cond_wait(&props->lock.writable, &props->lock.lock);
1225+
}
1226+
1227+
fprintf(stderr, "enque start\n");
1228+
1229+
uint32_t idx = props->buf_idx;
1230+
uint32_t sz = props->buf_sz;
1231+
uint32_t base = (idx + n > sz) ? (sz - idx) : n;
1232+
uint32_t left = n - base;
1233+
memcpy(props->intermediate + idx, payload, base);
1234+
if(left != 0)
1235+
memcpy(props->intermediate, payload + base, left);
1236+
props->buf_idx = (props->buf_idx + n) % sz;
1237+
/* Add a PCM frame to queue */
1238+
/* As stated in Linux Kernel mailing list [1], we keep the pointer
1239+
* points to the payload [2] so that we can always get up-to-date
1240+
* contents of PCM frames.
1241+
* References:
1242+
* [1] https://lore.kernel.org/all/[email protected]/T/
1243+
* [2]
1244+
* https://github.com/rust-vmm/vhost-device/blob/eb2e2227e41d48a52e4e6346189b772c5363879d/staging/vhost-device-sound/src/device.rs#L554
1245+
*/
1246+
/* FIXME: locate the root case of repeating artifact even we
1247+
* keep the pointer of the payload.
1248+
*/
1249+
vsnd_buf_queue_node_t *node = malloc(sizeof(*node));
1250+
node->addr = props->intermediate + idx;
1251+
node->len = n;
1252+
node->pos = 0;
1253+
list_push(&node->q, &props->buf_queue_head);
1254+
1255+
pthread_mutex_unlock(&props->lock.lock);
1256+
fprintf(stderr, "enque end\n");
1257+
fprintf(stderr, "+++ virtio_snd_rx_enqueue"
1258+
" idx %" PRIu32
1259+
" base %" PRIu32
1260+
" left %" PRIu32 " +++\n",
1261+
idx, base, left);
11741262
}
11751263

1264+
11761265
static void virtio_queue_notify_handler(
11771266
virtio_snd_state_t *vsnd,
11781267
int index,

0 commit comments

Comments
 (0)