/* timeout is in milliseconds */ static int wait_for_start(struct bluetooth_data *data, int timeout) { a2dp_state_t state = data->state; struct timeval tv; struct timespec ts; int err = 0; #ifdef ENABLE_TIMING uint64_t begin, end; begin = get_microseconds(); #endif gettimeofday(&tv, (struct timezone *) NULL); 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) { 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); } again: err = pthread_cond_timedwait(&data->client_wait, &data->mutex, &ts); if (err) { /* don't timeout if we're done */ if (data->state == A2DP_STATE_STARTED) { err = 0; break; } if (err == ETIMEDOUT) break; goto again; } if (state == data->state) goto again; state = data->state; if (state == A2DP_STATE_NONE) { err = ENODEV; break; } } pthread_mutex_unlock(&data->mutex); #ifdef ENABLE_TIMING end = get_microseconds(); print_time("wait_for_start", begin, end); #endif /* pthread_cond_timedwait returns positive errors */ return -err; }
/** * This version of cleanup does not require holding data->mutex. * This will have the effect of queing the A2DP_CMD_QUIT command * instead of blocking if another thread is holding the mutex (for * instance a2dp_write()). When the initial thread releases the mutex, * a2dp_thread() will execute; cleaning up and exiting the thread. */ void a2dp_cleanup_nolock(a2dpData d) { struct bluetooth_data* data = (struct bluetooth_data*)d; DBG("a2dp_cleanup_nolock\n"); pthread_mutex_lock(&data->mutex2); __set_command(data, A2DP_CMD_QUIT); pthread_mutex_unlock(&data->mutex2); }
static void set_command(struct bluetooth_data *data, a2dp_command_t command) { pthread_mutex_lock(&data->mutex); pthread_mutex_lock(&data->mutex2); __set_command(data, command); pthread_mutex_unlock(&data->mutex2); pthread_mutex_unlock(&data->mutex); }
static void a2dp_sig_thread(void *d) { struct bluetooth_data *data = d; a2dp_state_t state = data->state; int err = 0; struct timeval tv; struct timespec ts; #ifdef ENABLE_TIMING uint64_t begin, end; begin = get_microseconds(); #endif gettimeofday(&tv, (struct timezone *) NULL); ts.tv_sec = tv.tv_sec + (WRITE_TIMEOUT / 1000); ts.tv_nsec = (tv.tv_usec + (WRITE_TIMEOUT % 1000) * 1000L ) * 1000L; pthread_mutex_lock(&data->mutex); while (state != A2DP_STATE_STARTED) { 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); } again: err = pthread_cond_timedwait(&data->client_wait, &data->mutex, &ts); if (err) { /* don't timeout if we're done */ if (data->state == A2DP_STATE_STARTED) { err = 0; break; } if (err == ETIMEDOUT) { DBG(" Time out"); break; } goto again; } if (state == data->state) goto again; state = data->state; if (state == A2DP_STATE_NONE) { err = ENODEV; break; } } pthread_mutex_unlock(&data->mutex); #ifdef ENABLE_TIMING end = get_microseconds(); print_time("signalling process took", begin, end); #endif data->signalling_thread = 0; DBG("error returned is %d", err); /* pthread_cond_timedwait returns positive errors */ return; }