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 38 39 40 41 42 43 44
45
46 package ti.sdo.ipc.heaps;
47
48 import ti.sdo.ipc.SharedRegion;
49 import ti.sdo.ipc.Ipc;
50 import ti.sdo.ipc.GateMP;
51 import ti.sdo.utils.NameServer;
52
53 import xdc.rov.ViewInfo;
54
55 import xdc.runtime.Error;
56 import xdc.runtime.Assert;
57 import xdc.runtime.Memory;
58 import xdc.runtime.Startup;
59
60 /*!
61 * ======== HeapMultiBufMP ========
62 * Multi-processor fixed-size buffer heap implementation
63 *
64 * @p(html)
65 * This module has a common header that can be found in the {@link ti.ipc}
66 * package. Application code should include the common header file (not the
67 * RTSC-generated one):
68 *
69 * <PRE>#include <ti/ipc/HeapMultiBufMP.h></PRE>
70 *
71 * The RTSC module must be used in the application's RTSC configuration file
72 * (.cfg) if runtime APIs will be used in the application:
73 *
74 * <PRE>HeapMultiBufMP = xdc.useModule('ti.sdo.ipc.heaps.HeapMultiBufMP');
75 * </PRE>
76 *
77 * Documentation for all runtime APIs, instance configuration parameters,
78 * error codes macros and type definitions available to the application
79 * integrator can be found in the
80 * <A HREF="../../../../../doxygen/html/files.html">Doxygen documenation</A>
81 * for the IPC product. However, the documentation presented on this page
82 * should be referred to for information specific to the RTSC module, such as
83 * module configuration, Errors, and Asserts.
84 * @p
85 *
86 * It is important to note that max allocation tracking is disabled by default
87 * in {@link #trackMaxAllocs}. Disabling allocation tracking improves alloc/
88 * free performance especially when cache calls are required in shared memory.
89 */
90 @InstanceInitError
91 @InstanceFinalize
92
93 module HeapMultiBufMP inherits xdc.runtime.IHeap
94 {
95 /*! @_nodoc */
96 metaonly struct BasicView {
97 String name;
98 Ptr buf;
99 Memory.Size totalSize;
100 String objType;
101 Ptr gate;
102 Bool exact;
103 }
104
105 /*! @_nodoc */
106 metaonly struct BucketsView {
107 Ptr baseAddr;
108 UInt blockSize;
109 UInt align;
110 UInt numBlocks;
111 UInt numFreeBlocks;
112 UInt minFreeBlocks;
113 }
114
115 /*! @_nodoc */
116 @Facet
117 metaonly config ViewInfo.Instance rovViewInfo =
118 ViewInfo.create({
119 viewMap: [
120 [
121 'Basic',
122 {
123 type: ViewInfo.INSTANCE,
124 viewInitFxn: 'viewInitBasic',
125 structName: 'BasicView'
126 }
127 ],
128 [
129 'Buffer Information',
130 {
131 type: ViewInfo.INSTANCE_DATA,
132 viewInitFxn: 'viewInitData',
133 structName: 'BucketsView'
134 }
135 ],
136 ]
137 });
138
139 /*!
140 * Structure for bucket configuration
141 *
142 * An array of buckets is a required parameter to create any
143 * HeapMultiBufMP instance. The fields of each bucket correspond
144 * to the attributes of each buffer in the HeapMultiBufMP. The actual
145 * block sizes and alignments may be adjusted per the process described
146 * at {@link #bucketEntries}.
147 *
148 * @field(blockSize) Size of each block (in MADUs)
149 * @field(numBlocks) Number of blocks
150 * @field(align) Alignment of each block (in MADUs)
151 */
152 struct Bucket {
153 SizeT blockSize;
154 UInt numBlocks;
155 SizeT align;
156 }
157
158 /*!
159 * ======== ExtendedStats ========
160 * Stats structure for the getExtendedStats API.
161 *
162 * @field(numBuckets) Number of buckets
163 * @field(numBlocks) Number of blocks in each buffer
164 * @field(blockSize) Block size of each buffer
165 * @field(align) Alignment of each buffer
166 * @field(maxAllocatedBlocks) The maximum number of blocks allocated from
167 * this heap at any single point in time during
168 * the lifetime of this HeapMultiBufMP instance
169 *
170 * @field(numAllocatedBlocks) The total number of blocks currently
171 * allocated in this HeapMultiBufMP instance
172 */
173 struct ExtendedStats {
174 UInt numBuckets;
175 UInt numBlocks [8];
176 UInt blockSize [8];
177 UInt align [8];
178 UInt maxAllocatedBlocks [8];
179 UInt numAllocatedBlocks [8];
180 }
181
182 /*!
183 * Assert raised when the align parameter is not a power of 2.
184 */
185 config Assert.Id A_invalidAlign =
186 {msg: "align parameter must be a power of 2"};
187
188 /*!
189 * Assert raised when an invalid buffer size was passed to free()
190 */
191 config Assert.Id A_sizeNotFound =
192 {msg: "an invalid buffer size was passed to free"};
193
194 /*!
195 * Assert raised when an invalid block address was passed to free()
196 */
197 config Assert.Id A_addrNotFound =
198 {msg: "an invalid buffer address was passed to free"};
199
200 /*!
201 * Error raised when exact matching failed
202 */
203 config Error.Id E_exactFail =
204 {msg: "E_exactFail: Exact allocation failed (requested size = %u and buffer size = %u)"};
205
206 /*!
207 * Error raised when requested size exceeds all blockSizes.
208 */
209 config Error.Id E_size =
210 {msg: "E_size: requested size/alignment is too big (requested size = %u and requested align = %u)"};
211
212 /*!
213 * Error raised when there are no blocks left in the buffer corresponding to the requested size/alignment
214 */
215 config Error.Id E_noBlocksLeft =
216 {msg: "E_noBlocksLeft: No more blocks left in buffer (buffer size = %u and buffer align = %u)"};
217
218 /*!
219 * Maximum runtime entries
220 *
221 * Maximum number of HeapMultiBufMP's that can be dynamically created and
222 * added to the NameServer.
223 *
224 * To minimize the amount of runtime allocation, this parameter allows
225 * the pre-allocation of memory for the HeapMultiBufMP's NameServer table.
226 * The default is to allow growth (i.e. memory allocation when
227 * creating a new instance).
228 */
229 metaonly config UInt maxRuntimeEntries = NameServer.ALLOWGROWTH;
230
231 /*!
232 * Maximum length for heap names
233 */
234 config UInt maxNameLen = 32;
235
236 /*!
237 * Section name is used to place the names table
238 *
239 * The default value of NULL implies that no explicit placement is
240 * performed.
241 */
242 metaonly config String tableSection = null;
243
244 /*!
245 * Track the maximum number of allocated blocks
246 *
247 * This will enable/disable the tracking of the maximum number of
248 * allocations for a HeapMultiBufMP instance. This maximum refers to the
249 * "all time" maximum number of allocations for the history of a
250 * HeapMultiBufMP instance, not the current number of allocations.
251 *
252 * Tracking the maximum might adversely affect performance when allocating
253 * and/or freeing. If this feature is not needed, setting this to false
254 * avoids the performance penalty.
255 */
256 config Bool trackMaxAllocs = false;
257
258 instance:
259
260 /*!
261 * GateMP used for critical region management of the shared memory
262 *
263 * Using the default value of NULL will result in use of the GateMP
264 * system gate for context protection.
265 */
266 config GateMP.Handle gate = null;
267
268 /*! @_nodoc
269 * by the open() call. No one else should touch this!
270 */
271 config Bool openFlag = false;
272
273 /*!
274 * Use exact matching
275 *
276 * Setting this flag will allow allocation only if the requested size
277 * is equal to (rather than less than or equal to) a buffer's block size.
278 */
279 config Bool exact = false;
280
281 /*!
282 * Name of this instance.
283 *
284 * The name (if not NULL) must be unique among all HeapMultiBufMP
285 * instances in the entire system. When creating a new
286 * heap, it is necessary to supply an instance name.
287 */
288 config String name = null;
289
290 /*!
291 * Number of buckets in {@link #bucketEntries}
292 *
293 * This parameter is required to create any instance.
294 */
295 config Int numBuckets = 0;
296
297 /*!
298 * Bucket Entries
299 *
300 * The bucket entries are an array of {@link #Bucket}s whose values
301 * correspond to the desired alignment, block size and length for each
302 * buffer. It is important to note that the alignments and sizes for each
303 * buffer may be adjusted due to cache and alignment related constraints.
304 * Buffer sizes are rounded up by their corresponding alignments. Buffer
305 * alignments themselves will assume the value of region cache alignment
306 * size when the cache size is greater than the requested buffer alignment.
307 *
308 * For example, specifying a bucket with {blockSize: 192, align: 256} will
309 * result in a buffer of blockSize = 256 and alignment = 256. If cache
310 * alignment is required, then a bucket of {blockSize: 96, align: 64} will
311 * result in a buffer of blockSize = 128 and alignment = 128 (assuming
312 * cacheSize = 128).
313 */
314 config Bucket bucketEntries[];
315
316 /*!
317 * Shared region ID
318 *
319 * The index corresponding to the shared region from which shared memory
320 * will be allocated.
321 */
322 config UInt16 regionId = 0;
323
324 /*! @_nodoc
325 * Physical address of the shared memory
326 *
327 * This value can be left as 'null' unless it is required to place the
328 * heap at a specific location in shared memory. If sharedAddr is null,
329 * then shared memory for a new instance will be allocated from the
330 * heap belonging to the region identified by {@link #regionId}.
331 */
332 config Ptr sharedAddr = null;
333
334 @DirectCall
335 override Ptr alloc(SizeT size, SizeT align, xdc.runtime.Error.Block *eb);
336
337 @DirectCall
338 override Void free(Ptr block, SizeT size);
339
340 internal:
341
342 /*! Used in the attrs->status field */
343 const UInt32 CREATED = 0x05101920;
344
345 /*!
346 * This Params object is used for temporary storage of the
347 * module wide parameters that are for setting the NameServer instance.
348 */
349 metaonly config NameServer.Params nameSrvPrms;
350
351 /*! slice and dice the buffer */
352 Void postInit(Object *obj, Error.Block *eb);
353
354 /*!
355 * Takes in modifiable array of bucket entries, performs an in-place sort
356 * of the bucket entries, combines the entries as necessary, and returns
357 * the new number of buckets in the combined entries
358 */
359 UInt processBuckets(Bucket *bucketEntries, Params *params,
360 UInt16 regionId);
361
362 /*!
363 * Add the block to the tail; index specifies the buffer number
364 *
365 * Precondition: inv obj->attrs->bucket[index]
366 * Postcondition: wb obj->attrs->bucket[index] and wb the block
367 */
368 Void putTail(Object *obj, Int index, Elem *block);
369
370 /*!
371 * Removes a block from the head and returns it; index specifies
372 * the buffer number. The block is invalidated before returned
373 *
374 * Precondition: inv obj->attrs->bucket[index]
375 * Postcondition: wb obj->attrs->bucket[index]
376 */
377 Elem *getHead(Object *obj, Int index);
378
379 /*! Needed for freelist */
380 @Opaque struct Elem {
381
382 volatile SharedRegion.SRPtr next;
383 };
384
385 /*! Shared memory state for a single buffer. */
386 struct BucketAttrs {
387 SharedRegion.SRPtr head;
388 SharedRegion.SRPtr tail;
389 SharedRegion.SRPtr baseAddr;
390 Bits32 numFreeBlocks;
391 Bits32 minFreeBlocks;
392 Bits32 blockSize;
393 Bits32 align;
394 Bits32 numBlocks;
395 }
396
397 /*! Shared memory state for a HeapMultiBufMP instance */
398 struct Attrs {
399 Bits32 status;
400 SharedRegion.SRPtr gateMPAddr;
401 Bits32 numBuckets;
402 BucketAttrs buckets[8];
403 Bits16 exact;
404 }
405
406 struct Instance_State {
407 Attrs *attrs;
408 GateMP.Handle gate;
409 Ipc.ObjType objType;
410 Ptr nsKey;
411 Bool cacheEnabled;
412 UInt16 regionId;
413 SizeT allocSize;
414 Char *buf;
415 Bucket bucketEntries[];
416
417 UInt numBuckets;
418 Bool exact;
419 };
420
421 struct Module_State {
422 NameServer.Handle nameServer;
423 };
424 }