1 /*
2 * Copyright (c) 2013, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 /*
33 * ======== HeapBuf.xdc ========
34 *
35 */
36
37 package ti.sysbios.heaps;
38
39 import xdc.rov.ViewInfo;
40
41 /*!
42 * ======== HeapBuf ========
43 * Fixed size buffer heap manager
44 *
45 * The HeapBuf manager provides functions to allocate and free storage from a
46 * heap of type HeapBuf which inherits from IHeap. HeapBuf manages a single
47 * fixed-size buffer, split into equally sized allocable blocks.
48 *
49 * The HeapBuf manager is intended as a very fast and deterministic memory
50 * manager which can only allocate blocks of a single size. It is ideal for
51 * managing a heap that is only used for allocating a single type of object,
52 * or for objects that have very similar sizes.
53 *
54 * Allocation from and freeing to a HeapBuf instance is non-blocking and
55 * deterministic: a call to alloc or free will always take the same amount of
56 * time.
57 *
58 * Constraints:
59 * @p(blist) 60 * - Align parameter must be set to 0 for default, or be a power of 2 that is
61 * greater than or equal to the value returned by
62 * {@link xdc.runtime.Memory#getMaxDefaultTypeAlign}.
63 * - The buffer passed to dynamically create a HeapBuf must be aligned
64 * according to the alignment parameter, and must be large enough to account
65 * for the actual block size after it has been rounded up to a multiple of
66 * the alignment.
67 * @p 68 *
69 * @p(html) 70 * <h3> Calling Context </h3>
71 * <table border="1" cellpadding="3">
72 * <colgroup span="1"></colgroup> <colgroup span="5" align="center">
73 * </colgroup>
74 *
75 * <tr><th> Function </th><th> Hwi </th><th> Swi </th>
76 * <th> Task </th><th> Main </th><th> Startup </th></tr>
77 * <!-- -->
78 * <tr><td> Params_init </td><td> Y </td><td> Y </td>
79 * <td> Y </td><td> Y </td><td> Y </td></tr>
80 * <tr><td> alloc </td><td> Y </td><td> Y </td>
81 * <td> Y </td><td> Y </td><td> N </td></tr>
82 * <tr><td> construct </td><td> Y </td><td> Y </td>
83 * <td> Y </td><td> Y </td><td> N </td></tr>
84 * <tr><td> create </td><td> N* </td><td> N* </td>
85 * <td> Y </td><td> Y </td><td> N </td></tr>
86 * <tr><td> delete </td><td> N* </td><td> N* </td>
87 * <td> Y </td><td> Y </td><td> N </td></tr>
88 * <tr><td> destruct </td><td> Y </td><td> Y </td>
89 * <td> Y </td><td> Y </td><td> N </td></tr>
90 * <tr><td> free </td><td> Y </td><td> Y </td>
91 * <td> Y </td><td> Y </td><td> N </td></tr>
92 * <tr><td> getStats </td><td> Y </td><td> Y </td>
93 * <td> Y </td><td> Y </td><td> N </td></tr>
94 * <tr><td> getExtendedStats </td><td> Y </td><td> Y </td>
95 * <td> Y </td><td> Y </td><td> N </td></tr>
96 * <tr><td> isBlocking </td><td> Y </td><td> Y </td>
97 * <td> Y </td><td> Y </td><td> N </td></tr>
98 * <tr><td colspan="6"> Definitions: <br />
99 * <ul>
100 * <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
101 * <li> <b>Swi</b>: API is callable from a Swi thread. </li>
102 * <li> <b>Task</b>: API is callable from a Task thread. </li>
103 * <li> <b>Main</b>: API is callable during any of these phases: </li>
104 * <ul>
105 * <li> In your module startup after this module is started
106 * (e.g. HeapBuf_Module_startupDone() returns TRUE). </li>
107 * <li> During xdc.runtime.Startup.lastFxns. </li>
108 * <li> During main().</li>
109 * <li> During BIOS.startupFxns.</li>
110 * </ul>
111 * <li> <b>Startup</b>: API is callable during any of these phases:</li>
112 * <ul>
113 * <li> During xdc.runtime.Startup.firstFxns.</li>
114 * <li> In your module startup before this module is started
115 * (e.g. HeapBuf_Module_startupDone() returns FALSE).</li>
116 * </ul>
117 * </ul>
118 * <li> <b>*</b>: Assuming blocking Heap is used for creation. </li>
119 * </td></tr>
120 *
121 * </table>
122 * @p 123 */
124
125 @InstanceInitError /* Initialization may throw errors */
126 @ModuleStartup /* Instances require more initialization at startup */
127 @InstanceFinalize /* Destroys the freeList Q */
128
129 module HeapBuf inherits xdc.runtime.IHeap {
130
131 /*!
132 * ======== BasicView ========
133 * @_nodoc 134 */
135 metaonlystruct BasicView {
136 String label;
137 xdc.runtime.Memory.Size bufSize; /* Size of the entire buffer */
138 SizeT blockSize;
139 UInt numBlocks;
140 Int totalFreeSize;
141 UInt numberAllocatedBlocks;
142 UInt numFreeBlocks;
143 UInt maxAllocatedBlocks;
144 Ptr buf;
145
146 /* statStr contains "quick" info 4 HeapBuf that other mods will
147 * display. statStr won't be displayed by the HeapBuf ROV view itself.
148 */
149 String statStr;
150 }
151
152 /*!
153 * ======== DetailedView ========
154 * @_nodoc 155 */
156 metaonlystruct DetailedView {
157 String label;
158 xdc.runtime.Memory.Size bufSize; /* Size of the entire buffer */
159 SizeT blockSize;
160 UInt numBlocks;
161 Int totalFreeSize;
162 UInt numberAllocatedBlocks;
163 UInt numFreeBlocks;
164 UInt maxAllocatedBlocks;
165 Ptr buf;
166 Ptr freeList;
167
168 /* statStr contains "quick" info 4 HeapBuf that other mods will
169 * display. statStr won't be displayed by the HeapBuf ROV view itself.
170 */
171 String statStr;
172 }
173
174 /*! @_nodoc */
175 @Facet
176 metaonlyconfig ViewInfo.Instance rovViewInfo =
177 ViewInfo.create({
178 viewMap: [
179 ['Basic', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitInstance', structName: 'BasicView'}],
180 ['Detailed', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitDetailed', structName: 'DetailedView'}]
181 ]
182 });
183
184 /*!
185 * ======== ExtendedStats ========
186 * Stat structure for the HeapBuf_getExtendedStats function
187 *
188 * @field(maxAllocatedBlocks) The maximum number of blocks allocated from
189 * this heap at any single point in time, during
190 * the lifetime of this HeapBuf instance.
191 * The configuration parameter
192 * {@link #trackMaxAllocs} must be set to true
193 * for this field to have any meaning.
194 * Otherwise, this field will be set to '0'.
195 *
196 * @field(numAllocatedBlocks) The total number of blocks currently
197 * allocated in this HeapBuf instance.
198 */
199 struct ExtendedStats {
200 UInt maxAllocatedBlocks;
201 UInt numAllocatedBlocks;
202 }
203
204 /*!
205 * ======== A_nullBuf ========
206 * Null buf parameter
207 *
208 * This Assert is raised when the buf parameter has been omitted (null)
209 * for a dynamic create.
210 */
211 config xdc.runtime.Assert.Id A_nullBuf =
212 {msg: "buf parameter cannot be null"};
213
214 /*!
215 * ======== A_bufAlign ========
216 * Misalligned buffer
217 *
218 * This Assert is raised when the buf parameter has not been aligned
219 * on the requested alignment.
220 */
221 config xdc.runtime.Assert.Id A_bufAlign =
222 {msg: "buf not properly aligned"};
223
224 /*!
225 * ======== A_invalidAlign ========
226 * Invalid alignment
227 *
228 * This Assert is raised when the align parameter is not the default
229 * value of zero, or a power of 2 that is greater than or equal to
230 * the value defined by
231 * {@link xdc.runtime.Memory#getMaxDefaultTypeAlign}.
232 */
233 config xdc.runtime.Assert.Id A_invalidAlign =
234 {msg: "align parameter must be 0 or a power of 2 >= the value of Memory_getMaxDefaultTypeAlign()"};
235
236 /*!
237 * ======== A_invalidRequestedAlign ========
238 * Invalid alignment parameter in the alloc
239 *
240 * This Assert is raised when the align argument is not a power of 2 (or 0).
241 * It is also raised if the parameter is greater the alignment
242 * specified when creating the heap.
243 */
244 config xdc.runtime.Assert.Id A_invalidRequestedAlign =
245 {msg: "align parameter 1) must be 0 or a power of 2 and 2) not greater than the heaps alignment"};/*!
246 247 * ======== A_zeroBlockSize ========
248 * Assert raised when the blockSize parameter is 0
249 */
250 config xdc.runtime.Assert.Id A_zeroBlockSize =
251 {msg: "blockSize cannot be zero"};
252
253 /*!
254 * ======== A_zeroBlocks ========
255 * Assert raised when the numBlocks parameter is 0
256 */
257 config xdc.runtime.Assert.Id A_zeroBlocks =
258 {msg: "numBlocks cannot be zero"};
259
260 /*!
261 * ======== A_zeroBufSize ========
262 * Assert raised when the bufSize parameter is 0
263 */
264 config xdc.runtime.Assert.Id A_zeroBufSize =
265 {msg: "bufSize cannot be zero"};
266
267 /*!
268 * ======== A_invalidBufSize ========
269 * Invalid buffer size
270 *
271 * This Assert is raised when the bufSize parameter is too small
272 * to handle requested blocks.
273 */
274 config xdc.runtime.Assert.Id A_invalidBufSize =
275 {msg: "HeapBuf_create's bufSize parameter is invalid (too small)"};
276
277 /*!
278 * ======== A_noBlocksToFree ========
279 * No allocated blocks
280 *
281 * This Assert is raised when free is called and there are no blocks
282 * allocated.
283 */
284 config xdc.runtime.Assert.Id A_noBlocksToFree =
285 {msg: "Cannot call HeapBuf_free when no blocks have been allocated"};
286
287 /*!
288 * ======== A_invalidFree ========
289 * Assert raised when an invalid free occurs
290 *
291 * This assert can be caused for the following reasons
292 * @p(blist) 293 * - Passing a NULL pointer to the free.
294 * - The block is not within the heap's buffer range. This can occur if
295 * the block is freed to the wrong heap.
296 * - The block is not on the proper boundary. This can occur if the
297 * pointer returned from alloc is changed by the application and not set
298 * back to its original value when free is called.
299 * @p 300 */
301 config xdc.runtime.Assert.Id A_invalidFree =
302 {msg: "A_invalidFree: Invalid free"};
303
304 /*!
305 * ======== E_size ========
306 * Raised when requested size exceeds blockSize
307 */
308 config xdc.runtime.Error.Id E_size =
309 {msg: "requested size is too big: handle=0x%x, size=%u"};
310
311 /*!
312 * ======== trackMaxAllocs ========
313 * Track maximum number of allocations
314 *
315 * This will enable/disable the tracking of the maximum number of
316 * allocations for a HeapBuf instance. This maximum refers to the "all
317 * time" maximum number of allocations for the history of a HeapBuf
318 * instance, not the current number of allocations.
319 */
320 config Bool trackMaxAllocs = false;
321
322 instance:
323
324 /*!
325 * ======== align ========
326 * Alignment (in MAUs) of each block
327 *
328 * The alignment must be a power of 2 that is greater than or equal to
329 * the target dependent value defined by
330 * {@link xdc.runtime.Memory#getMaxDefaultTypeAlign}. If the default value
331 * of 0 is specified, this value will be changed to be the minimum
332 * structure alignment requirement, as defined by
333 * {@link xdc.runtime.Memory#getMaxDefaultTypeAlign}.
334 *
335 * For static creates, the HeapBuf module will allocate space for the
336 * buffer and will align it on this requested alignment.
337 *
338 * For dynamic creates, this parameter is used solely for error checking.
339 * The buffer provided to a dynamically created HeapBuf must be aligned
340 * manually, and an assert will be raised if the buffer is not properly
341 * aligned. For dynamic creates, HeapBuf will NOT adjust the buffer to
342 * satisfy the alignment.
343 *
344 */
345 config SizeT align = 0;
346
347 /*!
348 * ======== sectionName ========
349 * Section name for the buffer managed by the instance
350 *
351 * The buffer allocated for a statically created HeapBuf instance will be
352 * placed in this section.
353 *
354 * The default section is the 'dataSection' in the platform.
355 */
356 metaonlyconfig String sectionName = null;
357
358 /*!
359 * ======== numBlocks ========
360 * Number of fixed-size blocks
361 *
362 * Required parameter.
363 *
364 * The default number of blocks is 0.
365 */
366 config UInt numBlocks = 0;
367
368 /*!
369 * ======== blockSize ========
370 * Size (in MAUs) of each block
371 *
372 * HeapBuf will round the blockSize up to the nearest multiple of the
373 * alignment, so the actual blockSize may be larger. When creating a
374 * HeapBuf dynamically, this needs to be taken into account to determine
375 * the proper buffer size to pass in.
376 *
377 * Required parameter.
378 *
379 * The default size of the blocks is 0 MAUs.
380 */
381 config SizeT blockSize = 0;
382
383 /*!
384 * ======== bufSize ========
385 * Size (in MAUs) of the entire buffer; for dynamic creates only
386 *
387 * When dynamically creating a HeapBuf, this should be the actual size
388 * of the memory buffer provided for HeapBuf to manage.
389 *
390 * This parameter is used solely for error checking; an Error is raised
391 * if the bufSize is too small for the requested blockSize and numBlocks.
392 * Because of minimum alignment considerations, it's easy to provide too
393 * small of a buffer to manage, and difficult to detect if it happened.
394 *
395 * This parameter is required for dynamic creates and ignored for static
396 * creates.
397 *
398 * The default buffer size is 0 MAUs.
399 */
400 config xdc.runtime.Memory.Size bufSize = 0;
401
402 /*!
403 * ======== buf ========
404 * User supplied buffer; for dynamic creates only
405 *
406 * The caller must supply the memory buffer for a dynamically created
407 * HeapBuf to manage. The provided buffer must be aligned according to the
408 * HeapBuf's alignment parameter. i.e., if a buffer's alignment parameter
409 * is 128, then the buffer's start address must be a multiple of 128.
410 *
411 * For static creates, the buffer is allocated automatically based on the
412 * blockSize and numBlocks parameters.
413 *
414 * This parameter is required for dynamic creates and ignored for static
415 * creates.
416 *
417 */
418 config Ptr buf = 0;
419
420 /*!
421 * ======== alloc ========
422 * @HeapBuf All alignment is handled in the create, therefore the
423 * align argument in alloc is ignored.
424 *
425 * HeapBuf_alloc will only fail if there are no available blocks or if the
426 * requested block size is larger than the HeapBuf's blockSize. All other
427 * requests, regardless of size, will succeed.
428 */
429 override Ptr alloc(SizeT size, SizeT align, xdc.runtime.Error.Block *eb);
430
431 /*!
432 * ======== isBlocking ========
433 * @HeapBuf This function always returns FALSE since the alloc/free
434 * never block on a resource.
435 */
436 override Bool isBlocking();
437
438 /*!
439 * ======== getBlockSize ========
440 * @_nodoc 441 * Returns the HeapBuf's actual blockSize (adjusted for alignment)
442 *
443 * This getter is provided to allow other memory managers to build off
444 * of HeapBuf.
445 *
446 * The blockSize returned has been adjusted to match the alignment,
447 * so it may be larger than the user-specified blockSize.
448 */
449 SizeT getBlockSize();
450
451 /*!
452 * ======== getAlign ========
453 * @_nodoc 454 * Returns the HeapBuf's actual alignment (adjusted for minimum
455 * alignment requirements)
456 *
457 * This getter is provided to allow other memory managers to build off
458 * of HeapBuf.
459 */
460 SizeT getAlign();
461
462 /*!
463 * ======== getEndAddr ========
464 * @_nodoc 465 * Returns the last address in the buffer managed by the HeapBuf
466 *
467 * This getter is provided to allow other memory managers to build off
468 * of HeapBuf: Compare a block's address to the end address of the buffer
469 * to determine which buffer the block came from. The end address is the
470 * last address in the buffer, not the next address after the buffer.
471 *
472 * This will not return the correct value after addMemory has been called
473 * to add a noncontiguous buffer of memory to the HeapBuf.
474 *
475 */
476 Ptr getEndAddr();
477
478 /*! ======== getExtendedStats ========
479 * Retrieves the extended statistics for a HeapBuf instance.
480 *
481 * This function retrieves the extended statistics for a HeapBuf instance.
482 * It does not retrieve the standard xdc.runtime.Memory.Stats information.
483 *
484 * @param(stats) Location for the returned extended statistics.
485 */
486 Void getExtendedStats(ExtendedStats *stats);
487
488 /*!
489 * ======== mergeHeapBufs ========
490 * @_nodoc 491 */
492 Void mergeHeapBufs(HeapBuf.Handle heapBuf2);
493
494 internal: /* not for client use */
495
496 /*!
497 * ======== numConstructedHeaps ========
498 * @_nodoc 499 * Number of statically constructed Heap objects.
500 * Shouldn't be set directly by the user's
501 * config (it gets set by instance$static$init).
502 */
503 config UInt numConstructedHeaps = 0;
504
505 /*
506 * ======== postInit ========
507 * finish initializing static and dynamic HeapBufs
508 */
509 Void postInit(Object *heap);
510
511 /*
512 * ======== Instance_State ========
513 * Instance state
514 */
515 struct Instance_State {
516 SizeT blockSize; /* True size of each block */
517 SizeT align; /* Alignment of each block */
518 UInt numBlocks; /* Number of individual blocks. */
519 xdc.runtime.Memory.Size bufSize; /* Size of the entire buffer */
520 Char buf[]; /* Memory managed by instance */
521 ti.sysbios.knl.Queue.Object freeList; /* List of free buffers */
522 UInt numFreeBlocks;
523 UInt minFreeBlocks; /* used to compute max # allocs */
524 };
525
526 /*
527 * ======== Module_State ========
528 * Module state
529 */
530 struct Module_State {
531 Handle constructedHeaps[]; /* array of statically */
532 /* constructed Heaps */
533 };
534 }