SingingCat 0
application
umm_malloc_cfg.h
1/*
2 * Configuration for umm_malloc - DO NOT EDIT THIS FILE BY HAND!
3 *
4 * NOTE WELL: Your project MUST have a umm_malloc_cfgport.h - even if
5 * it's empty!!!
6 *
7 * Refer to the notes below for details on the umm_malloc configuration
8 * options.
9 */
10
11#ifndef _UMM_MALLOC_CFG_H
12#define _UMM_MALLOC_CFG_H
13
14#include <stdint.h>
15#include <stddef.h>
16#include <stdbool.h>
17
18/*
19 * There are a number of defines you can set at compile time that affect how
20 * the memory allocator will operate.
21 *
22 * You should NOT edit this file, it may be changed from time to time in
23 * the upstream project. Instead, you can do one of the following (in order
24 * of priority
25 *
26 * 1. Pass in the override values on the command line using -D UMM_xxx
27 * 2. Pass in the filename holding override values using -D UMM_CFGFILE
28 * 3. Set up defaults in a file called umm_malloc_cfgport.h
29 *
30 * NOTE WELL: For the command line -D options to take highest priority, your
31 * project level override file must check that the UMM_xxx
32 * value is not already defined before overriding
33 *
34 * Unless otherwise noted, the default state of these values is #undef-ined!
35 *
36 * As this is the top level configuration file, it is responsible for making
37 * sure that the configuration makes sense. For example the UMM_BLOCK_BODY_SIZE
38 * is a minimum of 8 and a multiple of 4.
39 *
40 * UMM_BLOCK_BODY_SIZE
41 *
42 * Defines the umm_block[].body size - it is 8 by default
43 *
44 * This assumes umm_ptr is a pair of uint16_t values
45 * which is 4 bytes plus the data[] array which is another 4 bytes
46 * for a total of 8.
47 *
48 * NOTE WELL that the umm_block[].body size must be multiple of
49 * the natural access size of the host machine to ensure
50 * that accesses are efficient.
51 *
52 * We have not verified the checks below for 64 bit machines
53 * because this library is targeted for 32 bit machines.
54 *
55 * UMM_NUM_HEAPS
56 *
57 * Set to the maximum number of heaps that can be defined by the
58 * application - defaults to 1.
59 *
60 * UMM_BEST_FIT (default)
61 *
62 * Set this if you want to use a best-fit algorithm for allocating new blocks.
63 * On by default, turned off by UMM_FIRST_FIT
64 *
65 * UMM_FIRST_FIT
66 *
67 * Set this if you want to use a first-fit algorithm for allocating new blocks.
68 * Faster than UMM_BEST_FIT but can result in higher fragmentation.
69 *
70 * UMM_INFO
71 *
72 * Set if you want the ability to calculate metrics on demand
73 *
74 * UMM_INLINE_METRICS
75 *
76 * Set this if you want to have access to a minimal set of heap metrics that
77 * can be used to gauge heap health.
78 * Setting this at compile time will automatically set UMM_INFO.
79 * Note that enabling this define will add a slight runtime penalty.
80 *
81 * UMM_CHECK_INITIALIZED
82 *
83 * Set if you want to be able to verify that the heap is intialized
84 * before any operation - the default is no check. You may set the
85 * UMM_CHECK_INITIALIZED macro to the following provided macros, or
86 * write your own handler:
87 *
88 * UMM_INIT_IF_UNINITIALIZED
89 * UMM_HANG_IF_UNINITIALIZED
90 *
91 * UMM_INTEGRITY_CHECK
92 *
93 * Set if you want to be able to verify that the heap is semantically correct
94 * before or after any heap operation - all of the block indexes in the heap
95 * make sense.
96 * Slows execution dramatically but catches errors really quickly.
97 *
98 * UMM_POISON_CHECK
99 *
100 * Set if you want to be able to leave a poison buffer around each allocation.
101 * Note this uses an extra 8 bytes per allocation, but you get the benefit of
102 * being able to detect if your program is writing past an allocated buffer.
103 *
104 * DBGLOG_ENABLE
105 *
106 * Set if you want to enable logging - the default is to use printf() but
107 * if you have any special requirements such as thread safety or a custom
108 * logging routine - you are free to everride the default
109 *
110 * DBGLOG_LEVEL=n
111 *
112 * Set n to a value from 0 to 6 depending on how verbose you want the debug
113 * log to be
114 *
115 * UMM_MAX_CRITICAL_DEPTH_CHECK=n
116 *
117 * Set this if you want to compile in code to verify that the critical
118 * section maximum depth is not exceeded. If set, the value must be greater
119 * than 0.
120 *
121 * The critical depth checking is only needed if your target environment
122 * does not support reading and writing the current interrupt enable state.
123 *
124 * Support for this library in a multitasking environment is provided when
125 * you add bodies to the UMM_CRITICAL_ENTRY and UMM_CRITICAL_EXIT macros
126 * (see below)
127 *
128 * ----------------------------------------------------------------------------
129 */
130
131#ifdef UMM_CFGFILE
132#include UMM_CFGFILE
133#else
134#include <umm_malloc_cfgport.h>
135#endif
136
137/* A couple of macros to make packing structures less compiler dependent */
138
139#define UMM_H_ATTPACKPRE
140#define UMM_H_ATTPACKSUF __attribute__((__packed__))
141
142/* -------------------------------------------------------------------------- */
143
144#ifndef UMM_INIT_IF_UNINITIALIZED
145#define UMM_INIT_IF_UNINITIALIZED() do { if (UMM_HEAP == NULL) { umm_init(); } } while(0)
146#endif
147
148#ifndef UMM_HANG_IF_UNINITIALIZED
149#define UMM_HANG_IF_UNINITIALIZED() do { if (UMM_HEAP == NULL) { while (1) {} } } while(0)
150#endif
151
152#ifndef UMM_CHECK_INITIALIZED
153#define UMM_CHECK_INITIALIZED()
154#endif
155
156/* -------------------------------------------------------------------------- */
157
158#ifndef UMM_BLOCK_BODY_SIZE
159#define UMM_BLOCK_BODY_SIZE (8)
160#endif
161
162#define UMM_MIN_BLOCK_BODY_SIZE (8)
163
164#if (UMM_BLOCK_BODY_SIZE < UMM_MIN_BLOCK_BODY_SIZE)
165#error UMM_BLOCK_BODY_SIZE must be at least 8!
166#endif
167
168#if ((UMM_BLOCK_BODY_SIZE % 4) != 0)
169#error UMM_BLOCK_BODY_SIZE must be multiple of 4!
170#endif
171
172/* -------------------------------------------------------------------------- */
173
174#ifndef UMM_NUM_HEAPS
175#define UMM_NUM_HEAPS (1)
176#endif
177
178#if (UMM_NUM_HEAPS < 1)
179#error UMM_NUM_HEAPS must be at least 1!
180#endif
181
182/* -------------------------------------------------------------------------- */
183
184#ifdef UMM_BEST_FIT
185#ifdef UMM_FIRST_FIT
186#error Both UMM_BEST_FIT and UMM_FIRST_FIT are defined - pick one!
187#endif
188#else /* UMM_BEST_FIT is not defined */
189#ifndef UMM_FIRST_FIT
190#define UMM_BEST_FIT
191#endif
192#endif
193
194/* -------------------------------------------------------------------------- */
195
196#ifdef UMM_INLINE_METRICS
197#define UMM_FRAGMENTATION_METRIC_INIT() umm_fragmentation_metric_init()
198#define UMM_FRAGMENTATION_METRIC_ADD(c) umm_fragmentation_metric_add(c)
199#define UMM_FRAGMENTATION_METRIC_REMOVE(c) umm_fragmentation_metric_remove(c)
200#ifndef UMM_INFO
201#define UMM_INFO
202#endif
203#else
204#define UMM_FRAGMENTATION_METRIC_INIT()
205#define UMM_FRAGMENTATION_METRIC_ADD(c)
206#define UMM_FRAGMENTATION_METRIC_REMOVE(c)
207#endif // UMM_INLINE_METRICS
208
209/* -------------------------------------------------------------------------- */
210
211#ifdef UMM_INFO
212typedef struct UMM_HEAP_INFO_t {
213 unsigned int totalEntries;
214 unsigned int usedEntries;
215 unsigned int freeEntries;
216
217 unsigned int totalBlocks;
218 unsigned int usedBlocks;
219 unsigned int freeBlocks;
220 unsigned int freeBlocksSquared;
221
222 unsigned int maxFreeContiguousBlocks;
223
224 int usage_metric;
225 int fragmentation_metric;
226}
227UMM_HEAP_INFO;
228
229extern UMM_HEAP_INFO ummHeapInfo;
230
231extern void *umm_info(void *ptr, bool force);
232extern size_t umm_free_heap_size(void);
233extern size_t umm_max_free_block_size(void);
234extern int umm_usage_metric(void);
235extern int umm_fragmentation_metric(void);
236#else
237#define umm_info(p, b)
238#define umm_free_heap_size() (0)
239#define umm_max_free_block_size() (0)
240#define umm_usage_metric() (0)
241#define umm_fragmentation_metric() (0)
242#endif
243
244/*
245 * Three macros to make it easier to protect the memory allocator in a
246 * multitasking system. You should set these macros up to use whatever your
247 * system uses for this purpose. You can disable interrupts entirely, or just
248 * disable task switching - it's up to you
249 *
250 * If needed, UMM_CRITICAL_DECL can be used to declare or initialize
251 * synchronization elements before their use. "tag" can be used to add context
252 * uniqueness to the declaration.
253 * exp. #define UMM_CRITICAL_DECL(tag) uint32_t _saved_ps_##tag
254 * Another possible use for "tag", activity identifier when profiling time
255 * spent in UMM_CRITICAL. The "tag" values used are id_malloc, id_realloc,
256 * id_free, id_poison, id_integrity, and id_info.
257 *
258 * NOTE WELL that these macros MUST be allowed to nest, because umm_free() is
259 * called from within umm_malloc()
260 */
261
262#ifndef UMM_CRITICAL_DECL
263#define UMM_CRITICAL_DECL(tag)
264#endif
265
266#ifdef UMM_MAX_CRITICAL_DEPTH_CHECK
267extern int umm_critical_depth;
268extern int umm_max_critical_depth;
269#ifndef UMM_CRITICAL_ENTRY
270#define UMM_CRITICAL_ENTRY(tag) { \
271 ++umm_critical_depth; \
272 if (umm_critical_depth > umm_max_critical_depth) { \
273 umm_max_critical_depth = umm_critical_depth; \
274 } \
275}
276#endif
277#ifndef UMM_CRITICAL_EXIT
278#define UMM_CRITICAL_EXIT(tag) (umm_critical_depth--)
279#endif
280#else
281#ifndef UMM_CRITICAL_ENTRY
282#define UMM_CRITICAL_ENTRY(tag)
283#endif
284#ifndef UMM_CRITICAL_EXIT
285#define UMM_CRITICAL_EXIT(tag)
286#endif
287#endif
288
289/*
290 * Enables heap integrity check before any heap operation. It affects
291 * performance, but does NOT consume extra memory.
292 *
293 * If integrity violation is detected, the message is printed and user-provided
294 * callback is called: `UMM_HEAP_CORRUPTION_CB()`
295 *
296 * Note that not all buffer overruns are detected: each buffer is aligned by
297 * 4 bytes, so there might be some trailing "extra" bytes which are not checked
298 * for corruption.
299 */
300
301#ifdef UMM_INTEGRITY_CHECK
302extern bool umm_integrity_check(void);
303#define INTEGRITY_CHECK() umm_integrity_check()
304extern void umm_corruption(void);
305#define UMM_HEAP_CORRUPTION_CB() printf("Heap Corruption!")
306#else
307#define INTEGRITY_CHECK() (1)
308#endif
309
310/*
311 * Enables heap poisoning: add predefined value (poison) before and after each
312 * allocation, and check before each heap operation that no poison is
313 * corrupted.
314 *
315 * Other than the poison itself, we need to store exact user-requested length
316 * for each buffer, so that overrun by just 1 byte will be always noticed.
317 *
318 * Customizations:
319 *
320 * UMM_POISON_SIZE_BEFORE:
321 * Number of poison bytes before each block, e.g. 4
322 * UMM_POISON_SIZE_AFTER:
323 * Number of poison bytes after each block e.g. 4
324 * UMM_POISONED_BLOCK_LEN_TYPE
325 * Type of the exact buffer length, e.g. `uint16_t`
326 *
327 * NOTE: each allocated buffer is aligned by 4 bytes. But when poisoning is
328 * enabled, actual pointer returned to user is shifted by
329 * `(sizeof(UMM_POISONED_BLOCK_LEN_TYPE) + UMM_POISON_SIZE_BEFORE)`.
330 *
331 * It's your responsibility to make resulting pointers aligned appropriately.
332 *
333 * If poison corruption is detected, the message is printed and user-provided
334 * callback is called: `UMM_HEAP_CORRUPTION_CB()`
335 */
336
337#ifdef UMM_POISON_CHECK
338#define UMM_POISON_SIZE_BEFORE (4)
339#define UMM_POISON_SIZE_AFTER (4)
340#define UMM_POISONED_BLOCK_LEN_TYPE uint16_t
341
342extern void *umm_poison_malloc(size_t size);
343extern void *umm_poison_calloc(size_t num, size_t size);
344extern void *umm_poison_realloc(void *ptr, size_t size);
345extern void umm_poison_free(void *ptr);
346extern bool umm_poison_check(void);
347
348#define POISON_CHECK() umm_poison_check()
349#else
350#define POISON_CHECK() (1)
351#endif
352
353/*
354 * Add blank macros for DBGLOG_xxx() - if you want to override these on
355 * a per-source module basis, you must define DBGLOG_LEVEL and then
356 * #include "dbglog.h"
357 */
358
359#define DBGLOG_TRACE(format, ...)
360#define DBGLOG_DEBUG(format, ...)
361#define DBGLOG_CRITICAL(format, ...)
362#define DBGLOG_ERROR(format, ...)
363#define DBGLOG_WARNING(format, ...)
364#define DBGLOG_INFO(format, ...)
365#define DBGLOG_FORCE(format, ...)
366
367#endif /* _UMM_MALLOC_CFG_H */