aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony Stange <stange@google.com>2019-04-05 14:29:48 -0400
committerAnthony Stange <stange@google.com>2019-04-11 11:05:30 -0400
commitfd7d41818065e8b8853e97e36878eef47a3bccc3 (patch)
treef7fb533f7de5a1ace41ff31be8e0e6aca913742d
parent8a970b3d305b004b328420478c9ca4c371e601d4 (diff)
downloadchre-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.h36
-rw-r--r--core/nanoapp.cc12
-rw-r--r--platform/include/chre/platform/memory_manager.h12
-rw-r--r--platform/shared/memory_manager.cc22
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