EVE 1.0
md-heap.h
Go to the documentation of this file.
1 #ifndef MD_HEAP_H_INCLUDED
2 #define MD_HEAP_H_INCLUDED
3 /**********************************************************************/
4 /*
5  * Copyright (c) 2016, Jetro AS
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without modification,
9  * are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice,
12  * this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  * derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONRIBUTORS ``AS IS'' AND ANY EXPRESS
20  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
22  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
24  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
28  * OF SUCH DAMAGE.
29  *
30  * This file is part of the EVE platform.
31  */
32 
33 /**
34  * \file
35  * @brief Movable and discardable heap.
36  *
37  * @author DT, Jetro AS
38  */ /******************************************************************/
39 
40 #ifdef __cplusplus
41  extern "C" {
42 #endif /* __cplusplus */
43 
44 /**
45  * \defgroup mdheap Movable and discardable heap
46  * \ingroup util
47  * \{
48  */
49 
50 struct md_heap_t;
51 
52 /**
53  * Heap index type
54  */
55 typedef uint8_t md_idx_t;
56 
57 /**
58  * Entry relocation handler
59  *
60  * @param Ptr Address of a variable which contains a pointer to the allocated memory block
61  * @param Addr New value for the pointer
62  */
63 typedef void (*md_reloc_handler_t)(void **Ptr, void *Addr);
64 
65 /**
66  * Swap-out user callback
67  *
68  * @param Heap Heap instance pointer
69  * @param Pos Position in the external memory where data to be swapped out
70  * @param Data Address of the data in the internal memory
71  * @param Size Size of the data
72  * @return true if data was swapped out, false otherwise
73  */
74 typedef bool (*md_swap_out_cb_t)(const struct md_heap_t *Heap, uint32_t Pos, const uint8_t **DataPtr, uint32_t Size);
75 
76 /**
77  * Swap-in user callback
78  *
79  * @param Heap Heap instance pointer
80  * @param Data Address of the data buffer in the internal memory to be filled by data
81  * @param Pos Position in the external memory where data is located
82  * @param Size Size of the data
83  * @return true if data was swapped in, false otherwise
84  */
85 typedef bool (*md_swap_in_cb_t)(const struct md_heap_t *Heap, uint8_t **DataPtr, uint32_t Pos, uint32_t Size);
86 
87 /**
88  * Tiny double-linked list
89  */
90 struct md_list_t
91 {
92  md_idx_t Prev; /*!< Index of the previous (left-hand) entry */
93  md_idx_t Next; /*!< Index of the next (right-hand) entry */
94 };
95 
96 /**
97  * Memory block descriptor
98  */
100 {
101  struct md_list_t Link; /*!< "All blocks" linked list entry */
102  struct md_list_t Free; /*!< "Free blocks" linked list entry */
103  uint16_t Size; /*!< Size of the block */
104  uint16_t Pos; /*!< Offset of the block in the arena */
105  void **RelocPtr; /*!< Client-defined relocation pointer */
106  md_reloc_handler_t RelocHandler; /*!< Client-defined relocation handler */
107 };
108 
109 /**
110  * Heap statistics
111  */
112 struct md_stat_t
113 {
114  uint32_t AllocSize; /*!< Amount of data allocated in the heap */
115  uint32_t AllocMaxSize; /*!< Max registered amount of data allocated in the heap */
116  uint32_t SwappedOut; /*!< Amount of data swapped out */
117  uint8_t AllocCount; /*!< Number of allocated blocks */
118  uint8_t AllocMaxCount; /*!< Max registered number of allocated blocks */
119  uint8_t DescrCount; /*!< Number of used descriptors */
120  uint8_t DescrMaxCount; /*!< Max registered number of used descriptors */
121 };
122 
123 /**
124  * Heap state
125  */
127 {
128  uint8_t FreeBlockIdx; /*!< Index of a free block currently used for allocation */
129  uint8_t ExternalRam; /*!< Index of the first block in the external RAM */
130  struct md_stat_t Stat; /*!< Heap statistics */
131 };
132 
133 /**
134  * MD Heap instance
135  */
136 struct md_heap_t
137 {
138  struct md_descriptor_t *Entries; /*!< Descriptor table */
139  uint32_t NumEntries; /*!< Number of entries in the descriptor table */
140  uint8_t *RamBuffer; /*!< Allocable memory region */
141  uint32_t RamBufferSize; /*!< Size of the allocable memory region */
142  struct md_state_t *State; /*!< Heap state */
143  uint32_t ExtRamSize; /*!< External RAM size */
144  md_swap_out_cb_t SwapOut; /*!< Swap out callback */
145  md_swap_in_cb_t SwapIn; /*!< Swap in callback */
146 };
147 
148 /**
149  * MD auto lock
150  */
152 {
153  const struct md_heap_t *Heap; /*!< Pointer to the heap */
154  md_reloc_handler_t Handler; /*!< Relocation handler */
155  void **Ptr; /*!< Address of a variable which contains
156  a pointer to the allocated memory block */
157 };
158 
159 void MemInit(const struct md_heap_t *Heap);
160 void *MemAlloc(const struct md_heap_t *Heap, uint32_t Size);
161 void MemFree(const struct md_heap_t *Heap, void *Ptr);
162 void MemUnlock(const struct md_heap_t *Heap, void *Ptr, md_reloc_handler_t Handler);
163 bool MemLock(const struct md_heap_t *Heap, void *Ptr, md_reloc_handler_t *PrevHandler);
164 
165 /**
166  * Compact the memory pool, collect small free blocks into a big one(s)
167  *
168  * @param Heap Heap instance pointer
169  */
170 void MemDefragment(const struct md_heap_t *Heap);
171 
172 void MemGenericRelocator(void **ptr, void *addr);
173 
174 static inline bool MemInHeap(const struct md_heap_t *Heap, void *Ptr)
175 {
176  return ((uint8_t *) Ptr >= &Heap->RamBuffer[0])
177  && ((uint8_t *) Ptr < &Heap->RamBuffer[Heap->RamBufferSize]);
178 }
179 
180 __attribute__((always_inline))
181 static inline void MemAutoLockDestructor(struct md_auto_lock_t *Lock)
182 {
183  MemUnlock(Lock->Heap, Lock->Ptr, Lock->Handler);
184 }
185 
186 void MemPrintStat(const struct md_heap_t *Heap);
187 void MemPrint(const struct md_heap_t *Heap);
188 void MemPrintExt(const struct md_heap_t *Heap);
189 
190 #define SYSTEM_HEAP(RequestedNumEntries) \
191  extern uint32_t __HeapBase, __StackLimit; \
192  static struct md_descriptor_t SystemHeapEntries[RequestedNumEntries]; \
193  static struct md_state_t SystemHeapState; \
194  struct md_heap_t SystemHeap; \
195  static void SystemHeapCtor(void) __attribute__((constructor)); \
196  static void SystemHeapCtor(void) \
197  { \
198  SystemHeap.Entries = SystemHeapEntries; \
199  SystemHeap.NumEntries = (RequestedNumEntries); \
200  SystemHeap.RamBuffer = (uint8_t *) &__HeapBase; \
201  SystemHeap.RamBufferSize = \
202  (uint32_t) &__StackLimit - (uint32_t) &__HeapBase; \
203  SystemHeap.State = &SystemHeapState; \
204  MemInit(&SystemHeap); \
205  printf("[HEAP] %d bytes (%d entries) in system heap.\n", \
206  (unsigned) SystemHeap.RamBufferSize, \
207  (unsigned) SystemHeap.NumEntries); \
208  } \
209  struct md_heap_t SystemHeap
210 
211 /** Auto lock */
212 #define MEM_AUTO_LOCK(TheName, TheHeap, ThePtr) \
213  struct md_auto_lock_t TheName \
214  __attribute__((cleanup(MemAutoLockDestructor))) \
215  = { .Heap = TheHeap, .Ptr = (void **) ThePtr, }; \
216  { \
217  bool Ret = MemLock(TheHeap, ThePtr, &TheName.Handler); \
218  assert(Ret); \
219  } \
220  do { } while (0)
221 
222 /** \} */
223 
224 #ifdef __cplusplus
225  }
226 #endif /* __cplusplus */
227 
228 #endif /* MD_HEAP_H_INCLUDED */
uint32_t AllocSize
Definition: md-heap.h:114
bool(* md_swap_in_cb_t)(const struct md_heap_t *Heap, uint8_t **DataPtr, uint32_t Pos, uint32_t Size)
Definition: md-heap.h:85
uint32_t ExtRamSize
Definition: md-heap.h:143
uint16_t Size
Definition: md-heap.h:103
uint32_t RamBufferSize
Definition: md-heap.h:141
md_swap_in_cb_t SwapIn
Definition: md-heap.h:145
uint8_t ExternalRam
Definition: md-heap.h:129
void ** Ptr
Definition: md-heap.h:155
__attribute__((always_inline)) static inline void swint_enable_indirect_adapter(swint_state_t *state)
Definition: work.h:245
md_idx_t Prev
Definition: md-heap.h:92
uint32_t AllocMaxSize
Definition: md-heap.h:115
uint8_t AllocMaxCount
Definition: md-heap.h:118
struct md_descriptor_t * Entries
Definition: md-heap.h:138
const struct md_heap_t * Heap
Definition: md-heap.h:153
uint8_t md_idx_t
Definition: md-heap.h:50
uint8_t DescrCount
Definition: md-heap.h:119
uint8_t DescrMaxCount
Definition: md-heap.h:120
uint8_t AllocCount
Definition: md-heap.h:117
md_idx_t Next
Definition: md-heap.h:93
uint32_t NumEntries
Definition: md-heap.h:139
uint16_t Pos
Definition: md-heap.h:104
md_reloc_handler_t Handler
Definition: md-heap.h:154
uint8_t * RamBuffer
Definition: md-heap.h:140
void ** RelocPtr
Definition: md-heap.h:105
uint8_t FreeBlockIdx
Definition: md-heap.h:128
void(* md_reloc_handler_t)(void **Ptr, void *Addr)
Definition: md-heap.h:63
md_reloc_handler_t RelocHandler
Definition: md-heap.h:106
md_swap_out_cb_t SwapOut
Definition: md-heap.h:144
bool(* md_swap_out_cb_t)(const struct md_heap_t *Heap, uint32_t Pos, const uint8_t **DataPtr, uint32_t Size)
Definition: md-heap.h:74
void MemDefragment(const struct md_heap_t *Heap)
struct md_state_t * State
Definition: md-heap.h:142
uint32_t SwappedOut
Definition: md-heap.h:116