SurfaceFlinger: add stack guards around SurfaceFlinger::postComposition
This is a debug patch for b/119477596 to try to catch a stack
corruption.
Test: Monkey
Change-Id: I270ace2660de7bab4a58deb2088275c2acc81be4
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index dc82b32..5cac524 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -52,6 +52,7 @@
#include <ui/GraphicBufferAllocator.h>
#include <ui/PixelFormat.h>
#include <ui/UiConfig.h>
+#include <utils/CallStack.h>
#include <utils/StopWatch.h>
#include <utils/String16.h>
#include <utils/String8.h>
@@ -1876,22 +1877,78 @@
getBE().mCompositorTiming.presentLatency = snappedCompositeToPresentLatency;
}
+// debug patch for b/119477596 - add stack guards to catch stack
+// corruptions and disable clang optimizations.
+// The code below is temporary and planned to be removed once stack
+// corruptions are found.
+#pragma clang optimize off
+class StackGuard {
+public:
+ StackGuard(const char* name, const char* func, int line) {
+ guarders.reserve(MIN_CAPACITY);
+ guarders.push_back({this, name, func, line});
+ validate();
+ }
+ ~StackGuard() {
+ for (auto i = guarders.end() - 1; i >= guarders.begin(); --i) {
+ if (i->guard == this) {
+ guarders.erase(i);
+ break;
+ }
+ }
+ }
+
+ static void validate() {
+ for (const auto& guard : guarders) {
+ if (guard.guard->cookie != COOKIE_VALUE) {
+ ALOGE("%s:%d: Stack corruption detected at %s", guard.func, guard.line, guard.name);
+ CallStack stack(LOG_TAG);
+ abort();
+ }
+ }
+ }
+
+private:
+ uint64_t cookie = COOKIE_VALUE;
+ static constexpr uint64_t COOKIE_VALUE = 0xc0febebedeadbeef;
+ static constexpr size_t MIN_CAPACITY = 16;
+
+ struct GuarderElement {
+ StackGuard* guard;
+ const char* name;
+ const char* func;
+ int line;
+ };
+
+ static std::vector<GuarderElement> guarders;
+};
+std::vector<StackGuard::GuarderElement> StackGuard::guarders;
+
+#define DEFINE_STACK_GUARD(__n) StackGuard __n##StackGuard(#__n, __FUNCTION__, __LINE__);
+
+#define ASSERT_ON_STACK_GUARD() StackGuard::validate();
void SurfaceFlinger::postComposition()
{
+ DEFINE_STACK_GUARD(begin);
ATRACE_CALL();
ALOGV("postComposition");
// Release any buffers which were replaced this frame
nsecs_t dequeueReadyTime = systemTime();
+ DEFINE_STACK_GUARD(dequeueReadyTime);
for (auto& layer : mLayersWithQueuedFrames) {
layer->releasePendingBuffer(dequeueReadyTime);
}
+ ASSERT_ON_STACK_GUARD();
// |mStateLock| not needed as we are on the main thread
const auto display = getDefaultDisplayDeviceLocked();
+ DEFINE_STACK_GUARD(display);
getBE().mGlCompositionDoneTimeline.updateSignalTimes();
std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
+ DEFINE_STACK_GUARD(glCompositionDoneFenceTime);
+
if (display && getHwComposer().hasClientComposition(display->getId())) {
glCompositionDoneFenceTime =
std::make_shared<FenceTime>(display->getClientTargetAcquireFence());
@@ -1900,13 +1957,17 @@
glCompositionDoneFenceTime = FenceTime::NO_FENCE;
}
+ ASSERT_ON_STACK_GUARD();
+
getBE().mDisplayTimeline.updateSignalTimes();
mPreviousPresentFence =
display ? getHwComposer().getPresentFence(*display->getId()) : Fence::NO_FENCE;
auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFence);
+ DEFINE_STACK_GUARD(presentFenceTime);
getBE().mDisplayTimeline.push(presentFenceTime);
DisplayStatInfo stats;
+ DEFINE_STACK_GUARD(stats);
if (mUseScheduler) {
mScheduler->getDisplayStatInfo(&stats);
} else {
@@ -1914,34 +1975,46 @@
stats.vsyncPeriod = mPrimaryDispSync->getPeriod();
}
+ ASSERT_ON_STACK_GUARD();
+
// We use the mRefreshStartTime which might be sampled a little later than
// when we started doing work for this frame, but that should be okay
// since updateCompositorTiming has snapping logic.
updateCompositorTiming(stats, mRefreshStartTime, presentFenceTime);
CompositorTiming compositorTiming;
+ DEFINE_STACK_GUARD(compositorTiming);
+
{
std::lock_guard<std::mutex> lock(getBE().mCompositorTimingLock);
+ DEFINE_STACK_GUARD(lock);
compositorTiming = getBE().mCompositorTiming;
+
+ ASSERT_ON_STACK_GUARD();
}
mDrawingState.traverseInZOrder([&](Layer* layer) {
bool frameLatched = layer->onPostComposition(display->getId(), glCompositionDoneFenceTime,
presentFenceTime, compositorTiming);
+ DEFINE_STACK_GUARD(frameLatched);
if (frameLatched) {
recordBufferingStats(layer->getName().string(),
layer->getOccupancyHistory(false));
}
+ ASSERT_ON_STACK_GUARD();
});
if (presentFenceTime->isValid()) {
+ ASSERT_ON_STACK_GUARD();
if (mUseScheduler) {
mScheduler->addPresentFence(presentFenceTime);
+ ASSERT_ON_STACK_GUARD();
} else {
if (mPrimaryDispSync->addPresentFence(presentFenceTime)) {
enableHardwareVsync();
} else {
disableHardwareVsync(false);
}
+ ASSERT_ON_STACK_GUARD();
}
}
@@ -1955,61 +2028,86 @@
}
}
+ ASSERT_ON_STACK_GUARD();
+
if (mAnimCompositionPending) {
mAnimCompositionPending = false;
if (presentFenceTime->isValid()) {
mAnimFrameTracker.setActualPresentFence(
std::move(presentFenceTime));
+
+ ASSERT_ON_STACK_GUARD();
} else if (display && getHwComposer().isConnected(*display->getId())) {
// The HWC doesn't support present fences, so use the refresh
// timestamp instead.
const nsecs_t presentTime = getHwComposer().getRefreshTimestamp(*display->getId());
+ DEFINE_STACK_GUARD(presentTime);
+
mAnimFrameTracker.setActualPresentTime(presentTime);
+ ASSERT_ON_STACK_GUARD();
}
mAnimFrameTracker.advanceFrame();
}
+ ASSERT_ON_STACK_GUARD();
+
mTimeStats->incrementTotalFrames();
if (mHadClientComposition) {
mTimeStats->incrementClientCompositionFrames();
}
+ ASSERT_ON_STACK_GUARD();
+
mTimeStats->setPresentFenceGlobal(presentFenceTime);
+ ASSERT_ON_STACK_GUARD();
+
if (display && getHwComposer().isConnected(*display->getId()) && !display->isPoweredOn()) {
return;
}
nsecs_t currentTime = systemTime();
+ DEFINE_STACK_GUARD(currentTime);
if (mHasPoweredOff) {
mHasPoweredOff = false;
} else {
nsecs_t elapsedTime = currentTime - getBE().mLastSwapTime;
+ DEFINE_STACK_GUARD(elapsedTime);
size_t numPeriods = static_cast<size_t>(elapsedTime / stats.vsyncPeriod);
+ DEFINE_STACK_GUARD(numPeriods);
if (numPeriods < SurfaceFlingerBE::NUM_BUCKETS - 1) {
getBE().mFrameBuckets[numPeriods] += elapsedTime;
} else {
getBE().mFrameBuckets[SurfaceFlingerBE::NUM_BUCKETS - 1] += elapsedTime;
}
getBE().mTotalTime += elapsedTime;
+
+ ASSERT_ON_STACK_GUARD();
}
getBE().mLastSwapTime = currentTime;
+ ASSERT_ON_STACK_GUARD();
{
std::lock_guard lock(mTexturePoolMutex);
+ DEFINE_STACK_GUARD(lock);
const size_t refillCount = mTexturePoolSize - mTexturePool.size();
+ DEFINE_STACK_GUARD(refillCount);
if (refillCount > 0) {
const size_t offset = mTexturePool.size();
mTexturePool.resize(mTexturePoolSize);
getRenderEngine().genTextures(refillCount, mTexturePool.data() + offset);
ATRACE_INT("TexturePoolSize", mTexturePool.size());
}
+ ASSERT_ON_STACK_GUARD();
}
mTransactionCompletedThread.addPresentFence(mPreviousPresentFence);
mTransactionCompletedThread.sendCallbacks();
+
+ ASSERT_ON_STACK_GUARD();
}
+#pragma clang optimize on // b/119477596
void SurfaceFlinger::rebuildLayerStacks() {
ATRACE_CALL();