Multiple fixed size buffer heap manager.
The HeapMultiBuf manager provides functions to allocate and free storage from a heap of type HeapMultiBuf which inherits from IHeap. HeapMultiBuf manages multiple fixed-size memory buffers. Each buffer contains a fixed number of allocable memory 'blocks' of the same size. Simply put, a HeapMultiBuf instance manages a collection of HeapBuf instances. HeapMultiBuf is intended as a fast and deterministic memory manager which can service requests for blocks of arbitrary size.
An example HeapMultiBuf instance might have sixteen 32-byte blocks in one buffer, and four 128-byte blocks in another buffer. A request for memory will be serviced by the smallest possible block, so a request for 100 bytes would receive a 128-byte block in our example.
Allocating from HeapMultiBuf will try to return a block from the first buffer which has:
- A block size that is >= to the requested size
AND
- An alignment that is >= to the requested alignment
If the first matching buffer is empty, HeapMultiBuf will only continue searching for a block if 'block borrowing' is enabled (see Block Borrowing).
HeapMultiBuf and HeapBuf
The HeapMultiBuf module is built on top of the HeapBuf module. Each buffer
in a HeapMultiBuf is in fact managed by a HeapBuf instance. Configuration
of a HeapMultiBuf is done by providing an array of configured HeapBuf
parameter structures. Refer to the HeapBuf documentation for information on
the buffer parameters. All of the documentation and parameters for HeapBuf
apply equally to HeapMultiBuf.
Another consequence of this is that configuration checking is left to the
HeapBuf module. If a buffer in a HeapMultiBuf has been incorrectly
configured (with blockSize = 0, for example), HeapBuf, not HeapMultiBuf,
will raise an Assert.
Since HeapMultiBuf is built on HeapBuf, it simply performs the logic to
determine which HeapBuf to allocate a block from or which HeapBuf to free
a block to.
Configuration Example
The following configuration code creates a HeapMultiBuf instance which manages 3 pools of 10 blocks each, with block sizes of 64, 128 and 256.
var HeapMultiBuf = xdc.useModule('ti.sysbios.heaps.HeapMultiBuf');
var HeapBuf = xdc.useModule('ti.sysbios.heaps.HeapBuf');
var hmbParams = new HeapMultiBuf.Params();
hmbParams.numBufs = 3;
hmbParams.bufParams.$add(new HeapBuf.Params());
hmbParams.bufParams[0].blockSize = 64;
hmbParams.bufParams[0].numBlocks = 10;
hmbParams.bufParams.$add(new HeapBuf.Params());
hmbParams.bufParams[1].blockSize = 128;
hmbParams.bufParams[1].numBlocks = 10;
hmbParams.bufParams.$add(new HeapBuf.Params());
hmbParams.bufParams[2].blockSize = 256;
hmbParams.bufParams[2].numBlocks = 10;
Program.global.multiBufHeap = HeapMultiBuf.create(hmbParams);
Block Borrowing
HeapMultiBuf can support "block borrowing". With this feature turned on,
if a request is made for a 32-byte block and none are available,
HeapMultiBuf will continue looking for an available block in other buffers.
When a borrowed block is freed, it will be returned back to its original
buffer. Enabling Block Borrowing changes the determinism of alloc, since it
may have to check any number of buffers to find an available block.
Block borrowing may also occur, even if it is disabled, if a block of a
particular size is requested with an alignment that is greater than the
configured alignment for that block size. For example, a HeapMultiBuf is
configured with a buffer of 32-byte blocks with an alignment of 8, and
a buffer of 64-byte blocks with an alignment of 16. If a request is made
for a 32-byte block with an alignment of 16, it will be serviced by the
buffer of 64-byte blocks.
Static vs. Dynamic Creation
As with HeapBuf, a statically created HeapMultiBuf instance will ignore the
bufSize and buf parameters. Dynamic creates require all of the parameters.
It should be noted that static creates are ideal if code space is a
concern; dynamically creating a HeapMultiBuf requires a relatively large
amount of initialization code to be pulled in to the executable.
Block Sizes and Alignment
- A buffer with a requested alignment of 0 will receive the target- specific minimum alignment. - The actual block sizes will be a multiple of the alignment. For example, if a buffer is configured to have 56-byte blocks with an alignment of 32, HeapMultiBuf will actually create 64-byte blocks. When providing the buffer for a dynamic create, make sure it is large enough to take this into account. - Multiple buffers with the same block size ARE allowed. This may occur, for example, if sizeof is used to specify the block sizes. - If any buffers have both the same block size and alignment, they will be merged. If this is a problem, consider managing these buffers directly with HeapBuf objects.
Real-Time Concerns
Allocation from and freeing to a HeapMultiBuf instance is non-blocking.
HeapMultiBuf is deterministic:
- A call to alloc will always take the same amount of time for a given block size (with block borrowing disabled). - The worst case call to free is constant and proportional to the number of buffers managed.
Restrictions
- Align parameters must be a power of 2. - The buffers passed to dynamically create a HeapMultiBuf must be aligned according to the alignment parameter, and must be large enough to account for the actual block size after it has been rounded up to a multiple of the alignment. - Buffers must be provided to dynamically create a HeapMultiBuf, and cannot be provided to statically create a HeapMultiBuf.
Unconstrained Functions
All functions
Calling Context
Function | Hwi | Swi | Task
| Main | Startup |
Params_init | Y | Y |
Y | Y | Y |
alloc
| Y | Y | Y | Y
| N |
construct | N*
| N* | Y | Y | N
|
create | N* | N* |
Y | Y | N |
delete
| N* | N* | Y | Y
| N |
destruct | N*
| N* | Y | Y | N
|
free | Y | Y |
Y | Y | N |
getStats
| Y | Y | Y | Y
| N |
isBlocking | Y
| Y | Y | Y | N
|
Definitions: - Hwi: API
is callable from a Hwi thread.
- Swi: API is callable from a
Swi thread.
- Task: API is callable from a Task thread.
- Main: API is callable during any of these phases:
-
In your module startup after this module is started (e.g.
HeapMultiBuf_Module_startupDone() returns true).
- During
xdc.runtime.Startup.lastFxns.
- During main().
- During
BIOS.startupFxns.
- Startup: API is callable during any
of these phases:
- During xdc.runtime.Startup.firstFxns.
- In your module startup before this module is started (e.g.
HeapMultiBuf_Module_startupDone() returns false).
- *:
Assuming blocking Heap is used for creation.
- **: Assuming
GateMutex is used as HeapMem's Gate.
- + : Cannot use HeapMem
object while it is being restored.
|