diff options
author | Wiwit Rifa'i <wiwitrifai@google.com> | 2022-04-20 14:37:15 +0800 |
---|---|---|
committer | Wiwit Rifa'i <wiwitrifai@google.com> | 2022-04-22 16:19:56 +0800 |
commit | 9fc11892fd11b094bc757c4029183a3f29034e14 (patch) | |
tree | 40e2f078ac31fc626665ad588a1faf81b66f9c24 | |
parent | ef71aecbee6ab58447d4d111018263dff3d5672c (diff) | |
download | common-9fc11892fd11b094bc757c4029183a3f29034e14.tar.gz |
libhwc2.1: refine fence tracer log
Bug: 221767691
Test: logcat
Test: vndservice call Exynos.HWCService 11 i32 0 i32 308 i32 1
Change-Id: I940479e04181a140f1891f725e2e2647b0b0e6c5
-rw-r--r-- | libhwc2.1/ExynosHWCDebug.cpp | 99 | ||||
-rw-r--r-- | libhwc2.1/libdevice/ExynosDevice.cpp | 6 | ||||
-rw-r--r-- | libhwc2.1/libdevice/ExynosDevice.h | 2 | ||||
-rw-r--r-- | libhwc2.1/libdevice/ExynosDisplay.cpp | 67 | ||||
-rw-r--r-- | libhwc2.1/libdevice/ExynosLayer.cpp | 3 | ||||
-rw-r--r-- | libhwc2.1/libhwchelper/ExynosHWCHelper.cpp | 262 | ||||
-rw-r--r-- | libhwc2.1/libhwchelper/ExynosHWCHelper.h | 110 | ||||
-rw-r--r-- | libhwc2.1/libresource/ExynosMPP.cpp | 32 | ||||
-rw-r--r-- | libhwc2.1/libvirtualdisplay/ExynosVirtualDisplay.cpp | 9 |
9 files changed, 192 insertions, 398 deletions
diff --git a/libhwc2.1/ExynosHWCDebug.cpp b/libhwc2.1/ExynosHWCDebug.cpp index 982a54d..bbf676c 100644 --- a/libhwc2.1/ExynosHWCDebug.cpp +++ b/libhwc2.1/ExynosHWCDebug.cpp @@ -50,23 +50,14 @@ int32_t saveErrorLog(const String8 &errString, ExynosDisplay *display) String8 saveString; struct timeval tv; - struct tm* localTime; gettimeofday(&tv, NULL); - localTime = (struct tm*)localtime((time_t*)&tv.tv_sec); if (display != NULL) { - saveString.appendFormat("%02d-%02d %02d:%02d:%02d.%03lu(%lu) %s %" PRIu64 ": %s\n", - localTime->tm_mon+1, localTime->tm_mday, - localTime->tm_hour, localTime->tm_min, - localTime->tm_sec, tv.tv_usec/1000, ((tv.tv_sec * 1000) + (tv.tv_usec / 1000)), - display->mDisplayName.string(), display->mErrorFrameCount, - errString.string()); + saveString.appendFormat("%s %s %" PRIu64 ": %s\n", getLocalTimeStr(tv).string(), + display->mDisplayName.string(), display->mErrorFrameCount, + errString.string()); } else { - saveString.appendFormat("%02d-%02d %02d:%02d:%02d.%03lu(%lu) : %s\n", - localTime->tm_mon+1, localTime->tm_mday, - localTime->tm_hour, localTime->tm_min, - localTime->tm_sec, tv.tv_usec/1000, ((tv.tv_sec * 1000) + (tv.tv_usec / 1000)), - errString.string()); + saveString.appendFormat("%s : %s\n", getLocalTimeStr(tv).string(), errString.string()); } if (pFile != NULL) { @@ -105,80 +96,24 @@ int32_t saveFenceTrace(ExynosDisplay *display) { return -1; } + ExynosDevice *device = display->mDevice; + String8 saveString; - struct timeval tv; - ExynosDevice *device = display->mDevice; + struct timeval tv; + gettimeofday(&tv, NULL); + saveString.appendFormat("\n====== Fences at time:%s ======\n", getLocalTimeStr(tv).string()); if (device != NULL) { - for (const auto &[i, info] : device->mFenceInfos) { -#if 0 - bool sysFdOpen = false; - - // FIXME: sync_fence_info and sync_pt_info are deprecated - // HWC guys should fix this - struct sync_pt_info* pt_info = NULL; - info.sync_data = sync_fence_info(i); - if (info.sync_data != NULL) { - pt_info = sync_pt_info(info.sync_data, pt_info); - if (pt_info !=NULL) { - saveString.appendFormat("\n-- FD sys : %d\n", i); - saveString.appendFormat("real name : %s, status : %s, pt_obj : %s, pt_drv : %s, time : %llu", - info.sync_data->name, info.sync_data->status==1 ? "Active":"Signaled", - pt_info->obj_name, pt_info->driver_name, static_cast<unsigned long long>(pt_info->timestamp_ns)); - } else { - saveString.appendFormat("\n-- FD sys : %d\n", i); - saveString.appendFormat("real name : %s, status : %d, pt_info : %p", - info.sync_data->name, info.sync_data->status, pt_info); - } - sysFdOpen = true; - sync_fence_info_free(info.sync_data); - } - - if ((info.usage == 0) && !sysFdOpen) continue; -#endif - - saveString.appendFormat("\n-- FD hwc : %d, usage %d\n", i, info.usage); - - switch(info.last_dir) { - case FENCE_FROM: - saveString.appendFormat("Last state : from %d, %d\n", - info.from.type, info.from.ip); - tv = info.from.time; - break; - case FENCE_TO: - saveString.appendFormat("Last state : to %d, %d\n", - info.to.type, info.to.ip); - tv = info.to.time; - break; - case FENCE_DUP: - saveString.appendFormat("Last state : dup %d, %d\n", - info.dup.type, info.dup.ip); - tv = info.dup.time; - break; - case FENCE_CLOSE: - saveString.appendFormat("Last state : Close %d, %d\n", - info.close.type, info.close.ip); - tv = info.close.time; - break; - break; - default: - saveString.appendFormat("Fence trace : Undefined direction!\n"); - break; + for (const auto &[fd, info] : device->mFenceInfos) { + saveString.appendFormat("---- Fence FD : %d, Display(%d) ----\n", fd, info.displayId); + saveString.appendFormat("usage: %d, dupFrom: %d, pendingAllowed: %d, leaking: %d\n", + info.usage, info.dupFrom, info.pendingAllowed, info.leaking); + + for (const auto &trace : info.traces) { + saveString.appendFormat("> dir: %d, type: %d, ip: %d, time:%s\n", trace.direction, + trace.type, trace.ip, getLocalTimeStr(trace.time).string()); } - - struct tm* localTime = (struct tm*)localtime((time_t*)&tv.tv_sec); - - saveString.appendFormat("from : %d, %d (cur : %d), to : %d, %d (cur : %d), hwc_dup : %d, %d (cur : %d), hwc_close : %d, %d (cur : %d)\n", - info.from.type, info.from.ip, info.from.curFlag, - info.to.type, info.to.ip, info.to.curFlag, - info.dup.type, info.dup.ip, info.dup.curFlag, - info.close.type, info.close.ip, info.close.curFlag); - saveString.appendFormat("usage : %d, time:%02d-%02d %02d:%02d:%02d.%03lu(%lu)", info.usage, - localTime->tm_mon+1, localTime->tm_mday, - localTime->tm_hour, localTime->tm_min, - localTime->tm_sec, tv.tv_usec/1000, - ((tv.tv_sec * 1000) + (tv.tv_usec / 1000))); } } diff --git a/libhwc2.1/libdevice/ExynosDevice.cpp b/libhwc2.1/libdevice/ExynosDevice.cpp index fbc92f0..d3c31d6 100644 --- a/libhwc2.1/libdevice/ExynosDevice.cpp +++ b/libhwc2.1/libdevice/ExynosDevice.cpp @@ -772,16 +772,14 @@ bool ExynosDevice::validateFences(ExynosDisplay *display) { } if (fenceWarn(display, MAX_FENCE_THRESHOLD)) { - ALOGE("Fence leak! --"); printLeakFds(display); saveFenceTrace(display); return false; } if (exynosHWCControl.doFenceFileDump) { - ALOGE("Fence file dump !"); - if (mFenceLogSize != 0) - ALOGE("Fence file not empty!"); + ALOGD("Fence file dump !"); + if (mFenceLogSize != 0) ALOGD("Fence file not empty!"); saveFenceTrace(display); exynosHWCControl.doFenceFileDump = false; } diff --git a/libhwc2.1/libdevice/ExynosDevice.h b/libhwc2.1/libdevice/ExynosDevice.h index d5a02fe..01b739c 100644 --- a/libhwc2.1/libdevice/ExynosDevice.h +++ b/libhwc2.1/libdevice/ExynosDevice.h @@ -202,7 +202,7 @@ class ExynosDevice { uint32_t mDisplayMode; // Variable for fence tracer - std::map<int, hwc_fence_info_t> mFenceInfos; + std::map<int, HwcFenceInfo> mFenceInfos; /** * This will be initialized with differnt class diff --git a/libhwc2.1/libdevice/ExynosDisplay.cpp b/libhwc2.1/libdevice/ExynosDisplay.cpp index f90d490..1542dca 100644 --- a/libhwc2.1/libdevice/ExynosDisplay.cpp +++ b/libhwc2.1/libdevice/ExynosDisplay.cpp @@ -1800,9 +1800,7 @@ int ExynosDisplay::doExynosComposition() { mExynosCompositionInfo.setExynosImage(src_img, dst_img); DISPLAY_LOGD(eDebugFence, "mExynosCompositionInfo acquireFencefd(%d)", - mExynosCompositionInfo.mAcquireFence); - // Test.. - // setFenceInfo(mExynosCompositionInfo.mAcquireFence, this, "G2D_DST_ACQ", FENCE_FROM); + mExynosCompositionInfo.mAcquireFence); if ((ret = mExynosCompositionInfo.mM2mMPP->resetDstReleaseFence()) != NO_ERROR) { @@ -2384,15 +2382,9 @@ void ExynosDisplay::printDebugInfos(String8 &reason) { FILE *pFile = NULL; struct timeval tv; - struct tm* localTime; gettimeofday(&tv, NULL); - localTime = (struct tm*)localtime((time_t*)&tv.tv_sec); - reason.appendFormat("errFrameNumber: %" PRId64 " time:%02d-%02d %02d:%02d:%02d.%03lu(%lu)\n", - mErrorFrameCount, - localTime->tm_mon+1, localTime->tm_mday, - localTime->tm_hour, localTime->tm_min, - localTime->tm_sec, tv.tv_usec/1000, - ((tv.tv_sec * 1000) + (tv.tv_usec / 1000))); + reason.appendFormat("errFrameNumber: %" PRId64 " time:%s\n", mErrorFrameCount, + getLocalTimeStr(tv).string()); ALOGD("%s", reason.string()); if (mErrorFrameCount < HWC_PRINT_FRAME_NUM) { @@ -2710,8 +2702,8 @@ int ExynosDisplay::deliverWinConfigData() { mRetireFenceAcquireTime = systemTime(); } for (size_t i = 0; i < mDpuData.configs.size(); i++) { - setFenceInfo(mDpuData.configs[i].acq_fence, this, - FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_DPP, FENCE_TO); + setFenceInfo(mDpuData.configs[i].acq_fence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_DPP, + HwcFenceDirection::TO); } if ((ret = mDisplayInterface->deliverWinConfigData()) < 0) { @@ -2722,11 +2714,11 @@ int ExynosDisplay::deliverWinConfigData() { } for (size_t i = 0; i < mDpuData.configs.size(); i++) { - setFenceInfo(mDpuData.configs[i].rel_fence, this, - FENCE_TYPE_SRC_RELEASE, FENCE_IP_DPP, FENCE_FROM); + setFenceInfo(mDpuData.configs[i].rel_fence, this, FENCE_TYPE_SRC_RELEASE, FENCE_IP_DPP, + HwcFenceDirection::FROM); } - setFenceInfo(mDpuData.retire_fence, this, - FENCE_TYPE_RETIRE, FENCE_IP_DPP, FENCE_FROM); + setFenceInfo(mDpuData.retire_fence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP, + HwcFenceDirection::FROM); } return ret; @@ -2829,8 +2821,8 @@ int ExynosDisplay::setReleaseFences() { if (config.rel_fence > 0) { release_fd = config.rel_fence; if (release_fd >= 0) { - setFenceName(release_fd, - this, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_DPP, FENCE_FROM, true); + setFenceInfo(release_fd, this, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_DPP, + HwcFenceDirection::UPDATE, true); mLayers[i]->mM2mMPP->setDstAcquireFence(release_fd); } else { DISPLAY_LOGE("fail to dup, ret(%d, %s)", errno, strerror(errno)); @@ -2907,8 +2899,8 @@ int ExynosDisplay::setReleaseFences() { mExynosCompositionInfo.mM2mMPP->setDstAcquireFence(-1); #else if (config.rel_fence > 0) { - setFenceName(config.rel_fence, - this, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_DPP, FENCE_FROM, true); + setFenceInfo(config.rel_fence, this, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_DPP, + HwcFenceDirection::UPDATE, true); mExynosCompositionInfo.mM2mMPP->setDstAcquireFence(config.rel_fence); } else { mExynosCompositionInfo.mM2mMPP->setDstAcquireFence(-1); @@ -3626,15 +3618,14 @@ int32_t ExynosDisplay::presentDisplay(int32_t* outRetireFence) { *outRetireFence = hwcCheckFenceDebug(this, FENCE_TYPE_RETIRE, FENCE_IP_DPP, mDpuData.retire_fence); #endif - setFenceInfo(mDpuData.retire_fence, this, - FENCE_TYPE_RETIRE, FENCE_IP_LAYER, FENCE_TO); + setFenceInfo(mDpuData.retire_fence, this, FENCE_TYPE_RETIRE, FENCE_IP_LAYER, + HwcFenceDirection::TO); } else *outRetireFence = -1; /* Update last retire fence */ mLastRetireFence = fence_close(mLastRetireFence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP); - mLastRetireFence = hwc_dup((*outRetireFence), this, FENCE_TYPE_RETIRE, FENCE_IP_DPP); - setFenceName(mLastRetireFence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP, FENCE_DUP, true); + mLastRetireFence = hwc_dup((*outRetireFence), this, FENCE_TYPE_RETIRE, FENCE_IP_DPP, true); setFenceName(mLastRetireFence, FENCE_RETIRE); increaseMPPDstBufIndex(); @@ -3668,16 +3659,14 @@ int32_t ExynosDisplay::presentDisplay(int32_t* outRetireFence) { /* All of release fences are tranferred */ for (size_t i=0; i < mLayers.size(); i++) { - setFenceInfo(mLayers[i]->mReleaseFence, this, - FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER, FENCE_TO); + setFenceInfo(mLayers[i]->mReleaseFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER, + HwcFenceDirection::TO); } doPostProcessing(); - if (!mDevice->validateFences(this)){ - String8 errString; - errString.appendFormat("%s:: validate fence failed. \n", __func__); - printDebugInfos(errString); + if (!mDevice->validateFences(this)) { + ALOGE("%s:: validate fence failed.", __func__); } mDpuData.reset(); @@ -3721,9 +3710,8 @@ err: mDpuData.reset(); - if (!mDevice->validateFences(this)){ - errString.appendFormat("%s:: validate fence failed. \n", __func__); - printDebugInfos(errString); + if (!mDevice->validateFences(this)) { + ALOGE("%s:: validate fence failed.", __func__); } mDisplayInterface->setForcePanic(); @@ -3841,8 +3829,7 @@ int32_t ExynosDisplay::setClientTarget( } } mClientCompositionInfo.setTargetBuffer(this, handle, acquireFence, (android_dataspace)dataspace); - setFenceInfo(acquireFence, this, - FENCE_TYPE_SRC_RELEASE, FENCE_IP_FB, FENCE_FROM); + setFenceInfo(acquireFence, this, FENCE_TYPE_SRC_RELEASE, FENCE_IP_FB, HwcFenceDirection::FROM); if (handle) { mClientCompositionInfo.mCompressed = isAFBCCompressed(handle); @@ -5779,8 +5766,8 @@ void ExynosDisplay::setReadbackBufferInternal(buffer_handle_t buffer, DISPLAY_LOGE("previous readback release fence is not delivered to display device"); } if (releaseFence >= 0) { - setFenceInfo(releaseFence, this, FENCE_TYPE_READBACK_RELEASE, - FENCE_IP_FB, FENCE_FROM); + setFenceInfo(releaseFence, this, FENCE_TYPE_READBACK_RELEASE, FENCE_IP_FB, + HwcFenceDirection::FROM); } mDpuData.readback_info.rel_fence = releaseFence; @@ -5821,8 +5808,8 @@ int32_t ExynosDisplay::setReadbackBufferAcqFence(int32_t acqFence) { * so validateFences should not check this fence * in presentDisplay so this function sets pendingAllowed parameter. */ - setFenceInfo(acqFence, this, FENCE_TYPE_READBACK_ACQUIRE, - FENCE_IP_DPP, FENCE_FROM, true); + setFenceInfo(acqFence, this, FENCE_TYPE_READBACK_ACQUIRE, FENCE_IP_DPP, + HwcFenceDirection::FROM, true); } return NO_ERROR; diff --git a/libhwc2.1/libdevice/ExynosLayer.cpp b/libhwc2.1/libdevice/ExynosLayer.cpp index b06b093..105437e 100644 --- a/libhwc2.1/libdevice/ExynosLayer.cpp +++ b/libhwc2.1/libdevice/ExynosLayer.cpp @@ -967,7 +967,8 @@ void ExynosLayer::setSrcAcquireFence() { hwc_dup(mPrevAcquireFence, mDisplay, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER)); } else if (mAcquireFence != -1) { - setFenceInfo(mAcquireFence, mDisplay, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER, FENCE_FROM); + setFenceInfo(mAcquireFence, mDisplay, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER, + HwcFenceDirection::FROM); } } diff --git a/libhwc2.1/libhwchelper/ExynosHWCHelper.cpp b/libhwc2.1/libhwchelper/ExynosHWCHelper.cpp index 75762fc..60593c8 100644 --- a/libhwc2.1/libhwchelper/ExynosHWCHelper.cpp +++ b/libhwc2.1/libhwchelper/ExynosHWCHelper.cpp @@ -15,6 +15,7 @@ */ #include "ExynosHWCHelper.h" +#include <android-base/properties.h> #include <linux/videodev2.h> #include <linux/videodev2_exynos_media.h> #include <png.h> @@ -30,7 +31,6 @@ #include "ExynosLayer.h" #include "ExynosResourceRestriction.h" #include "VendorVideoAPI.h" -#include "android-base/properties.h" #include "exynos_sync.h" using vendor::graphics::BufferUsage; @@ -613,8 +613,7 @@ uint32_t getBytePerPixelOfPrimaryPlane(int format) { return 0; } -void setFenceName(int fenceFd, hwc_fence_type fenceType) -{ +void setFenceName(int fenceFd, HwcFenceType fenceType) { if (fenceFd >= 3) ioctl(fenceFd, SYNC_IOC_FENCE_NAME, fence_names[fenceType]); else if (fenceFd == -1) { @@ -753,10 +752,8 @@ int getBufLength(buffer_handle_t handle, uint32_t planerNum, size_t *length, int return NO_ERROR; } -int fence_close(int fence, ExynosDisplay* display, - hwc_fdebug_fence_type type, hwc_fdebug_ip_type ip) { - if (display != NULL) - setFenceInfo(fence, display, type, ip, FENCE_CLOSE); +int fence_close(int fence, ExynosDisplay* display, HwcFdebugFenceType type, HwcFdebugIpType ip) { + if (display != NULL) setFenceInfo(fence, display, type, ip, HwcFenceDirection::CLOSE); return hwcFdClose(fence); } @@ -784,7 +781,7 @@ int hwcFdClose(int fd) { return -1; } -int hwc_dup(int fd, ExynosDisplay* display, hwc_fdebug_fence_type type, hwc_fdebug_ip_type ip, +int hwc_dup(int fd, ExynosDisplay* display, HwcFdebugFenceType type, HwcFdebugIpType ip, bool pendingAllowed) { int dup_fd = -1; @@ -802,7 +799,7 @@ int hwc_dup(int fd, ExynosDisplay* display, hwc_fdebug_fence_type type, hwc_fdeb hwc_print_stack(); } - setFenceInfo(dup_fd, display, type, ip, FENCE_FROM, pendingAllowed); + setFenceInfo(dup_fd, display, type, ip, HwcFenceDirection::DUP, pendingAllowed, fd); FT_LOGD("duplicated %d from %d", dup_fd, fd); return dup_fd; @@ -815,157 +812,95 @@ int hwc_print_stack() { return 0; } -struct tm* getLocalTime(struct timeval tv) { - return (struct tm*)localtime((time_t*)&tv.tv_sec); +String8 getLocalTimeStr(struct timeval tv) { + struct tm* localTime = (struct tm*)localtime((time_t*)&tv.tv_sec); + return String8::format("%02d-%02d %02d:%02d:%02d.%03lu(%lu)", localTime->tm_mon + 1, + localTime->tm_mday, localTime->tm_hour, localTime->tm_min, + localTime->tm_sec, tv.tv_usec / 1000, + ((tv.tv_sec * 1000) + (tv.tv_usec / 1000))); } -void setFenceInfo(uint32_t fd, ExynosDisplay* display, hwc_fdebug_fence_type type, - hwc_fdebug_ip_type ip, uint32_t direction, bool pendingAllowed) { +void setFenceInfo(uint32_t fd, ExynosDisplay* display, HwcFdebugFenceType type, HwcFdebugIpType ip, + HwcFenceDirection direction, bool pendingAllowed, int32_t dupFrom) { if (!fence_valid(fd) || display == NULL) return; ExynosDevice* device = display->mDevice; - hwc_fence_info_t& info = device->mFenceInfos[fd]; + HwcFenceInfo& info = device->mFenceInfos[fd]; info.displayId = display->mDisplayId; - struct timeval tv; - - // FIXME: sync_fence_info, sync_pt_info are deprecated - // HWC guys should fix this. -#if 0 - if (exynosHWCControl.sysFenceLogging) { - struct sync_pt_info* pt_info = NULL; - info.sync_data = NULL; - if (info.sync_data != NULL) { - pt_info = sync_pt_info(info.sync_data, pt_info); - if (pt_info !=NULL) { - FT_LOGD("real name : %s status : %s pt_obj : %s pt_drv : %s", - info.sync_data->name, info.sync_data->status==1 ? "Active":"Signaled", - pt_info->obj_name, pt_info->driver_name); - } else { - FT_LOGD("real name : %s status : %d pt_info : %p", - info.sync_data->name, info.sync_data->status, pt_info); - } - sync_fence_info_free(info.sync_data); - } - } -#endif - - fenceTrace_t *trace = NULL; - switch(direction) { - case FENCE_FROM: - trace = &info.from; - info.to.type = FENCE_TYPE_UNDEFINED; - info.to.ip = FENCE_IP_UNDEFINED; - info.usage++; - break; - case FENCE_TO: - trace = &info.to; - info.usage--; - break; - case FENCE_DUP: - trace = &info.dup; - info.usage++; - break; - case FENCE_CLOSE: - trace = &info.close; - info.usage--; - if (info.usage < 0) info.usage = 0; - break; - default: - ALOGE("Fence trace : Undefined direction!"); - break; + if (info.leaking) { + return; } - if (trace != NULL) { - trace->type = type; - trace->ip = ip; - gettimeofday(&trace->time, NULL); - tv = trace->time; - trace->curFlag = 1; - FT_LOGW("FD : %d, direction : %d, type : %d, ip : %d", fd, direction, trace->type, trace->ip); - // device->fenceTracing.appendFormat("FD : %d, From : %s\n", fd, info.trace.fromName); + switch (direction) { + case HwcFenceDirection::FROM: + info.usage++; + break; + case HwcFenceDirection::TO: + info.usage--; + break; + case HwcFenceDirection::DUP: + info.usage++; + info.dupFrom = dupFrom; + break; + case HwcFenceDirection::CLOSE: + info.usage--; + if (info.usage < 0) info.usage = 0; + break; + case HwcFenceDirection::UPDATE: + break; + default: + ALOGE("Fence trace : Undefined direction!"); + break; } -#if 0 // To be used ? - struct tm* localTime = getLocalTime(tv); - device->fenceTracing.appendFormat("usage : %d, time:%02d-%02d %02d:%02d:%02d.%03lu(%lu)\n", info.usage, - localTime->tm_mon+1, localTime->tm_mday, - localTime->tm_hour, localTime->tm_min, - localTime->tm_sec, tv.tv_usec/1000, - ((tv.tv_sec * 1000) + (tv.tv_usec / 1000))); -#endif - - // Fence's usage count shuld be zero at end of frame(present done). - // This flag means usage count of the fence can be pended over frame. - info.pendingAllowed = pendingAllowed; - - info.last_dir = direction; - if (info.usage == 0) { device->mFenceInfos.erase(fd); + return; } else if (info.usage < 0) { ALOGE("%s : Invalid negative usage (%d) for Fence FD:%d", __func__, info.usage, fd); printLastFenceInfo(fd, display); } -} -void printLastFenceInfo(uint32_t fd, ExynosDisplay* display) { + HwcFenceTrace trace = {.direction = direction, .type = type, .ip = ip, .time = {0, 0}}; + + gettimeofday(&trace.time, NULL); - struct timeval tv; + info.traces.push_back(trace); + FT_LOGW("FD : %d, direction : %d, type : %d, ip : %d", fd, direction, type, ip); + + // Fence's usage count shuld be zero at end of frame(present done). + // This flag means usage count of the fence can be pended over frame. + info.pendingAllowed = pendingAllowed; +} + +void printLastFenceInfo(uint32_t fd, ExynosDisplay* display) { if (!fence_valid(fd)) return; ExynosDevice* device = display->mDevice; auto it = device->mFenceInfos.find(fd); if (it == device->mFenceInfos.end()) return; - hwc_fence_info_t& info = it->second; + HwcFenceInfo& info = it->second; FT_LOGD("---- Fence FD : %d, Display(%d) ----", fd, info.displayId); + FT_LOGD("usage: %d, dupFrom: %d, pendingAllowed: %d, leaking: %d", info.usage, info.dupFrom, + info.pendingAllowed, info.leaking); - fenceTrace_t *trace = NULL; - - switch (info.last_dir) { - case FENCE_FROM: - trace = &info.from; - break; - case FENCE_TO: - trace = &info.to; - break; - case FENCE_DUP: - trace = &info.dup; - break; - case FENCE_CLOSE: - trace = &info.close; - break; - default: - ALOGE("Fence trace : Undefined direction!"); - break; - } - - if (trace != NULL) { - FT_LOGD("Last state : %d, type(%d), ip(%d)", info.last_dir, trace->type, trace->ip); - tv = info.from.time; + for (const auto& trace : info.traces) { + FT_LOGD("> dir: %d, type: %d, ip: %d, time:%s", trace.direction, trace.type, trace.ip, + getLocalTimeStr(trace.time).string()); } - - FT_LOGD("from : %d, %d (cur : %d), to : %d, %d (cur : %d), hwc_dup : %d, %d (cur : " - "%d),hwc_close : %d, %d (cur : %d)", - info.from.type, info.from.ip, info.from.curFlag, info.to.type, info.to.ip, - info.to.curFlag, info.dup.type, info.dup.ip, info.dup.curFlag, info.close.type, - info.close.ip, info.close.curFlag); - - struct tm* localTime = getLocalTime(tv); - - FT_LOGD("usage : %d, time:%02d-%02d %02d:%02d:%02d.%03lu(%lu)", info.usage, - localTime->tm_mon + 1, localTime->tm_mday, localTime->tm_hour, localTime->tm_min, - localTime->tm_sec, tv.tv_usec / 1000, ((tv.tv_sec * 1000) + (tv.tv_usec / 1000))); } -void dumpFenceInfo(ExynosDisplay* display, int32_t __unused depth) { +void dumpFenceInfo(ExynosDisplay* display, int32_t count) { ExynosDevice* device = display->mDevice; - FT_LOGD("Dump fence ++"); + FT_LOGD("Dump fence (up to %d fences) ++", count); for (const auto& [fd, info] : device->mFenceInfos) { - if (!info.pendingAllowed) printLastFenceInfo(fd, display); + if (info.pendingAllowed) continue; + if (count-- <= 0) break; + printLastFenceInfo(fd, display); } FT_LOGD("Dump fence --"); } @@ -979,6 +914,7 @@ void printLeakFds(ExynosDisplay* display) { int cnt = 0; for (const auto& [fd, info] : fenceInfos) { + if (!info.leaking) continue; if (info.usage * sign > 0) { errString.appendFormat("%d,", fd); if ((++cnt % 10) == 0) { @@ -1018,32 +954,17 @@ void dumpNCheckLeak(ExynosDisplay* display, int32_t __unused depth) { bool fenceWarn(ExynosDisplay* display, uint32_t threshold) { ExynosDevice* device = display->mDevice; - uint32_t cnt = device->mFenceInfos.size(), r_cnt = 0; - - // FIXME: sync_fence_info() is deprecated - // HWC guys should fix this. -#if 0 - if (exynosHWCControl.sysFenceLogging) { - for (int i=3; i < MAX_FD_NUM; i++){ - struct sync_fence_info_data* data = nullptr; - data = NULL; //sync_fence_info(i); - if (data != NULL) { - r_cnt++; - sync_fence_info_free(data); - } - } - } -#endif - - if ((cnt>threshold) || (exynosHWCControl.fenceTracer > 0)) - dumpFenceInfo(display, 0); - - if (r_cnt>threshold) - ALOGE("Fence leak somewhare!!"); + uint32_t cnt = device->mFenceInfos.size(); - FT_LOGD("fence hwc : %d, real : %d", cnt, r_cnt); + if (cnt > threshold) { + ALOGE("Fence leak! -- the number of fences(%d) exceeds threshold(%d)", cnt, threshold); + int priv = exynosHWCControl.fenceTracer; + exynosHWCControl.fenceTracer = 3; + dumpFenceInfo(display, 10); + exynosHWCControl.fenceTracer = priv; + } - return (cnt>threshold) ? true : false; + return (cnt > threshold); } bool validateFencePerFrame(ExynosDisplay* display) { @@ -1068,47 +989,6 @@ bool validateFencePerFrame(ExynosDisplay* display) { return ret; } -void setFenceName(uint32_t fd, ExynosDisplay *display, - hwc_fdebug_fence_type type, hwc_fdebug_ip_type ip, - uint32_t direction, bool pendingAllowed) { - - ExynosDevice* device = display->mDevice; - if (!fence_valid(fd) || device == NULL) return; - - auto it = device->mFenceInfos.find(fd); - if (it == device->mFenceInfos.end()) return; - - hwc_fence_info_t& info = it->second; - info.displayId = display->mDisplayId; - fenceTrace_t *trace = NULL; - - switch(direction) { - case FENCE_FROM: - trace = &info.from; - break; - case FENCE_TO: - trace = &info.to; - break; - case FENCE_DUP: - trace = &info.dup; - break; - case FENCE_CLOSE: - trace = &info.close; - break; - default: - ALOGE("Fence trace : Undefined direction!"); - break; - } - - if (trace != NULL) { - trace->type = type; - trace->ip = ip; - FT_LOGD("FD : %d, direction : %d, type(%d), ip(%d) (changed)", fd, direction, type, ip); - } - - info.pendingAllowed = pendingAllowed; -} - String8 getMPPStr(int typeId) { if (typeId < MPP_DPP_NUM){ int cnt = sizeof(AVAILABLE_OTF_MPP_UNITS)/sizeof(exynos_mpp_t); diff --git a/libhwc2.1/libhwchelper/ExynosHWCHelper.h b/libhwc2.1/libhwchelper/ExynosHWCHelper.h index 69d9fe1..6fb9ea5 100644 --- a/libhwc2.1/libhwchelper/ExynosHWCHelper.h +++ b/libhwc2.1/libhwchelper/ExynosHWCHelper.h @@ -21,6 +21,7 @@ #include <utils/String8.h> #include <fstream> +#include <list> #include <optional> #include <sstream> #include <string> @@ -258,7 +259,7 @@ const format_description_t exynos_format_desc[] = { constexpr size_t FORMAT_MAX_CNT = sizeof(exynos_format_desc) / sizeof(format_description); -typedef enum hwc_fdebug_fence_type_t { +enum HwcFdebugFenceType { FENCE_TYPE_SRC_RELEASE = 1, FENCE_TYPE_SRC_ACQUIRE = 2, FENCE_TYPE_DST_RELEASE = 3, @@ -271,9 +272,9 @@ typedef enum hwc_fdebug_fence_type_t { FENCE_TYPE_READBACK_RELEASE = 10, FENCE_TYPE_ALL = 11, FENCE_TYPE_UNDEFINED = 100 -} hwc_fdebug_fence_type; +}; -typedef enum hwc_fdebug_ip_type_t { +enum HwcFdebugIpType { FENCE_IP_DPP = 0, FENCE_IP_MSC = 1, FENCE_IP_G2D = 2, @@ -281,30 +282,30 @@ typedef enum hwc_fdebug_ip_type_t { FENCE_IP_LAYER = 4, FENCE_IP_ALL = 5, FENCE_IP_UNDEFINED = 100 -} hwc_fdebug_ip_type; - -typedef enum hwc_fence_type_t { - FENCE_LAYER_RELEASE_DPP = 0, - FENCE_LAYER_RELEASE_MPP = 1, - FENCE_LAYER_RELEASE_MSC = 2, - FENCE_LAYER_RELEASE_G2D = 3, - FENCE_DPP_HW_STATE = 4, - FENCE_MSC_HW_STATE = 5, - FENCE_G2D_HW_STATE = 6, - FENCE_MSC_SRC_LAYER = 7, - FENCE_G2D_SRC_LAYER = 8, - FENCE_MPP_DST_DPP = 9, - FENCE_MSC_DST_DPP = 10, - FENCE_G2D_DST_DPP = 11, - FENCE_DPP_SRC_MPP = 12, - FENCE_DPP_SRC_MSC = 13, - FENCE_DPP_SRC_G2D = 14, - FENCE_DPP_SRC_LAYER = 15, - FENCE_MPP_FREE_BUF_ACQUIRE = 16, - FENCE_MPP_FREE_BUF_RELEASE = 17, - FENCE_RETIRE = 18, +}; + +enum HwcFenceType { + FENCE_LAYER_RELEASE_DPP = 0, + FENCE_LAYER_RELEASE_MPP = 1, + FENCE_LAYER_RELEASE_MSC = 2, + FENCE_LAYER_RELEASE_G2D = 3, + FENCE_DPP_HW_STATE = 4, + FENCE_MSC_HW_STATE = 5, + FENCE_G2D_HW_STATE = 6, + FENCE_MSC_SRC_LAYER = 7, + FENCE_G2D_SRC_LAYER = 8, + FENCE_MPP_DST_DPP = 9, + FENCE_MSC_DST_DPP = 10, + FENCE_G2D_DST_DPP = 11, + FENCE_DPP_SRC_MPP = 12, + FENCE_DPP_SRC_MSC = 13, + FENCE_DPP_SRC_G2D = 14, + FENCE_DPP_SRC_LAYER = 15, + FENCE_MPP_FREE_BUF_ACQUIRE = 16, + FENCE_MPP_FREE_BUF_RELEASE = 17, + FENCE_RETIRE = 18, FENCE_MAX -} hwc_fence_type; +}; enum { EXYNOS_ERROR_NONE = 0, @@ -446,12 +447,11 @@ uint32_t getBufferNumOfFormat(int format, uint32_t compressType); uint32_t getPlaneNumOfFormat(int format, uint32_t compressType); uint32_t getBytePerPixelOfPrimaryPlane(int format); -int fence_close(int fence, ExynosDisplay* display, - hwc_fdebug_fence_type type, hwc_fdebug_ip_type ip); +int fence_close(int fence, ExynosDisplay *display, HwcFdebugFenceType type, HwcFdebugIpType ip); bool fence_valid(int fence); int hwcFdClose(int fd); -int hwc_dup(int fd, ExynosDisplay *display, hwc_fdebug_fence_type type, hwc_fdebug_ip_type ip, +int hwc_dup(int fd, ExynosDisplay *display, HwcFdebugFenceType type, HwcFdebugIpType ip, bool pendingAllowed = false); int hwc_print_stack(); @@ -482,37 +482,29 @@ inline T pixel_align(const T x, const uint32_t a) { uint32_t getExynosBufferYLength(uint32_t width, uint32_t height, int format); int getBufLength(buffer_handle_t handle, uint32_t planer_num, size_t *length, int format, uint32_t width, uint32_t height); -//class hwc_fence_info(sync_fence_info_data* data, sync_pt_info* info) { -struct tm* getHwcFenceTime(); - -enum { - FENCE_FROM = 0, - FENCE_TO, - FENCE_DUP, - FENCE_CLOSE, +enum class HwcFenceDirection { + FROM = 0, + TO, + DUP, + CLOSE, + UPDATE, }; -typedef struct fenceTrace { - hwc_fdebug_fence_type type = FENCE_TYPE_UNDEFINED; - hwc_fdebug_ip_type ip = FENCE_IP_UNDEFINED; +struct HwcFenceTrace { + HwcFenceDirection direction = HwcFenceDirection::FROM; + HwcFdebugFenceType type = FENCE_TYPE_UNDEFINED; + HwcFdebugIpType ip = FENCE_IP_UNDEFINED; struct timeval time = {0, 0}; - int32_t curFlag = 0; -} fenceTrace_t; +}; -typedef struct hwc_fence_info { +struct HwcFenceInfo { uint32_t displayId = HWC_DISPLAY_PRIMARY; - struct sync_fence_info_data *sync_data = nullptr; - struct sync_pt_info *pt_info = nullptr; - fenceTrace_t from = {}; - fenceTrace_t to = {}; - fenceTrace_t dup = {}; - fenceTrace_t close = {}; int32_t usage = 0; - int32_t curFlag = 0; - uint32_t last_dir = 0; + int32_t dupFrom = -1; bool pendingAllowed = false; bool leaking = false; -} hwc_fence_info_t; + std::list<HwcFenceTrace> traces = {}; +}; class funcReturnCallback { public: @@ -522,15 +514,13 @@ class funcReturnCallback { const std::function<void(void)> mCb; }; -void setFenceName(int fenceFd, hwc_fence_type fenceType); -void setFenceName(uint32_t fd, ExynosDisplay *display, - hwc_fdebug_fence_type type, hwc_fdebug_ip_type ip, - uint32_t direction, bool pendingAllowed = false); -void setFenceInfo(uint32_t fd, ExynosDisplay *display, - hwc_fdebug_fence_type type, hwc_fdebug_ip_type ip, - uint32_t direction, bool pendingAllowed = false); +String8 getLocalTimeStr(struct timeval tv); + +void setFenceName(int fenceFd, HwcFenceType fenceType); +void setFenceInfo(uint32_t fd, ExynosDisplay *display, HwcFdebugFenceType type, HwcFdebugIpType ip, + HwcFenceDirection direction, bool pendingAllowed = false, int32_t dupFrom = -1); void printLastFenceInfo(uint32_t fd, ExynosDisplay *display); -void dumpFenceInfo(ExynosDisplay *display, int32_t __unused depth); +void dumpFenceInfo(ExynosDisplay *display, int32_t count); bool fenceWarn(ExynosDisplay *display, uint32_t threshold); void printLeakFds(ExynosDisplay *display); bool validateFencePerFrame(ExynosDisplay *display); diff --git a/libhwc2.1/libresource/ExynosMPP.cpp b/libhwc2.1/libresource/ExynosMPP.cpp index 84b3b24..ae44283 100644 --- a/libhwc2.1/libresource/ExynosMPP.cpp +++ b/libhwc2.1/libresource/ExynosMPP.cpp @@ -1261,12 +1261,12 @@ int32_t ExynosMPP::setupLayer(exynos_mpp_img_info *srcImgInfo, struct exynos_ima if (mPhysicalType == MPP_G2D) { setFenceName(srcImgInfo->acrylicAcquireFenceFd, FENCE_G2D_SRC_LAYER); - setFenceInfo(srcImgInfo->acrylicAcquireFenceFd, mAssignedDisplay, - FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_G2D, FENCE_TO); + setFenceInfo(srcImgInfo->acrylicAcquireFenceFd, mAssignedDisplay, FENCE_TYPE_SRC_ACQUIRE, + FENCE_IP_G2D, HwcFenceDirection::TO); } else if (mPhysicalType == MPP_MSC) { setFenceName(srcImgInfo->acrylicAcquireFenceFd, FENCE_MSC_SRC_LAYER); - setFenceInfo(srcImgInfo->acrylicAcquireFenceFd, mAssignedDisplay, - FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_MSC, FENCE_TO); + setFenceInfo(srcImgInfo->acrylicAcquireFenceFd, mAssignedDisplay, FENCE_TYPE_SRC_ACQUIRE, + FENCE_IP_MSC, HwcFenceDirection::TO); } else { MPP_LOGE("%s:: invalid mPhysicalType(%d)", __func__, mPhysicalType); } @@ -1389,13 +1389,13 @@ int32_t ExynosMPP::setupDst(exynos_mpp_img_info *dstImgInfo) if (mPhysicalType == MPP_G2D) { setFenceName(dstImgInfo->acrylicAcquireFenceFd, FENCE_G2D_DST_DPP); /* Might be closed next frame */ - setFenceInfo(dstImgInfo->acrylicAcquireFenceFd, mAssignedDisplay, - FENCE_TYPE_DST_ACQUIRE, FENCE_IP_G2D, FENCE_TO); + setFenceInfo(dstImgInfo->acrylicAcquireFenceFd, mAssignedDisplay, FENCE_TYPE_DST_ACQUIRE, + FENCE_IP_G2D, HwcFenceDirection::TO); } else if (mPhysicalType == MPP_MSC) { setFenceName(dstImgInfo->acrylicAcquireFenceFd, FENCE_MSC_DST_DPP); /* Might be closed next frame */ - setFenceInfo(dstImgInfo->acrylicAcquireFenceFd, mAssignedDisplay, - FENCE_TYPE_DST_ACQUIRE, FENCE_IP_MSC, FENCE_TO); + setFenceInfo(dstImgInfo->acrylicAcquireFenceFd, mAssignedDisplay, FENCE_TYPE_DST_ACQUIRE, + FENCE_IP_MSC, HwcFenceDirection::TO); } else { MPP_LOGE("%s:: invalid mPhysicalType(%d)", __func__, mPhysicalType); } @@ -1534,23 +1534,23 @@ int32_t ExynosMPP::doPostProcessingInternal() // set fence informations from acryl if (mPhysicalType == MPP_G2D) { - setFenceInfo(releaseFences[dstBufIdx], mAssignedDisplay, - FENCE_TYPE_DST_ACQUIRE, FENCE_IP_G2D, FENCE_FROM); + setFenceInfo(releaseFences[dstBufIdx], mAssignedDisplay, FENCE_TYPE_DST_ACQUIRE, + FENCE_IP_G2D, HwcFenceDirection::FROM); if (usingFenceCnt > 1) { for(size_t i = 0; i < sourceNum; i++) { // TODO DPU release fence is tranferred to m2mMPP's source layer fence - setFenceInfo(releaseFences[i], mAssignedDisplay, - FENCE_TYPE_SRC_RELEASE, FENCE_IP_G2D, FENCE_FROM); + setFenceInfo(releaseFences[i], mAssignedDisplay, FENCE_TYPE_SRC_RELEASE, + FENCE_IP_G2D, HwcFenceDirection::FROM); } } } else if (mPhysicalType == MPP_MSC) { - setFenceInfo(releaseFences[dstBufIdx], mAssignedDisplay, - FENCE_TYPE_DST_ACQUIRE, FENCE_IP_MSC, FENCE_FROM); + setFenceInfo(releaseFences[dstBufIdx], mAssignedDisplay, FENCE_TYPE_DST_ACQUIRE, + FENCE_IP_MSC, HwcFenceDirection::FROM); if (usingFenceCnt > 1) { for(size_t i = 0; i < sourceNum; i++) { // TODO DPU release fence is tranferred to m2mMPP's source layer fence - setFenceInfo(releaseFences[i], mAssignedDisplay, - FENCE_TYPE_SRC_RELEASE, FENCE_IP_MSC, FENCE_FROM); + setFenceInfo(releaseFences[i], mAssignedDisplay, FENCE_TYPE_SRC_RELEASE, + FENCE_IP_MSC, HwcFenceDirection::FROM); } } } else { diff --git a/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplay.cpp b/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplay.cpp index a9cadc3..d6ce85f 100644 --- a/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplay.cpp +++ b/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplay.cpp @@ -348,7 +348,8 @@ int ExynosVirtualDisplay::setReleaseFences() ret = ExynosDisplay::setReleaseFences(); mOutputBufferReleaseFenceFd = hwcCheckFenceDebug(this, FENCE_TYPE_RETIRE, FENCE_IP_G2D, mExynosCompositionInfo.mAcquireFence); - setFenceInfo(mExynosCompositionInfo.mAcquireFence, this, FENCE_TYPE_RETIRE, FENCE_IP_G2D, FENCE_TO); + setFenceInfo(mExynosCompositionInfo.mAcquireFence, this, FENCE_TYPE_RETIRE, FENCE_IP_G2D, + HwcFenceDirection::TO); mExynosCompositionInfo.mAcquireFence = -1; /* mClientCompositionInfo.mAcquireFence is delivered to G2D */ mClientCompositionInfo.mAcquireFence = -1; @@ -505,12 +506,14 @@ void ExynosVirtualDisplay::handleAcquireFence() if (layer->mValidateCompositionType == HWC2_COMPOSITION_DEVICE || layer->mValidateCompositionType == HWC2_COMPOSITION_EXYNOS) { layer->mReleaseFence = layer->mAcquireFence; - setFenceInfo(layer->mAcquireFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER, FENCE_TO); + setFenceInfo(layer->mAcquireFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER, + HwcFenceDirection::TO); layer->mAcquireFence = -1; } } mClientCompositionInfo.mReleaseFence = mClientCompositionInfo.mAcquireFence; - setFenceInfo(mClientCompositionInfo.mAcquireFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_FB, FENCE_TO); + setFenceInfo(mClientCompositionInfo.mAcquireFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_FB, + HwcFenceDirection::TO); mClientCompositionInfo.mAcquireFence = -1; mOutputBufferReleaseFenceFd = mOutputBufferAcquireFenceFd; |