Realtime
compliant Dynamic Memory Management
In many realtime embedded systems, you do not want to use dynamic
memory management via the standard C library functions malloc() and
free(). Moreover, in certain secure environments you are not allowed to
use those functions. The main reason for not using heap functions is
fragmentation: after allocating and freeing chunks of memory, the heap
gets cluttered with areas which are in use, and areas which are free
and it becomes more and more difficult to find a suitable area for some
object or structure which must be allocated at runtime.
Instead of using the heap, the OO RTX offers static pools for various purposes:
- a static pool for events. The size of this pool can be specified
in your Rhapsody model via a property and its usage can be monitored
via a high water mark.
- a static pool for timeouts. Each tm() you are specifying in your
Rhapsody model results in a timeout structure which is kept in a static
pool. Thesize of this pool can be specified via a property and its usage can be monitored via a high water mark.
- three static buffer pools; one for small-, for medium- and large
chunks. The number of elements in each pool as well as the size of a
small, medium and large block can be configured via properties. The
usage of the pools can be monitored via high water marks.
If you want to prevent the use of these pools, you should override the property CG::Event::BaseNumberOfInstances so it has no value.
In the profile which comes with your product, we have provided a stereotype called StaticComponent,
which sets certain properties in Rhapsody to use the dynamic memory
functions of the OO RTX which work on the three buffer pools. Next to
that, any call to malloc() and free() is mapped onto the appropiate
equivalent via macros which are included in the generated sources and
OO RTX.
When allocating a chunk, the function which operates on the buffer
pools tries to allocate the chunk in the pool which matches the size
needed; thsi way we try to prevent fragmentation.
Events
The pool for the events is actually a pool for pointers to events: the
size of an event will vary depending if you are using arguments in
events. So the pointer array is allocated staticly. The events itself
are allocated in the buffer pools: depending on any object you allocate
dynamically you might want to finetune the size of the elements in the
small buffer to the size of your largest event.
Timeouts
The timeouts are stored in their static pool. Because the size of a
timeout structure is always the same, the pool itself holds the
timeouts. A timeout is actually translated into an event: the timeout
structure itself remains in the timeout pool, but its address is
inserted in the event (pointer) pool.
Objects
You may use singletons in your Rhapsody model or use the three static
pools (small, medium and large buffers) for allocation of your objects. It is also possible to use a
mixture of static and dynamic memory: you can disable the
constant NO_MALLOC
which prevents the memory management of the OO RTX of calling malloc()
when a static buffer pool is exhausted. If you inspect the memory map
file created by the linker (verify the settings in your IDE to create
one), you can calculate the size of your objects - provided you
start with static allocated objects
- and see if you can finetune the dimensions of your three static
buffer pools. You can use the high water marks to verify how much these
are used at runtime.
Mapping malloc() and free()
If you have defined NO_MALLOC (e.g. by selecting the
StaticComponent stereotype), malloc() and free() will be mapped to
RiCAllocator_getMemory() and RiCAllocator_returnMemory(). This means
also if you use malloc() and free() in your Rhapsody user code, these
will be mapped to the static pools. You should check you mapfile in
your project to be sure, malloc and free are not used anymore.
Please note: Mapping of realloc is currently not supported, because the
stdlib.h function just needs pointer and new size as arguments, but
RiCAllocator_reallocMemory expects three arguments: the pointer,
current size and new size. Also calloc is not being mapped.
If you want to work with NO_MALLOC defined but need to deactivate the
mapping of malloc() and free(), make sure to define the macro WST_DO_NOT_MAP_MALLOC.
Copyright (c) Willert
Software Tools GmbH. All rights reserved.