]>
git.proxmox.com Git - mirror_frr.git/blob - lib/memory.h
1 // SPDX-License-Identifier: ISC
3 * Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc.
6 #ifndef _QUAGGA_MEMORY_H
7 #define _QUAGGA_MEMORY_H
12 #include <frratomic.h>
19 #if defined(HAVE_MALLOC_SIZE) && !defined(HAVE_MALLOC_USABLE_SIZE)
20 #define malloc_usable_size(x) malloc_size(x)
21 #define HAVE_MALLOC_USABLE_SIZE
26 struct memtype
*next
, **ref
;
28 atomic_size_t n_alloc
;
31 #ifdef HAVE_MALLOC_USABLE_SIZE
33 atomic_size_t max_size
;
38 struct memgroup
*next
, **ref
;
39 struct memtype
*types
, **insert
;
41 /* ignore group on dumping memleaks at exit */
48 * DECLARE_MGROUP(MYDAEMON);
49 * DECLARE_MTYPE(MYDAEMON_COMMON);
52 * DEFINE_MGROUP(MYDAEMON, "my daemon memory");
53 * DEFINE_MTYPE(MYDAEMON, MYDAEMON_COMMON,
54 * "this mtype is used in multiple files in mydaemon");
55 * foo = qmalloc(MTYPE_MYDAEMON_COMMON, sizeof(*foo))
58 * bar = qmalloc(MTYPE_MYDAEMON_COMMON, sizeof(*bar))
60 * DEFINE_MTYPE_STATIC(MYDAEMON, MYDAEMON_IO,
61 * "this mtype is used only in this file");
62 * baz = qmalloc(MTYPE_MYDAEMON_IO, sizeof(*baz))
64 * Note: Naming conventions (MGROUP_ and MTYPE_ prefixes are enforced
65 * by not having these as part of the macro arguments)
66 * Note: MTYPE_* are symbols to the compiler (of type struct memtype *),
67 * but MGROUP_* aren't.
70 #define DECLARE_MGROUP(name) extern struct memgroup _mg_##name
71 #define _DEFINE_MGROUP(mname, desc, ...) \
72 struct memgroup _mg_##mname \
73 __attribute__((section(".data.mgroups"))) = { \
81 static void _mginit_##mname(void) __attribute__((_CONSTRUCTOR(1000))); \
82 static void _mginit_##mname(void) \
84 extern struct memgroup **mg_insert; \
85 _mg_##mname.ref = mg_insert; \
86 *mg_insert = &_mg_##mname; \
87 mg_insert = &_mg_##mname.next; \
89 static void _mgfini_##mname(void) __attribute__((_DESTRUCTOR(1000))); \
90 static void _mgfini_##mname(void) \
92 if (_mg_##mname.next) \
93 _mg_##mname.next->ref = _mg_##mname.ref; \
94 *_mg_##mname.ref = _mg_##mname.next; \
96 MACRO_REQUIRE_SEMICOLON() /* end */
98 #define DEFINE_MGROUP(mname, desc) \
99 _DEFINE_MGROUP(mname, desc, )
100 #define DEFINE_MGROUP_ACTIVEATEXIT(mname, desc) \
101 _DEFINE_MGROUP(mname, desc, .active_at_exit = true)
103 #define DECLARE_MTYPE(name) \
104 extern struct memtype MTYPE_##name[1] \
107 #define DEFINE_MTYPE_ATTR(group, mname, attr, desc) \
108 attr struct memtype MTYPE_##mname[1] \
109 __attribute__((section(".data.mtypes"))) = { { \
116 static void _mtinit_##mname(void) __attribute__((_CONSTRUCTOR(1001))); \
117 static void _mtinit_##mname(void) \
119 if (_mg_##group.insert == NULL) \
120 _mg_##group.insert = &_mg_##group.types; \
121 MTYPE_##mname->ref = _mg_##group.insert; \
122 *_mg_##group.insert = MTYPE_##mname; \
123 _mg_##group.insert = &MTYPE_##mname->next; \
125 static void _mtfini_##mname(void) __attribute__((_DESTRUCTOR(1001))); \
126 static void _mtfini_##mname(void) \
128 if (MTYPE_##mname->next) \
129 MTYPE_##mname->next->ref = MTYPE_##mname->ref; \
130 *MTYPE_##mname->ref = MTYPE_##mname->next; \
132 MACRO_REQUIRE_SEMICOLON() /* end */
134 #define DEFINE_MTYPE(group, name, desc) \
135 DEFINE_MTYPE_ATTR(group, name, , desc) \
138 #define DEFINE_MTYPE_STATIC(group, name, desc) \
139 DEFINE_MTYPE_ATTR(group, name, static, desc) \
146 extern void *qmalloc(struct memtype
*mt
, size_t size
)
147 __attribute__((malloc
, _ALLOC_SIZE(2), nonnull(1) _RET_NONNULL
));
148 extern void *qcalloc(struct memtype
*mt
, size_t size
)
149 __attribute__((malloc
, _ALLOC_SIZE(2), nonnull(1) _RET_NONNULL
));
150 extern void *qrealloc(struct memtype
*mt
, void *ptr
, size_t size
)
151 __attribute__((_ALLOC_SIZE(3), nonnull(1) _RET_NONNULL
));
152 extern void *qstrdup(struct memtype
*mt
, const char *str
)
153 __attribute__((malloc
, nonnull(1) _RET_NONNULL
));
154 extern void qcountfree(struct memtype
*mt
, void *ptr
)
155 __attribute__((nonnull(1)));
156 extern void qfree(struct memtype
*mt
, void *ptr
) __attribute__((nonnull(1)));
158 #define XMALLOC(mtype, size) qmalloc(mtype, size)
159 #define XCALLOC(mtype, size) qcalloc(mtype, size)
160 #define XREALLOC(mtype, ptr, size) qrealloc(mtype, ptr, size)
161 #define XSTRDUP(mtype, str) qstrdup(mtype, str)
162 #define XCOUNTFREE(mtype, ptr) qcountfree(mtype, ptr)
163 #define XFREE(mtype, ptr) \
169 static inline size_t mtype_stats_alloc(struct memtype
*mt
)
174 /* NB: calls are ordered by memgroup; and there is a call with mt == NULL for
175 * each memgroup (so that a header can be printed, and empty memgroups show)
177 * return value: 0: continue, !0: abort walk. qmem_walk will return the
178 * last value from qmem_walk_fn. */
179 typedef int qmem_walk_fn(void *arg
, struct memgroup
*mg
, struct memtype
*mt
);
180 extern int qmem_walk(qmem_walk_fn
*func
, void *arg
);
181 extern int log_memstats(FILE *fp
, const char *);
182 #define log_memstats_stderr(prefix) log_memstats(stderr, prefix)
184 extern __attribute__((__noreturn__
)) void memory_oom(size_t size
,
191 #endif /* _QUAGGA_MEMORY_H */