back to topotato report
topotato coverage report
Current view: top level - lib - memory.h (source / functions) Hit Total Coverage
Test: test_bgp_distance_change.py::BGPDistanceChange Lines: 0 2 0.0 %
Date: 2023-02-24 18:37:13 Functions: 0 0 -

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015-16  David Lamparter, for NetDEF, Inc.
       3             :  *
       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.
       7             :  *
       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.
      15             :  */
      16             : 
      17             : #ifndef _QUAGGA_MEMORY_H
      18             : #define _QUAGGA_MEMORY_H
      19             : 
      20             : #include <stdbool.h>
      21             : #include <stdlib.h>
      22             : #include <stdio.h>
      23             : #include <frratomic.h>
      24             : #include "compiler.h"
      25             : 
      26             : #ifdef __cplusplus
      27             : extern "C" {
      28             : #endif
      29             : 
      30             : #if defined(HAVE_MALLOC_SIZE) && !defined(HAVE_MALLOC_USABLE_SIZE)
      31             : #define malloc_usable_size(x) malloc_size(x)
      32             : #define HAVE_MALLOC_USABLE_SIZE
      33             : #endif
      34             : 
      35             : #define SIZE_VAR ~0UL
      36             : struct memtype {
      37             :         struct memtype *next, **ref;
      38             :         const char *name;
      39             :         atomic_size_t n_alloc;
      40             :         atomic_size_t n_max;
      41             :         atomic_size_t size;
      42             : #ifdef HAVE_MALLOC_USABLE_SIZE
      43             :         atomic_size_t total;
      44             :         atomic_size_t max_size;
      45             : #endif
      46             : };
      47             : 
      48             : struct memgroup {
      49             :         struct memgroup *next, **ref;
      50             :         struct memtype *types, **insert;
      51             :         const char *name;
      52             :         /* ignore group on dumping memleaks at exit */
      53             :         bool active_at_exit;
      54             : };
      55             : 
      56             : /* macro usage:
      57             :  *
      58             :  *  mydaemon.h
      59             :  *    DECLARE_MGROUP(MYDAEMON);
      60             :  *    DECLARE_MTYPE(MYDAEMON_COMMON);
      61             :  *
      62             :  *  mydaemon.c
      63             :  *    DEFINE_MGROUP(MYDAEMON, "my daemon memory");
      64             :  *    DEFINE_MTYPE(MYDAEMON, MYDAEMON_COMMON,
      65             :  *                   "this mtype is used in multiple files in mydaemon");
      66             :  *    foo = qmalloc(MTYPE_MYDAEMON_COMMON, sizeof(*foo))
      67             :  *
      68             :  *  mydaemon_io.c
      69             :  *    bar = qmalloc(MTYPE_MYDAEMON_COMMON, sizeof(*bar))
      70             :  *
      71             :  *    DEFINE_MTYPE_STATIC(MYDAEMON, MYDAEMON_IO,
      72             :  *                          "this mtype is used only in this file");
      73             :  *    baz = qmalloc(MTYPE_MYDAEMON_IO, sizeof(*baz))
      74             :  *
      75             :  *  Note:  Naming conventions (MGROUP_ and MTYPE_ prefixes are enforced
      76             :  *         by not having these as part of the macro arguments)
      77             :  *  Note:  MTYPE_* are symbols to the compiler (of type struct memtype *),
      78             :  *         but MGROUP_* aren't.
      79             :  */
      80             : 
      81             : #define DECLARE_MGROUP(name) extern struct memgroup _mg_##name
      82             : #define _DEFINE_MGROUP(mname, desc, ...)                                       \
      83             :         struct memgroup _mg_##mname                                            \
      84             :                 __attribute__((section(".data.mgroups"))) = {                  \
      85             :                         .name = desc,                                          \
      86             :                         .types = NULL,                                         \
      87             :                         .next = NULL,                                          \
      88             :                         .insert = NULL,                                        \
      89             :                         .ref = NULL,                                           \
      90             :                         __VA_ARGS__                                            \
      91             :         };                                                                     \
      92             :         static void _mginit_##mname(void) __attribute__((_CONSTRUCTOR(1000))); \
      93             :         static void _mginit_##mname(void)                                      \
      94             :         {                                                                      \
      95             :                 extern struct memgroup **mg_insert;                            \
      96             :                 _mg_##mname.ref = mg_insert;                                   \
      97             :                 *mg_insert = &_mg_##mname;                                     \
      98             :                 mg_insert = &_mg_##mname.next;                                 \
      99             :         }                                                                      \
     100             :         static void _mgfini_##mname(void) __attribute__((_DESTRUCTOR(1000)));  \
     101             :         static void _mgfini_##mname(void)                                      \
     102             :         {                                                                      \
     103             :                 if (_mg_##mname.next)                                          \
     104             :                         _mg_##mname.next->ref = _mg_##mname.ref;               \
     105             :                 *_mg_##mname.ref = _mg_##mname.next;                           \
     106             :         }                                                                      \
     107             :         MACRO_REQUIRE_SEMICOLON() /* end */
     108             : 
     109             : #define DEFINE_MGROUP(mname, desc) \
     110             :         _DEFINE_MGROUP(mname, desc, )
     111             : #define DEFINE_MGROUP_ACTIVEATEXIT(mname, desc) \
     112             :         _DEFINE_MGROUP(mname, desc, .active_at_exit = true)
     113             : 
     114             : #define DECLARE_MTYPE(name)                                                    \
     115             :         extern struct memtype MTYPE_##name[1]                                  \
     116             :         /* end */
     117             : 
     118             : #define DEFINE_MTYPE_ATTR(group, mname, attr, desc)                            \
     119             :         attr struct memtype MTYPE_##mname[1]                                   \
     120             :                 __attribute__((section(".data.mtypes"))) = { {                 \
     121             :                         .name = desc,                                          \
     122             :                         .next = NULL,                                          \
     123             :                         .n_alloc = 0,                                          \
     124             :                         .size = 0,                                             \
     125             :                         .ref = NULL,                                           \
     126             :         } };                                                                   \
     127             :         static void _mtinit_##mname(void) __attribute__((_CONSTRUCTOR(1001))); \
     128             :         static void _mtinit_##mname(void)                                      \
     129             :         {                                                                      \
     130             :                 if (_mg_##group.insert == NULL)                                \
     131             :                         _mg_##group.insert = &_mg_##group.types;               \
     132             :                 MTYPE_##mname->ref = _mg_##group.insert;                       \
     133             :                 *_mg_##group.insert = MTYPE_##mname;                           \
     134             :                 _mg_##group.insert = &MTYPE_##mname->next;                      \
     135             :         }                                                                      \
     136             :         static void _mtfini_##mname(void) __attribute__((_DESTRUCTOR(1001)));  \
     137             :         static void _mtfini_##mname(void)                                      \
     138             :         {                                                                      \
     139             :                 if (MTYPE_##mname->next)                                       \
     140             :                         MTYPE_##mname->next->ref = MTYPE_##mname->ref;         \
     141             :                 *MTYPE_##mname->ref = MTYPE_##mname->next;                     \
     142             :         }                                                                      \
     143             :         MACRO_REQUIRE_SEMICOLON() /* end */
     144             : 
     145             : #define DEFINE_MTYPE(group, name, desc)                                        \
     146             :         DEFINE_MTYPE_ATTR(group, name, , desc)                                 \
     147             :         /* end */
     148             : 
     149             : #define DEFINE_MTYPE_STATIC(group, name, desc)                                 \
     150             :         DEFINE_MTYPE_ATTR(group, name, static, desc)                           \
     151             :         /* end */
     152             : 
     153             : DECLARE_MGROUP(LIB);
     154             : DECLARE_MTYPE(TMP);
     155             : 
     156             : 
     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 qcountfree(struct memtype *mt, void *ptr)
     166             :         __attribute__((nonnull(1)));
     167             : extern void qfree(struct memtype *mt, void *ptr) __attribute__((nonnull(1)));
     168             : 
     169             : #define XMALLOC(mtype, size)            qmalloc(mtype, size)
     170             : #define XCALLOC(mtype, size)            qcalloc(mtype, size)
     171             : #define XREALLOC(mtype, ptr, size)      qrealloc(mtype, ptr, size)
     172             : #define XSTRDUP(mtype, str)             qstrdup(mtype, str)
     173             : #define XCOUNTFREE(mtype, ptr)          qcountfree(mtype, ptr)
     174             : #define XFREE(mtype, ptr)                                                      \
     175             :         do {                                                                   \
     176             :                 qfree(mtype, ptr);                                             \
     177             :                 ptr = NULL;                                                    \
     178             :         } while (0)
     179             : 
     180           0 : static inline size_t mtype_stats_alloc(struct memtype *mt)
     181             : {
     182           0 :         return mt->n_alloc;
     183             : }
     184             : 
     185             : /* NB: calls are ordered by memgroup; and there is a call with mt == NULL for
     186             :  * each memgroup (so that a header can be printed, and empty memgroups show)
     187             :  *
     188             :  * return value: 0: continue, !0: abort walk.  qmem_walk will return the
     189             :  * last value from qmem_walk_fn. */
     190             : typedef int qmem_walk_fn(void *arg, struct memgroup *mg, struct memtype *mt);
     191             : extern int qmem_walk(qmem_walk_fn *func, void *arg);
     192             : extern int log_memstats(FILE *fp, const char *);
     193             : #define log_memstats_stderr(prefix) log_memstats(stderr, prefix)
     194             : 
     195             : extern __attribute__((__noreturn__)) void memory_oom(size_t size,
     196             :                                                      const char *name);
     197             : 
     198             : #ifdef __cplusplus
     199             : }
     200             : #endif
     201             : 
     202             : #endif /* _QUAGGA_MEMORY_H */

Generated by: LCOV version v1.16-topotato