bluez a2dp - fix wait_for_start() synchronization
On entry to wait_for_start() it's possible we are in state
A2DP_STATE_NONE if a2dp_thread() has not completed bluetooth_init().
Also, we call the pthread_mutex_*() functions more frequently than
we really need to.
Move the mutex locking outside the loop and let condition wait
take care of the locking. Also move the A2DP_STATE_NONE check
below the condition wait so we can be sure the state machine
has been poked before we test it.
Change-Id: I020bea365a623e88cb1a5f7e5fccd8f8aa948518
diff --git a/audio/liba2dp.c b/audio/liba2dp.c
index 98fd8cd..222b188 100755
--- a/audio/liba2dp.c
+++ b/audio/liba2dp.c
@@ -884,12 +884,18 @@
pthread_cond_signal(&data->client_wait);
}
-static void set_command(struct bluetooth_data *data, a2dp_command_t command)
+static void __set_command(struct bluetooth_data *data, a2dp_command_t command)
{
VDBG("set_command %d\n", command);
- pthread_mutex_lock(&data->mutex);
data->command = command;
pthread_cond_signal(&data->thread_wait);
+ return;
+}
+
+static void set_command(struct bluetooth_data *data, a2dp_command_t command)
+{
+ pthread_mutex_lock(&data->mutex);
+ __set_command(data, command);
pthread_mutex_unlock(&data->mutex);
}
@@ -910,20 +916,26 @@
ts.tv_sec = tv.tv_sec + (timeout / 1000);
ts.tv_nsec = (tv.tv_usec + (timeout % 1000) * 1000L ) * 1000L;
+ pthread_mutex_lock(&data->mutex);
while (state != A2DP_STATE_STARTED && !err) {
if (state == A2DP_STATE_NONE)
set_command(data, A2DP_CMD_INIT);
else if (state == A2DP_STATE_INITIALIZED)
- set_command(data, A2DP_CMD_CONFIGURE);
- else if (state == A2DP_STATE_CONFIGURED)
- set_command(data, A2DP_CMD_START);
+ __set_command(data, A2DP_CMD_CONFIGURE);
+ else if (state == A2DP_STATE_CONFIGURED) {
+ __set_command(data, A2DP_CMD_START);
+ }
- pthread_mutex_lock(&data->mutex);
while ((err = pthread_cond_timedwait(&data->client_wait, &data->mutex, &ts))
== EINTR) ;
state = data->state;
- pthread_mutex_unlock(&data->mutex);
+
+ if (state == A2DP_STATE_NONE) {
+ err = ENODEV;
+ break;
+ }
}
+ pthread_mutex_unlock(&data->mutex);
#ifdef ENABLE_TIMING
end = get_microseconds();