1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
32 33 34 35
36
37 package ti.sysbios.heaps;
38
39 import xdc.rov.ViewInfo;
40 import xdc.runtime.Memory;
41 import xdc.runtime.Error;
42
43 /*!
44 * ======== HeapMem ========
45 * Variable size buffer heap manager
46 *
47 * HeapMem manager provides functions to allocate and free storage from a
48 * heap of type HeapMem which inherits from IHeap.
49 *
50 * @p(html)
51 * <h3> HeapMem Gate </h3>
52 * A HeapMem instance will use the HeapMem module Gate to protect any accesses
53 * to its list of free memory blocks. The HeapMem instance will enter and
54 * leave the module Gate when allocating blocks, freeing blocks, and
55 * retrieving statistics about the HeapMem.
56 *
57 * By default, the Gate is of type GateMutex.
58 *
59 * A different Gate can be specified using the common$.gate parameter.
60 * For example, to use a GateTask to protect HeapMem:
61 * HeapMem.common$.gate = GateTask.create();
62 *
63 * To save on overhead, HeapMem does not create additional Gate instances on a
64 * per-instance basis; there is only one Gate instance shared across all of
65 * the HeapMem instances. Therefore, the HeapMem.common$.gateParams parameter
66 * (used for configuring per-instance Gates) is ignored.
67 *
68 * The type of Gate used should be chosen based on the type of threads (Hwi,
69 * Swi, Task, etc.) using the heap. It should also consider the
70 * non-deterministic nature of the HeapMem. A call to alloc or free will
71 * traverse a list of free blocks, so a GateHwi, for example, is likely an
72 * inappropriate Gate for HeapMem.
73 *
74 * @p(html)
75 * <h3> Calling Context </h3>
76 * <table border="1" cellpadding="3">
77 * <colgroup span="1"></colgroup> <colgroup span="5" align="center">
78 * </colgroup>
79 *
80 * <tr><th> Function </th><th> Hwi </th><th> Swi </th>
81 * <th> Task </th><th> Main </th><th> Startup </th></tr>
82 * <!-- -->
83 * <tr><td> Params_init </td><td> Y </td><td> Y </td>
84 * <td> Y </td><td> Y </td><td> Y </td></tr>
85 * <tr><td> alloc </td><td> N** </td><td> N** </td>
86 * <td> Y** </td><td> Y </td><td> N </td></tr>
87 * <tr><td> construct </td><td> Y </td><td> Y </td>
88 * <td> Y </td><td> Y </td><td> N </td></tr>
89 * <tr><td> create </td><td> N* </td><td> N* </td>
90 * <td> Y </td><td> Y </td><td> N </td></tr>
91 * <tr><td> delete </td><td> N* </td><td> N* </td>
92 * <td> Y </td><td> Y </td><td> N </td></tr>
93 * <tr><td> destruct </td><td> Y </td><td> Y </td>
94 * <td> Y </td><td> Y </td><td> N </td></tr>
95 * <tr><td> free </td><td> N** </td><td> N** </td>
96 * <td> Y** </td><td> Y </td><td> N </td></tr>
97 * <tr><td> getExtendedStats </td><td> Y </td><td> Y </td>
98 * <td> Y </td><td> Y </td><td> N </td></tr>
99 * <tr><td> getStats </td><td> N** </td><td> N** </td>
100 * <td> Y** </td><td> Y </td><td> N </td></tr>
101 * <tr><td> isBlocking </td><td> Y </td><td> Y </td>
102 * <td> Y </td><td> Y </td><td> N </td></tr>
103 * <tr><td> restore </td><td> Y+ </td><td> Y+ </td>
104 * <td> Y+ </td><td> Y </td><td> N </td></tr>
105 * <tr><td colspan="6"> Definitions: <br />
106 * <ul>
107 * <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
108 * <li> <b>Swi</b>: API is callable from a Swi thread. </li>
109 * <li> <b>Task</b>: API is callable from a Task thread. </li>
110 * <li> <b>Main</b>: API is callable during any of these phases: </li>
111 * <ul>
112 * <li> In your module startup after this module is started
113 * (e.g. HeapMem_Module_startupDone() returns TRUE). </li>
114 * <li> During xdc.runtime.Startup.lastFxns. </li>
115 * <li> During main().</li>
116 * <li> During BIOS.startupFxns.</li>
117 * </ul>
118 * <li> <b>Startup</b>: API is callable during any of these phases:</li>
119 * <ul>
120 * <li> During xdc.runtime.Startup.firstFxns.</li>
121 * <li> In your module startup before this module is started
122 * (e.g. HeapMem_Module_startupDone() returns FALSE).</li>
123 * </ul>
124 * <li> <b>*</b> : Assuming blocking Heap is used for creation. </li>
125 * <li> <b>**</b>: Assuming GateMutex is used as HeapMem's Gate. </li>
126 * <li> <b>+</b> : Cannot use HeapMem object while it is being
127 * restored. </li>
128 * </ul>
129 * </td></tr>
130 *
131 * </table>
132 * @p
133 */
134 @Gated
135 module HeapMem inherits xdc.runtime.IHeap {
136
137 /*! @_nodoc */
138 @XmlDtd
139 metaonly struct BasicView {
140 String label;
141 Ptr buf;
142 String sectionName;
143 }
144
145 /*! @_nodoc */
146 @XmlDtd
147 metaonly struct DetailedView {
148 String label;
149 Ptr buf;
150 String sectionName;
151 Memory.Size totalSize;
152 Memory.Size totalFreeSize;
153 Memory.Size largestFreeSize;
154 }
155
156 /*!
157 * ======== FreeBlockView ========
158 * @_nodoc
159 */
160 metaonly struct FreeBlockView {
161 String Address;
162 String size;
163 String status;
164 }
165
166 /*! @_nodoc */
167 @Facet
168 metaonly config ViewInfo.Instance rovViewInfo =
169 ViewInfo.create({
170 viewMap: [
171 [
172 'Basic',
173 {
174 type: ViewInfo.INSTANCE,
175 viewInitFxn: 'viewInitBasic',
176 structName: 'BasicView'
177 }
178 ],
179 [
180 'Detailed',
181 {
182 type: ViewInfo.INSTANCE,
183 viewInitFxn: 'viewInitDetailed',
184 structName: 'DetailedView'
185 }
186 ],
187 [
188 'FreeList',
189 {
190 type: ViewInfo.INSTANCE_DATA,
191 viewInitFxn: 'viewInitData',
192 structName: 'FreeBlockView'
193 }
194 ]
195 ]
196 });
197
198
199 /*!
200 * ======== ExtendedStats ========
201 * Stat structure for the HeapMem_getExtendedStats function
202 *
203 * @field(buf) Base address of the internal buffer.
204 * This may be different from the original buf
205 * parameter due to alignment requirements.
206 * @field(size) Size of the internal buffer.
207 * This may be different from the original size
208 * parameter due to alignment requirements.
209 */
210 struct ExtendedStats {
211 Ptr buf;
212 SizeT size;
213 }
214
215 /*!
216 * ======== A_zeroBlock ========
217 * Assert raised when a block of size 0 is requested
218 *
219 * This error can also be raised if the requested size wraps
220 * the contents of a SizeT type when it is adjusted for a minimum
221 * alignment. For example, when SizeT is 16-bits and a size request
222 * is made for 0xFFFB.
223 */
224 config xdc.runtime.Assert.Id A_zeroBlock =
225 {msg: "A_zeroBlock: Cannot allocate size 0"};
226
227 /*!
228 * ======== A_heapSize ========
229 * Assert raised when the requested heap size is too small
230 */
231 config xdc.runtime.Assert.Id A_heapSize =
232 {msg: "A_heapSize: Requested heap size is too small"};
233
234 /*!
235 * ======== A_align ========
236 * Assert raised when the requested alignment is not a power of 2
237 */
238 config xdc.runtime.Assert.Id A_align =
239 {msg: "A_align: Requested align is not a power of 2"};
240
241 /*!
242 * ======== E_memory ========
243 * Raised when requested size exceeds largest free block
244 */
245 config Error.Id E_memory = {msg: "out of memory: handle=0x%x, size=%u"};
246
247 /*!
248 * ======== A_invalidFree ========
249 * Assert raised when the free detects that an invalid addr or size
250 *
251 * This could arise when multiple frees are done on the same buffer or
252 * if corruption occurred.
253 *
254 * This also could occur when an alloc is made with size N and the
255 * free for this buffer specifies size M where M > N. Note: not every
256 * case is detectable.
257 *
258 * This assert can also be caused when passing an invalid addr to free
259 * or if the size is causing the end of the buffer to be
260 * out of the expected range.
261 */
262 config xdc.runtime.Assert.Id A_invalidFree =
263 {msg: "A_invalidFree: Invalid free"};
264
265 /*!
266 * ======== enter ========
267 * @_nodoc
268 * Enter the module's gate. This is needed to support
269 * the legacy MEM module. It allows MEM to use the same
270 * gate for thread-safety.
271 */
272 @DirectCall
273 IArg enter();
274
275 /*!
276 * ======== leave ========
277 * @_nodoc
278 * Leave the module's gate. This is needed to support
279 * the legacy MEM module. It allows MEM to use the same
280 * gate for thread-safety.
281 */
282 @DirectCall
283 Void leave(IArg key);
284
285 instance:
286
287 /*!
288 * ======== align ========
289 * Alignment of the buffer being managed by this heap instance
290 *
291 * In the static HeapMem.create() call, the buffer allocated for the
292 * HeapMem instance will have the alignment specified by this parameter.
293 *
294 * In the dynamic case, the client must supply the buffer, so it is the
295 * client's responsibility to manage the buffer's alignment, and there is
296 * no 'align' parameter.
297 *
298 * The specified alignment must be a power of 2.
299 *
300 * HeapMem requires that the buffer be aligned on a target-specific minimum
301 * alignment, and will adjust (round up) the requested alignment as
302 * necessary to satisfy this requirement.
303 *
304 * The default alignment is 0.
305 */
306 metaonly config SizeT align = 0;
307
308 /*!
309 * ======== sectionName ========
310 * Section name for the buffer managed by the instance
311 *
312 * The default section is the 'dataSection' in the platform.
313 */
314 metaonly config String sectionName = null;
315
316 /*!
317 * ======== buf ========
318 * Buffer being managed by this heap instance
319 *
320 * This parameter is ignored in the static HeapMem.create() call. It is a
321 * required parameter in the dynamic HeapMem_create() call.
322 *
323 * HeapMem requires that the buffer be aligned on a target-specific minimum
324 * alignment, and will adjust the buffer's start address and size as
325 * necessary to satisfy this requirement.
326 */
327 config Ptr buf = 0;
328
329 /*!
330 * ======== size ========
331 * Size of buffer being managed by this heap instance
332 *
333 * The usable size may be smaller depending on alignment requirements.
334 */
335 config Memory.Size size = 0;
336
337 /*!
338 * ======== alloc ========
339 *
340 * @HeapMem
341 * The actual block returned may be larger than requested to satisfy
342 * alignment requirements
343 *
344 * HeapMem_alloc() will lock the heap using the HeapMem Gate while it
345 * traverses the list of free blocks to find a large enough block for
346 * the request.
347 *
348 * Guidelines for using large heaps and multiple alloc() calls.
349 * @p(blist)
350 * - If possible, allocate larger blocks first. Previous
351 * allocations of small memory blocks can reduce the size
352 * of the blocks available for larger memory allocations.
353 * - Realize that alloc() can fail even if the heap contains a
354 * sufficient absolute amount of unallocated space. This is
355 * because the largest free memory block may be smaller than
356 * total amount of unallocated memory.
357 * @p
358 */
359 @DirectCall
360 override Ptr alloc(SizeT size, SizeT align, xdc.runtime.Error.Block *eb);
361
362 /*!
363 * ======== free ========
364 *
365 * @HeapMem
366 * free() places the memory block specified by addr and size back into the
367 * free pool of the heap specified. The newly freed block is combined with
368 * any adjacent free blocks. The space is then available for further
369 * allocation by alloc().
370 *
371 * free() will lock the heap using the HeapMem Gate, if one is specified
372 * using 'HeapMem.common$.gate'.
373 */
374 @DirectCall
375 override Void free(Ptr block, SizeT size);
376
377 /*!
378 * ======== isBlocking ========
379 *
380 * @HeapMem
381 * This function queries the gate (as specified by 'HeapMem.common$.gate')
382 * to determine if the alloc/free can be blocking.
383 */
384 @DirectCall
385 override Bool isBlocking();
386
387 /*!
388 * ======== getStats ========
389 *
390 * @HeapMem
391 * getStats() will lock the heap using the HeapMem Gate while it retrieves
392 * the HeapMem's statistics.
393 *
394 * The returned totalSize reflects the usable size of the buffer, not
395 * necessarily the size specified during create.
396 */
397 @DirectCall
398 override Void getStats(xdc.runtime.Memory.Stats *stats);
399
400
401 /*!
402 * ======== restore ========
403 * Restores an instance to its original created state
404 *
405 * This function restores a static or dynamically created instance to
406 * its original created state. Any memory previously allocated from the
407 * heap is no longer valid after this API is called. This function
408 * does not check whether there is allocated memory or not.
409 */
410 @DirectCall
411 Void restore();
412
413 /*!
414 * ======== getExtendedStats ========
415 * Retrieves the extended statistics for a HeapMem instance
416 *
417 * This function retrieves the extended statistics for a HeapMem instance.
418 * It does not retrieve the standard xdc.runtime.Memory.Stats information.
419 *
420 * @param(stats) Location for the returned extended statistics.
421 */
422 @DirectCall
423 Void getExtendedStats(ExtendedStats *stats);
424
425 internal:
426
427 /*!
428 * ======== init ========
429 * Initialize instance at runtime
430 *
431 * This function is plugged as a Startup.firstFxn so that the
432 * HeapMem objects are ready and usable by malloc() and
433 * Memory_alloc() by the time the module startup functions
434 * get called so that any calls to atexit(), which in some targets
435 * invokes malloc(), will be handled cleanly.
436 */
437 Void init();
438
439
440 config Int reqAlign;
441
442
443 config Int reqAlignMask;
444
445
446 struct Header {
447 Header *next;
448 Memory.Size size;
449 };
450
451 struct Instance_State {
452 xdc.runtime.Memory.Size align;
453 Char buf[];
454 Header head; 455 456 457
458 };
459 }
460
461 462 463 464
465