#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"
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;
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)
}
return NULL;
}
- mt_count_alloc(mt, size);
+ mt_count_alloc(mt, size, ptr);
return ptr;
}
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);
}
void qfree(struct memtype *mt, void *ptr)
{
if (ptr)
- mt_count_free(mt);
+ mt_count_free(mt, ptr);
free(ptr);
}
#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 {
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;