]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib: count total memory allocation per MTYPE
authorDavid Lamparter <equinox@opensourcerouting.org>
Wed, 8 Aug 2018 14:44:43 +0000 (16:44 +0200)
committerDavid Lamparter <equinox@opensourcerouting.org>
Wed, 8 Aug 2018 18:17:55 +0000 (20:17 +0200)
If malloc_usable_size() or malloc_size() are available, we can count
total usage of a particular MTYPE.  (Without the functions, we don't
know how much to subtract on free.)

Signed-off-by: David Lamparter <equinox@diac24.net>
lib/memory.c
lib/memory.h
lib/memory_vty.c

index e279b17d122b4aef0508cf6e7a5637a0c997e437..87cba69fc51536b579f01997fe6351ad29ee7ff2 100644 (file)
 #include <zebra.h>
 
 #include <stdlib.h>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#ifdef HAVE_MALLOC_MALLOC_H
+#include <malloc/malloc.h>
+#endif
 
 #include "memory.h"
 #include "log.h"
@@ -28,7 +34,7 @@ DEFINE_MGROUP(LIB, "libfrr")
 DEFINE_MTYPE(LIB, TMP, "Temporary memory")
 DEFINE_MTYPE(LIB, PREFIX_FLOWSPEC, "Prefix Flowspec")
 
-static inline void mt_count_alloc(struct memtype *mt, size_t size)
+static inline void mt_count_alloc(struct memtype *mt, size_t size, void *ptr)
 {
        size_t oldsize;
 
@@ -41,12 +47,24 @@ static inline void mt_count_alloc(struct memtype *mt, size_t size)
        if (oldsize != 0 && oldsize != size && oldsize != SIZE_VAR)
                atomic_store_explicit(&mt->size, SIZE_VAR,
                                      memory_order_relaxed);
+
+#ifdef HAVE_MALLOC_USABLE_SIZE
+       size_t mallocsz = malloc_usable_size(ptr);
+
+       atomic_fetch_add_explicit(&mt->total, mallocsz, memory_order_relaxed);
+#endif
 }
 
-static inline void mt_count_free(struct memtype *mt)
+static inline void mt_count_free(struct memtype *mt, void *ptr)
 {
        assert(mt->n_alloc);
        atomic_fetch_sub_explicit(&mt->n_alloc, 1, memory_order_relaxed);
+
+#ifdef HAVE_MALLOC_USABLE_SIZE
+       size_t mallocsz = malloc_usable_size(ptr);
+
+       atomic_fetch_sub_explicit(&mt->total, mallocsz, memory_order_relaxed);
+#endif
 }
 
 static inline void *mt_checkalloc(struct memtype *mt, void *ptr, size_t size)
@@ -58,7 +76,7 @@ static inline void *mt_checkalloc(struct memtype *mt, void *ptr, size_t size)
                }
                return NULL;
        }
-       mt_count_alloc(mt, size);
+       mt_count_alloc(mt, size, ptr);
        return ptr;
 }
 
@@ -75,7 +93,7 @@ void *qcalloc(struct memtype *mt, size_t size)
 void *qrealloc(struct memtype *mt, void *ptr, size_t size)
 {
        if (ptr)
-               mt_count_free(mt);
+               mt_count_free(mt, ptr);
        return mt_checkalloc(mt, ptr ? realloc(ptr, size) : malloc(size), size);
 }
 
@@ -87,7 +105,7 @@ void *qstrdup(struct memtype *mt, const char *str)
 void qfree(struct memtype *mt, void *ptr)
 {
        if (ptr)
-               mt_count_free(mt);
+               mt_count_free(mt, ptr);
        free(ptr);
 }
 
index 1fbbbe4231de2a5d2ff5410396e67e5337dc94af..c39f34e3a7f8a313f2c3c5d9497b5e18650a4468 100644 (file)
 
 #define array_size(ar) (sizeof(ar) / sizeof(ar[0]))
 
+#if defined(HAVE_MALLOC_SIZE) && !defined(HAVE_MALLOC_USABLE_SIZE)
+#define malloc_usable_size(x) malloc_size(x)
+#define HAVE_MALLOC_USABLE_SIZE
+#endif
+
 #define SIZE_VAR ~0UL
 struct memtype {
        struct memtype *next, **ref;
        const char *name;
        _Atomic size_t n_alloc;
        _Atomic size_t size;
+#ifdef HAVE_MALLOC_USABLE_SIZE
+       _Atomic size_t total;
+#endif
 };
 
 struct memgroup {
index 388273128e251ea247a8f388cc62ed746ddc679e..9ee2e52ec751cacb33b42209ea6b974e520729ac 100644 (file)
@@ -79,12 +79,21 @@ static int qmem_walker(void *arg, struct memgroup *mg, struct memtype *mt)
                if (mt->n_alloc != 0) {
                        char size[32];
                        snprintf(size, sizeof(size), "%6zu", mt->size);
-                       vty_out(vty, "%-30s: %10zu  %s\n", mt->name,
+
+#ifdef HAVE_MALLOC_USABLE_SIZE
+#define TSTR " %9zu"
+#define TARG , mt->total
+#else
+#define TSTR ""
+#define TARG
+#endif
+                       vty_out(vty, "%-30s: %10zu  %-16s"TSTR"\n", mt->name,
                                mt->n_alloc,
                                mt->size == 0 ? ""
                                              : mt->size == SIZE_VAR
                                                        ? "(variably sized)"
-                                                       : size);
+                                                       : size
+                               TARG);
                }
        }
        return 0;