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

Commit e8478652 authored by Sungtak Lee's avatar Sungtak Lee Committed by Gerrit Code Review
Browse files

Merge "C2BqBuffer: resolve 3 way deadlock"

parents 08e431aa d36be3a0
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -72,12 +72,13 @@ struct C2SyncVariables {
    /**
     * Notify a buffer is queued. Return whether the upcoming dequeue operation
     * is not blocked. if it's blocked and waitId is non-null, waitId is returned
     * to be used for waiting.
     * to be used for waiting. Notify(wake-up) waitors only when 'notify' is
     * true.
     *
     * \retval false    dequeue operation is blocked now.
     * \retval true     dequeue operation is possible.
     */
    bool notifyQueuedLocked(uint32_t *waitId = nullptr);
    bool notifyQueuedLocked(uint32_t *waitId = nullptr, bool notify = true);

    /**
     * Notify a buffer is dequeued.
+10 −12
Original line number Diff line number Diff line
@@ -436,8 +436,8 @@ private:
            if (status == -ETIME) {
                // fence is not signalled yet.
                if (syncVar) {
                    syncVar->lock();
                    (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
                    syncVar->lock();
                    dequeueable = syncVar->notifyQueuedLocked(&waitId);
                    syncVar->unlock();
                    if (c2Fence) {
@@ -452,8 +452,8 @@ private:
            if (status != android::NO_ERROR) {
                ALOGD("buffer fence wait error %d", status);
                if (syncVar) {
                    syncVar->lock();
                    (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
                    syncVar->lock();
                    syncVar->notifyQueuedLocked();
                    syncVar->unlock();
                    if (c2Fence) {
@@ -502,8 +502,8 @@ private:
            } else if (status != android::NO_ERROR) {
                slotBuffer.clear();
                if (syncVar) {
                    syncVar->lock();
                    (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
                    syncVar->lock();
                    syncVar->notifyQueuedLocked();
                    syncVar->unlock();
                    if (c2Fence) {
@@ -550,8 +550,8 @@ private:
            // Block was not created. call requestBuffer# again next time.
            slotBuffer.clear();
            if (syncVar) {
                syncVar->lock();
                (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
                syncVar->lock();
                syncVar->notifyQueuedLocked();
                syncVar->unlock();
                if (c2Fence) {
@@ -813,11 +813,10 @@ C2BufferQueueBlockPoolData::~C2BufferQueueBlockPoolData() {
        if (mGeneration == mCurrentGeneration && mBqId == mCurrentBqId && !mOwner.expired()) {
            C2SyncVariables *syncVar = mSyncMem ? mSyncMem->mem() : nullptr;
            if (syncVar) {
                syncVar->lock();
                if (syncVar->getSyncStatusLocked() == C2SyncVariables::STATUS_ACTIVE) {
                mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
                    syncVar->notifyQueuedLocked();
                }
                syncVar->lock();
                syncVar->notifyQueuedLocked(nullptr,
                        syncVar->getSyncStatusLocked() == C2SyncVariables::STATUS_ACTIVE);
                syncVar->unlock();
            } else {
                mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
@@ -826,11 +825,10 @@ C2BufferQueueBlockPoolData::~C2BufferQueueBlockPoolData() {
    } else if (!mOwner.expired()) {
        C2SyncVariables *syncVar = mSyncMem ? mSyncMem->mem() : nullptr;
        if (syncVar) {
            syncVar->lock();
            if (syncVar->getSyncStatusLocked() != C2SyncVariables::STATUS_SWITCHING) {
            mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
                syncVar->notifyQueuedLocked();
            }
            syncVar->lock();
            syncVar->notifyQueuedLocked(nullptr,
                    syncVar->getSyncStatusLocked() != C2SyncVariables::STATUS_SWITCHING);
            syncVar->unlock();
        } else {
            mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
+4 −2
Original line number Diff line number Diff line
@@ -177,12 +177,14 @@ bool C2SyncVariables::isDequeueableLocked(uint32_t *waitId) {
    return true;
}

bool C2SyncVariables::notifyQueuedLocked(uint32_t *waitId) {
bool C2SyncVariables::notifyQueuedLocked(uint32_t *waitId, bool notify) {
    // Note. thundering herds may occur. Edge trigged signalling.
    // But one waiter will guarantee to dequeue. others may wait again.
    // Minimize futex syscall(trap) for the main use case(one waiter case).
    if (mMaxDequeueCount == mCurDequeueCount--) {
        if (notify) {
            broadcast();
        }
        return true;
    }