qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/2] add malloc statistics infrastructure
@ 2011-05-02  7:59 Paolo Bonzini
  2011-05-02  7:59 ` [Qemu-devel] [PATCH 1/2] malloc: move memalign/vmalloc to qemu-malloc.c Paolo Bonzini
  2011-05-02  7:59 ` [Qemu-devel] [PATCH 2/2] malloc: add statistics infrastructure Paolo Bonzini
  0 siblings, 2 replies; 3+ messages in thread
From: Paolo Bonzini @ 2011-05-02  7:59 UTC (permalink / raw)
  To: qemu-devel

These patches add a --enable-malloc-stats configure options, which
will make qemu trace its memory allocations.  A new monitor command
dump-malloc-stats lets the user dump them to a file.

Using statistics with KVM depends on the patch I posted recently to
use qemu_free consistently.  However, there is no regression without
the configure flag.

Paolo Bonzini (2):
  malloc: move memalign/vmalloc to qemu-malloc.c
  malloc: add statistics infrastructure

 configure       |    9 ++
 hmp-commands.hx |   16 ++++
 monitor.c       |   12 +++
 osdep.h         |    5 +-
 oslib-posix.c   |   32 ++------
 oslib-win32.c   |   31 +-------
 qemu-common.h   |   46 +++++++++--
 qemu-malloc.c   |  244 +++++++++++++++++++++++++++++++++++++++++++++++++++----
 trace-events    |    1 -
 9 files changed, 316 insertions(+), 80 deletions(-)

-- 
1.7.4.4

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [Qemu-devel] [PATCH 1/2] malloc: move memalign/vmalloc to qemu-malloc.c
  2011-05-02  7:59 [Qemu-devel] [PATCH 0/2] add malloc statistics infrastructure Paolo Bonzini
@ 2011-05-02  7:59 ` Paolo Bonzini
  2011-05-02  7:59 ` [Qemu-devel] [PATCH 2/2] malloc: add statistics infrastructure Paolo Bonzini
  1 sibling, 0 replies; 3+ messages in thread
From: Paolo Bonzini @ 2011-05-02  7:59 UTC (permalink / raw)
  To: qemu-devel

This splits qemu_memalign and qemu_vfree in two: a part that does
just the allocation in oslib, and a part that includes the tracing
in qemu-malloc.c.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 osdep.h       |    5 ++---
 oslib-posix.c |   32 +++++++-------------------------
 oslib-win32.c |   31 ++-----------------------------
 qemu-common.h |    7 +++++--
 qemu-malloc.c |   33 +++++++++++++++++++++++++++++++++
 trace-events  |    1 -
 6 files changed, 49 insertions(+), 60 deletions(-)

diff --git a/osdep.h b/osdep.h
index 970d767..4ca7c9e 100644
--- a/osdep.h
+++ b/osdep.h
@@ -88,9 +88,8 @@
 # define QEMU_GNUC_PREREQ(maj, min) 0
 #endif
 
-void *qemu_memalign(size_t alignment, size_t size);
-void *qemu_vmalloc(size_t size);
-void qemu_vfree(void *ptr);
+void *os_memalign(size_t alignment, size_t size);
+void os_vfree(void *ptr);
 
 #define QEMU_MADV_INVALID -1
 
diff --git a/oslib-posix.c b/oslib-posix.c
index 7bc5f7c..1566f18 100644
--- a/oslib-posix.c
+++ b/oslib-posix.c
@@ -28,47 +28,29 @@
 
 #include "config-host.h"
 #include "sysemu.h"
-#include "trace.h"
 #include "qemu_socket.h"
 
-void *qemu_oom_check(void *ptr)
-{
-    if (ptr == NULL) {
-        fprintf(stderr, "Failed to allocate memory: %s\n", strerror(errno));
-        abort();
-    }
-    return ptr;
-}
-
-void *qemu_memalign(size_t alignment, size_t size)
+void *os_memalign(size_t alignment, size_t size)
 {
     void *ptr;
+    assert(alignment > sizeof(void *));
+    assert((alignment & (alignment - 1)) == 0);
 #if defined(_POSIX_C_SOURCE) && !defined(__sun__)
     int ret;
     ret = posix_memalign(&ptr, alignment, size);
     if (ret != 0) {
-        fprintf(stderr, "Failed to allocate %zu B: %s\n",
-                size, strerror(ret));
-        abort();
+        ptr = NULL;
     }
 #elif defined(CONFIG_BSD)
-    ptr = qemu_oom_check(valloc(size));
+    ptr = valloc(size);
 #else
-    ptr = qemu_oom_check(memalign(alignment, size));
+    ptr = memalign(alignment, size);
 #endif
-    trace_qemu_memalign(alignment, size, ptr);
     return ptr;
 }
 
-/* alloc shared memory pages */
-void *qemu_vmalloc(size_t size)
-{
-    return qemu_memalign(getpagesize(), size);
-}
-
-void qemu_vfree(void *ptr)
+void os_vfree(void *ptr)
 {
-    trace_qemu_vfree(ptr);
     free(ptr);
 }
 
diff --git a/oslib-win32.c b/oslib-win32.c
index 5f0759f..a32451e 100644
--- a/oslib-win32.c
+++ b/oslib-win32.c
@@ -28,48 +28,21 @@
 #include <windows.h>
 #include "config-host.h"
 #include "sysemu.h"
-#include "trace.h"
 #include "qemu_socket.h"
 
-void *qemu_oom_check(void *ptr)
+void *os_memalign(size_t alignment, size_t size)
 {
-    if (ptr == NULL) {
-        fprintf(stderr, "Failed to allocate memory: %lu\n", GetLastError());
-        abort();
-    }
-    return ptr;
-}
-
-void *qemu_memalign(size_t alignment, size_t size)
-{
-    void *ptr;
-
-    if (!size) {
-        abort();
-    }
-    ptr = qemu_oom_check(VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE));
-    trace_qemu_memalign(alignment, size, ptr);
-    return ptr;
-}
-
-void *qemu_vmalloc(size_t size)
-{
-    void *ptr;
-
     /* FIXME: this is not exactly optimal solution since VirtualAlloc
        has 64Kb granularity, but at least it guarantees us that the
        memory is page aligned. */
     if (!size) {
         abort();
     }
-    ptr = qemu_oom_check(VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE));
-    trace_qemu_vmalloc(size, ptr);
-    return ptr;
+    return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
 }
 
 void qemu_vfree(void *ptr)
 {
-    trace_qemu_vfree(ptr);
     VirtualFree(ptr, 0, MEM_RELEASE);
 }
 
diff --git a/qemu-common.h b/qemu-common.h
index f9f705d..1382e7e 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -206,13 +206,16 @@ const char *path(const char *pathname);
 int ffs(int i);
 #endif
 
-void *qemu_oom_check(void *ptr);
 void *qemu_malloc(size_t size);
 void *qemu_realloc(void *ptr, size_t size);
 void *qemu_mallocz(size_t size);
-void qemu_free(void *ptr);
 char *qemu_strdup(const char *str);
 char *qemu_strndup(const char *str, size_t size);
+void *qemu_memalign(size_t alignment, size_t size);
+void *qemu_vmalloc(size_t size);
+
+void qemu_free(void *ptr);
+void qemu_vfree(void *ptr);
 
 void qemu_mutex_lock_iothread(void);
 void qemu_mutex_unlock_iothread(void);
diff --git a/qemu-malloc.c b/qemu-malloc.c
index b9b3851..cc1305c 100644
--- a/qemu-malloc.c
+++ b/qemu-malloc.c
@@ -31,6 +31,15 @@ void qemu_free(void *ptr)
     free(ptr);
 }
 
+static void *qemu_oom_check(void *ptr)
+{
+    if (ptr == NULL) {
+        fprintf(stderr, "Failed to allocate memory: %s\n", strerror(errno));
+        abort();
+    }
+    return ptr;
+}
+
 static int allow_zero_malloc(void)
 {
 #if defined(CONFIG_ZERO_MALLOC)
@@ -96,3 +105,27 @@ char *qemu_strndup(const char *str, size_t size)
 
     return memcpy(new, str, size);
 }
+
+void *qemu_memalign(size_t alignment, size_t size)
+{
+    char *ptr;
+    assert(size <= LONG_MAX);
+    if (!size && !allow_zero_malloc()) {
+        abort();
+    }
+    ptr = qemu_oom_check(os_memalign(alignment, size ? size : 1));
+    trace_qemu_memalign(alignment, size, (char *)ptr);
+    return ptr;
+}
+
+/* alloc shared memory pages */
+void *qemu_vmalloc(size_t size)
+{
+    return qemu_memalign(getpagesize(), size);
+}
+
+void qemu_vfree(void *ptr)
+{
+    trace_qemu_vfree(ptr);
+    os_vfree(ptr);
+}
diff --git a/trace-events b/trace-events
index 77c96a5..bd2f74e 100644
--- a/trace-events
+++ b/trace-events
@@ -35,7 +35,6 @@ disable qemu_free(void *ptr) "ptr %p"
 
 # osdep.c
 disable qemu_memalign(size_t alignment, size_t size, void *ptr) "alignment %zu size %zu ptr %p"
-disable qemu_vmalloc(size_t size, void *ptr) "size %zu ptr %p"
 disable qemu_vfree(void *ptr) "ptr %p"
 
 # hw/virtio.c
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [Qemu-devel] [PATCH 2/2] malloc: add statistics infrastructure
  2011-05-02  7:59 [Qemu-devel] [PATCH 0/2] add malloc statistics infrastructure Paolo Bonzini
  2011-05-02  7:59 ` [Qemu-devel] [PATCH 1/2] malloc: move memalign/vmalloc to qemu-malloc.c Paolo Bonzini
@ 2011-05-02  7:59 ` Paolo Bonzini
  1 sibling, 0 replies; 3+ messages in thread
From: Paolo Bonzini @ 2011-05-02  7:59 UTC (permalink / raw)
  To: qemu-devel

The infrastructure tracks the following items for each allocation locus:
number of currently allocated blocks, total number of allocated blocks,
number of currently allocated bytes, maximum number of allocated bytes,
total number of allocated bytes.  Accounting is thread safe, which is
why I didn't use qemu-queue functions.

Tracing is done by sticking an extra header in front of the allocated
block.  The header is needed so that free can account bytes correctly
and to the correct allocation locus.  The header is variable-sized
because of memalign, with the information stored at the tail so it is
easily accessible from free's parameter.  Hence it also has to include
a pointer to the actual base of the memory block.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 configure       |    9 ++
 hmp-commands.hx |   16 ++++
 monitor.c       |   12 +++
 qemu-common.h   |   45 ++++++++++--
 qemu-malloc.c   |  223 +++++++++++++++++++++++++++++++++++++++++++++++++------
 5 files changed, 276 insertions(+), 29 deletions(-)

diff --git a/configure b/configure
index 6f75e2e..48003cf 100755
--- a/configure
+++ b/configure
@@ -171,6 +171,7 @@ pkgversion=""
 check_utests="no"
 user_pie="no"
 zero_malloc=""
+malloc_stats="no"
 trace_backend="nop"
 trace_file="trace"
 spice=""
@@ -665,6 +666,10 @@ for opt do
   ;;
   --disable-guest-base) guest_base="no"
   ;;
+  --enable-malloc-stats) malloc_stats="yes"
+  ;;
+  --disable-malloc-stats) malloc_stats="no"
+  ;;
   --enable-user-pie) user_pie="yes"
   ;;
   --disable-user-pie) user_pie="no"
@@ -2602,6 +2607,7 @@ echo "Documentation     $docs"
 echo "uname -r          $uname_release"
 echo "NPTL support      $nptl"
 echo "GUEST_BASE        $guest_base"
+echo "Malloc statistics $malloc_stats"
 echo "PIE user targets  $user_pie"
 echo "vde support       $vde"
 echo "IO thread         $io_thread"
@@ -2924,6 +2930,9 @@ fi
 
 echo "CONFIG_UNAME_RELEASE=\"$uname_release\"" >> $config_host_mak
 
+if test "$malloc_stats" = "yes" ; then
+  echo "CONFIG_MALLOC_STATS=y" >> $config_host_mak
+fi
 if test "$zero_malloc" = "yes" ; then
   echo "CONFIG_ZERO_MALLOC=y" >> $config_host_mak
 fi
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 834e6a8..54567dc 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -180,6 +180,22 @@ STEXI
 Output logs to @var{filename}.
 ETEXI
 
+#ifdef CONFIG_MALLOC_STATS
+    {
+        .name       = "dump-malloc-stats",
+        .args_type  = "name:F",
+        .params     = "name",
+        .help       = "dump memory allocation statistics to a file",
+        .mhandler.cmd = do_dump_malloc_stats,
+    },
+
+STEXI
+@item dump-malloc-stats @var{filename}
+@findex dump-malloc-stats
+Dump memory allocation statistics to @var{filename}.
+ETEXI
+#endif
+
 #ifdef CONFIG_SIMPLE_TRACE
     {
         .name       = "trace-event",
diff --git a/monitor.c b/monitor.c
index 5f3bc72..361c90b 100644
--- a/monitor.c
+++ b/monitor.c
@@ -592,6 +592,18 @@ static void do_help_cmd(Monitor *mon, const QDict *qdict)
     help_cmd(mon, qdict_get_try_str(qdict, "name"));
 }
 
+#ifdef CONFIG_MALLOC_STATS
+static void do_dump_malloc_stats(Monitor *mon, const QDict *qdict)
+{
+    const char *file_name = qdict_get_str(qdict, "name");
+    int ret = dump_malloc_stats(file_name);
+
+    if (ret < 0) {
+        monitor_printf(mon, "error writing file: %s\n", strerror(-ret));
+    }
+}
+#endif
+
 #ifdef CONFIG_SIMPLE_TRACE
 static void do_change_trace_event_state(Monitor *mon, const QDict *qdict)
 {
diff --git a/qemu-common.h b/qemu-common.h
index 1382e7e..f2d4614 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -206,17 +206,48 @@ const char *path(const char *pathname);
 int ffs(int i);
 #endif
 
-void *qemu_malloc(size_t size);
-void *qemu_realloc(void *ptr, size_t size);
-void *qemu_mallocz(size_t size);
-char *qemu_strdup(const char *str);
-char *qemu_strndup(const char *str, size_t size);
-void *qemu_memalign(size_t alignment, size_t size);
-void *qemu_vmalloc(size_t size);
+typedef struct QEMUMallocStatsLocus QEMUMallocStatsLocus;
+
+struct QEMUMallocStatsLocus {
+    const char *file;
+    const char *func;
+    int line;
+    uint64_t live;
+    uint64_t count;
+    uint64_t alloc_tot;
+    size_t alloc;
+    size_t alloc_max;
+    struct QEMUMallocStatsLocus *next;
+};
+
+#ifdef CONFIG_MALLOC_STATS
+#define MALLOC_STATS_ARG ({ \
+    static struct QEMUMallocStatsLocus t = { __FILE__, __func__, __LINE__ }; \
+    &t; })
+#else
+#define MALLOC_STATS_ARG NULL
+#endif
+
+void *qemu_malloc(size_t size, struct QEMUMallocStatsLocus *locus);
+void *qemu_mallocz(size_t size, struct QEMUMallocStatsLocus *locus);
+void *qemu_realloc(void *ptr, size_t size, struct QEMUMallocStatsLocus *locus);
+char *qemu_strdup(const char *str, struct QEMUMallocStatsLocus *locus);
+char *qemu_strndup(const char *str, size_t size, struct QEMUMallocStatsLocus *locus);
+void *qemu_memalign(size_t alignment, size_t size, QEMUMallocStatsLocus *locus);
+void *qemu_vmalloc(size_t size, QEMUMallocStatsLocus *locus);
+int dump_malloc_stats(const char *file_name);
 
 void qemu_free(void *ptr);
 void qemu_vfree(void *ptr);
 
+#define qemu_malloc(size) ((qemu_malloc)(size, MALLOC_STATS_ARG))
+#define qemu_mallocz(size) ((qemu_mallocz)(size, MALLOC_STATS_ARG))
+#define qemu_realloc(ptr, size) ((qemu_realloc)(ptr, size, MALLOC_STATS_ARG))
+#define qemu_memalign(alignment, size) ((qemu_memalign)(alignment, size, MALLOC_STATS_ARG))
+#define qemu_vmalloc(size) ((qemu_vmalloc)(size, MALLOC_STATS_ARG))
+#define qemu_strdup(str) ((qemu_strdup)(str, MALLOC_STATS_ARG))
+#define qemu_strndup(str, size) ((qemu_strndup)(str, size, MALLOC_STATS_ARG))
+
 void qemu_mutex_lock_iothread(void);
 void qemu_mutex_unlock_iothread(void);
 
diff --git a/qemu-malloc.c b/qemu-malloc.c
index cc1305c..ae00083 100644
--- a/qemu-malloc.c
+++ b/qemu-malloc.c
@@ -25,11 +25,19 @@
 #include "trace.h"
 #include <stdlib.h>
 
-void qemu_free(void *ptr)
-{
-    trace_qemu_free(ptr);
-    free(ptr);
-}
+#ifdef CONFIG_MALLOC_STATS
+struct QEMUMallocStatsData {
+    void *base;
+    QEMUMallocStatsLocus *locus;
+    size_t size;
+};
+
+typedef struct QEMUMallocStatsData QEMUMallocStatsData;
+
+#define STATS_DATA_SIZE sizeof(QEMUMallocStatsData)
+#else
+#define STATS_DATA_SIZE 0
+#endif
 
 static void *qemu_oom_check(void *ptr)
 {
@@ -49,49 +57,153 @@ static int allow_zero_malloc(void)
 #endif
 }
 
-void *qemu_malloc(size_t size)
+#ifdef CONFIG_MALLOC_STATS
+static inline QEMUMallocStatsData *fetch_mem_data(void *ptr)
 {
-    void *ptr;
+    return ((QEMUMallocStatsData *)ptr) - 1;
+}
+#endif
+
+static inline void *store_mem_data(char *ptr, int extra,
+                                   QEMUMallocStatsLocus *locus, size_t size)
+{
+#ifdef CONFIG_MALLOC_STATS
+    QEMUMallocStatsData *data;
+    data = (QEMUMallocStatsData *) (ptr + extra - STATS_DATA_SIZE);
+    data->base = ptr;
+    data->locus = locus;
+    data->size = size;
+    return &data[1];
+#else
+    return ptr;
+#endif
+}
+
+#ifdef CONFIG_MALLOC_STATS
+static QEMUMallocStatsLocus *malloc_loci_head;
+#endif
+
+static inline void update_mem_stats(QEMUMallocStatsLocus *locus,
+                                    ptrdiff_t size, int dir)
+{
+#ifdef CONFIG_MALLOC_STATS
+    size_t alloc, alloc_max, alloc_tot;
+
+    __sync_add_and_fetch(&locus->live, dir);
+    alloc = __sync_add_and_fetch(&locus->alloc, size);
+    if (dir < 0) {
+        return;
+    }
+
+    __sync_add_and_fetch(&locus->count, dir);
+    do {
+        alloc_max = locus->alloc_max;
+    } while (alloc > alloc_max &&
+             !__sync_bool_compare_and_swap(&locus->alloc_max, alloc_max, alloc));
+
+    if (size < 0) {
+        return;
+    }
+
+    /* On the first allocation, put the struct into the list.  */
+    alloc_tot = __sync_fetch_and_add(&locus->alloc_tot, size);
+    if (alloc_tot == 0) {
+        do {
+            locus->next = malloc_loci_head;
+        } while (!__sync_bool_compare_and_swap(&malloc_loci_head,
+                                               locus->next, locus));
+    }
+#endif
+}
+
+void qemu_free(void *ptr)
+{
+    trace_qemu_free(ptr);
+#ifdef CONFIG_MALLOC_STATS
+    if (ptr) {
+        QEMUMallocStatsData *data = fetch_mem_data(ptr);
+        update_mem_stats(data->locus, -data->size, -1);
+        ptr = data->base;
+    }
+#endif
+    free(ptr);
+}
+
+#undef qemu_malloc
+void *qemu_malloc(size_t size, QEMUMallocStatsLocus *locus)
+{
+    char *ptr;
+    size_t real_size = size;
+    assert(size <= LONG_MAX);
     if (!size && !allow_zero_malloc()) {
         abort();
     }
+    size += STATS_DATA_SIZE;
     ptr = qemu_oom_check(malloc(size ? size : 1));
-    trace_qemu_malloc(size, ptr);
+    ptr = store_mem_data(ptr, STATS_DATA_SIZE, locus, real_size);
+    trace_qemu_malloc(real_size, ptr);
+    update_mem_stats(locus, real_size, 1);
     return ptr;
 }
 
-void *qemu_realloc(void *ptr, size_t size)
+#undef qemu_realloc
+void *qemu_realloc(void *ptr, size_t size, QEMUMallocStatsLocus *locus)
 {
-    void *newptr;
+    void *oldptr, *newptr;
+    size_t old_size;
+    size_t real_size = size;
+    assert(size <= LONG_MAX);
+    oldptr = ptr;
+    old_size = 0;
+
+#ifdef CONFIG_MALLOC_STATS
+    if (ptr) {
+        QEMUMallocStatsData *data = fetch_mem_data(ptr);
+        locus = data->locus;
+        old_size = data->size;
+        oldptr = data->base;
+    }
+#endif
     if (!size && !allow_zero_malloc()) {
         abort();
     }
-    newptr = qemu_oom_check(realloc(ptr, size ? size : 1));
-    trace_qemu_realloc(ptr, size, newptr);
+    size += STATS_DATA_SIZE;
+    newptr = qemu_oom_check(realloc(oldptr, size ? size : 1));
+    newptr = store_mem_data(newptr, STATS_DATA_SIZE, locus, real_size);
+    trace_qemu_realloc(ptr, real_size, newptr);
+    update_mem_stats(locus, real_size - old_size, ptr ? 0 : 1);
     return newptr;
 }
 
-void *qemu_mallocz(size_t size)
+#undef qemu_mallocz
+void *qemu_mallocz(size_t size, QEMUMallocStatsLocus *locus)
 {
     void *ptr;
+    size_t real_size = size;
+    assert(size <= LONG_MAX);
     if (!size && !allow_zero_malloc()) {
         abort();
     }
+    size += STATS_DATA_SIZE;
     ptr = qemu_oom_check(calloc(1, size ? size : 1));
-    trace_qemu_malloc(size, ptr);
+    ptr = store_mem_data(ptr, STATS_DATA_SIZE, locus, real_size);
+    trace_qemu_malloc(real_size, ptr);
+    update_mem_stats(locus, real_size, 1);
     return ptr;
 }
 
-char *qemu_strdup(const char *str)
+#undef qemu_strdup
+char *qemu_strdup(const char *str, QEMUMallocStatsLocus *locus)
 {
     char *ptr;
     size_t len = strlen(str);
-    ptr = qemu_malloc(len + 1);
+    ptr = (qemu_malloc)(len + 1, locus);
     memcpy(ptr, str, len + 1);
     return ptr;
 }
 
-char *qemu_strndup(const char *str, size_t size)
+#undef qemu_strndup
+char *qemu_strndup(const char *str, size_t size, QEMUMallocStatsLocus *locus)
 {
     const char *end = memchr(str, 0, size);
     char *new;
@@ -100,32 +212,99 @@ char *qemu_strndup(const char *str, size_t size)
         size = end - str;
     }
 
-    new = qemu_malloc(size + 1);
+    new = (qemu_malloc)(size + 1, locus);
     new[size] = 0;
 
     return memcpy(new, str, size);
 }
 
-void *qemu_memalign(size_t alignment, size_t size)
+#ifdef CONFIG_MALLOC_STATS
+int dump_malloc_stats(const char *file_name)
+{
+    FILE *file = fopen(file_name, "w");
+    QEMUMallocStatsLocus *p = malloc_loci_head;
+
+    const char *this_file = __FILE__;
+    const char *base = strrchr(this_file, '/');
+    int skip = base ? base + 1 - this_file : 0;
+    int rc = 0;
+
+    fprintf(file,
+            "FILE:LINE (FUNCTION)                      Live  "
+            "Count   Curr bytes    Max bytes        Tot bytes\n"
+            "------------------------------------------------"
+            "------------------------------------------------\n");
+
+    while (p && !ferror(file)) {
+        const char *locus_file, *prefix = "";
+        char s[40];
+        if (skip && !memcmp(p->file, this_file, skip)) {
+            locus_file = p->file + skip;
+        } else {
+            locus_file = strrchr(p->file, '/');
+            if (locus_file) {
+                prefix = "...";
+            } else {
+                locus_file = p->file;
+            }
+        }
+        snprintf(s, sizeof(s), "%s%s:%d (%s)",
+                 prefix, locus_file, p->line, p->func);
+        fprintf(file,
+                "%-40s %5"PRIu64 " %6"PRIu64 " %12"PRIu64" %12"PRIu64
+                " %16"PRIu64"\n",
+                s, p->live, p->count, p->alloc, p->alloc_max, p->alloc_tot);
+        p = p->next;
+    }
+
+    if (ferror(file)) {
+        rc = -errno;
+    }
+    if (fflush(file) == EOF && rc == 0) {
+        rc = -errno;
+    }
+    if (fclose(file) == EOF && rc == 0) {
+        rc = -errno;
+    }
+    return rc;
+}
+#endif
+
+#undef qemu_memalign
+void *qemu_memalign(size_t alignment, size_t size, QEMUMallocStatsLocus *locus)
 {
     char *ptr;
+    size_t real_size = size;
+    size_t extra;
     assert(size <= LONG_MAX);
     if (!size && !allow_zero_malloc()) {
         abort();
     }
+    extra = (STATS_DATA_SIZE + alignment - 1) & -alignment;
+    size += extra;
     ptr = qemu_oom_check(os_memalign(alignment, size ? size : 1));
-    trace_qemu_memalign(alignment, size, (char *)ptr);
+    ptr = store_mem_data(ptr, extra, locus, real_size);
+    trace_qemu_memalign(alignment, real_size, ptr);
+    update_mem_stats(locus, real_size, 1);
     return ptr;
 }
 
 /* alloc shared memory pages */
-void *qemu_vmalloc(size_t size)
+#undef qemu_vmalloc
+void *qemu_vmalloc(size_t size, QEMUMallocStatsLocus *locus)
 {
-    return qemu_memalign(getpagesize(), size);
+    return qemu_memalign(getpagesize(), size, locus);
 }
 
 void qemu_vfree(void *ptr)
 {
     trace_qemu_vfree(ptr);
+#ifdef CONFIG_MALLOC_STATS
+    if (ptr) {
+        QEMUMallocStatsData *data = fetch_mem_data(ptr);
+        update_mem_stats(data->locus, -data->size, -1);
+        ptr = data->base;
+    }
+#endif
     os_vfree(ptr);
 }
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2011-05-02  7:59 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-05-02  7:59 [Qemu-devel] [PATCH 0/2] add malloc statistics infrastructure Paolo Bonzini
2011-05-02  7:59 ` [Qemu-devel] [PATCH 1/2] malloc: move memalign/vmalloc to qemu-malloc.c Paolo Bonzini
2011-05-02  7:59 ` [Qemu-devel] [PATCH 2/2] malloc: add statistics infrastructure Paolo Bonzini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).