Contiki-NG
Loading...
Searching...
No Matches
heapmem.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2005, Nicolas Tsiftes
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the author nor the names of the contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30/**
31 * \addtogroup mem
32 * @{
33 */
34
35/**
36 * \defgroup heapmem heapmem: Dynamic heap memory allocator
37 *
38 * The heapmem module is a dynamic heap memory allocator similar to
39 * malloc() in standard C. The heap memory is managed in a block of
40 * static memory, whose size is determined at compile-time by setting
41 * the HEAPMEM_CONF_ARENA_SIZE parameter.
42 *
43 * Each allocated memory object is referred to as a "chunk". The
44 * allocator manages free chunks in a double-linked list. While this
45 * adds some memory overhead compared to a single-linked list, it
46 * improves the performance of list management.
47 *
48 * Internally, allocated chunks can be retrieved using the pointer to
49 * the allocated memory returned by heapmem_alloc() and
50 * heapmem_realloc(), because the chunk structure immediately precedes
51 * the memory of the chunk.
52 *
53 * HeapMem zones provide independent heaps with their own static memory
54 * buffers. Each zone has its own free list and usage tracking, so
55 * fragmentation in one zone cannot affect another. Use
56 * HEAPMEM_ZONE_DEFINE() to create a zone with a dedicated buffer.
57 *
58 * \note The HEAPMEM_CONF_ARENA_SIZE parameter enables the general
59 * zone and the convenience macros (heapmem_alloc, heapmem_free, etc.).
60 * Zone-specific functions (heapmem_zone_alloc, etc.) and the
61 * HEAPMEM_ZONE_DEFINE macro are always available.
62 *
63 * \note Dynamic memory should be used carefully on
64 * memory-constrained embedded systems, because fragmentation
65 * may be induced through various allocation/deallocation
66 * patterns, and no guarantees are given regarding the
67 * availability of memory.
68 *
69 * @{
70 */
71
72/**
73 * \file
74 * Header file for the dynamic heap memory allocator.
75 * \author
76 * Nicolas Tsiftes <nvt@acm.org>
77 */
78
79#ifndef HEAPMEM_H
80#define HEAPMEM_H
81
82#include "contiki.h"
83#include "sys/cc.h"
84
85#include <stdlib.h>
86/*****************************************************************************/
87#ifndef HEAPMEM_DEBUG
88#define HEAPMEM_DEBUG 0
89#endif
90/*****************************************************************************/
91/* Alignment configuration -- needed in the header for HEAPMEM_ZONE_DEFINE. */
92#if __STDC_VERSION__ >= 201112L
93#include <stdalign.h>
94#define HEAPMEM_DEFAULT_ALIGNMENT alignof(max_align_t)
95#else
96#define HEAPMEM_DEFAULT_ALIGNMENT sizeof(size_t)
97#endif
98
99#ifdef HEAPMEM_CONF_ALIGNMENT
100#define HEAPMEM_ALIGNMENT HEAPMEM_CONF_ALIGNMENT
101#else
102#define HEAPMEM_ALIGNMENT HEAPMEM_DEFAULT_ALIGNMENT
103#endif /* HEAPMEM_CONF_ALIGNMENT */
104/*****************************************************************************/
105typedef struct heapmem_stats {
106 size_t allocated;
107 size_t overhead;
108 size_t available;
109 size_t heap_usage;
110 size_t max_heap_usage;
111 size_t chunks;
112} heapmem_stats_t;
113/*****************************************************************************/
114/*
115 * A heapmem zone is an independent heap with its own static memory
116 * buffer, free list, and usage tracking. Each zone provides true
117 * memory isolation: fragmentation in one zone cannot affect another,
118 * and each zone's memory is physically reserved.
119 *
120 * Use HEAPMEM_ZONE_DEFINE() to create a zone with its own static buffer.
121 * When HEAPMEM_CONF_ARENA_SIZE is set, a general zone is available
122 * internally and can be accessed by passing NULL as the zone parameter.
123 */
124
125/* Forward declaration for the free list pointer. */
126struct heapmem_chunk;
127
128typedef struct heapmem_zone {
129 const char *name;
130 char *heap_base;
131 size_t arena_size;
132 size_t heap_usage;
133 size_t max_heap_usage;
134 struct heapmem_chunk *free_list;
135} heapmem_zone_t;
136
137/**
138 * \brief Define a zone with its own static memory buffer.
139 * \param varname The variable name for the zone.
140 * \param bufsize The size of the zone's memory buffer in bytes.
141 *
142 * This macro creates a file-scoped zone with a statically allocated
143 * buffer. The zone provides an independent heap that is isolated from
144 * all other zones.
145 *
146 * Example usage:
147 * HEAPMEM_ZONE_DEFINE(packet_zone, 4096);
148 * void *p = heapmem_zone_alloc(&packet_zone, 128);
149 * heapmem_zone_free(&packet_zone, p);
150 */
151#define HEAPMEM_ZONE_DEFINE(varname, bufsize) \
152 static char varname##_buf_[bufsize] CC_ALIGN(HEAPMEM_ALIGNMENT); \
153 static heapmem_zone_t varname = { \
154 .name = #varname, \
155 .heap_base = varname##_buf_, \
156 .arena_size = bufsize, \
157 }
158/*****************************************************************************/
159
160/**
161 * \brief Allocate a chunk of memory in the specified zone.
162 * \param zone A pointer to the zone in which to allocate the memory,
163 * or NULL to use the general zone.
164 * \param size The number of bytes to allocate.
165 * \return A pointer to the allocated memory chunk,
166 * or NULL if the allocation failed.
167 *
168 * \sa heapmem_zone_realloc
169 * \sa heapmem_zone_free
170 */
171void *heapmem_zone_alloc(heapmem_zone_t *zone, size_t size);
172
173/**
174 * \brief Deallocate a chunk of memory in the specified zone.
175 * \param zone A pointer to the zone from which the memory was allocated,
176 * or NULL to use the general zone.
177 * \param ptr A pointer to a chunk that has been allocated using
178 * heapmem_zone_alloc() or heapmem_zone_realloc().
179 * \return A boolean indicating whether the memory could be deallocated.
180 *
181 * \sa heapmem_zone_alloc
182 * \sa heapmem_zone_realloc
183 */
184bool heapmem_zone_free(heapmem_zone_t *zone, void *ptr);
185
186/**
187 * \brief Reallocate a chunk of memory in the specified zone.
188 * \param zone A pointer to the zone in which to reallocate the memory,
189 * or NULL to use the general zone.
190 * \param ptr A pointer to a chunk that has been allocated using
191 * heapmem_zone_alloc() or heapmem_zone_realloc().
192 * \param size The number of bytes to allocate.
193 * \return A pointer to the allocated memory chunk,
194 * or NULL if the allocation failed.
195 *
196 * \note If ptr is NULL, this function behaves the same as heapmem_zone_alloc.
197 * \note If ptr is not NULL and size is zero, the function deallocates
198 * the chunk and returns NULL.
199 *
200 * \sa heapmem_zone_alloc
201 * \sa heapmem_zone_free
202 */
203void *heapmem_zone_realloc(heapmem_zone_t *zone, void *ptr, size_t size);
204
205/**
206 * \brief Allocate memory for a zero-initialized array in the
207 * specified zone.
208 * \param zone A pointer to the zone in which to allocate the memory,
209 * or NULL to use the general zone.
210 * \param nmemb The number of elements to allocate.
211 * \param size The size of each element.
212 * \return A pointer to the allocated memory,
213 * or NULL if the allocation failed.
214 *
215 * \sa heapmem_zone_alloc
216 * \sa heapmem_zone_free
217 */
218void *heapmem_zone_calloc(heapmem_zone_t *zone, size_t nmemb, size_t size);
219
220#if HEAPMEM_DEBUG
221void *heapmem_zone_alloc_debug(heapmem_zone_t *zone, size_t size,
222 const char *file, unsigned line);
223bool heapmem_zone_free_debug(heapmem_zone_t *zone, void *ptr,
224 const char *file, unsigned line);
225void *heapmem_zone_realloc_debug(heapmem_zone_t *zone, void *ptr, size_t size,
226 const char *file, unsigned line);
227void *heapmem_zone_calloc_debug(heapmem_zone_t *zone, size_t nmemb, size_t size,
228 const char *file, unsigned line);
229#define heapmem_zone_alloc(zone, size) \
230 heapmem_zone_alloc_debug((zone), (size), __FILE__, __LINE__)
231#define heapmem_zone_free(zone, ptr) \
232 heapmem_zone_free_debug((zone), (ptr), __FILE__, __LINE__)
233#define heapmem_zone_realloc(zone, ptr, size) \
234 heapmem_zone_realloc_debug((zone), (ptr), (size), __FILE__, __LINE__)
235#define heapmem_zone_calloc(zone, nmemb, size) \
236 heapmem_zone_calloc_debug((zone), (nmemb), (size), __FILE__, __LINE__)
237#endif /* HEAPMEM_DEBUG */
238
239/**
240 * \brief Obtain internal statistics for a heapmem zone.
241 * \param zone A pointer to the zone to query.
242 * \param stats A pointer to an object of type heapmem_stats_t, which
243 * will be filled when calling this function.
244 */
245void heapmem_zone_stats(heapmem_zone_t *zone, heapmem_stats_t *stats);
246
247/**
248 * \brief Print debugging information for a heapmem zone.
249 * \param zone A pointer to the zone to query.
250 * \param print_chunks Determines whether to print information about
251 * all allocated chunks.
252 */
253void heapmem_zone_print_debug_info(heapmem_zone_t *zone, bool print_chunks);
254
255/*****************************************************************************/
256/* Convenience macros for the general zone. These provide backward
257 compatibility with the non-zone API. */
258#ifdef HEAPMEM_CONF_ARENA_SIZE
259
260#define heapmem_alloc(size) \
261 heapmem_zone_alloc(NULL, (size))
262#define heapmem_free(ptr) \
263 heapmem_zone_free(NULL, (ptr))
264#define heapmem_realloc(ptr, size) \
265 heapmem_zone_realloc(NULL, (ptr), (size))
266#define heapmem_calloc(nmemb, size) \
267 heapmem_zone_calloc(NULL, (nmemb), (size))
268#define heapmem_stats(stats) \
269 heapmem_zone_stats(NULL, (stats))
270#define heapmem_print_debug_info(print_chunks) \
271 heapmem_zone_print_debug_info(NULL, (print_chunks))
272
273#endif /* HEAPMEM_CONF_ARENA_SIZE */
274
275#endif /* !HEAPMEM_H */
276
277/** @} */
278/** @} */
Default definitions of C compiler quirk work-arounds.
void * heapmem_zone_alloc(heapmem_zone_t *zone, size_t size)
Allocate a chunk of memory in the specified zone.
Definition heapmem.c:362
void heapmem_zone_stats(heapmem_zone_t *zone, heapmem_stats_t *stats)
Obtain internal statistics for a heapmem zone.
Definition heapmem.c:594
void * heapmem_zone_realloc(heapmem_zone_t *zone, void *ptr, size_t size)
Reallocate a chunk of memory in the specified zone.
Definition heapmem.c:553
void * heapmem_zone_calloc(heapmem_zone_t *zone, size_t nmemb, size_t size)
Allocate memory for a zero-initialized array in the specified zone.
Definition heapmem.c:586
void heapmem_zone_print_debug_info(heapmem_zone_t *zone, bool print_chunks)
Print debugging information for a heapmem zone.
Definition heapmem.c:622
bool heapmem_zone_free(heapmem_zone_t *zone, void *ptr)
Deallocate a chunk of memory in the specified zone.
Definition heapmem.c:415