]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib: deregister memtypes on exit/unload
authorDavid Lamparter <equinox@opensourcerouting.org>
Sun, 20 Mar 2016 09:09:18 +0000 (10:09 +0100)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Mon, 19 Sep 2016 20:31:08 +0000 (16:31 -0400)
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>
lib/memory.h

index 8f7d85a98303ef3a3c724df6bc094df44f987a4f..d287f229f7d1d1cf0766b8dbf3545edbeb4863ac 100644 (file)
@@ -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)