summaryrefslogtreecommitdiffstats
path: root/media/libmedia/MemoryLeakTrackUtil.cpp
diff options
context:
space:
mode:
authorJames Dong <jdong@google.com>2011-03-14 17:01:38 -0700
committerJames Dong <jdong@google.com>2011-03-14 18:48:19 -0700
commit8635b7b095fbf7ffc63d3ce791891a9116ace1f6 (patch)
tree6c9bbe1d0cec53f0c83099f1028302a178928cb9 /media/libmedia/MemoryLeakTrackUtil.cpp
parent1b99cc90afffbda6013ebbb45d64f17b1d90b9f5 (diff)
downloadframeworks_av-8635b7b095fbf7ffc63d3ce791891a9116ace1f6.zip
frameworks_av-8635b7b095fbf7ffc63d3ce791891a9116ace1f6.tar.gz
frameworks_av-8635b7b095fbf7ffc63d3ce791891a9116ace1f6.tar.bz2
Add memory leak tracking/debugging code to drm server
bug - 4099038 Change-Id: I6c048eaf3d7f34bc144b8daaa5fdef1ed474af66
Diffstat (limited to 'media/libmedia/MemoryLeakTrackUtil.cpp')
-rw-r--r--media/libmedia/MemoryLeakTrackUtil.cpp169
1 files changed, 169 insertions, 0 deletions
diff --git a/media/libmedia/MemoryLeakTrackUtil.cpp b/media/libmedia/MemoryLeakTrackUtil.cpp
new file mode 100644
index 0000000..6a108ae
--- /dev/null
+++ b/media/libmedia/MemoryLeakTrackUtil.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <media/MemoryLeakTrackUtil.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+/*
+ * The code here originally resided in MediaPlayerService.cpp and was
+ * shamelessly copied over to support memory leak tracking from
+ * multiple places.
+ */
+namespace android {
+
+#if defined(__arm__)
+
+extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
+ size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
+
+extern "C" void free_malloc_leak_info(uint8_t* info);
+
+// Use the String-class below instead of String8 to allocate all memory
+// beforehand and not reenter the heap while we are examining it...
+struct MyString8 {
+ static const size_t MAX_SIZE = 256 * 1024;
+
+ MyString8()
+ : mPtr((char *)malloc(MAX_SIZE)) {
+ *mPtr = '\0';
+ }
+
+ ~MyString8() {
+ free(mPtr);
+ }
+
+ void append(const char *s) {
+ strcat(mPtr, s);
+ }
+
+ const char *string() const {
+ return mPtr;
+ }
+
+ size_t size() const {
+ return strlen(mPtr);
+ }
+
+private:
+ char *mPtr;
+
+ MyString8(const MyString8 &);
+ MyString8 &operator=(const MyString8 &);
+};
+
+void dumpMemoryAddresses(int fd)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ MyString8 result;
+
+ typedef struct {
+ size_t size;
+ size_t dups;
+ intptr_t * backtrace;
+ } AllocEntry;
+
+ uint8_t *info = NULL;
+ size_t overallSize = 0;
+ size_t infoSize = 0;
+ size_t totalMemory = 0;
+ size_t backtraceSize = 0;
+
+ get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize);
+ if (info) {
+ uint8_t *ptr = info;
+ size_t count = overallSize / infoSize;
+
+ snprintf(buffer, SIZE, " Allocation count %i\n", count);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Total memory %i\n", totalMemory);
+ result.append(buffer);
+
+ AllocEntry * entries = new AllocEntry[count];
+
+ for (size_t i = 0; i < count; i++) {
+ // Each entry should be size_t, size_t, intptr_t[backtraceSize]
+ AllocEntry *e = &entries[i];
+
+ e->size = *reinterpret_cast<size_t *>(ptr);
+ ptr += sizeof(size_t);
+
+ e->dups = *reinterpret_cast<size_t *>(ptr);
+ ptr += sizeof(size_t);
+
+ e->backtrace = reinterpret_cast<intptr_t *>(ptr);
+ ptr += sizeof(intptr_t) * backtraceSize;
+ }
+
+ // Now we need to sort the entries. They come sorted by size but
+ // not by stack trace which causes problems using diff.
+ bool moved;
+ do {
+ moved = false;
+ for (size_t i = 0; i < (count - 1); i++) {
+ AllocEntry *e1 = &entries[i];
+ AllocEntry *e2 = &entries[i+1];
+
+ bool swap = e1->size < e2->size;
+ if (e1->size == e2->size) {
+ for(size_t j = 0; j < backtraceSize; j++) {
+ if (e1->backtrace[j] == e2->backtrace[j]) {
+ continue;
+ }
+ swap = e1->backtrace[j] < e2->backtrace[j];
+ break;
+ }
+ }
+ if (swap) {
+ AllocEntry t = entries[i];
+ entries[i] = entries[i+1];
+ entries[i+1] = t;
+ moved = true;
+ }
+ }
+ } while (moved);
+
+ for (size_t i = 0; i < count; i++) {
+ AllocEntry *e = &entries[i];
+
+ snprintf(buffer, SIZE, "size %8i, dup %4i, ", e->size, e->dups);
+ result.append(buffer);
+ for (size_t ct = 0; (ct < backtraceSize) && e->backtrace[ct]; ct++) {
+ if (ct) {
+ result.append(", ");
+ }
+ snprintf(buffer, SIZE, "0x%08x", e->backtrace[ct]);
+ result.append(buffer);
+ }
+ result.append("\n");
+ }
+
+ delete[] entries;
+ free_malloc_leak_info(info);
+ }
+
+ write(fd, result.string(), result.size());
+}
+
+#else
+// Does nothing
+void dumpMemoryAddresses(int fd) {}
+
+#endif
+} // namespace android