summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Lamparter <equinox@opensourcerouting.org>2016-03-20 10:09:18 +0100
committerDonald Sharp <sharpd@cumulusnetworks.com>2016-09-19 16:31:08 -0400
commitaf2d0efcac11723f9be52a3dae22dec31d157e24 (patch)
treec54125702276e38cd5555214b51e74e263681967
parent802e2cdd3ad770f3e1f360437dcf910dc3e81c04 (diff)
lib: deregister memtypes on exit/unload
This is useful for DSO modules in order to get support for unloading them dynamically. It also runs on exit, which doesn't matter much. At some future point, the code could be extended to check that allocation counts are 0 on unloading a module. Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
-rw-r--r--lib/memory.h31
1 files changed, 25 insertions, 6 deletions
diff --git a/lib/memory.h b/lib/memory.h
index 8f7d85a983..d287f229f7 100644
--- a/lib/memory.h
+++ b/lib/memory.h
@@ -30,7 +30,7 @@
#define SIZE_VAR ~0UL
struct memtype
{
- struct memtype *next;
+ struct memtype *next, **ref;
const char *name;
size_t n_alloc;
size_t size;
@@ -38,7 +38,7 @@ struct memtype
struct memgroup
{
- struct memgroup *next;
+ struct memgroup *next, **ref;
struct memtype *types, **insert;
const char *name;
};
@@ -54,6 +54,7 @@ struct memgroup
# endif
# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
# define _CONSTRUCTOR(x) constructor(x)
+# define _DESTRUCTOR(x) destructor(x)
# define _ALLOC_SIZE(x) alloc_size(x)
# endif
#endif
@@ -61,6 +62,7 @@ struct memgroup
#ifdef __sun
/* Solaris doesn't do constructor priorities due to linker restrictions */
# undef _CONSTRUCTOR
+# undef _DESTRUCTOR
#endif
#ifndef _RET_NONNULL
@@ -69,6 +71,9 @@ struct memgroup
#ifndef _CONSTRUCTOR
# define _CONSTRUCTOR(x) constructor
#endif
+#ifndef _DESTRUCTOR
+# define _DESTRUCTOR(x) destructor
+#endif
#ifndef _ALLOC_SIZE
# define _ALLOC_SIZE(x)
#endif
@@ -104,14 +109,21 @@ struct memgroup
struct memgroup _mg_##mname \
__attribute__ ((section (".data.mgroups"))) = { \
.name = desc, \
- .types = NULL, .next = NULL, .insert = NULL, \
+ .types = NULL, .next = NULL, .insert = NULL, .ref = NULL, \
}; \
static void _mginit_##mname (void) \
__attribute__ ((_CONSTRUCTOR (1000))); \
static void _mginit_##mname (void) \
{ extern struct memgroup **mg_insert; \
+ _mg_##mname.ref = mg_insert; \
*mg_insert = &_mg_##mname; \
- mg_insert = &_mg_##mname.next; }
+ mg_insert = &_mg_##mname.next; } \
+ static void _mgfini_##mname (void) \
+ __attribute__ ((_DESTRUCTOR (1000))); \
+ static void _mgfini_##mname (void) \
+ { if (_mg_##mname.next) \
+ _mg_##mname.next->ref = _mg_##mname.ref; \
+ *_mg_##mname.ref = _mg_##mname.next; }
#define DECLARE_MTYPE(name) \
@@ -122,15 +134,22 @@ struct memgroup
attr struct memtype _mt_##mname \
__attribute__ ((section (".data.mtypes"))) = { \
.name = desc, \
- .next = NULL, .n_alloc = 0, .size = 0, \
+ .next = NULL, .n_alloc = 0, .size = 0, .ref = NULL, \
}; \
static void _mtinit_##mname (void) \
__attribute__ ((_CONSTRUCTOR (1001))); \
static void _mtinit_##mname (void) \
{ if (_mg_##group.insert == NULL) \
_mg_##group.insert = &_mg_##group.types; \
+ _mt_##mname.ref = _mg_##group.insert; \
*_mg_##group.insert = &_mt_##mname; \
- _mg_##group.insert = &_mt_##mname.next; }
+ _mg_##group.insert = &_mt_##mname.next; } \
+ static void _mtfini_##mname (void) \
+ __attribute__ ((_DESTRUCTOR (1001))); \
+ static void _mtfini_##mname (void) \
+ { if (_mt_##mname.next) \
+ _mt_##mname.next->ref = _mt_##mname.ref; \
+ *_mt_##mname.ref = _mt_##mname.next; }
#define DEFINE_MTYPE(group, name, desc) \
DEFINE_MTYPE_ATTR(group, name, , desc)