systrace: monitor GPU completion fence and HWC release fence
Bug: 127781085
Test: build, flash, boot and take systrace with gfx category
Change-Id: I7a1e28a7498bcdfd1b4286fffbe6d58bddddf049
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 3affa23..af6373d 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -20,6 +20,11 @@
#include <gui/Surface.h>
+#include <condition_variable>
+#include <deque>
+#include <mutex>
+#include <thread>
+
#include <inttypes.h>
#include <android/native_window.h>
@@ -450,6 +455,74 @@
return NO_ERROR;
}
+class FenceMonitor {
+public:
+ explicit FenceMonitor(const char* name) : mName(name), mFencesQueued(0), mFencesSignaled(0) {
+ std::thread thread(&FenceMonitor::loop, this);
+ pthread_setname_np(thread.native_handle(), mName);
+ thread.detach();
+ }
+
+ void queueFence(const sp<Fence>& fence) {
+ char message[64];
+
+ std::lock_guard<std::mutex> lock(mMutex);
+ snprintf(message, sizeof(message), "Trace fence %u", mFencesQueued);
+ ATRACE_NAME(message);
+
+ mQueue.push_back(fence);
+ mCondition.notify_one();
+ mFencesQueued++;
+ ATRACE_INT(mName, int32_t(mQueue.size()));
+ }
+
+private:
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmissing-noreturn"
+ void loop() {
+ while (true) {
+ threadLoop();
+ }
+ }
+#pragma clang diagnostic pop
+
+ void threadLoop() {
+ sp<Fence> fence;
+ uint32_t fenceNum;
+ {
+ std::unique_lock<std::mutex> lock(mMutex);
+ while (mQueue.empty()) {
+ mCondition.wait(lock);
+ }
+ fence = mQueue[0];
+ fenceNum = mFencesSignaled;
+ }
+ {
+ char message[64];
+ snprintf(message, sizeof(message), "waiting for %s %u", mName, fenceNum);
+ ATRACE_NAME(message);
+
+ status_t result = fence->waitForever(message);
+ if (result != OK) {
+ ALOGE("Error waiting for fence: %d", result);
+ }
+ }
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mQueue.pop_front();
+ mFencesSignaled++;
+ ATRACE_INT(mName, int32_t(mQueue.size()));
+ }
+ }
+
+ const char* mName;
+ uint32_t mFencesQueued;
+ uint32_t mFencesSignaled;
+ std::deque<sp<Fence>> mQueue;
+ std::condition_variable mCondition;
+ std::mutex mMutex;
+};
+
int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
ATRACE_CALL();
ALOGV("Surface::dequeueBuffer");
@@ -519,6 +592,11 @@
// this should never happen
ALOGE_IF(fence == nullptr, "Surface::dequeueBuffer: received null Fence! buf=%d", buf);
+ if (CC_UNLIKELY(atrace_is_tag_enabled(ATRACE_TAG_GRAPHICS))) {
+ static FenceMonitor hwcReleaseThread("HWC release");
+ hwcReleaseThread.queueFence(fence);
+ }
+
if (result & IGraphicBufferProducer::RELEASE_ALL_BUFFERS) {
freeAllBuffers();
}
@@ -761,6 +839,11 @@
mQueueBufferCondition.broadcast();
+ if (CC_UNLIKELY(atrace_is_tag_enabled(ATRACE_TAG_GRAPHICS))) {
+ static FenceMonitor gpuCompletionThread("GPU completion");
+ gpuCompletionThread.queueFence(fence);
+ }
+
return err;
}