1 2 3 4 5 6 7 8 9
10 11 12 13
14
15 package ti.sysbios.heaps;
16
17 import xdc.rov.ViewInfo;
18
19 /*!
20 * ======== HeapBuf ========
21 * Fixed size buffer heap implementation.
22 *
23 * The HeapBuf manager provides functions to allocate and free storage from a
24 * heap of type HeapBuf which inherits from IHeap. HeapBuf manages a single
25 * fixed-size buffer, split into equally sized allocable blocks.
26 *
27 * The HeapBuf manager is intended as a very fast and deterministic memory
28 * manager which can only allocate blocks of a single size. It is ideal for
29 * managing a heap that is only used for allocating a single type of object,
30 * or for objects that have very similar sizes.
31 *
32 * Allocation from and freeing to a HeapBuf instance is non-blocking and
33 * deterministic: a call to alloc or free will always take the same amount of
34 * time.
35 *
36 * Constraints:
37 * @p(blist)
38 * - Align parameter must be set to 0 for default, or be a power of 2 that is
39 * greater than or equal to the value returned by
40 * {@link xdc.runtime.Memory#getMaxDefaultTypeAlign}.
41 * - The buffer passed to dynamically create a HeapBuf must be aligned
42 * according to the alignment parameter, and must be large enough to account
43 * for the actual block size after it has been rounded up to a multiple of
44 * the alignment.
45 * @p
46 *
47 * @p(html)
48 * <h3> Calling Context </h3>
49 * <table border="1" cellpadding="3">
50 * <colgroup span="1"></colgroup> <colgroup span="5" align="center"></colgroup>
51 *
52 * <tr><th> Function </th><th> Hwi </th><th> Swi </th><th> Task </th><th> Main </th><th> Startup </th></tr>
53 * <!-- -->
54 * <tr><td> Params_init </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td></tr>
55 * <tr><td> alloc </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
56 * <tr><td> construct </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
57 * <tr><td> create </td><td> N* </td><td> N* </td><td> Y </td><td> Y </td><td> N </td></tr>
58 * <tr><td> delete </td><td> N* </td><td> N* </td><td> Y </td><td> Y </td><td> N </td></tr>
59 * <tr><td> destruct </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
60 * <tr><td> free </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
61 * <tr><td> getStats </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
62 * <tr><td> getExtendedStats </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
63 * <tr><td> isBlocking </td><td> Y </td><td> Y </td><td> Y </td><td> Y </td><td> N </td></tr>
64 * <tr><td colspan="6"> Definitions: <br />
65 * <ul>
66 * <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
67 * <li> <b>Swi</b>: API is callable from a Swi thread. </li>
68 * <li> <b>Task</b>: API is callable from a Task thread. </li>
69 * <li> <b>Main</b>: API is callable during any of these phases: </li>
70 * <ul>
71 * <li> In your module startup after this module is started (e.g. HeapBuf_Module_startupDone() returns TRUE). </li>
72 * <li> During xdc.runtime.Startup.lastFxns. </li>
73 * <li> During main().</li>
74 * <li> During BIOS.startupFxns.</li>
75 * </ul>
76 * <li> <b>Startup</b>: API is callable during any of these phases:</li>
77 * <ul>
78 * <li> During xdc.runtime.Startup.firstFxns.</li>
79 * <li> In your module startup before this module is started (e.g. HeapBuf_Module_startupDone() returns FALSE).</li>
80 * </ul>
81 * </ul>
82 * <li> <b>*</b>: Assuming blocking Heap is used for creation. </li>
83 * <li> <b>**</b>: Assuming GateMutex is used as HeapMem's Gate. </li>
84 * <li> <b>+</b> : Cannot use HeapMem object while it is being restored. </li>
85 * </td></tr>
86 *
87 * </table>
88 * @p
89 */
90
91 @InstanceInitError
92 @ModuleStartup
93 @InstanceFinalize
94
95 module HeapBuf inherits xdc.runtime.IHeap {
96
97 metaonly struct BasicView {
98 String label;
99 xdc.runtime.Memory.Size bufSize;
100 SizeT align;
101 SizeT blockSize;
102 UInt numBlocks;
103 Int totalFreeSize;
104 UInt numberAllocatedBlocks;
105 UInt numFreeBlocks;
106 UInt maxAllocatedBlocks;
107 Ptr buf;
108
109
110
111 String statStr;
112 }
113
114 metaonly struct DetailedView {
115 String label;
116 xdc.runtime.Memory.Size bufSize;
117 SizeT align;
118 SizeT blockSize;
119 UInt numBlocks;
120 Int totalFreeSize;
121 UInt numberAllocatedBlocks;
122 UInt numFreeBlocks;
123 UInt maxAllocatedBlocks;
124 Ptr buf;
125 Ptr freeList;
126
127
128
129 String statStr;
130 }
131
132 /*! @_nodoc */
133 @Facet
134 metaonly config ViewInfo.Instance rovViewInfo =
135 ViewInfo.create({
136 viewMap: [
137 ['Basic', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitInstance', structName: 'BasicView'}],
138 ['Detailed', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitDetailed', structName: 'DetailedView'}]
139 ]
140 });
141
142 /*!
143 * ======== ExtendedStats ========
144 * Stats structure for the getExtendedStats API.
145 *
146 * @field(maxAllocatedBlocks) The maximum number of blocks allocated from
147 * this heap at any single point in time, during
148 * the lifetime of this HeapBuf instance.
149 *
150 * @field(numAllocatedBlocks) The total number of blocks currently
151 * allocated in this HeapBuf instance.
152 */
153 struct ExtendedStats {
154 UInt maxAllocatedBlocks;
155 UInt numAllocatedBlocks;
156 }
157
158 /*!
159 * Assert raised when the buf parameter has been omitted (null) for a
160 * dynamic create.
161 */
162 config xdc.runtime.Assert.Id A_nullBuf =
163 {msg: "buf parameter cannot be null"};
164
165 /*!
166 * Assert raised when the buf parameter has not been aligned on the
167 * requested alignment.
168 */
169 config xdc.runtime.Assert.Id A_bufAlign =
170 {msg: "buf not properly aligned"};
171
172 /*!
173 * Assert raised when the align parameter is not the default value of zero,
174 * or a power of 2 that is greater than or equal to the value defined by
175 * {@link xdc.runtime.Memory#getMaxDefaultTypeAlign}.
176 */
177 config xdc.runtime.Assert.Id A_invalidAlign =
178 {msg: "align parameter must be 0 or a power of 2 >= the value of Memory_getMaxDefaultTypeAlign()"};
179
180 /*!
181 * Assert raised when the blockSize parameter is 0.
182 */
183 config xdc.runtime.Assert.Id A_zeroBlockSize =
184 {msg: "blockSize cannot be zero"};
185
186 /*!
187 * Assert raised when the numBlocks parameter is 0.
188 */
189 config xdc.runtime.Assert.Id A_zeroBlocks =
190 {msg: "numBlocks cannot be zero"};
191
192 /*!
193 * Assert raised when the bufSize parameter is 0.
194 */
195 config xdc.runtime.Assert.Id A_zeroBufSize =
196 {msg: "bufSize cannot be zero"};
197
198 /*!
199 * Assert raised when the bufSize parameter is too small
200 * to handle requested blocks.
201 */
202 config xdc.runtime.Assert.Id A_invalidBufSize =
203 {msg: "HeapBuf_create's bufSize parameter is invalid (too small)"};
204
205 /*!
206 * Assert raised when free is called and there are no blocks allocated.
207 */
208 config xdc.runtime.Assert.Id A_noBlocksToFree =
209 {msg: "Cannot call HeapBuf_free when no blocks have been allocated"};
210
211 /*!
212 * This will enable/disable the tracking of the maximum number of
213 * allocations for a HeapBuf instance. This maximum refers to the "all
214 * time" maximum number of allocations for the history of a HeapBuf
215 * instance, not the current number of allocations.
216 */
217 config Bool trackMaxAllocs = false;
218
219 instance:
220
221 /*!
222 * Alignment (in MAUs) of each block.
223 *
224 * The alignment must be a power of 2 that is greater than or equal to
225 * the target dependent value defined by
226 * {@link xdc.runtime.Memory#getMaxDefaultTypeAlign}. If the default value
227 * of 0 is specified, this value will be changed to be the minimum
228 * structure alignment requirement, as defined by
229 * {@link xdc.runtime.Memory#getMaxDefaultTypeAlign}.
230 *
231 * For static creates, the HeapBuf module will allocate space for the
232 * buffer and will align it on this requested alignment.
233 *
234 * For dynamic creates, this parameter is used solely for error checking.
235 * The buffer provided to a dynamically created HeapBuf must be aligned
236 * manually, and an assert will be raised if the buffer is not properly
237 * aligned. For dynamic creates, HeapBuf will NOT adjust the buffer to
238 * satisfy the alignment.
239 *
240 */
241 config SizeT align = 0;
242
243 /*!
244 * ======== sectionName ========
245 * Section name for the buffer managed by the instance.
246 *
247 * The buffer allocated for a statically created HeapBuf instance will be
248 * placed in this section.
249 *
250 * The default section is the 'dataSection' in the platform.
251 */
252 metaonly config String sectionName = null;
253
254 /*!
255 * Number of fixed-size blocks.
256 *
257 * Required parameter.
258 *
259 * The default number of blocks is 0.
260 */
261 config UInt numBlocks = 0;
262
263 /*!
264 * Size (in MAUs) of each block.
265 *
266 * HeapBuf will round the blockSize up to the nearest multiple of the
267 * alignment, so the actual blockSize may be larger. When creating a
268 * HeapBuf dynamically, this needs to be taken into account to determine
269 * the proper buffer size to pass in.
270 *
271 * Required parameter.
272 *
273 * The default size of the blocks is 0 MAUs.
274 */
275 config SizeT blockSize = 0;
276
277 /*!
278 * Size (in MAUs) of the entire buffer; for dynamic creates only.
279 *
280 * When dynamically creating a HeapBuf, this should be the actual size
281 * of the memory buffer provided for HeapBuf to manage.
282 *
283 * This parameter is used soley for error checking; an Error is raised
284 * if the bufSize is too small for the requested blockSize and numBlocks.
285 * Because of minimum alignment considerations, it's easy to provide too
286 * small of a buffer to manage, and difficult to detect if it happened.
287 *
288 * This parameter is required for dynamic creates and ignored for static
289 * creates.
290 *
291 * The default buffer size is 0 MAUs.
292 */
293 config xdc.runtime.Memory.Size bufSize = 0;
294
295 /*!
296 * User supplied buffer; for dynamic creates only.
297 *
298 * The caller must supply the memory buffer for a dynamically created
299 * HeapBuf to manage. The provided buffer must be aligned according to the
300 * HeapBuf's alignment parameter. i.e., if a buffer's alignment parameter
301 * is 128, then the buffer's start address must be a multiple of 128.
302 *
303 * For static creates, the buffer is allocated automatically based on the
304 * blockSize and numBlocks parameters.
305 *
306 * This parameter is required for dynamic creates and ignored for static
307 * creates.
308 *
309 */
310 config Ptr buf = 0;
311
312 /*!
313 * @HeapBuf All alignment is handled in the create, therefore the
314 * align argument in alloc is ignored.
315 *
316 * HeapBuf_alloc will only fail if there are no available blocks or if the
317 * requested block size is larger than the HeapBuf's blockSize. All other
318 * requests, regardless of size, will succeed.
319 */
320 override Ptr alloc(SizeT size, SizeT align, xdc.runtime.Error.Block *eb);
321
322 /*!
323 * @HeapBuf This function always returns FALSE since the alloc/free
324 * never block on a resource.
325 */
326 override Bool isBlocking();
327
328 /*!
329 * ======== getBlockSize ========
330 * @_nodoc
331 * Returns the HeapBuf's actual blockSize (adjusted for alignment).
332 *
333 * This getter is provided to allow other memory managers to build off
334 * of HeapBuf.
335 *
336 * The blockSize returned has been adjusted to match the alignment,
337 * so it may be larger than the user-specified blockSize.
338 */
339 SizeT getBlockSize();
340
341 /*!
342 * ======== getAlign ========
343 * @_nodoc
344 * Returns the HeapBuf's actual alignment (adjusted for minimum
345 * alignment requirements).
346 *
347 * This getter is provided to allow other memory managers to build off
348 * of HeapBuf.
349 */
350 SizeT getAlign();
351
352 /*!
353 * ======== getEndAddr ========
354 * @_nodoc
355 * Returns the last address in the buffer managed by the HeapBuf.
356 *
357 * This getter is provided to allow other memory managers to build off
358 * of HeapBuf: Compare a block's address to the end address of the buffer
359 * to determine which buffer the block came from. The end address is the
360 * last address in the buffer, not the next address after the buffer.
361 *
362 * This will not return the correct value after addMemory has been called
363 * to add a noncontiguous buffer of memory to the HeapBuf.
364 *
365 */
366 Ptr getEndAddr();
367
368 /*! ======== getExtendedStats ========
369 * @a(HeapBuf)
370 * Retrieves the extended statistics for a HeapBuf instance.
371 *
372 * This function retrieves the extended statistics for a HeapBuf instance.
373 * It does not retrieve the standard xdc.runtime.Memory.Stats information.
374 *
375 * @param(stats) Location for the returned extended statistics.
376 */
377 Void getExtendedStats(ExtendedStats *stats);
378
379 /*!
380 * ======== mergeHeapBufs ========
381 * @_nodoc
382 */
383 Void mergeHeapBufs(HeapBuf.Handle heapBuf2);
384
385 internal:
386 /*!
387 * @_nodoc
388 * Number of statically constructed Heap objects.
389 * Shouldn't be set directly by the user's
390 * config (it gets set by instance$static$init).
391 */
392 config UInt numConstructedHeaps = 0;
393
394
395
396
397 struct Instance_State {
398 SizeT blockSize;
399 SizeT align;
400 UInt numBlocks;
401 xdc.runtime.Memory.Size bufSize;
402 Char buf[];
403 ti.sysbios.misc.Queue.Object freeList;
404 UInt numFreeBlocks;
405 UInt minFreeBlocks;
406 };
407
408 struct Module_State {
409 Handle constructedHeaps[];
410
411 };
412 }
413 414 415
416