diff options
author | Anthony Stange <stange@google.com> | 2019-04-05 14:29:48 -0400 |
---|---|---|
committer | Anthony Stange <stange@google.com> | 2019-04-11 11:05:30 -0400 |
commit | fd7d41818065e8b8853e97e36878eef47a3bccc3 (patch) | |
tree | f7fb533f7de5a1ace41ff31be8e0e6aca913742d | |
parent | 8a970b3d305b004b328420478c9ca4c371e601d4 (diff) | |
download | chre-fd7d41818065e8b8853e97e36878eef47a3bccc3.tar.gz |
Keep track of allocated bytes per nanoapp
Logs an error when CHRE exits and a nanoapp
still has memory allocated to help identify
nanoapps with memory leaks.
Test: ./run_sim.sh w/ gnss_world having a mem leak.
Verify logs are printed.
Bug: 119144776
Bug: 127549493
Change-Id: I41c55392dd849d58b6be02b2d457a91a6c0466ae
-rw-r--r-- | core/include/chre/core/nanoapp.h | 36 | ||||
-rw-r--r-- | core/nanoapp.cc | 12 | ||||
-rw-r--r-- | platform/include/chre/platform/memory_manager.h | 12 | ||||
-rw-r--r-- | platform/shared/memory_manager.cc | 22 |
4 files changed, 77 insertions, 5 deletions
diff --git a/core/include/chre/core/nanoapp.h b/core/include/chre/core/nanoapp.h index f897aa79..c1b255ca 100644 --- a/core/include/chre/core/nanoapp.h +++ b/core/include/chre/core/nanoapp.h @@ -39,6 +39,8 @@ namespace chre { */ class Nanoapp : public PlatformNanoapp { public: + ~Nanoapp(); + /** * @return The unique identifier for this Nanoapp instance */ @@ -55,6 +57,34 @@ class Nanoapp : public PlatformNanoapp { } /** + * @return The current total number of bytes the nanoapp has allocated. + */ + size_t getTotalAllocatedBytes() const { + return mTotalAllocatedBytes; + } + + /** + * @return The peak total number of bytes the nanoapp has allocated. + */ + size_t getPeakAllocatedBytes() const { + return mPeakAllocatedBytes; + } + + + /** + * Sets the total number of bytes the nanoapp has allocated. Also, modifies + * the peak allocated bytes if the current total is higher than the peak. + * + * @param The total number of bytes the nanoapp has allocated. + */ + void setTotalAllocatedBytes(size_t totalAllocatedBytes) { + mTotalAllocatedBytes = totalAllocatedBytes; + if (mTotalAllocatedBytes > mPeakAllocatedBytes) { + mPeakAllocatedBytes = mTotalAllocatedBytes; + } + } + + /** * @return true if the nanoapp should receive broadcast events with the given * type */ @@ -130,6 +160,12 @@ class Nanoapp : public PlatformNanoapp { private: uint32_t mInstanceId = kInvalidInstanceId; + //! The total memory allocated by the nanoapp in bytes. + size_t mTotalAllocatedBytes = 0; + + //! The peak total number of bytes allocated by the nanoapp. + size_t mPeakAllocatedBytes = 0; + //! The set of broadcast events that this app is registered for. // TODO: Implement a set container and replace DynamicVector here. There may // also be a better way of handling this (perhaps we map event type to apps diff --git a/core/nanoapp.cc b/core/nanoapp.cc index d898628a..41a294e6 100644 --- a/core/nanoapp.cc +++ b/core/nanoapp.cc @@ -24,6 +24,12 @@ namespace chre { +Nanoapp::~Nanoapp() { + CHRE_ASSERT_LOG(getTotalAllocatedBytes() == 0, + "Nanoapp ID=0x%016" PRIx64 " still has %zu allocated bytes!", getAppId(), + getTotalAllocatedBytes()); +} + bool Nanoapp::isRegisteredForBroadcastEvent(uint16_t eventType) const { return (mRegisteredEvents.find(eventType) != mRegisteredEvents.size()); } @@ -87,8 +93,10 @@ void Nanoapp::logStateToBuffer(char *buffer, size_t *bufferPos, debugDumpPrint( buffer, bufferPos, bufferSize, " Id=%" PRIu32 " AppId=0x%016" PRIx64 - " ver=0x%" PRIx32 " targetAPI=0x%" PRIx32 "\n", - getInstanceId(), getAppId(), getAppVersion(), getTargetApiVersion()); + " ver=0x%" PRIx32 " targetAPI=0x%" PRIx32 + " currentAllocatedBytes=%zu peakAllocatedBytes=%zu\n", + getInstanceId(), getAppId(), getAppVersion(), getTargetApiVersion(), + getTotalAllocatedBytes(), getPeakAllocatedBytes()); } } // namespace chre diff --git a/platform/include/chre/platform/memory_manager.h b/platform/include/chre/platform/memory_manager.h index 37a19ca2..226c8d66 100644 --- a/platform/include/chre/platform/memory_manager.h +++ b/platform/include/chre/platform/memory_manager.h @@ -63,6 +63,13 @@ class MemoryManager : public NonCopyable { } /** + * @return peak total allocated memory in bytes. + */ + size_t getPeakAllocatedBytes() const { + return mPeakAllocatedBytes; + } + + /** * @return current count of allocated memory spaces. */ size_t getAllocationCount() const { @@ -112,9 +119,12 @@ class MemoryManager : public NonCopyable { max_align_t aligner; }; - //! Stores total allocated memory in bytes (not including header). + //! The total allocated memory in bytes (not including header). size_t mTotalAllocatedBytes = 0; + //! The peak allocated memory in bytes (not including header). + size_t mPeakAllocatedBytes = 0; + //! Stores total number of allocated memory spaces. size_t mAllocationCount = 0; diff --git a/platform/shared/memory_manager.cc b/platform/shared/memory_manager.cc index 3b24f153..93a974c6 100644 --- a/platform/shared/memory_manager.cc +++ b/platform/shared/memory_manager.cc @@ -34,6 +34,7 @@ void *MemoryManager::nanoappAlloc(Nanoapp *app, uint32_t bytes) { doAlloc(app, sizeof(AllocHeader) + bytes)); if (header != nullptr) { + app->setTotalAllocatedBytes(app->getTotalAllocatedBytes() + bytes); mTotalAllocatedBytes += bytes; mAllocationCount++; header->data.bytes = bytes; @@ -50,6 +51,22 @@ void MemoryManager::nanoappFree(Nanoapp *app, void *ptr) { AllocHeader *header = static_cast<AllocHeader*>(ptr); header--; + // TODO: Clean up API contract of chreSendEvent to specify nanoapps can't + // release ownership of data to other nanoapps so a CHRE_ASSERT_LOG can be + // used below and the code can return. + if (app->getInstanceId() != header->data.instanceId) { + LOGW("Nanoapp ID=%" PRIu32 " tried to free data from nanoapp ID=%" PRIu32, + app->getInstanceId(), header->data.instanceId); + } + + size_t nanoAppTotalAllocatedBytes = app->getTotalAllocatedBytes(); + if (nanoAppTotalAllocatedBytes >= header->data.bytes) { + app->setTotalAllocatedBytes( + nanoAppTotalAllocatedBytes - header->data.bytes); + } else { + app->setTotalAllocatedBytes(0); + } + if (mTotalAllocatedBytes >= header->data.bytes) { mTotalAllocatedBytes -= header->data.bytes; } else { @@ -66,8 +83,9 @@ void MemoryManager::nanoappFree(Nanoapp *app, void *ptr) { void MemoryManager::logStateToBuffer(char *buffer, size_t *bufferPos, size_t bufferSize) const { debugDumpPrint(buffer, bufferPos, bufferSize, - "\nNanoapp heap usage: %zu bytes allocated, count %zu\n", - getTotalAllocatedBytes(), getAllocationCount()); + "\nNanoapp heap usage: %zu bytes allocated, %zu peak bytes" + " allocated, count %zu\n", getTotalAllocatedBytes(), + getPeakAllocatedBytes(), getAllocationCount()); } } // namespace chre |