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

Commit 45246605 authored by Sungtak Lee's avatar Sungtak Lee Committed by Wonsik Kim
Browse files

media.c2 aidl GraphicsTracker: Synchronize mDequeueable and pipe fds

Synchronize mDequeueable with the size of the internal pending buffer of
pipe fds.

Bug: 254050314
Change-Id: Ic2f3fc0464531b26ef9476869f3923cd35b31fee
parent e625b93c
Loading
Loading
Loading
Loading
+46 −87
Original line number Original line Diff line number Diff line
@@ -192,20 +192,15 @@ GraphicsTracker::GraphicsTracker(int maxDequeueCount)


    mReadPipeFd.reset(pipefd[0]);
    mReadPipeFd.reset(pipefd[0]);
    mWritePipeFd.reset(pipefd[1]);
    mWritePipeFd.reset(pipefd[1]);
    mIncDequeueable = 0;


    mEventQueueThread = std::thread([this](){processEvent();});
    // ctor does not require lock to be held.
    writeIncDequeueable(mDequeueable);
    writeIncDequeueableLocked(mDequeueable);


    CHECK(ret >= 0);
    CHECK(ret >= 0);
    CHECK(mEventQueueThread.joinable());
}
}


GraphicsTracker::~GraphicsTracker() {
GraphicsTracker::~GraphicsTracker() {
    stop();
    stop();
    if (mEventQueueThread.joinable()) {
        mEventQueueThread.join();
    }
}
}


bool GraphicsTracker::adjustDequeueConfLocked(bool *updateDequeue) {
bool GraphicsTracker::adjustDequeueConfLocked(bool *updateDequeue) {
@@ -238,6 +233,7 @@ bool GraphicsTracker::adjustDequeueConfLocked(bool *updateDequeue) {


c2_status_t GraphicsTracker::configureGraphics(
c2_status_t GraphicsTracker::configureGraphics(
        const sp<IGraphicBufferProducer>& igbp, uint32_t generation) {
        const sp<IGraphicBufferProducer>& igbp, uint32_t generation) {
    // TODO: wait until operations to previous IGBP is completed.
    std::shared_ptr<BufferCache> prevCache;
    std::shared_ptr<BufferCache> prevCache;
    int prevDequeueCommitted;
    int prevDequeueCommitted;


@@ -363,8 +359,7 @@ c2_status_t GraphicsTracker::configureMaxDequeueCount(int maxDequeueCount) {
            int delta = mMaxDequeueCommitted - oldMaxDequeue;
            int delta = mMaxDequeueCommitted - oldMaxDequeue;
            if (delta > 0) {
            if (delta > 0) {
                mDequeueable += delta;
                mDequeueable += delta;
                l.unlock();
                writeIncDequeueableLocked(delta);
                writeIncDequeueable(delta);
            }
            }
        }
        }
    }
    }
@@ -446,43 +441,42 @@ int GraphicsTracker::getCurDequeueable() {
}
}


void GraphicsTracker::stop() {
void GraphicsTracker::stop() {
    bool expected = false;
   // TODO: wait until all operation to current IGBP
    std::unique_lock<std::mutex> l(mEventLock);
   // being completed.
    bool updated = mStopped.compare_exchange_strong(expected, true);
    std::unique_lock<std::mutex> l(mLock);
    if (updated) {
    if (mStopped) {
        // TODO: synchronize close and other i/o.
        return;
    }
    mStopped = true;
    int writeFd = mWritePipeFd.release();
    int writeFd = mWritePipeFd.release();
    if (writeFd >= 0) {
        ::close(writeFd);
        ::close(writeFd);
        int readFd = mReadPipeFd.release();
        ::close(readFd);
        mEventCv.notify_one();
    }
    }
}
}


void GraphicsTracker::writeIncDequeueable(int inc) {
void GraphicsTracker::writeIncDequeueableLocked(int inc) {
    CHECK(inc > 0 && inc < kMaxDequeueMax);
    CHECK(inc > 0 && inc < kMaxDequeueMax);
    thread_local char buf[kMaxDequeueMax];
    thread_local char buf[kMaxDequeueMax];
    int diff = 0;
    if (mStopped) { // reading end closed;
    {
        std::unique_lock<std::mutex> l(mEventLock);
        if (mStopped) {
        return;
        return;
    }
    }
        CHECK(mWritePipeFd.get() >= 0);
    int writeFd = mWritePipeFd.get();
        int ret = ::write(mWritePipeFd.get(), buf, inc);
    if (writeFd < 0) {
        if (ret == inc) {
        // initialization fail and not valid though.
        return;
        return;
    }
    }
        diff = ret < 0 ? inc : inc - ret;
    int ret = ::write(writeFd, buf, inc);

    // Since this is non-blocking i/o, it never returns EINTR.
        // Partial write or EINTR. This will not happen in a real scenario.
    //
        mIncDequeueable += diff;
    // ::write() to pipe guarantee to succeed atomically if it writes less than
        if (mIncDequeueable > 0) {
    // the given PIPE_BUF. And the buffer size in pipe/fifo is at least 4K and our total
            l.unlock();
    // max pending buffer size is 64. So it never returns EAGAIN here either.
            mEventCv.notify_one();
    // See pipe(7) for further information.
            ALOGW("updating dequeueable to pipefd pending");
    //
        }
    // Other errors are serious errors and we cannot synchronize mDequeueable to
    }
    // length of pending buffer in pipe/fifo anymore. So better to abort here.
    // TODO: do not abort here. (b/318717399)
    CHECK(ret == inc);
}
}


void GraphicsTracker::drainDequeueableLocked(int dec) {
void GraphicsTracker::drainDequeueableLocked(int dec) {
@@ -491,43 +485,14 @@ void GraphicsTracker::drainDequeueableLocked(int dec) {
    if (mStopped) {
    if (mStopped) {
        return;
        return;
    }
    }
    CHECK(mReadPipeFd.get() >= 0);
    int readFd = mReadPipeFd.get();
    int ret = ::read(mReadPipeFd.get(), buf, dec);
    if (readFd < 0) {
    if (ret < 0 && errno == EINTR) {
        // initializationf fail and not valid though.
        // signal cancel try again.
        return;
        ret = ::read(mReadPipeFd.get(), buf, dec);
    }
    CHECK(mStopped || ret == dec);
    // TODO: remove CHECK
    // if ret < dec, drain the amount from EventThread.
}

void GraphicsTracker::processEvent() {
    // This is for partial/failed writes to the writing end.
    // This may not happen in the real scenario.
    thread_local char buf[kMaxDequeueMax];
    while (true) {
        std::unique_lock<std::mutex> l(mEventLock);
        if (mStopped) {
            break;
        }
        if (mIncDequeueable > 0) {
            int inc = mIncDequeueable > kMaxDequeueMax ? kMaxDequeueMax : mIncDequeueable;
            int ret = ::write(mWritePipeFd.get(), buf, inc);
            int written = ret <= 0 ? 0 : ret;
            mIncDequeueable -= written;
            if (mIncDequeueable > 0) {
                l.unlock();
                if (ret < 0) {
                    ALOGE("write to writing end failed %d", errno);
                } else {
                    ALOGW("partial write %d(%d)", inc, written);
                }
                continue;
            }
        }
        mEventCv.wait(l);
    }
    }
    int ret = ::read(readFd, buf, dec);
    // TODO: no dot abort here. (b/318717399)
    CHECK(ret == dec);
}
}


c2_status_t GraphicsTracker::getWaitableFd(int *pipeFd) {
c2_status_t GraphicsTracker::getWaitableFd(int *pipeFd) {
@@ -603,8 +568,7 @@ void GraphicsTracker::commitAllocate(c2_status_t res, const std::shared_ptr<Buff
            return;
            return;
        }
        }
        mDequeueable++;
        mDequeueable++;
        l.unlock();
        writeIncDequeueableLocked(1);
        writeIncDequeueable(1);
    }
    }
}
}


@@ -779,8 +743,7 @@ c2_status_t GraphicsTracker::requestDeallocate(uint64_t bid, const sp<Fence> &fe
            return C2_OK;
            return C2_OK;
        }
        }
        mDequeueable++;
        mDequeueable++;
        l.unlock();
        writeIncDequeueableLocked(1);
        writeIncDequeueable(1);
    }
    }
    return C2_OK;
    return C2_OK;
}
}
@@ -798,8 +761,7 @@ void GraphicsTracker::commitDeallocate(
        return;
        return;
    }
    }
    mDequeueable++;
    mDequeueable++;
    l.unlock();
    writeIncDequeueableLocked(1);
    writeIncDequeueable(1);
}
}




@@ -855,8 +817,7 @@ c2_status_t GraphicsTracker::requestRender(uint64_t bid, std::shared_ptr<BufferC
            return C2_BAD_STATE;
            return C2_BAD_STATE;
        }
        }
        mDequeueable++;
        mDequeueable++;
        l.unlock();
        writeIncDequeueableLocked(1);
        writeIncDequeueable(1);
        return C2_BAD_STATE;
        return C2_BAD_STATE;
    }
    }
    std::shared_ptr<BufferItem> buffer = it->second;
    std::shared_ptr<BufferItem> buffer = it->second;
@@ -898,8 +859,7 @@ void GraphicsTracker::commitRender(const std::shared_ptr<BufferCache> &cache,
            return;
            return;
        }
        }
        mDequeueable++;
        mDequeueable++;
        l.unlock();
        writeIncDequeueableLocked(1);
        writeIncDequeueable(1);
        return;
        return;
    }
    }
}
}
@@ -990,8 +950,7 @@ void GraphicsTracker::onReleased(uint32_t generation) {
        if (mBufferCache->mGeneration == generation) {
        if (mBufferCache->mGeneration == generation) {
            if (!adjustDequeueConfLocked(&updateDequeue)) {
            if (!adjustDequeueConfLocked(&updateDequeue)) {
                mDequeueable++;
                mDequeueable++;
                l.unlock();
                writeIncDequeueableLocked(1);
                writeIncDequeueable(1);
            }
            }
        }
        }
    }
    }
+1 −9
Original line number Original line Diff line number Diff line
@@ -274,13 +274,6 @@ private:
    ::android::base::unique_fd mWritePipeFd;  // The writing end file descriptor
    ::android::base::unique_fd mWritePipeFd;  // The writing end file descriptor


    std::atomic<bool> mStopped;
    std::atomic<bool> mStopped;
    std::thread mEventQueueThread; // Thread to handle interrupted
                                   // writes to the writing end.
    std::mutex mEventLock;
    std::condition_variable mEventCv;

    bool mStopEventThread;
    int mIncDequeueable; // pending # of write to increase dequeueable eventfd


private:
private:
    explicit GraphicsTracker(int maxDequeueCount);
    explicit GraphicsTracker(int maxDequeueCount);
@@ -326,9 +319,8 @@ private:
            bool *cached, int *rSlotId, sp<Fence> *rFence,
            bool *cached, int *rSlotId, sp<Fence> *rFence,
            std::shared_ptr<BufferItem> *buffer);
            std::shared_ptr<BufferItem> *buffer);


    void writeIncDequeueable(int inc);
    void writeIncDequeueableLocked(int inc);
    void drainDequeueableLocked(int dec);
    void drainDequeueableLocked(int dec);
    void processEvent();
};
};


} // namespace aidl::android::hardware::media::c2::implementation
} // namespace aidl::android::hardware::media::c2::implementation