X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=lib%2Fmemory.h;h=9e8803a8b2a6dbc1881df66e050cfe83c2072c4a;hb=073845da5e32aa15b9636bcbe7be994e2bd7f8b4;hp=52e3bc11ddb3c9ab97ab4d10b0be58b899a103db;hpb=718e3744195351130f4ce7dbe0613f4b3e23df93;p=mirror_frr.git diff --git a/lib/memory.h b/lib/memory.h index 52e3bc11d..9e8803a8b 100644 --- a/lib/memory.h +++ b/lib/memory.h @@ -1,245 +1,191 @@ -/* 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 +#include + +#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 */