]>
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
21 #include <frratomic.h>
23 #define array_size(ar) (sizeof(ar) / sizeof(ar[0]))
27 struct memtype
*next
, **ref
;
29 _Atomic
size_t n_alloc
;
34 struct memgroup
*next
, **ref
;
35 struct memtype
*types
, **insert
;
39 #if defined(__clang__)
40 # if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 5)
41 # define _RET_NONNULL , returns_nonnull
43 # define _CONSTRUCTOR(x) constructor(x)
44 #elif defined(__GNUC__)
45 # if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
46 # define _RET_NONNULL , returns_nonnull
48 # if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
49 # define _CONSTRUCTOR(x) constructor(x)
50 # define _DESTRUCTOR(x) destructor(x)
51 # define _ALLOC_SIZE(x) alloc_size(x)
56 /* Solaris doesn't do constructor priorities due to linker restrictions */
65 # define _CONSTRUCTOR(x) constructor
68 # define _DESTRUCTOR(x) destructor
71 # define _ALLOC_SIZE(x)
77 * DECLARE_MGROUP(MYDAEMON)
78 * DECLARE_MTYPE(MYDAEMON_COMMON)
81 * DEFINE_MGROUP(MYDAEMON, "my daemon memory")
82 * DEFINE_MTYPE(MYDAEMON, MYDAEMON_COMMON,
83 * "this mtype is used in multiple files in mydaemon")
84 * foo = qmalloc(MTYPE_MYDAEMON_COMMON, sizeof(*foo))
87 * bar = qmalloc(MTYPE_MYDAEMON_COMMON, sizeof(*bar))
89 * DEFINE_MTYPE_STATIC(MYDAEMON, MYDAEMON_IO,
90 * "this mtype is used only in this file")
91 * baz = qmalloc(MTYPE_MYDAEMON_IO, sizeof(*baz))
93 * Note: Naming conventions (MGROUP_ and MTYPE_ prefixes are enforced
94 * by not having these as part of the macro arguments)
95 * Note: MTYPE_* are symbols to the compiler (of type struct memtype *),
96 * but MGROUP_* aren't.
99 #define DECLARE_MGROUP(name) \
100 extern struct memgroup _mg_##name;
101 #define DEFINE_MGROUP(mname, desc) \
102 struct memgroup _mg_##mname \
103 __attribute__ ((section (".data.mgroups"))) = { \
105 .types = NULL, .next = NULL, .insert = NULL, .ref = NULL, \
107 static void _mginit_##mname (void) \
108 __attribute__ ((_CONSTRUCTOR (1000))); \
109 static void _mginit_##mname (void) \
110 { extern struct memgroup **mg_insert; \
111 _mg_##mname.ref = mg_insert; \
112 *mg_insert = &_mg_##mname; \
113 mg_insert = &_mg_##mname.next; } \
114 static void _mgfini_##mname (void) \
115 __attribute__ ((_DESTRUCTOR (1000))); \
116 static void _mgfini_##mname (void) \
117 { if (_mg_##mname.next) \
118 _mg_##mname.next->ref = _mg_##mname.ref; \
119 *_mg_##mname.ref = _mg_##mname.next; }
122 #define DECLARE_MTYPE(name) \
123 extern struct memtype _mt_##name; \
124 static struct memtype * const MTYPE_ ## name = &_mt_##name;
126 #define DEFINE_MTYPE_ATTR(group, mname, attr, desc) \
127 attr struct memtype _mt_##mname \
128 __attribute__ ((section (".data.mtypes"))) = { \
130 .next = NULL, .n_alloc = 0, .size = 0, .ref = NULL, \
132 static void _mtinit_##mname (void) \
133 __attribute__ ((_CONSTRUCTOR (1001))); \
134 static void _mtinit_##mname (void) \
135 { if (_mg_##group.insert == NULL) \
136 _mg_##group.insert = &_mg_##group.types; \
137 _mt_##mname.ref = _mg_##group.insert; \
138 *_mg_##group.insert = &_mt_##mname; \
139 _mg_##group.insert = &_mt_##mname.next; } \
140 static void _mtfini_##mname (void) \
141 __attribute__ ((_DESTRUCTOR (1001))); \
142 static void _mtfini_##mname (void) \
143 { if (_mt_##mname.next) \
144 _mt_##mname.next->ref = _mt_##mname.ref; \
145 *_mt_##mname.ref = _mt_##mname.next; }
147 #define DEFINE_MTYPE(group, name, desc) \
148 DEFINE_MTYPE_ATTR(group, name, , desc)
149 #define DEFINE_MTYPE_STATIC(group, name, desc) \
150 DEFINE_MTYPE_ATTR(group, name, static, desc) \
151 static struct memtype * const MTYPE_ ## name = &_mt_##name;
157 extern void *qmalloc(struct memtype
*mt
, size_t size
)
158 __attribute__ ((malloc
, _ALLOC_SIZE(2), nonnull (1) _RET_NONNULL
));
159 extern void *qcalloc(struct memtype
*mt
, size_t size
)
160 __attribute__ ((malloc
, _ALLOC_SIZE(2), nonnull (1) _RET_NONNULL
));
161 extern void *qrealloc(struct memtype
*mt
, void *ptr
, size_t size
)
162 __attribute__ ((_ALLOC_SIZE(3), nonnull (1) _RET_NONNULL
));
163 extern void *qstrdup (struct memtype
*mt
, const char *str
)
164 __attribute__ ((malloc
, nonnull (1) _RET_NONNULL
));
165 extern void qfree(struct memtype
*mt
, void *ptr
)
166 __attribute__ ((nonnull (1)));
168 #define XMALLOC(mtype, size) qmalloc(mtype, size)
169 #define XCALLOC(mtype, size) qcalloc(mtype, size)
170 #define XREALLOC(mtype, ptr, size) qrealloc(mtype, ptr, size)
171 #define XSTRDUP(mtype, str) qstrdup(mtype, str)
172 #define XFREE(mtype, ptr) do { qfree(mtype, ptr); ptr = NULL; } \
175 static inline size_t mtype_stats_alloc(struct memtype
*mt
)
180 /* NB: calls are ordered by memgroup; and there is a call with mt == NULL for
181 * each memgroup (so that a header can be printed, and empty memgroups show)
183 * return value: 0: continue, !0: abort walk. qmem_walk will return the
184 * last value from qmem_walk_fn. */
185 typedef int qmem_walk_fn(void *arg
, struct memgroup
*mg
, struct memtype
*mt
);
186 extern int qmem_walk(qmem_walk_fn
*func
, void *arg
);
187 extern void log_memstats_stderr(const char *);
189 extern void memory_oom(size_t size
, const char *name
);
191 #endif /* _QUAGGA_MEMORY_H */