1 /******************************************************************************\r
2 * FILE PURPOSE: Multiple heap manager.\r
3 ******************************************************************************\r
4 * FILE NAME: mhm.c\r
5 *\r
6 * DESCRIPTION: Contains routines for multiple heap management. These functions\r
7 * may be used in allocating memory from several independent\r
8 * memory pools.\r
9 *\r
10 * NOTE: Current implementation does NOT provide deallocation!\r
11 *\r
12 * TABS: NONE\r
13 *\r
14 * $Id: mhm.c 1.1 1997/06/25 11:40:55 BOGDANK Exp $\r
15 *\r
16 * REVISION HISTORY:\r
17 *\r
18 * $Log: mhm.c $\r
19 * Revision 1.1 1997/06/25 11:40:55 BOGDANK\r
20 * Initial revision\r
21 *\r
22 * Copyright (c) 2016, Texas Instruments Incorporated
23 * All rights reserved.
24 *
25 * Redistribution and use in source and binary forms, with or without
26 * modification, are permitted provided that the following conditions
27 * are met:
28 *
29 * * Redistributions of source code must retain the above copyright
30 * notice, this list of conditions and the following disclaimer.
31 *
32 * * Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 *
36 * * Neither the name of Texas Instruments Incorporated nor the names of
37 * its contributors may be used to endorse or promote products derived
38 * from this software without specific prior written permission.
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
41 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
42 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
44 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
46 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
47 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
48 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
49 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
50 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51 *
52 */
53 \r
54 #include <stdlib.h>\r
55 #include <string.h> /* for memset */\r
56 \r
57 #include <xdc/std.h>\r
58 /* System definitions and utilities */\r
59 #include <ti/mas/types/types.h> /* DSP types */\r
60 \r
61 //#include <ti/mas/mhm/mhm.h>\r
62 //#include <ti/mas/mhm/src/mhmport.h>\r
63 \r
64 #include "../mhm.h"\r
65 #include "mhmport.h"\r
66 \r
67 /* Heap header that is placed at the beginning of a memory pool. */\r
68 typedef struct {\r
69 tuint total_size; /* total number of words in a memory pool */\r
70 tuint used_size; /* index of the first available word */\r
71 } mhmHead_t;\r
72 \r
73 /* The minimum and maximum number of words in a memory pool. Align gap and\r
74 * maximum size value are specified in mhmport.h. */\r
75 #define MHM_MIN_POOLSIZE (sizeof(mhmHead_t)+MHM_MAX_ALIGNGAP+1)\r
76 #define MHM_MAX_POOLSIZE MHM_MAX_SIZEVAL\r
78 /******************************************************************************\r
79 * FUNCTION PURPOSE: Create and initialize a heap.\r
80 ******************************************************************************\r
81 * DESCRIPTION: Creates and initializes a heap. If successful returns a heap\r
82 * handle, otherwise returns NULL.\r
83 *\r
84 * void *mhmCreate (\r
85 * void *base, - base address of a memory pool (!= NULL)\r
86 * tuint size, - number of words within the memory pool\r
87 * word initPattern) - initializing pattern for the heap\r
88 *\r
89 * RETURN VALUE: A heap handle, or NULL in case of error.\r
90 *\r
91 *****************************************************************************/\r
92 \r
93 void *mhmCreate (void *base, tuint size, tword initPattern)\r
94 {\r
95 tuint used_size;\r
96 mhmHead_t *head;\r
97 tword *w_base = (tword *)base;\r
98 tword *block;\r
99 mhmAddress_t wa_base_new, wa_block_new;\r
100 \r
101 /* initialize the raw space */\r
102 memset (w_base, initPattern, size);\r
103 \r
104 /* In the first part we align the base address of the memory pool */\r
105 used_size = 0;\r
106 wa_base_new = ((mhmAddress_t)w_base + MHM_MAX_ALIGNGAP) & (~MHM_ALIGN_MASK);\r
107 used_size += wa_base_new - (mhmAddress_t)w_base;\r
108 w_base = (tword *)wa_base_new; /* this is the new base after any gap */\r
109 \r
110 if (size < used_size+MHM_MIN_POOLSIZE || size-used_size > MHM_MAX_POOLSIZE ||\r
111 base == NULL)\r
112 return(NULL);\r
113 \r
114 /* Skip the pool alignment gap and start fresh. Do not forget to reset used size. */\r
115 /* w_base points to aligned address now and used_size is currently the gap size (if any) */\r
116 head = (mhmHead_t*)w_base; /* This will be the actual head of the heap */\r
117 head->total_size = size - used_size; /* record total heap size by removing the gap size */\r
118 \r
119 used_size = sizeof(mhmHead_t); /* reserve space for the header and make that the used size */\r
120 block = &w_base[used_size]; /* skip the header */\r
121 \r
122 /* Remember to align the remaining pool to the minimum alignment required by MHM */\r
123 wa_block_new = ((mhmAddress_t)block + MHM_MAX_ALIGNGAP) & (~MHM_ALIGN_MASK);\r
124 used_size += wa_block_new - (mhmAddress_t)block;\r
125 \r
126 head->used_size = used_size; /* record an index to empty space which is with minimum alignment */\r
127 return(head); /* return heap handle */\r
128 } /* mhmCreate */\r
130 /******************************************************************************\r
131 * FUNCTION PURPOSE: Allocate a block of memory from a heap.\r
132 ******************************************************************************\r
133 * DESCRIPTION: Allocates a block of memory from a heap. Block size must be\r
134 * bigger than zero. It returns a pointer to block start or a\r
135 * NULL if unsuccessful.\r
136 *\r
137 * void *mhmAlloc (\r
138 * void *handle, - heap handle obtained in mhmCreate()\r
139 * tuint size) - number of words to allocate for the block\r
140 *\r
141 * RETURN VALUE: A pointer to block start, or NULL when unsuccessful.\r
142 *\r
143 *****************************************************************************/\r
144 \r
145 void *mhmAlloc (void *handle, tuint size)\r
146 {\r
147 tuint left;\r
148 mhmHead_t *head = (mhmHead_t*)handle;\r
149 tword *w_base = (tword *)handle;\r
150 tword *block;\r
151 \r
152 if (size == 0 || size > MHM_MAX_SIZE || head->total_size <= head->used_size)\r
153 return(NULL);\r
154 \r
155 /* Make sure the actual used size will be resulting in minimum required MHM alignment */\r
156 size = (tuint)((size + MHM_MAX_ALIGNGAP) & (~MHM_ALIGN_MASK));\r
157 \r
158 left = head->total_size - head->used_size;\r
159 if (left < size) /* do we have space for this block? */\r
160 return(NULL);\r
161 block = &w_base[head->used_size];\r
162 head->used_size += (tuint)size; /* increase the used space */\r
163 \r
164 /* no need for additional alignment since the size was already aligned above and base is\r
165 * always kept aligned to the minimum requried MHM alignment */\r
166 \r
167 return(block); /* return a pointer to start */\r
168 } /* mhmAlloc */\r
169 \r
170 /******************************************************************************\r
171 * FUNCTION PURPOSE: Allocate a block of memory from a heap log2 aligned\r
172 ******************************************************************************\r
173 * DESCRIPTION: Allocates a block of memory from a heap. Block size must be\r
174 * bigger than zero. It returns a pointer to block start or a\r
175 * NULL if unsuccessful. The start address will be aligned to pow-2\r
176 * boundary.\r
177 *\r
178 * void *mhmAllocAligned (\r
179 * void *handle, - heap handle obtained in mhmCreate()\r
180 * tuint size, - number of words to allocate for the block\r
181 * tint log2align) - log2 alignment that is required (e.g. 3 for 0xFF..FF8 mask)\r
182 *\r
183 * RETURN VALUE: A pointer to block start, or NULL when unsuccessful.\r
184 *\r
185 *****************************************************************************/\r
186 \r
187 void *mhmAllocAligned (void *handle, tuint size, tint log2align)\r
188 {\r
189 tuint left, used_size;\r
190 mhmHead_t *head = (mhmHead_t*)handle;\r
191 tword *w_base = (tword *)handle;\r
192 tword *block;\r
193 tulong align_mask, align_gap;\r
194 mhmAddress_t wa_block_new;\r
195 \r
196 if (size == 0 || size > MHM_MAX_SIZE || head->total_size <= head->used_size)\r
197 return(NULL);\r
198 \r
199 if (log2align < 1) { /* use simple alloc function if no alignment required */\r
200 block = mhmAlloc(handle, size);\r
201 return(block);\r
202 }\r
203 used_size = head->used_size; /* current used size */\r
204 block = &w_base[used_size]; /* skip the already used size */\r
205 \r
206 /* Remember to align the new block address to the requested alignment */\r
207 align_mask = ((~0UL) << log2align);\r
208 align_gap = (~align_mask);\r
209 \r
210 wa_block_new = (((mhmAddress_t)block + align_gap) & align_mask);\r
211 size += wa_block_new - (mhmAddress_t)block; /* update size with the gap (if any) */\r
212 \r
213 /* Make sure the actual used size will be resulting in minimum required MHM alignment */\r
214 /* This in general may be different from the requested start address alignment! */\r
215 size = (tuint)((size + MHM_MAX_ALIGNGAP) & (~MHM_ALIGN_MASK));\r
216 \r
217 left = head->total_size - used_size;\r
218 if (left < size) /* do we have space for this block? (and any gaps) */\r
219 return(NULL);\r
220 block = (tword*)wa_block_new; /* this is where we would start new block */\r
221 head->used_size = used_size+size; /* increase the used space */\r
222 \r
223 /* no need for additional alignment since the size and base were already aligned above */\r
224 \r
225 return(block); /* return a pointer to start */\r
226 } /* mhmAllocAligned */\r
227 \r
228 /******************************************************************************\r
229 * FUNCTION PURPOSE: Deallocate a memory block from a heap.\r
230 ******************************************************************************\r
231 * DESCRIPTION: Deallocates a memory block from a heap.\r
232 *\r
233 * void mhmFree (\r
234 * void *handle, - a heap handle\r
235 * void *base) - base address of a block\r
236 *\r
237 *****************************************************************************/\r
238 \r
239 void mhmFree (void *handle, void *base)\r
240 {\r
241 return; /* currently NOT supported */\r
242 } /* mhmFree */\r
243 \r
244 /******************************************************************************\r
245 * FUNCTION PURPOSE: Reset heap and start allocating form the beginning.\r
246 ******************************************************************************\r
247 * DESCRIPTION: Resets heap and allows for allocation to start from the beginning.\r
248 *\r
249 * void mhmReset (\r
250 * void *handle) - a heap handle\r
251 *\r
252 *****************************************************************************/\r
253 \r
254 void mhmReset (void *handle)\r
255 {\r
256 tuint used_size;\r
257 mhmHead_t *head = (mhmHead_t*)handle;\r
258 tword *w_base = (tword*)handle;\r
259 tword *block;\r
260 mhmAddress_t wa_block_new;\r
261 \r
262 /* no need to change the total size */\r
263 /* we start from empty heap */\r
264 used_size = sizeof(mhmHead_t); /* reserve space for the header and make that the used size */\r
265 block = &w_base[used_size]; /* skip the header */\r
266 \r
267 /* Remember to align the remaining pool to the minimum alignment required by MHM */\r
268 wa_block_new = ((mhmAddress_t)block + MHM_MAX_ALIGNGAP) & (~MHM_ALIGN_MASK);\r
269 used_size += wa_block_new - (mhmAddress_t)block;\r
270 \r
271 head->used_size = used_size; /* record an index to empty space which is with minimum alignment */\r
272 \r
273 /* the head which is the base of the heap is already aligned */\r
274 return;\r
275 } /* mhmreset */\r
276 \r
277 /* nothing past this point */\r
278 \r