]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: debug/memstats: permit to pass the size to free()
authorWilly Tarreau <w@1wt.eu>
Tue, 9 Aug 2022 07:08:18 +0000 (09:08 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 9 Aug 2022 07:11:27 +0000 (09:11 +0200)
Right now the free() call is not intercepted since all this is done
using macros and that would break a lot of stuff. Instead a __free()
macro was provided but never used. In addition it used to only report
a zero size, which is not very convenient.

With this patch comes a better solution. Instead it provides a new
will_free() macro that can be prepended before a call to free(). It
only keeps the counters up to date, and also supports being passed a
size. The pool_free_area() command now uses it, which finally allows
the stats to look correct:

  pool-os.h:38   MALLOC  size:   5802127832  calls:   3868044  size/call:   1500
  pool-os.h:47     FREE  size:   5800041576  calls:   3867444  size/call:   1499

The few other places directly calling free() could now be instrumented to
use this and to pass the correct sizeof() when known.

include/haproxy/bug.h
include/haproxy/pool-os.h

index f4cc71b4bab29d1ff5c7bd2dc40ed9c8ea295867..d65c1567c3388da70ecb1fd88277c6bcf1168881 100644 (file)
@@ -265,11 +265,14 @@ struct mem_stats {
 })
 
 /* note: we can't redefine free() because we have a few variables and struct
- * members called like this.
+ * members called like this. This one may be used before a call to free(),
+ * and when known, the size should be indicated, otherwise pass zero. The
+ * pointer is used to know whether the call should be accounted for (null is
+ * ignored).
  */
-#undef __free
-#define __free(x)  ({                                                  \
-       void *__x = (x);                                                \
+#undef will_free
+#define will_free(x, y)  ({                                            \
+       void *__x = (x); size_t __y = (y);                              \
        static struct mem_stats _ __attribute__((used,__section__("mem_stats"),__aligned__(sizeof(void*)))) = { \
                .file = __FILE__, .line = __LINE__,                     \
                .type = MEM_STATS_TYPE_FREE,                            \
@@ -277,9 +280,10 @@ struct mem_stats {
        };                                                              \
        HA_WEAK("__start_mem_stats");                                   \
        HA_WEAK("__stop_mem_stats");                                    \
-       if (__x)                                                        \
+       if (__x) {                                                      \
                _HA_ATOMIC_INC(&_.calls);                               \
-       free(__x);                                                      \
+               _HA_ATOMIC_ADD(&_.size, __y);                           \
+       }                                                               \
 })
 
 #undef ha_free
@@ -345,6 +349,10 @@ struct mem_stats {
        _HA_ATOMIC_ADD(&_.size, __y);                                   \
        strdup(__x);                                                    \
 })
+#else // DEBUG_MEM_STATS
+
+#define will_free(x, y) do { } while (0)
+
 #endif /* DEBUG_MEM_STATS*/
 
 #endif /* _HAPROXY_BUG_H */
index ef3c9353cc987c0414ad482b2fc6ab97665de448..d6612e8fe01076b12e6191bd8c926d8297d4bf03 100644 (file)
@@ -44,6 +44,7 @@ static forceinline void *pool_alloc_area(size_t size)
  */
 static forceinline void pool_free_area(void *area, size_t __maybe_unused size)
 {
+       will_free(area, size);
        free(area);
 }