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

Commit 2ea68a82 authored by Sungtak Lee's avatar Sungtak Lee Committed by Automerger Merge Worker
Browse files

Merge "C2BqBuffer: resolve 3 way deadlock" am: e8478652 am: e50a2706 am: a31f7f96

parents 906a73d6 a31f7f96
Loading
Loading
Loading
Loading
+3 −2
Original line number Original line Diff line number Diff line
@@ -72,12 +72,13 @@ struct C2SyncVariables {
    /**
    /**
     * Notify a buffer is queued. Return whether the upcoming dequeue operation
     * 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
     * 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 false    dequeue operation is blocked now.
     * \retval true     dequeue operation is possible.
     * \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.
     * Notify a buffer is dequeued.
+10 −12
Original line number Original line Diff line number Diff line
@@ -440,8 +440,8 @@ private:
            if (status == -ETIME) {
            if (status == -ETIME) {
                // fence is not signalled yet.
                // fence is not signalled yet.
                if (syncVar) {
                if (syncVar) {
                    syncVar->lock();
                    (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
                    (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
                    syncVar->lock();
                    dequeueable = syncVar->notifyQueuedLocked(&waitId);
                    dequeueable = syncVar->notifyQueuedLocked(&waitId);
                    syncVar->unlock();
                    syncVar->unlock();
                    if (c2Fence) {
                    if (c2Fence) {
@@ -456,8 +456,8 @@ private:
            if (status != android::NO_ERROR) {
            if (status != android::NO_ERROR) {
                ALOGD("buffer fence wait error %d", status);
                ALOGD("buffer fence wait error %d", status);
                if (syncVar) {
                if (syncVar) {
                    syncVar->lock();
                    (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
                    (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
                    syncVar->lock();
                    syncVar->notifyQueuedLocked();
                    syncVar->notifyQueuedLocked();
                    syncVar->unlock();
                    syncVar->unlock();
                    if (c2Fence) {
                    if (c2Fence) {
@@ -506,8 +506,8 @@ private:
            } else if (status != android::NO_ERROR) {
            } else if (status != android::NO_ERROR) {
                slotBuffer.clear();
                slotBuffer.clear();
                if (syncVar) {
                if (syncVar) {
                    syncVar->lock();
                    (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
                    (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
                    syncVar->lock();
                    syncVar->notifyQueuedLocked();
                    syncVar->notifyQueuedLocked();
                    syncVar->unlock();
                    syncVar->unlock();
                    if (c2Fence) {
                    if (c2Fence) {
@@ -554,8 +554,8 @@ private:
            // Block was not created. call requestBuffer# again next time.
            // Block was not created. call requestBuffer# again next time.
            slotBuffer.clear();
            slotBuffer.clear();
            if (syncVar) {
            if (syncVar) {
                syncVar->lock();
                (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
                (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
                syncVar->lock();
                syncVar->notifyQueuedLocked();
                syncVar->notifyQueuedLocked();
                syncVar->unlock();
                syncVar->unlock();
                if (c2Fence) {
                if (c2Fence) {
@@ -817,11 +817,10 @@ C2BufferQueueBlockPoolData::~C2BufferQueueBlockPoolData() {
        if (mGeneration == mCurrentGeneration && mBqId == mCurrentBqId && !mOwner.expired()) {
        if (mGeneration == mCurrentGeneration && mBqId == mCurrentBqId && !mOwner.expired()) {
            C2SyncVariables *syncVar = mSyncMem ? mSyncMem->mem() : nullptr;
            C2SyncVariables *syncVar = mSyncMem ? mSyncMem->mem() : nullptr;
            if (syncVar) {
            if (syncVar) {
                syncVar->lock();
                if (syncVar->getSyncStatusLocked() == C2SyncVariables::STATUS_ACTIVE) {
                mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
                mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
                    syncVar->notifyQueuedLocked();
                syncVar->lock();
                }
                syncVar->notifyQueuedLocked(nullptr,
                        syncVar->getSyncStatusLocked() == C2SyncVariables::STATUS_ACTIVE);
                syncVar->unlock();
                syncVar->unlock();
            } else {
            } else {
                mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
                mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
@@ -830,11 +829,10 @@ C2BufferQueueBlockPoolData::~C2BufferQueueBlockPoolData() {
    } else if (!mOwner.expired()) {
    } else if (!mOwner.expired()) {
        C2SyncVariables *syncVar = mSyncMem ? mSyncMem->mem() : nullptr;
        C2SyncVariables *syncVar = mSyncMem ? mSyncMem->mem() : nullptr;
        if (syncVar) {
        if (syncVar) {
            syncVar->lock();
            if (syncVar->getSyncStatusLocked() != C2SyncVariables::STATUS_SWITCHING) {
            mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
            mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
                syncVar->notifyQueuedLocked();
            syncVar->lock();
            }
            syncVar->notifyQueuedLocked(nullptr,
                    syncVar->getSyncStatusLocked() != C2SyncVariables::STATUS_SWITCHING);
            syncVar->unlock();
            syncVar->unlock();
        } else {
        } else {
            mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
            mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
+4 −2
Original line number Original line Diff line number Diff line
@@ -177,12 +177,14 @@ bool C2SyncVariables::isDequeueableLocked(uint32_t *waitId) {
    return true;
    return true;
}
}


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