Skip to content

Commit

Permalink
bluez a2dp - fix state machine synchronization
Browse files Browse the repository at this point in the history
Using a worker thread implementation for A2DP means that if we don't
have some way to syncroniize state transitions we can get overlap of
requested command functions or lost signals. In order for the A2DP
state machine to function each command operation must complete before
the next is initiated or we will get errors caused by these out of
sequence commands. And if we signal the thread when it is not waiting
on the condition the signal will be missed.

This could be partly resolved by implementing a queue but then there
is an overhead with also implementing a wait mechamism for state
transitions. It's much easier and simpler to just hold the mutex
during command processing which also deals with the lost signals issue.
This may well not achieve the original goal of the worker thread
implementation but neither would a queue implementation. It looks
like this is just the way things are!
  • Loading branch information
raven-au authored and Nick Pelly committed Sep 30, 2009
1 parent fa4032c commit 6047fd6
Showing 1 changed file with 10 additions and 8 deletions.
18 changes: 10 additions & 8 deletions audio/liba2dp.c
Original file line number Diff line number Diff line change
Expand Up @@ -880,10 +880,8 @@ static int bluetooth_configure(struct bluetooth_data *data)

static void set_state(struct bluetooth_data *data, a2dp_state_t state)
{
pthread_mutex_lock(&data->mutex);
data->state = state;
pthread_cond_signal(&data->client_wait);
pthread_mutex_unlock(&data->mutex);
}

static void set_command(struct bluetooth_data *data, a2dp_command_t command)
Expand Down Expand Up @@ -943,18 +941,17 @@ static void* a2dp_thread(void *d)
DBG("a2dp_thread started");
prctl(PR_SET_NAME, "a2dp_thread", 0, 0, 0);

pthread_mutex_lock(&data->mutex);

data->started = 1;
pthread_cond_signal(&data->thread_start);

while (1)
{
a2dp_command_t command;

pthread_mutex_lock(&data->mutex);
if (!data->started) {
data->started = 1;
pthread_cond_signal(&data->thread_start);
}
pthread_cond_wait(&data->thread_wait, &data->mutex);
command = data->command;
pthread_mutex_unlock(&data->mutex);

switch (command) {
case A2DP_CMD_INIT:
Expand Down Expand Up @@ -992,6 +989,7 @@ static void* a2dp_thread(void *d)
}

done:
pthread_mutex_unlock(&data->mutex);
DBG("a2dp_thread finished");
return NULL;
}
Expand Down Expand Up @@ -1038,10 +1036,14 @@ int a2dp_init(int rate, int channels, a2dpData* dataPtr)
goto error;
}

/* Make sure the state machine is ready and waiting */
while (!data->started) {
pthread_cond_wait(&data->thread_start, &data->mutex);
}

/* Poke the state machine to get it going */
pthread_cond_signal(&data->thread_wait);

pthread_mutex_unlock(&data->mutex);

*dataPtr = data;
Expand Down

0 comments on commit 6047fd6

Please sign in to comment.