summaryrefslogtreecommitdiffstats
path: root/doc/developer/memtypes.rst
blob: 2e181c4f2bd6a27526e5cf8a8cd846be4e564b93 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
.. highlight:: c

Memtypes
========

FRR includes wrappers around ``malloc()`` and ``free()`` that count the number
of objects currently allocated, for each of a defined ``MTYPE``.

To this extent, there are *memory groups* and *memory types*.  Each memory
type must belong to a memory group, this is used just to provide some basic
structure.

Example:

.. code-block:: c
   :caption: mydaemon.h

   DECLARE_MGROUP(MYDAEMON);
   DECLARE_MTYPE(MYNEIGHBOR);

.. code-block:: c
   :caption: mydaemon.c

   DEFINE_MGROUP(      MYDAEMON, "My daemon's memory");
   DEFINE_MTYPE(       MYDAEMON, MYNEIGHBOR,     "Neighbor entry");
   DEFINE_MTYPE_STATIC(MYDAEMON, MYNEIGHBORNAME, "Neighbor name");

   struct neigh *neighbor_new(const char *name)
   {
           struct neigh *n = XMALLOC(MYNEIGHBOR, sizeof(*n));
           n->name = XSTRDUP(MYNEIGHBORNAME, name);
           return n;
   }

   void neighbor_free(struct neigh *n)
   {
           XFREE(MYNEIGHBORNAME, n->name);
           XFREE(MYNEIGHBOR, n);
   }


Definition
----------

.. c:struct:: memtype

   This is the (internal) type used for MTYPE definitions.  The macros below
   should be used to create these, but in some cases it is useful to pass a
   ``struct memtype *`` pointer to some helper function.

   The ``MTYPE_name`` created by the macros is declared as a pointer, i.e.
   a function taking a ``struct memtype *`` argument can be called with an
   ``MTYPE_name`` argument (as opposed to ``&MTYPE_name``.)

   .. note::

      As ``MTYPE_name`` is a variable assigned from ``&_mt_name`` and not a
      constant expression, it cannot be used as initializer for static
      variables. In the case please fall back to ``&_mt_name``.

.. c:macro:: DECLARE_MGROUP(name)

   This macro forward-declares a memory group and should be placed in a
   ``.h`` file.  It expands to an ``extern struct memgroup`` statement.

.. c:macro:: DEFINE_MGROUP(mname, description)

   Defines/implements a memory group.  Must be placed into exactly one ``.c``
   file (multiple inclusion will result in a link-time symbol conflict).

   Contains additional logic (constructor and destructor) to register the
   memory group in a global list.

.. c:macro:: DECLARE_MTYPE(name)

   Forward-declares a memory type and makes ``MTYPE_name`` available for use.
   Note that the ``MTYPE_`` prefix must not be included in the name, it is
   automatically prefixed.

   ``MTYPE_name`` is created as a `static const` symbol, i.e. a compile-time
   constant.  It refers to an ``extern struct memtype _mt_name``, where `name`
   is replaced with the actual name.

.. c:macro:: DEFINE_MTYPE(group, name, description)

   Define/implement a memory type, must be placed into exactly one ``.c``
   file (multiple inclusion will result in a link-time symbol conflict).

   Like ``DEFINE_MGROUP``, this contains actual code to register the MTYPE
   under its group.

.. c:macro:: DEFINE_MTYPE_STATIC(group, name, description)

   Same as ``DEFINE_MTYPE``, but the ``DEFINE_MTYPE_STATIC`` variant places
   the C ``static`` keyword on the definition, restricting the MTYPE's
   availability to the current source file.  This should be appropriate in
   >80% of cases.

   .. todo::

      Daemons currently have ``daemon_memory.[ch]`` files listing all of
      their MTYPEs.  This is not how it should be, most of these types
      should be moved into the appropriate files where they are used.
      Only a few MTYPEs should remain non-static after that.


Usage
-----

.. c:function:: void *XMALLOC(struct memtype *mtype, size_t size)

.. c:function:: void *XCALLOC(struct memtype *mtype, size_t size)

.. c:function:: void *XSTRDUP(struct memtype *mtype, const char *name)

   Allocation wrappers for malloc/calloc/realloc/strdup, taking an extra
   mtype parameter.

.. c:function:: void *XREALLOC(struct memtype *mtype, void *ptr, size_t size)

   Wrapper around realloc() with MTYPE tracking.  Note that ``ptr`` may
   be NULL, in which case the function does the same as XMALLOC (regardless
   of whether the system realloc() supports this.)

.. c:function:: void XFREE(struct memtype *mtype, void *ptr)

   Wrapper around free(), again taking an extra mtype parameter.  This is
   actually a macro, with the following additional properties:

   - the macro contains ``ptr = NULL``
   - if ptr is NULL, no operation is performed (as is guaranteed by system
     implementations.)  Do not surround XFREE with ``if (ptr != NULL)``
     checks.

.. c:function:: void XCOUNTFREE(struct memtype *mtype, void *ptr)

   This macro is used to count the ``ptr`` as freed without actually freeing
   it. This may be needed in some very specific cases, for example, when the
   ``ptr`` was allocated using any of the above wrappers and will be freed
   by some external library using simple ``free()``.