Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 14c198b4 authored by Gautam Manam's avatar Gautam Manam
Browse files

hal: deadlock with pause and SSR for compressed offload

For compress offload playback, during SSR offline
callback will hold out and latch lock and set
offload state to idle and wait on compress
offload thread state to be marked as unblocked.

In the mean time pause is triggered and it acquires
out lock and waits for out_latch lock.

And in another thread compress_wait completes and
wait for out lock causing dead lock.

Fix this by moving latch lock to protect only
offload_state, so that latch lock can be released.

Change-Id: Iec42eaf6c18477b4f87bb5bafe54fb346c7af73b
parent eefc99fd
Loading
Loading
Loading
Loading
+5 −10
Original line number Diff line number Diff line
@@ -3402,10 +3402,12 @@ static int send_offload_cmd_l(struct stream_out* out, int command)
    return 0;
}

/* must be called with out->lock and latch lock */
/* must be called with out->lock */
static void stop_compressed_output_l(struct stream_out *out)
{
    pthread_mutex_lock(&out->latch_lock);
    out->offload_state = OFFLOAD_STATE_IDLE;
    pthread_mutex_unlock(&out->latch_lock);
    out->playback_started = 0;
    out->send_new_metadata = 1;
    if (out->compr != NULL) {
@@ -3663,11 +3665,9 @@ static int create_offload_callback_thread(struct stream_out *out)
static int destroy_offload_callback_thread(struct stream_out *out)
{
    lock_output_stream(out);
    pthread_mutex_lock(&out->latch_lock);
    stop_compressed_output_l(out);
    send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);

    pthread_mutex_unlock(&out->latch_lock);
    pthread_mutex_unlock(&out->lock);
    pthread_join(out->offload_thread, (void **) NULL);
    pthread_cond_destroy(&out->offload_cond);
@@ -4565,9 +4565,7 @@ static int out_standby(struct audio_stream *stream)
            adev->adm_deregister_stream(adev->adm_data, out->handle);

        if (is_offload_usecase(out->usecase)) {
            pthread_mutex_lock(&out->latch_lock);
            stop_compressed_output_l(out);
            pthread_mutex_unlock(&out->latch_lock);
        }

        pthread_mutex_lock(&adev->lock);
@@ -4642,9 +4640,7 @@ static int out_on_error(struct audio_stream *stream)
    // is needed e.g. when SSR happens within compress_open
    // since the stream is active, offload_callback_thread is also active.
    if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
        pthread_mutex_lock(&out->latch_lock);
        stop_compressed_output_l(out);
        pthread_mutex_unlock(&out->latch_lock);
    }
    pthread_mutex_unlock(&out->lock);

@@ -4683,9 +4679,7 @@ int out_standby_l(struct audio_stream *stream)
            adev->adm_deregister_stream(adev->adm_data, out->handle);

        if (is_offload_usecase(out->usecase)) {
            pthread_mutex_lock(&out->latch_lock);
            stop_compressed_output_l(out);
            pthread_mutex_unlock(&out->latch_lock);
        }

        out->standby = true;
@@ -6529,12 +6523,13 @@ static int out_flush(struct audio_stream_out* stream)
        lock_output_stream(out);
        pthread_mutex_lock(&out->latch_lock);
        if (out->offload_state == OFFLOAD_STATE_PAUSED) {
            pthread_mutex_unlock(&out->latch_lock);
            stop_compressed_output_l(out);
        } else {
            ALOGW("%s called in invalid state %d", __func__, out->offload_state);
            pthread_mutex_unlock(&out->latch_lock);
        }
        out->written = 0;
        pthread_mutex_unlock(&out->latch_lock);
        pthread_mutex_unlock(&out->lock);
        ALOGD("copl(%p):out of compress flush", out);
        return 0;