3 Copyright (C) Dean Camera, 2009.
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
10 Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
12 Permission to use, copy, modify, and distribute this software
13 and its documentation for any purpose and without fee is hereby
14 granted, provided that the above copyright notice appear in all
15 copies and that both that the copyright notice and this
16 permission notice and warranty disclaimer appear in supporting
17 documentation, and that the name of the author not be used in
18 advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
21 The author disclaim all warranties with regard to this
22 software, including all implied warranties of merchantability
23 and fitness. In no event shall the author be liable for any
24 special, indirect or consequential damages or any damages
25 whatsoever resulting from loss of use, data or profits, whether
26 in an action of contract, negligence or other tortious action,
27 arising out of or in connection with the use or performance of
33 * Dynamic, auto-defragmenting block memory allocator library. This library provides a convenient replacement for
34 * the standard avr-libc dynamic memory allocation routines. Memory is handed out in block chunks, to reduce the
35 * management memory overhead.
37 * Unlike the normal memory allocation routines, this library gives out handles to memory which must be dereferenced
38 * at the exact time of use, rather than handing back direct memory pointers. By using library managed handles
39 * instead of pointers, allocated memory blocks can be shifted around as needed transparently to defragment the
40 * memory as more blocks are requested.
42 * The memory heap is static, thus the total memory usage of the compiled application (as reported by the avr-size
43 * tool of the AVR-GCC toolchain) includes the dynamic memory heap.
45 * The constants NUM_BLOCKS, BLOCK_SIZE and NUM_HANDLES must be defined in the project makefile (and passed to the
46 * preprocessor via the -D GCC switch) for this library to compile.
48 * NUM_BLOCKS indicates the number of memory blocks in the memory psudoheap which can be chaned together and handed
49 * to the application via a memory handle. NUM_HANDLES is the maximum number of memory handles (pointing to one or
50 * more chained memory blocks) which can be handed out simultaneously before requring a handle (and its associated
51 * memory) to be freed. BLOCK_SIZE gives the number of bytes in each memory block.
62 /* Preprocessor Checks: */
63 #if (!defined(NUM_BLOCKS) || !defined(BLOCK_SIZE) || !defined(NUM_HANDLES))
64 #error NUM_BLOCKS, BLOCK_SIZE and NUM_HANDLES must be defined before use via makefile.
67 /* Public Interface - May be used in end-application: */
69 /** Macro to dereference a given memory handle into the given type. The given type should be a pointer
70 * if the memory is to contain an array of items, or should be a standard type (such as a primative or
71 * structure) if the memory is to hold a single item of a single type. */
72 #define DEREF(handle, type) (*(type*)handle)
74 /** Constant, giving the total heap size in bytes. */
75 #define ALLOCABLE_BYTES (1UL * NUM_BLOCKS * BLOCK_SIZE)
78 /** Memory handle type, used to store handles given by the library functions. */
79 typedef const void** Mem_Handle_t
;
81 #if (ALLOCABLE_BYTES > 0xFFFF) || defined(__DOXYGEN__)
82 /** Type define for the size (in bytes) for an allocation for passing to the library functions.
83 * The exact type width varies depending on the value of ALLOCABLE_BYTES to ensure that a single
84 * allocation can request the entire heap if needed.
86 typedef uint32_t Alloc_Size_t
;
87 #elif (ALLOCABLE_BYTES > 0xFF)
88 typedef uint16_t Alloc_Size_t
;
90 typedef uint8_t Alloc_Size_t
;
93 #if (NUM_BLOCKS > 0xFFFF) || defined(__DOXYGEN__)
94 /** Type define for a block number in the heap. The exact type width varies depending on the
95 * value of NUM_BLOCKS to ensure that the type can store an index to any block in the block pool.
97 typedef uint32_t Block_Number_t
;
98 #elif (NUM_BLOCKS > 0xFF)
99 typedef uint16_t Block_Number_t
;
101 typedef uint8_t Block_Number_t
;
104 #if (NUM_HANDLES > 0xFFFF) || defined(__DOXYGEN__)
105 /** Type define for a handle number. The exact type width varies depending on the value of NUM_HANDLES
106 * to ensure that the type can store the index of any handle in the handle pool.
108 typedef uint32_t Handle_Number_t
;
109 #elif (NUM_HANDLES > 0xFF)
110 typedef uint16_t Handle_Number_t
;
112 typedef uint8_t Handle_Number_t
;
115 /* Function Prototypes: */
116 /** Allocates a given number of blocks from the heap (calculated from the requested number of bytes) and
117 * returns a handle to the newly allocated memory.
119 * \param Bytes The number of bytes requested to be allocated from the heap
121 * \return NULL handle if the allocation fails, or handle to the allocated memory if the allocation succeeds
123 Mem_Handle_t
Mem_Alloc(const Alloc_Size_t Bytes
);
125 /** Allocates a given number of blocks from the heap (calculated from the requested number of bytes) and
126 * returns a handle to the newly allocated memory. Calloced memory is automatically cleared to all 0x00
127 * values at the time of allocation.
129 * \param Bytes The number of pre-cleared bytes requested to be allocated from the heap
131 * \return NULL handle if the allocation fails, or handle to the allocated memory if the allocation succeeds
133 Mem_Handle_t
Mem_Calloc(const Alloc_Size_t Bytes
);
135 /** Deallocates a given memory handle, and attempts to allocates the given number of blocks from the heap
136 * (calculated from the requested number of bytes) immediately following the deallocation. The new memory
137 * may be located in the same area as the previous memory, but this is not guaranteed.
139 * \param CurrAllocHdl Handle to an already allocated section of memory in the heap to deallocate
140 * \param Bytes The number of bytes requested to be allocated from the heap following the
143 * \return NULL handle if the allocation fails, or handle to the allocated memory if the allocation succeeds
145 * \warning Even if the allocation fails, the deallocation will still occur. Care should be taken to ensure
146 * that the previously allocated memory is not used following an unsuccessful realloc().
148 Mem_Handle_t
Mem_Realloc(Mem_Handle_t CurrAllocHdl
, const Alloc_Size_t Bytes
);
150 /** Deallocates a given previously allocated section of memory from the heap.
152 * \param CurrAllocHdl Handle to a previously allocated section of memory in the heap
154 void Mem_Free(Mem_Handle_t CurrAllocHdl
);
156 /** Returns the total number of unallocated blocks in the heap.
158 * \return Number of free blocks in the heap, as a Block_Number_t integer
160 Block_Number_t
Mem_TotalFreeBlocks(void);
162 /** Returns the total number of unallocated handles in the handle pool.
164 * \return Number of free handles in the handle pool, as a Handle_Number_t integer
166 Handle_Number_t
Mem_TotalFreeHandles(void);
168 /* Private Interface - For use in library only: */
169 #if !defined(__DOXYGEN__)
171 #define BLOCK_USED_MASK (1 << 0)
172 #define BLOCK_LINKED_MASK (1 << 1)
174 /* Function Prototypes: */
175 #if defined(INCLUDE_FROM_DYNALLOC_C)
176 static uint8_t Mem_GetBlockFlags(const Block_Number_t BlockNum
);
177 static void Mem_SetBlockFlags(const Block_Number_t BlockNum
, const uint8_t Flags
);
178 static void Mem_Defrag(void);