1 /*
2 * Copyright (c) 2015, 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 /*!
248 * ======== A_invalidBlockSize ========
249 * Assert raised when the blockSize parameter is not large enough to
250 * hold two pointers.
251 */
252 config xdc.runtime.Assert.Id A_invalidBlockSize =
253 {msg: "blockSize must be large enough to hold atleast two pointers"};
254
255 /*!
256 * ======== A_zeroBlocks ========
257 * Assert raised when the numBlocks parameter is 0
258 */
259 config xdc.runtime.Assert.Id A_zeroBlocks =
260 {msg: "numBlocks cannot be zero"};
261
262 /*!
263 * ======== A_zeroBufSize ========
264 * Assert raised when the bufSize parameter is 0
265 */
266 config xdc.runtime.Assert.Id A_zeroBufSize =
267 {msg: "bufSize cannot be zero"};
268
269 /*!
270 * ======== A_invalidBufSize ========
271 * Invalid buffer size
272 *
273 * This Assert is raised when the bufSize parameter is too small
274 * to handle requested blocks.
275 */
276 config xdc.runtime.Assert.Id A_invalidBufSize =
277 {msg: "HeapBuf_create's bufSize parameter is invalid (too small)"};
278
279 /*!
280 * ======== A_noBlocksToFree ========
281 * No allocated blocks
282 *
283 * This Assert is raised when free is called and there are no blocks
284 * allocated.
285 */
286 config xdc.runtime.Assert.Id A_noBlocksToFree =
287 {msg: "Cannot call HeapBuf_free when no blocks have been allocated"};
288
289 /*!
290 * ======== A_invalidFree ========
291 * Assert raised when an invalid free occurs
292 *
293 * This assert can be caused for the following reasons
294 * @p(blist) 295 * - Passing a NULL pointer to the free.
296 * - The block is not within the heap's buffer range. This can occur if
297 * the block is freed to the wrong heap.
298 * - The block is not on the proper boundary. This can occur if the
299 * pointer returned from alloc is changed by the application and not set
300 * back to its original value when free is called.
301 * @p 302 */
303 config xdc.runtime.Assert.Id A_invalidFree =
304 {msg: "A_invalidFree: Invalid free"};
305
306 /*!
307 * ======== E_size ========
308 * Raised when requested size exceeds blockSize
309 */
310 config xdc.runtime.Error.Id E_size =
311 {msg: "requested size is too big: handle=0x%x, size=%u"};
312
313 /*!
314 * ======== trackMaxAllocs ========
315 * Track maximum number of allocations
316 *
317 * This will enable/disable the tracking of the maximum number of
318 * allocations for a HeapBuf instance. This maximum refers to the "all
319 * time" maximum number of allocations for the history of a HeapBuf
320 * instance, not the current number of allocations.
321 */
322 config Bool trackMaxAllocs = false;
323
324 instance:
325
326 /*!
327 * ======== align ========
328 * Alignment (in MAUs) of each block
329 *
330 * The alignment must be a power of 2 that is greater than or equal to
331 * the target dependent value defined by
332 * {@link xdc.runtime.Memory#getMaxDefaultTypeAlign}. If the default value
333 * of 0 is specified, this value will be changed to be the minimum
334 * structure alignment requirement, as defined by
335 * {@link xdc.runtime.Memory#getMaxDefaultTypeAlign}.
336 *
337 * For static creates, the HeapBuf module will allocate space for the
338 * buffer and will align it on this requested alignment.
339 *
340 * For dynamic creates, this parameter is used solely for error checking.
341 * The buffer provided to a dynamically created HeapBuf must be aligned
342 * manually, and an assert will be raised if the buffer is not properly
343 * aligned. For dynamic creates, HeapBuf will NOT adjust the buffer to
344 * satisfy the alignment.
345 *
346 */
347 config SizeT align = 0;
348
349 /*!
350 * ======== sectionName ========
351 * Section name for the buffer managed by the instance
352 *
353 * The buffer allocated for a statically created HeapBuf instance will be
354 * placed in this section.
355 *
356 * The default section is the 'dataSection' in the platform.
357 */
358 metaonlyconfig String sectionName = null;
359
360 /*!
361 * ======== numBlocks ========
362 * Number of fixed-size blocks
363 *
364 * Required parameter.
365 *
366 * The default number of blocks is 0.
367 */
368 config UInt numBlocks = 0;
369
370 /*!
371 * ======== blockSize ========
372 * Size (in MAUs) of each block
373 *
374 * HeapBuf will round the blockSize up to the nearest multiple of the
375 * alignment, so the actual blockSize may be larger. When creating a
376 * HeapBuf dynamically, this needs to be taken into account to determine
377 * the proper buffer size to pass in.
378 *
379 * Required parameter.
380 *
381 * The default size of the blocks is 0 MAUs.
382 */
383 config SizeT blockSize = 0;
384
385 /*!
386 * ======== bufSize ========
387 * Size (in MAUs) of the entire buffer; for dynamic creates only
388 *
389 * When dynamically creating a HeapBuf, this should be the actual size
390 * of the memory buffer provided for HeapBuf to manage.
391 *
392 * This parameter is used solely for error checking; an Error is raised
393 * if the bufSize is too small for the requested blockSize and numBlocks.
394 * Because of minimum alignment considerations, it's easy to provide too
395 * small of a buffer to manage, and difficult to detect if it happened.
396 *
397 * This parameter is required for dynamic creates and ignored for static
398 * creates.
399 *
400 * The default buffer size is 0 MAUs.
401 */
402 config xdc.runtime.Memory.Size bufSize = 0;
403
404 /*!
405 * ======== buf ========
406 * User supplied buffer; for dynamic creates only
407 *
408 * The caller must supply the memory buffer for a dynamically created
409 * HeapBuf to manage. The provided buffer must be aligned according to the
410 * HeapBuf's alignment parameter. i.e., if a buffer's alignment parameter
411 * is 128, then the buffer's start address must be a multiple of 128.
412 *
413 * For static creates, the buffer is allocated automatically based on the
414 * blockSize and numBlocks parameters.
415 *
416 * This parameter is required for dynamic creates and ignored for static
417 * creates.
418 *
419 */
420 config Ptr buf = 0;
421
422 /*!
423 * ======== alloc ========
424 * @HeapBuf All alignment is handled in the create, therefore the
425 * align argument in alloc is ignored.
426 *
427 * HeapBuf_alloc will only fail if there are no available blocks or if the
428 * requested block size is larger than the HeapBuf's blockSize. All other
429 * requests, regardless of size, will succeed.
430 */
431 override Ptr alloc(SizeT size, SizeT align, xdc.runtime.Error.Block *eb);
432
433 /*!
434 * ======== isBlocking ========
435 * @HeapBuf This function always returns FALSE since the alloc/free
436 * never block on a resource.
437 */
438 override Bool isBlocking();
439
440 /*!
441 * ======== getBlockSize ========
442 * @_nodoc 443 * Returns the HeapBuf's actual blockSize (adjusted for alignment)
444 *
445 * This getter is provided to allow other memory managers to build off
446 * of HeapBuf.
447 *
448 * The blockSize returned has been adjusted to match the alignment,
449 * so it may be larger than the user-specified blockSize.
450 */
451 SizeT getBlockSize();
452
453 /*!
454 * ======== getAlign ========
455 * @_nodoc 456 * Returns the HeapBuf's actual alignment (adjusted for minimum
457 * alignment requirements)
458 *
459 * This getter is provided to allow other memory managers to build off
460 * of HeapBuf.
461 */
462 SizeT getAlign();
463
464 /*!
465 * ======== getEndAddr ========
466 * @_nodoc 467 * Returns the last address in the buffer managed by the HeapBuf
468 *
469 * This getter is provided to allow other memory managers to build off
470 * of HeapBuf: Compare a block's address to the end address of the buffer
471 * to determine which buffer the block came from. The end address is the
472 * last address in the buffer, not the next address after the buffer.
473 *
474 * This will not return the correct value after addMemory has been called
475 * to add a noncontiguous buffer of memory to the HeapBuf.
476 *
477 */
478 Ptr getEndAddr();
479
480 /*! ======== getExtendedStats ========
481 * Retrieves the extended statistics for a HeapBuf instance.
482 *
483 * This function retrieves the extended statistics for a HeapBuf instance.
484 * It does not retrieve the standard xdc.runtime.Memory.Stats information.
485 *
486 * @param(stats) Location for the returned extended statistics.
487 */
488 Void getExtendedStats(ExtendedStats *stats);
489
490 /*!
491 * ======== mergeHeapBufs ========
492 * @_nodoc 493 */
494 Void mergeHeapBufs(HeapBuf.Handle heapBuf2);
495
496 internal: /* not for client use */
497
498 /*!
499 * ======== numConstructedHeaps ========
500 * @_nodoc 501 * Number of statically constructed Heap objects.
502 * Shouldn't be set directly by the user's
503 * config (it gets set by instance$static$init).
504 */
505 config UInt numConstructedHeaps = 0;
506
507 /*
508 * ======== postInit ========
509 * finish initializing static and dynamic HeapBufs
510 */
511 Void postInit(Object *heap);
512
513 /*
514 * ======== Instance_State ========
515 * Instance state
516 */
517 struct Instance_State {
518 SizeT blockSize; /* True size of each block */
519 SizeT align; /* Alignment of each block */
520 UInt numBlocks; /* Number of individual blocks. */
521 xdc.runtime.Memory.Size bufSize; /* Size of the entire buffer */
522 Char buf[]; /* Memory managed by instance */
523 ti.sysbios.knl.Queue.Object freeList; /* List of free buffers */
524 UInt numFreeBlocks;
525 UInt minFreeBlocks; /* used to compute max # allocs */
526 };
527
528 /*
529 * ======== Module_State ========
530 * Module state
531 */
532 struct Module_State {
533 Handle constructedHeaps[]; /* array of statically */
534 /* constructed Heaps */
535 };
536 }