merge in jb-mr1.1-release history after reset to jb-mr1.1-dev
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index 72acd7d..fb43410 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -90,6 +90,105 @@
ALOGD("%s", s.string());
}
+class BufferLiberatorThread : public Thread {
+public:
+
+ static void queueCaptiveBuffer(buffer_handle_t handle) {
+ size_t queueSize;
+ {
+ Mutex::Autolock lock(sMutex);
+ if (sThread == NULL) {
+ sThread = new BufferLiberatorThread;
+ sThread->run("BufferLiberator");
+ }
+
+ sThread->mQueue.push_back(handle);
+ sThread->mQueuedCondition.signal();
+ queueSize = sThread->mQueue.size();
+ }
+ }
+
+ static void waitForLiberation() {
+ Mutex::Autolock lock(sMutex);
+
+ waitForLiberationLocked();
+ }
+
+ static void maybeWaitForLiberation() {
+ Mutex::Autolock lock(sMutex);
+ if (sThread != NULL) {
+ if (sThread->mQueue.size() > 8) {
+ waitForLiberationLocked();
+ }
+ }
+ }
+
+private:
+
+ BufferLiberatorThread() {}
+
+ virtual bool threadLoop() {
+ buffer_handle_t handle;
+ { // Scope for mutex
+ Mutex::Autolock lock(sMutex);
+ while (mQueue.isEmpty()) {
+ mQueuedCondition.wait(sMutex);
+ }
+ handle = mQueue[0];
+ }
+
+ status_t err;
+ GraphicBufferAllocator& gba(GraphicBufferAllocator::get());
+ { // Scope for tracing
+ ATRACE_NAME("gralloc::free");
+ err = gba.mAllocDev->free(gba.mAllocDev, handle);
+ }
+ ALOGW_IF(err, "free(...) failed %d (%s)", err, strerror(-err));
+
+ if (err == NO_ERROR) {
+ Mutex::Autolock _l(GraphicBufferAllocator::sLock);
+ KeyedVector<buffer_handle_t, GraphicBufferAllocator::alloc_rec_t>&
+ list(GraphicBufferAllocator::sAllocList);
+ list.removeItem(handle);
+ }
+
+ { // Scope for mutex
+ Mutex::Autolock lock(sMutex);
+ mQueue.removeAt(0);
+ mFreedCondition.broadcast();
+ }
+
+ return true;
+ }
+
+ static void waitForLiberationLocked() {
+ if (sThread == NULL) {
+ return;
+ }
+
+ const nsecs_t timeout = 500 * 1000 * 1000;
+ nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+ nsecs_t timeToStop = now + timeout;
+ while (!sThread->mQueue.isEmpty() && now < timeToStop) {
+ sThread->mFreedCondition.waitRelative(sMutex, timeToStop - now);
+ now = systemTime(SYSTEM_TIME_MONOTONIC);
+ }
+
+ if (!sThread->mQueue.isEmpty()) {
+ ALOGW("waitForLiberationLocked timed out");
+ }
+ }
+
+ static Mutex sMutex;
+ static sp<BufferLiberatorThread> sThread;
+ Vector<buffer_handle_t> mQueue;
+ Condition mQueuedCondition;
+ Condition mFreedCondition;
+};
+
+Mutex BufferLiberatorThread::sMutex;
+sp<BufferLiberatorThread> BufferLiberatorThread::sThread;
+
status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format,
int usage, buffer_handle_t* handle, int32_t* stride)
{
@@ -100,13 +199,24 @@
w = h = 1;
// we have a h/w allocator and h/w buffer is requested
- status_t err;
-
+ status_t err;
+
+ // If too many async frees are queued up then wait for some of them to
+ // complete before attempting to allocate more memory. This is exercised
+ // by the android.opengl.cts.GLSurfaceViewTest CTS test.
+ BufferLiberatorThread::maybeWaitForLiberation();
+
err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride);
+ if (err != NO_ERROR) {
+ ALOGW("WOW! gralloc alloc failed, waiting for pending frees!");
+ BufferLiberatorThread::waitForLiberation();
+ err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride);
+ }
+
ALOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)",
w, h, format, usage, err, strerror(-err));
-
+
if (err == NO_ERROR) {
Mutex::Autolock _l(sLock);
KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
@@ -129,60 +239,6 @@
return err;
}
-class BufferLiberatorThread : public Thread {
-public:
-
- static void queueCaptiveBuffer(buffer_handle_t handle) {
- static sp<BufferLiberatorThread> thread(new BufferLiberatorThread);
- static bool running = false;
- if (!running) {
- thread->run("BufferLiberator");
- running = true;
- }
- {
- Mutex::Autolock lock(thread->mMutex);
- thread->mQueue.push_back(handle);
- thread->mCondition.signal();
- }
- }
-
-private:
-
- BufferLiberatorThread() {}
-
- virtual bool threadLoop() {
- buffer_handle_t handle;
- {
- Mutex::Autolock lock(mMutex);
- while (mQueue.isEmpty()) {
- mCondition.wait(mMutex);
- }
- handle = mQueue[0];
- mQueue.removeAt(0);
- }
-
- status_t err;
- GraphicBufferAllocator& gba(GraphicBufferAllocator::get());
- { // Scope for tracing
- ATRACE_NAME("gralloc::free");
- err = gba.mAllocDev->free(gba.mAllocDev, handle);
- }
- ALOGW_IF(err, "free(...) failed %d (%s)", err, strerror(-err));
-
- if (err == NO_ERROR) {
- Mutex::Autolock _l(GraphicBufferAllocator::sLock);
- KeyedVector<buffer_handle_t, GraphicBufferAllocator::alloc_rec_t>&
- list(GraphicBufferAllocator::sAllocList);
- list.removeItem(handle);
- }
-
- return true;
- }
-
- Vector<buffer_handle_t> mQueue;
- Condition mCondition;
- Mutex mMutex;
-};
status_t GraphicBufferAllocator::free(buffer_handle_t handle)
{