]> git.proxmox.com Git - mirror_frr.git/blobdiff - lib/memory.h
lib: add #pragma's to ignore flex sign cmp error
[mirror_frr.git] / lib / memory.h
index 52e3bc11ddb3c9ab97ab4d10b0be58b899a103db..9e8803a8b2a6dbc1881df66e050cfe83c2072c4a 100644 (file)
-/* Memory management routine
-   Copyright (C) 1998 Kunihiro Ishiguro
-
-This file is part of GNU Zebra.
-
-GNU Zebra is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-GNU Zebra is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
+/*
+ * Copyright (c) 2015-16  David Lamparter, for NetDEF, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _QUAGGA_MEMORY_H
+#define _QUAGGA_MEMORY_H
+
+#include <stdlib.h>
+#include <frratomic.h>
+
+#define array_size(ar) (sizeof(ar) / sizeof(ar[0]))
+
+#define SIZE_VAR ~0UL
+struct memtype {
+       struct memtype *next, **ref;
+       const char *name;
+       _Atomic size_t n_alloc;
+       _Atomic size_t size;
+};
 
-You should have received a copy of the GNU General Public License
-along with GNU Zebra; see the file COPYING.  If not, write to the Free
-Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+struct memgroup {
+       struct memgroup *next, **ref;
+       struct memtype *types, **insert;
+       const char *name;
+};
 
-#ifndef _ZEBRA_MEMORY_H
-#define _ZEBRA_MEMORY_H
+#if defined(__clang__)
+# if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 5)
+#  define _RET_NONNULL  , returns_nonnull
+# endif
+# define _CONSTRUCTOR(x) constructor(x)
+#elif defined(__GNUC__)
+# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
+#  define _RET_NONNULL  , returns_nonnull
+# 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
+
+#ifdef __sun
+/* Solaris doesn't do constructor priorities due to linker restrictions */
+# undef _CONSTRUCTOR
+# undef _DESTRUCTOR
+#endif
+
+#ifndef _RET_NONNULL
+# define _RET_NONNULL
+#endif
+#ifndef _CONSTRUCTOR
+# define _CONSTRUCTOR(x) constructor
+#endif
+#ifndef _DESTRUCTOR
+# define _DESTRUCTOR(x) destructor
+#endif
+#ifndef _ALLOC_SIZE
+# define _ALLOC_SIZE(x)
+#endif
+
+/* macro usage:
+ *
+ *  mydaemon.h
+ *    DECLARE_MGROUP(MYDAEMON)
+ *    DECLARE_MTYPE(MYDAEMON_COMMON)
+ *
+ *  mydaemon.c
+ *    DEFINE_MGROUP(MYDAEMON, "my daemon memory")
+ *    DEFINE_MTYPE(MYDAEMON, MYDAEMON_COMMON,
+ *                   "this mtype is used in multiple files in mydaemon")
+ *    foo = qmalloc(MTYPE_MYDAEMON_COMMON, sizeof(*foo))
+ *
+ *  mydaemon_io.c
+ *    bar = qmalloc(MTYPE_MYDAEMON_COMMON, sizeof(*bar))
+ *
+ *    DEFINE_MTYPE_STATIC(MYDAEMON, MYDAEMON_IO,
+ *                          "this mtype is used only in this file")
+ *    baz = qmalloc(MTYPE_MYDAEMON_IO, sizeof(*baz))
+ *
+ *  Note:  Naming conventions (MGROUP_ and MTYPE_ prefixes are enforced
+ *         by not having these as part of the macro arguments)
+ *  Note:  MTYPE_* are symbols to the compiler (of type struct memtype *),
+ *         but MGROUP_* aren't.
+ */
+
+#define DECLARE_MGROUP(name) \
+       extern struct memgroup _mg_##name;
+#define DEFINE_MGROUP(mname, desc) \
+       struct memgroup _mg_##mname \
+       __attribute__ ((section (".data.mgroups"))) = { \
+               .name = desc, \
+               .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; } \
+       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) \
+       extern struct memtype _mt_##name; \
+       static struct memtype * const MTYPE_ ## name = &_mt_##name;
+
+#define DEFINE_MTYPE_ATTR(group, mname, attr, desc) \
+       attr struct memtype _mt_##mname \
+       __attribute__ ((section (".data.mtypes"))) = { \
+               .name = desc, \
+               .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; } \
+       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)
+#define DEFINE_MTYPE_STATIC(group, name, desc) \
+       DEFINE_MTYPE_ATTR(group, name, static, desc) \
+       static struct memtype * const MTYPE_ ## name = &_mt_##name;
+
+DECLARE_MGROUP(LIB)
+DECLARE_MTYPE(TMP)
+
+
+extern void *qmalloc(struct memtype *mt, size_t size)
+       __attribute__ ((malloc, _ALLOC_SIZE(2), nonnull (1) _RET_NONNULL));
+extern void *qcalloc(struct memtype *mt, size_t size)
+       __attribute__ ((malloc, _ALLOC_SIZE(2), nonnull (1) _RET_NONNULL));
+extern void *qrealloc(struct memtype *mt, void *ptr, size_t size)
+       __attribute__ ((_ALLOC_SIZE(3), nonnull (1) _RET_NONNULL));
+extern void *qstrdup (struct memtype *mt, const char *str)
+       __attribute__ ((malloc, nonnull (1) _RET_NONNULL));
+extern void qfree(struct memtype *mt, void *ptr)
+       __attribute__ ((nonnull (1)));
+
+#define XMALLOC(mtype, size)           qmalloc(mtype, size)
+#define XCALLOC(mtype, size)           qcalloc(mtype, size)
+#define XREALLOC(mtype, ptr, size)     qrealloc(mtype, ptr, size)
+#define XSTRDUP(mtype, str)            qstrdup(mtype, str)
+#define XFREE(mtype, ptr)              do { qfree(mtype, ptr); ptr = NULL; } \
+                                       while (0)
+
+static inline size_t mtype_stats_alloc(struct memtype *mt)
+{
+       return mt->n_alloc;
+}
 
-/* #define MEMORY_LOG */
+/* NB: calls are ordered by memgroup; and there is a call with mt == NULL for
+ * each memgroup (so that a header can be printed, and empty memgroups show)
+ *
+ * return value: 0: continue, !0: abort walk.  qmem_walk will return the
+ * last value from qmem_walk_fn. */
+typedef int qmem_walk_fn(void *arg, struct memgroup *mg, struct memtype *mt);
+extern int qmem_walk(qmem_walk_fn *func, void *arg);
+extern void log_memstats_stderr(const char *);
 
-/* For tagging memory, below is the type of the memory. */
-enum
-{
-  MTYPE_TMP = 1,
-  MTYPE_STRVEC,
-  MTYPE_VECTOR,
-  MTYPE_VECTOR_INDEX,
-  MTYPE_LINK_LIST,
-  MTYPE_LINK_NODE,
-  MTYPE_THREAD,
-  MTYPE_THREAD_MASTER,
-  MTYPE_VTY,
-  MTYPE_VTY_HIST,
-  MTYPE_VTY_OUT_BUF,
-  MTYPE_IF,
-  MTYPE_CONNECTED,
-  MTYPE_AS_SEG,
-  MTYPE_AS_STR,
-  MTYPE_AS_PATH,
-  MTYPE_CLUSTER,
-  MTYPE_CLUSTER_VAL,
-  MTYPE_ATTR,
-  MTYPE_TRANSIT,
-  MTYPE_TRANSIT_VAL,
-  MTYPE_BUFFER,
-  MTYPE_BUFFER_DATA,
-  MTYPE_STREAM,
-  MTYPE_STREAM_DATA,
-  MTYPE_STREAM_FIFO,
-  MTYPE_PREFIX,
-  MTYPE_PREFIX_IPV4,
-  MTYPE_PREFIX_IPV6,
-  MTYPE_HASH,
-  MTYPE_HASH_INDEX,
-  MTYPE_HASH_BACKET,
-  MTYPE_RIPNG_ROUTE,
-  MTYPE_RIPNG_AGGREGATE,
-  MTYPE_ROUTE_TABLE,
-  MTYPE_ROUTE_NODE,
-  MTYPE_ACCESS_LIST,
-  MTYPE_ACCESS_LIST_STR,
-  MTYPE_ACCESS_FILTER,
-  MTYPE_PREFIX_LIST,
-  MTYPE_PREFIX_LIST_STR,
-  MTYPE_PREFIX_LIST_ENTRY,
-  MTYPE_ROUTE_MAP,
-  MTYPE_ROUTE_MAP_NAME,
-  MTYPE_ROUTE_MAP_INDEX,
-  MTYPE_ROUTE_MAP_RULE,
-  MTYPE_ROUTE_MAP_RULE_STR,
-  MTYPE_ROUTE_MAP_COMPILED,
-
-  MTYPE_RIB,
-  MTYPE_DISTRIBUTE,
-  MTYPE_ZLOG,
-  MTYPE_ZCLIENT,
-  MTYPE_NEXTHOP,
-  MTYPE_RTADV_PREFIX,
-  MTYPE_IF_RMAP,
-  MTYPE_SOCKUNION,
-  MTYPE_STATIC_IPV4,
-  MTYPE_STATIC_IPV6,
-
-  MTYPE_DESC,
-  MTYPE_OSPF_TOP,
-  MTYPE_OSPF_AREA,
-  MTYPE_OSPF_AREA_RANGE,
-  MTYPE_OSPF_NETWORK,
-  MTYPE_OSPF_NEIGHBOR_STATIC,
-  MTYPE_OSPF_IF,
-  MTYPE_OSPF_NEIGHBOR,
-  MTYPE_OSPF_ROUTE,
-  MTYPE_OSPF_TMP,
-  MTYPE_OSPF_LSA,
-  MTYPE_OSPF_LSA_DATA,
-  MTYPE_OSPF_LSDB,
-  MTYPE_OSPF_PACKET,
-  MTYPE_OSPF_FIFO,
-  MTYPE_OSPF_VERTEX,
-  MTYPE_OSPF_NEXTHOP,
-  MTYPE_OSPF_PATH,
-  MTYPE_OSPF_VL_DATA,
-  MTYPE_OSPF_CRYPT_KEY,
-  MTYPE_OSPF_EXTERNAL_INFO,
-  MTYPE_OSPF_MESSAGE,
-  MTYPE_OSPF_DISTANCE,
-  MTYPE_OSPF_IF_INFO,
-  MTYPE_OSPF_IF_PARAMS,
-
-  MTYPE_OSPF6_TOP,
-  MTYPE_OSPF6_AREA,
-  MTYPE_OSPF6_IF,
-  MTYPE_OSPF6_NEIGHBOR,
-  MTYPE_OSPF6_ROUTE,
-  MTYPE_OSPF6_PREFIX,
-  MTYPE_OSPF6_MESSAGE,
-  MTYPE_OSPF6_LSA,
-  MTYPE_OSPF6_LSA_SUMMARY,
-  MTYPE_OSPF6_LSDB,
-  MTYPE_OSPF6_VERTEX,
-  MTYPE_OSPF6_SPFTREE,
-  MTYPE_OSPF6_NEXTHOP,
-  MTYPE_OSPF6_EXTERNAL_INFO,
-  MTYPE_OSPF6_OTHER,
-
-  MTYPE_BGP,
-  MTYPE_BGP_PEER,
-  MTYPE_PEER_GROUP,
-  MTYPE_PEER_DESC,
-  MTYPE_PEER_UPDATE_SOURCE,
-  MTYPE_BGP_STATIC,
-  MTYPE_BGP_AGGREGATE,
-  MTYPE_BGP_CONFED_LIST,
-  MTYPE_BGP_NEXTHOP_CACHE,
-  MTYPE_BGP_DAMP_INFO,
-  MTYPE_BGP_DAMP_ARRAY,
-  MTYPE_BGP_ANNOUNCE,
-  MTYPE_BGP_ATTR_QUEUE,
-  MTYPE_BGP_ROUTE_QUEUE,
-  MTYPE_BGP_DISTANCE,
-  MTYPE_BGP_ROUTE,
-  MTYPE_BGP_TABLE,
-  MTYPE_BGP_NODE,
-  MTYPE_BGP_ADVERTISE_ATTR,
-  MTYPE_BGP_ADVERTISE,
-  MTYPE_BGP_ADJ_IN,
-  MTYPE_BGP_ADJ_OUT,
-  MTYPE_BGP_REGEXP,
-  MTYPE_AS_FILTER,
-  MTYPE_AS_FILTER_STR,
-  MTYPE_AS_LIST,
-
-  MTYPE_COMMUNITY,
-  MTYPE_COMMUNITY_VAL,
-  MTYPE_COMMUNITY_STR,
-
-  MTYPE_ECOMMUNITY,
-  MTYPE_ECOMMUNITY_VAL,
-  MTYPE_ECOMMUNITY_STR,
-
-  /* community-list and extcommunity-list.  */
-  MTYPE_COMMUNITY_LIST_HANDLER,
-  MTYPE_COMMUNITY_LIST,
-  MTYPE_COMMUNITY_LIST_NAME,
-  MTYPE_COMMUNITY_LIST_ENTRY,
-  MTYPE_COMMUNITY_LIST_CONFIG,
-
-  MTYPE_RIP,
-  MTYPE_RIP_INTERFACE,
-  MTYPE_RIP_DISTANCE,
-  MTYPE_RIP_OFFSET_LIST,
-  MTYPE_RIP_INFO,
-  MTYPE_RIP_PEER,
-  MTYPE_KEYCHAIN,
-  MTYPE_KEY,
-
-  MTYPE_VTYSH_CONFIG,
-  MTYPE_VTYSH_CONFIG_LINE,
-
-  MTYPE_VRF,
-  MTYPE_VRF_NAME,
-
-  MTYPE_MAX
-};
+extern void memory_oom(size_t size, const char *name);
 
-#ifdef MEMORY_LOG
-#define XMALLOC(mtype, size) \
-  mtype_zmalloc (__FILE__, __LINE__, (mtype), (size))
-#define XCALLOC(mtype, size) \
-  mtype_zcalloc (__FILE__, __LINE__, (mtype), (size))
-#define XREALLOC(mtype, ptr, size)  \
-  mtype_zrealloc (__FILE__, __LINE__, (mtype), (ptr), (size))
-#define XFREE(mtype, ptr) \
-  mtype_zfree (__FILE__, __LINE__, (mtype), (ptr))
-#define XSTRDUP(mtype, str) \
-  mtype_zstrdup (__FILE__, __LINE__, (mtype), (str))
-#else
-#define XMALLOC(mtype, size)       zmalloc ((mtype), (size))
-#define XCALLOC(mtype, size)       zcalloc ((mtype), (size))
-#define XREALLOC(mtype, ptr, size) zrealloc ((mtype), (ptr), (size))
-#define XFREE(mtype, ptr)          zfree ((mtype), (ptr))
-#define XSTRDUP(mtype, str)        zstrdup ((mtype), (str))
-#endif /* MEMORY_LOG */
-
-/* Prototypes of memory function. */
-void *zmalloc (int type, size_t size);
-void *zcalloc (int type, size_t size);
-void *zrealloc (int type, void *ptr, size_t size);
-void  zfree (int type, void *ptr);
-char *zstrdup (int type, char *str);
-
-void *mtype_zmalloc (const char *file,
-                    int line,
-                    int type,
-                    size_t size);
-
-void *mtype_zcalloc (const char *file,
-                    int line,
-                    int type,
-                    size_t num,
-                    size_t size);
-
-void *mtype_zrealloc (const char *file,
-                    int line,
-                    int type, 
-                    void *ptr,
-                    size_t size);
-
-void mtype_zfree (const char *file,
-                 int line,
-                 int type,
-                 void *ptr);
-
-char *mtype_zstrdup (const char *file,
-                    int line,
-                    int type,
-                    char *str);
-void memory_init ();
-
-#endif /* _ZEBRA_MEMORY_H */
+#endif /* _QUAGGA_MEMORY_H */