diff options
| author | 2013-07-25 02:17:52 +0000 | |
|---|---|---|
| committer | 2013-07-25 02:17:52 +0000 | |
| commit | 9642dba11046bf4ae6fe9db285e07ef9075da64e (patch) | |
| tree | 148028e2d6b680317d483ff1dcf3a7bc0657069f | |
| parent | 87bf0d97be5ef2689546b246dfb6c21c4eec3ce0 (diff) | |
| parent | 6bac363cbdca7f5c4135d66c0e379475ecbd7319 (diff) | |
Merge "Fix a race in BufferQueue"
| -rw-r--r-- | libs/gui/BufferQueue.cpp | 44 |
1 files changed, 27 insertions, 17 deletions
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp index ad2f1bb618..95ba09528a 100644 --- a/libs/gui/BufferQueue.cpp +++ b/libs/gui/BufferQueue.cpp @@ -268,7 +268,6 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence, bool async usage |= mConsumerUsageBits; int found = -1; - int dequeuedCount = 0; bool tryAgain = true; while (tryAgain) { if (mAbandoned) { @@ -299,23 +298,28 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence, bool async // look for a free buffer to give to the client found = INVALID_BUFFER_SLOT; - dequeuedCount = 0; + int dequeuedCount = 0; + int acquiredCount = 0; for (int i = 0; i < maxBufferCount; i++) { const int state = mSlots[i].mBufferState; - if (state == BufferSlot::DEQUEUED) { - dequeuedCount++; - } - - if (state == BufferSlot::FREE) { - /* We return the oldest of the free buffers to avoid - * stalling the producer if possible. This is because - * the consumer may still have pending reads of the - * buffers in flight. - */ - if ((found < 0) || - mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) { - found = i; - } + switch (state) { + case BufferSlot::DEQUEUED: + dequeuedCount++; + break; + case BufferSlot::ACQUIRED: + acquiredCount++; + break; + case BufferSlot::FREE: + /* We return the oldest of the free buffers to avoid + * stalling the producer if possible. This is because + * the consumer may still have pending reads of the + * buffers in flight. + */ + if ((found < 0) || + mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) { + found = i; + } + break; } } @@ -348,7 +352,13 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence, bool async // the max buffer count to change. tryAgain = found == INVALID_BUFFER_SLOT; if (tryAgain) { - if (mDequeueBufferCannotBlock) { + // return an error if we're in "cannot block" mode (producer and consumer + // are controlled by the application) -- however, the consumer is allowed + // to acquire briefly an extra buffer (which could cause us to have to wait here) + // and that's okay because we know the wait will be brief (it happens + // if we dequeue a buffer while the consumer has acquired one but not released + // the old one yet -- for e.g.: see GLConsumer::updateTexImage()). + if (mDequeueBufferCannotBlock && (acquiredCount <= mMaxAcquiredBufferCount)) { ST_LOGE("dequeueBuffer: would block! returning an error instead."); return WOULD_BLOCK; } |