Skip to content

Commit

Permalink
Fix PCM drain synchronization - use mutex for sync
Browse files Browse the repository at this point in the history
  • Loading branch information
arkq committed Nov 26, 2022
1 parent fe76e2e commit 7ae09a4
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 30 deletions.
31 changes: 14 additions & 17 deletions src/ba-transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,7 @@ static int transport_pcm_init(
ba_transport_pcm_volume_set(&pcm->volume[1], NULL, NULL, NULL);

pthread_mutex_init(&pcm->mutex, NULL);
pthread_mutex_init(&pcm->synced_mtx, NULL);
pthread_cond_init(&pcm->synced, NULL);
pthread_cond_init(&pcm->cond, NULL);

pcm->ba_dbus_path = g_strdup_printf("%s/%s/%s",
t->d->ba_dbus_path, transport_get_dbus_path_type(t->profile),
Expand All @@ -112,8 +111,7 @@ static void transport_pcm_free(
pthread_mutex_unlock(&pcm->mutex);

pthread_mutex_destroy(&pcm->mutex);
pthread_mutex_destroy(&pcm->synced_mtx);
pthread_cond_destroy(&pcm->synced);
pthread_cond_destroy(&pcm->cond);

if (pcm->ba_dbus_path != NULL)
g_free(pcm->ba_dbus_path);
Expand Down Expand Up @@ -164,7 +162,7 @@ static int transport_thread_init(
th->pipe[1] = -1;

pthread_mutex_init(&th->mutex, NULL);
pthread_cond_init(&th->changed, NULL);
pthread_cond_init(&th->cond, NULL);

if (pipe(th->pipe) == -1)
return -1;
Expand Down Expand Up @@ -198,7 +196,7 @@ static void transport_thread_cancel(struct ba_transport_thread *th) {
* supposed to be synchronous. */
if (th->state == BA_TRANSPORT_THREAD_STATE_JOINING) {
while (!pthread_equal(th->id, config.main_thread))
pthread_cond_wait(&th->changed, &th->mutex);
pthread_cond_wait(&th->cond, &th->mutex);
pthread_mutex_unlock(&th->mutex);
return;
}
Expand Down Expand Up @@ -230,7 +228,7 @@ static void transport_thread_cancel(struct ba_transport_thread *th) {
pthread_mutex_unlock(&th->mutex);

/* Notify others that the thread has been terminated. */
pthread_cond_broadcast(&th->changed);
pthread_cond_broadcast(&th->cond);

}

Expand All @@ -239,7 +237,7 @@ static void transport_thread_cancel(struct ba_transport_thread *th) {
static void transport_thread_cancel_wait(struct ba_transport_thread *th) {
pthread_mutex_lock(&th->mutex);
while (!pthread_equal(th->id, config.main_thread))
pthread_cond_wait(&th->changed, &th->mutex);
pthread_cond_wait(&th->cond, &th->mutex);
pthread_mutex_unlock(&th->mutex);
}

Expand All @@ -254,7 +252,7 @@ static void transport_thread_free(
if (th->pipe[1] != -1)
close(th->pipe[1]);
pthread_mutex_destroy(&th->mutex);
pthread_cond_destroy(&th->changed);
pthread_cond_destroy(&th->cond);
}

int ba_transport_thread_set_state(
Expand All @@ -278,7 +276,7 @@ int ba_transport_thread_set_state(
pthread_mutex_unlock(&th->mutex);

if (!skip)
pthread_cond_signal(&th->changed);
pthread_cond_signal(&th->cond);

return 0;
}
Expand Down Expand Up @@ -1498,18 +1496,17 @@ int ba_transport_pcm_drain(struct ba_transport_pcm *pcm) {
if (pthread_equal(pcm->th->id, config.main_thread))
return errno = ESRCH, -1;

#if DEBUG
pthread_mutex_lock(&pcm->mutex);
debug("PCM drain: %d", pcm->fd);
pthread_mutex_unlock(&pcm->mutex);
#endif

pthread_mutex_lock(&pcm->synced_mtx);
debug("PCM drain: %d", pcm->fd);

pcm->synced = false;
ba_transport_thread_signal_send(pcm->th, BA_TRANSPORT_THREAD_SIGNAL_PCM_SYNC);
pthread_cond_wait(&pcm->synced, &pcm->synced_mtx);

pthread_mutex_unlock(&pcm->synced_mtx);
while (!pcm->synced)
pthread_cond_wait(&pcm->cond, &pcm->mutex);

pthread_mutex_unlock(&pcm->mutex);

/* TODO: Asynchronous transport release.
*
Expand Down
18 changes: 9 additions & 9 deletions src/ba-transport.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,10 @@ struct ba_transport_pcm {
/* PCM stream operation mode */
enum ba_transport_pcm_mode mode;

/* PCM access guard */
/* guard PCM data updates */
pthread_mutex_t mutex;
/* updates notification */
pthread_cond_t cond;

/* FIFO file descriptor */
int fd;
Expand All @@ -80,6 +82,9 @@ struct ba_transport_pcm {
* audio encoding or decoding and data transfer. */
unsigned int delay;

/* indicates whether FIFO buffer was synchronized */
bool synced;

/* internal software volume control */
bool soft_volume;

Expand All @@ -99,10 +104,6 @@ struct ba_transport_pcm {
double scale;
} volume[2];

/* data synchronization */
pthread_mutex_t synced_mtx;
pthread_cond_t synced;

/* exported PCM D-Bus API */
char *ba_dbus_path;
bool ba_dbus_exported;
Expand Down Expand Up @@ -138,8 +139,10 @@ struct ba_transport_thread {
/* backward reference to transport */
struct ba_transport *t;

/* guard thread structure */
/* guard transport thread data updates */
pthread_mutex_t mutex;
/* state/id updates notification */
pthread_cond_t cond;

/* current state of the thread */
enum ba_transport_thread_state state;
Expand All @@ -153,9 +156,6 @@ struct ba_transport_thread {
/* notification PIPE */
int pipe[2];

/* state/id changed notification */
pthread_cond_t changed;

};

int ba_transport_thread_set_state(
Expand Down
2 changes: 1 addition & 1 deletion src/bluealsa-dbus.c
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ static void bluealsa_pcm_open(GDBusMethodInvocation *inv, void *userdata) {
/* wait until ready to process audio */
pthread_mutex_lock(&th->mutex);
while ((state = th->state) < BA_TRANSPORT_THREAD_STATE_RUNNING)
pthread_cond_wait(&th->changed, &th->mutex);
pthread_cond_wait(&th->cond, &th->mutex);
pthread_mutex_unlock(&th->mutex);

/* bail if something has gone wrong */
Expand Down
9 changes: 6 additions & 3 deletions src/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ ssize_t io_pcm_read(
errno == EINTR)
continue;
if (ret == 0) {
debug("PCM has been closed: %d", fd);
debug("PCM client closed connection: %d", fd);
ba_transport_pcm_release(pcm);
}
}
Expand Down Expand Up @@ -237,7 +237,7 @@ ssize_t io_pcm_write(
case EPIPE:
/* This errno value will be received only, when the SIGPIPE
* signal is caught, blocked or ignored. */
debug("PCM has been closed: %d", fd);
debug("PCM client closed connection: %d", fd);
ba_transport_pcm_release(pcm);
ret = 0;
/* fall-through */
Expand Down Expand Up @@ -337,7 +337,10 @@ ssize_t io_poll_and_read_pcm(
/* Poll for reading with optional sync timeout. */
switch (poll_rv) {
case 0:
pthread_cond_signal(&pcm->synced);
pthread_mutex_lock(&pcm->mutex);
pcm->synced = true;
pthread_mutex_unlock(&pcm->mutex);
pthread_cond_signal(&pcm->cond);
io->timeout = -1;
return 0;
case -1:
Expand Down

0 comments on commit 7ae09a4

Please sign in to comment.