]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/jemalloc/include/jemalloc/internal/log.h
Update jemalloc to version 5.1.0.
[FreeBSD/FreeBSD.git] / contrib / jemalloc / include / jemalloc / internal / log.h
1 #ifndef JEMALLOC_INTERNAL_LOG_H
2 #define JEMALLOC_INTERNAL_LOG_H
3
4 #include "jemalloc/internal/atomic.h"
5 #include "jemalloc/internal/malloc_io.h"
6 #include "jemalloc/internal/mutex.h"
7
8 #ifdef JEMALLOC_LOG
9 #  define JEMALLOC_LOG_VAR_BUFSIZE 1000
10 #else
11 #  define JEMALLOC_LOG_VAR_BUFSIZE 1
12 #endif
13
14 #define JEMALLOC_LOG_BUFSIZE 4096
15
16 /*
17  * The log malloc_conf option is a '|'-delimited list of log_var name segments
18  * which should be logged.  The names are themselves hierarchical, with '.' as
19  * the delimiter (a "segment" is just a prefix in the log namespace).  So, if
20  * you have:
21  *
22  * log("arena", "log msg for arena"); // 1
23  * log("arena.a", "log msg for arena.a"); // 2
24  * log("arena.b", "log msg for arena.b"); // 3
25  * log("arena.a.a", "log msg for arena.a.a"); // 4
26  * log("extent.a", "log msg for extent.a"); // 5
27  * log("extent.b", "log msg for extent.b"); // 6
28  *
29  * And your malloc_conf option is "log=arena.a|extent", then lines 2, 4, 5, and
30  * 6 will print at runtime.  You can enable logging from all log vars by
31  * writing "log=.".
32  *
33  * None of this should be regarded as a stable API for right now.  It's intended
34  * as a debugging interface, to let us keep around some of our printf-debugging
35  * statements.
36  */
37
38 extern char log_var_names[JEMALLOC_LOG_VAR_BUFSIZE];
39 extern atomic_b_t log_init_done;
40
41 typedef struct log_var_s log_var_t;
42 struct log_var_s {
43         /*
44          * Lowest bit is "inited", second lowest is "enabled".  Putting them in
45          * a single word lets us avoid any fences on weak architectures.
46          */
47         atomic_u_t state;
48         const char *name;
49 };
50
51 #define LOG_NOT_INITIALIZED 0U
52 #define LOG_INITIALIZED_NOT_ENABLED 1U
53 #define LOG_ENABLED 2U
54
55 #define LOG_VAR_INIT(name_str) {ATOMIC_INIT(LOG_NOT_INITIALIZED), name_str}
56
57 /*
58  * Returns the value we should assume for state (which is not necessarily
59  * accurate; if logging is done before logging has finished initializing, then
60  * we default to doing the safe thing by logging everything).
61  */
62 unsigned log_var_update_state(log_var_t *log_var);
63
64 /* We factor out the metadata management to allow us to test more easily. */
65 #define log_do_begin(log_var)                                           \
66 if (config_log) {                                                       \
67         unsigned log_state = atomic_load_u(&(log_var).state,            \
68             ATOMIC_RELAXED);                                            \
69         if (unlikely(log_state == LOG_NOT_INITIALIZED)) {               \
70                 log_state = log_var_update_state(&(log_var));           \
71                 assert(log_state != LOG_NOT_INITIALIZED);               \
72         }                                                               \
73         if (log_state == LOG_ENABLED) {                                 \
74                 {
75                         /* User code executes here. */
76 #define log_do_end(log_var)                                             \
77                 }                                                       \
78         }                                                               \
79 }
80
81 /*
82  * MSVC has some preprocessor bugs in its expansion of __VA_ARGS__ during
83  * preprocessing.  To work around this, we take all potential extra arguments in
84  * a var-args functions.  Since a varargs macro needs at least one argument in
85  * the "...", we accept the format string there, and require that the first
86  * argument in this "..." is a const char *.
87  */
88 static inline void
89 log_impl_varargs(const char *name, ...) {
90         char buf[JEMALLOC_LOG_BUFSIZE];
91         va_list ap;
92
93         va_start(ap, name);
94         const char *format = va_arg(ap, const char *);
95         size_t dst_offset = 0;
96         dst_offset += malloc_snprintf(buf, JEMALLOC_LOG_BUFSIZE, "%s: ", name);
97         dst_offset += malloc_vsnprintf(buf + dst_offset,
98             JEMALLOC_LOG_BUFSIZE - dst_offset, format, ap);
99         dst_offset += malloc_snprintf(buf + dst_offset,
100             JEMALLOC_LOG_BUFSIZE - dst_offset, "\n");
101         va_end(ap);
102
103         malloc_write(buf);
104 }
105
106 /* Call as log("log.var.str", "format_string %d", arg_for_format_string); */
107 #define LOG(log_var_str, ...)                                           \
108 do {                                                                    \
109         static log_var_t log_var = LOG_VAR_INIT(log_var_str);           \
110         log_do_begin(log_var)                                           \
111                 log_impl_varargs((log_var).name, __VA_ARGS__);          \
112         log_do_end(log_var)                                             \
113 } while (0)
114
115 #endif /* JEMALLOC_INTERNAL_LOG_H */