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