]>
git.proxmox.com Git - mirror_frr.git/blob - lib/memory.h
2 * Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc.
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #ifndef _QUAGGA_MEMORY_H
18 #define _QUAGGA_MEMORY_H
22 #include <frratomic.h>
25 #define array_size(ar) (sizeof(ar) / sizeof(ar[0]))
27 #if defined(HAVE_MALLOC_SIZE) && !defined(HAVE_MALLOC_USABLE_SIZE)
28 #define malloc_usable_size(x) malloc_size(x)
29 #define HAVE_MALLOC_USABLE_SIZE
34 struct memtype
*next
, **ref
;
36 _Atomic
size_t n_alloc
;
39 #ifdef HAVE_MALLOC_USABLE_SIZE
41 _Atomic
size_t max_size
;
46 struct memgroup
*next
, **ref
;
47 struct memtype
*types
, **insert
;
54 * DECLARE_MGROUP(MYDAEMON)
55 * DECLARE_MTYPE(MYDAEMON_COMMON)
58 * DEFINE_MGROUP(MYDAEMON, "my daemon memory")
59 * DEFINE_MTYPE(MYDAEMON, MYDAEMON_COMMON,
60 * "this mtype is used in multiple files in mydaemon")
61 * foo = qmalloc(MTYPE_MYDAEMON_COMMON, sizeof(*foo))
64 * bar = qmalloc(MTYPE_MYDAEMON_COMMON, sizeof(*bar))
66 * DEFINE_MTYPE_STATIC(MYDAEMON, MYDAEMON_IO,
67 * "this mtype is used only in this file")
68 * baz = qmalloc(MTYPE_MYDAEMON_IO, sizeof(*baz))
70 * Note: Naming conventions (MGROUP_ and MTYPE_ prefixes are enforced
71 * by not having these as part of the macro arguments)
72 * Note: MTYPE_* are symbols to the compiler (of type struct memtype *),
73 * but MGROUP_* aren't.
76 #define DECLARE_MGROUP(name) extern struct memgroup _mg_##name;
77 #define DEFINE_MGROUP(mname, desc) \
78 struct memgroup _mg_##mname \
79 __attribute__((section(".data.mgroups"))) = { \
86 static void _mginit_##mname(void) __attribute__((_CONSTRUCTOR(1000))); \
87 static void _mginit_##mname(void) \
89 extern struct memgroup **mg_insert; \
90 _mg_##mname.ref = mg_insert; \
91 *mg_insert = &_mg_##mname; \
92 mg_insert = &_mg_##mname.next; \
94 static void _mgfini_##mname(void) __attribute__((_DESTRUCTOR(1000))); \
95 static void _mgfini_##mname(void) \
97 if (_mg_##mname.next) \
98 _mg_##mname.next->ref = _mg_##mname.ref; \
99 *_mg_##mname.ref = _mg_##mname.next; \
103 #define DECLARE_MTYPE(name) \
104 extern struct memtype _mt_##name; \
105 static struct memtype *const MTYPE_##name = &_mt_##name;
107 #define DEFINE_MTYPE_ATTR(group, mname, attr, desc) \
108 attr struct memtype _mt_##mname \
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 _mt_##mname.ref = _mg_##group.insert; \
122 *_mg_##group.insert = &_mt_##mname; \
123 _mg_##group.insert = &_mt_##mname.next; \
125 static void _mtfini_##mname(void) __attribute__((_DESTRUCTOR(1001))); \
126 static void _mtfini_##mname(void) \
128 if (_mt_##mname.next) \
129 _mt_##mname.next->ref = _mt_##mname.ref; \
130 *_mt_##mname.ref = _mt_##mname.next; \
133 #define DEFINE_MTYPE(group, name, desc) DEFINE_MTYPE_ATTR(group, name, , desc)
134 #define DEFINE_MTYPE_STATIC(group, name, desc) \
135 DEFINE_MTYPE_ATTR(group, name, static, desc) \
136 static struct memtype *const MTYPE_##name = &_mt_##name;
140 DECLARE_MTYPE(PREFIX_FLOWSPEC
)
143 extern void *qmalloc(struct memtype
*mt
, size_t size
)
144 __attribute__((malloc
, _ALLOC_SIZE(2), nonnull(1) _RET_NONNULL
));
145 extern void *qcalloc(struct memtype
*mt
, size_t size
)
146 __attribute__((malloc
, _ALLOC_SIZE(2), nonnull(1) _RET_NONNULL
));
147 extern void *qrealloc(struct memtype
*mt
, void *ptr
, size_t size
)
148 __attribute__((_ALLOC_SIZE(3), nonnull(1) _RET_NONNULL
));
149 extern void *qstrdup(struct memtype
*mt
, const char *str
)
150 __attribute__((malloc
, nonnull(1) _RET_NONNULL
));
151 extern void qfree(struct memtype
*mt
, void *ptr
) __attribute__((nonnull(1)));
153 #define XMALLOC(mtype, size) qmalloc(mtype, size)
154 #define XCALLOC(mtype, size) qcalloc(mtype, size)
155 #define XREALLOC(mtype, ptr, size) qrealloc(mtype, ptr, size)
156 #define XSTRDUP(mtype, str) qstrdup(mtype, str)
157 #define XFREE(mtype, ptr) \
163 static inline size_t mtype_stats_alloc(struct memtype
*mt
)
168 /* NB: calls are ordered by memgroup; and there is a call with mt == NULL for
169 * each memgroup (so that a header can be printed, and empty memgroups show)
171 * return value: 0: continue, !0: abort walk. qmem_walk will return the
172 * last value from qmem_walk_fn. */
173 typedef int qmem_walk_fn(void *arg
, struct memgroup
*mg
, struct memtype
*mt
);
174 extern int qmem_walk(qmem_walk_fn
*func
, void *arg
);
175 extern int log_memstats(FILE *fp
, const char *);
176 #define log_memstats_stderr(prefix) log_memstats(stderr, prefix)
178 extern void memory_oom(size_t size
, const char *name
);
180 #endif /* _QUAGGA_MEMORY_H */