+#ifdef NETDATA_LOG_ALLOCATIONS
+static struct memory_statistics {
+ volatile size_t malloc_calls_made;
+ volatile size_t calloc_calls_made;
+ volatile size_t realloc_calls_made;
+ volatile size_t strdup_calls_made;
+ volatile size_t free_calls_made;
+ volatile size_t memory_calls_made;
+ volatile size_t allocated_memory;
+ volatile size_t mmapped_memory;
+} memory_statistics;
+
+static inline void print_allocations(const char *file, const char *function, const unsigned long line) {
+ static struct memory_statistics old = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ //if(unlikely(!(memory_statistics.memory_calls_made % 5))) {
+ fprintf(stderr, "(%04lu@%-10.10s:%-15.15s): Allocated %zu KB (+%zu B), mmapped %zu KB (+%zu B): malloc %zu (+%zu), calloc %zu (+%zu), realloc %zu (+%zu), strdup %zu (+%zu), free %zu (+%zu)\n",
+ line, file, function,
+ (memory_statistics.allocated_memory + 512) / 1024, memory_statistics.allocated_memory - old.allocated_memory,
+ (memory_statistics.mmapped_memory + 512) / 1024, memory_statistics.mmapped_memory - old.mmapped_memory,
+ memory_statistics.malloc_calls_made, memory_statistics.malloc_calls_made - old.malloc_calls_made,
+ memory_statistics.calloc_calls_made, memory_statistics.calloc_calls_made - old.calloc_calls_made,
+ memory_statistics.realloc_calls_made, memory_statistics.realloc_calls_made - old.realloc_calls_made,
+ memory_statistics.strdup_calls_made, memory_statistics.strdup_calls_made - old.strdup_calls_made,
+ memory_statistics.free_calls_made, memory_statistics.free_calls_made - old.free_calls_made
+ );
+
+ memcpy(&old, &memory_statistics, sizeof(struct memory_statistics));
+ //}
+}
+
+static inline void malloc_accounting(const char *file, const char *function, const unsigned long line, size_t size) {
+#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
+ __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
+ __atomic_fetch_add(&memory_statistics.malloc_calls_made, 1, __ATOMIC_SEQ_CST);
+ __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST);
+#else
+ // this is for debugging - we don't care locking it
+ memory_statistics.memory_calls_made++;
+ memory_statistics.malloc_calls_made++;
+ memory_statistics.allocated_memory += size;
+#endif
+ print_allocations(file, function, line);
+}
+
+static inline void mmap_accounting(size_t size) {
+#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
+ __atomic_fetch_add(&memory_statistics.malloc_calls_made, 1, __ATOMIC_SEQ_CST);
+ __atomic_fetch_add(&memory_statistics.mmapped_memory, size, __ATOMIC_SEQ_CST);
+#else
+ // this is for debugging - we don't care locking it
+ memory_statistics.memory_calls_made++;
+ memory_statistics.mmapped_memory += size;
+#endif
+}
+
+static inline void calloc_accounting(const char *file, const char *function, const unsigned long line, size_t size) {
+#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
+ __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
+ __atomic_fetch_add(&memory_statistics.calloc_calls_made, 1, __ATOMIC_SEQ_CST);
+ __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST);
+#else
+ // this is for debugging - we don't care locking it
+ memory_statistics.memory_calls_made++;
+ memory_statistics.calloc_calls_made++;
+ memory_statistics.allocated_memory += size;
+#endif
+ print_allocations(file, function, line);
+}
+
+static inline void realloc_accounting(const char *file, const char *function, const unsigned long line, void *ptr, size_t size) {
+ (void)ptr;
+
+#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
+ __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
+ __atomic_fetch_add(&memory_statistics.realloc_calls_made, 1, __ATOMIC_SEQ_CST);
+ __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST);
+#else
+ // this is for debugging - we don't care locking it
+ memory_statistics.memory_calls_made++;
+ memory_statistics.realloc_calls_made++;
+ memory_statistics.allocated_memory += size;
+#endif
+ print_allocations(file, function, line);
+}
+
+static inline void strdup_accounting(const char *file, const char *function, const unsigned long line, const char *s) {
+ size_t size = strlen(s) + 1;
+
+#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
+ __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
+ __atomic_fetch_add(&memory_statistics.strdup_calls_made, 1, __ATOMIC_SEQ_CST);
+ __atomic_fetch_add(&memory_statistics.allocated_memory, size, __ATOMIC_SEQ_CST);
+#else
+ // this is for debugging - we don't care locking it
+ memory_statistics.memory_calls_made++;
+ memory_statistics.strdup_calls_made++;
+ memory_statistics.allocated_memory += size;
+#endif
+ print_allocations(file, function, line);
+}
+
+static inline void free_accounting(const char *file, const char *function, const unsigned long line, void *ptr) {
+ (void)file;
+ (void)function;
+ (void)line;
+
+ if(likely(ptr)) {
+#if defined(HAVE_C___ATOMIC) && !defined(NETDATA_NO_ATOMIC_INSTRUCTIONS)
+ __atomic_fetch_add(&memory_statistics.memory_calls_made, 1, __ATOMIC_SEQ_CST);
+ __atomic_fetch_add(&memory_statistics.free_calls_made, 1, __ATOMIC_SEQ_CST);
+#else
+ // this is for debugging - we don't care locking it
+ memory_statistics.memory_calls_made++;
+ memory_statistics.free_calls_made++;
+#endif
+ }
+}
+#endif
+
+#ifdef NETDATA_LOG_ALLOCATIONS
+char *strdupz_int(const char *file, const char *function, const unsigned long line, const char *s) {
+ strdup_accounting(file, function, line, s);
+#else