Notes
…
This module encapsulates an allocator that supports dynamic memory management.
- standard library contains similar functions, but not in a freestanding runtime environment.
- dynamic memory management
- reference counting
- allocate, release, retain
- actual implementation in a submodule, that must be chosen via configuration
- allocator functions can be called from both task and interrupt context.
-
consequently, the allocator does not track, which block is allocated to which task. the application must take care thereof, in order to avoid memory leaks.
-
the allocator is a dynamic memory management option, that both the kernel and the application can. However, neither is committed to using the allocator.
- wiki: “provide ways to dynamically allocate portions of memory to programs at their request, and free it for reuse when no longer needed”
…
Include
stdbool.h |
stddef.h |
Configuration
AO_ALLOC
#define AO_ALLOC (2)
Selects the allocator implementation. The following options are available.
ao_alloc_0 |
Stub |
ao_alloc_1 |
Linear-time allocator based on pools of fixed-size memory blocks |
ao_alloc_2 |
Constant-time allocator based on the two-level segregated fit algorithm |
AO_ACQUIRED
AO_RELEASED
AO_RETAINED
#define AO_ACQUIRED (false)
#define AO_RELEASED (false)
#define AO_RETAINED (false)
Defines whether to notify the application of each to ao_acquire()
, ao_release()
, or ao_retain()
, respectively, which can aid in debugging an application or tracing and optimizing the memory usage of the allocator.
Types
ao_acquired_t
ao_released_t
ao_retained_t
typedef struct ao_acquired_t ao_acquired_t;
typedef struct ao_released_t ao_released_t;
typedef struct ao_retained_t ao_retained_t;
Represents information in the context of a call to ao_acquire()
, ao_release()
, or ao_retain()
, respectively.
Structs
ao_acquired_t
struct ao_acquired_t
{
void * ptr;
bool result;
size_t size_body;
size_t size_body_requested;
size_t size_head;
};
ptr |
The pointer returned by the function. |
result |
Indicates whether the operation has succeeded (true ) or failed (false ). |
size_body |
The actual size of the body of the memory block. |
size_body_requested |
The requested size of the body of the memory block, that is, the parameter value that the function was called with. |
size_head |
The size of the head of the memory block. |
ao_released_t
struct ao_released_t
{
void * ptr;
size_t ref;
bool result;
size_t size_body;
size_t size_head;
};
ptr |
The pointer to the memory block, that is, the parameter value that the function was called with. |
ref |
The current reference count of the memory block. If the operation has succeeded, then the value 0 indicates, that the memory block has just been deallocated. |
result |
Indicates whether the operation has succeeded (true ) or failed (false ). |
size_body |
The size of the body of the memory block. |
size_head |
The size of the head of the memory block. |
ao_retained_t
struct ao_retained_t
{
void * ptr;
size_t ref;
bool result;
size_t size_body;
size_t size_head;
};
ptr |
The pointer to the memory block, that is, the parameter value that the function was called with. |
ref |
The current reference count of the memory block. If the operation has succeeded, then this value should be greater than 1. |
result |
Indicates whether the operation has succeeded (true ) or failed (false ). |
size_body |
The size of the body of the memory block. |
size_head |
The size of the head of the memory block. |
Functions
ao_acquire
void * ao_acquire(size_t size);
Allocates a memory block of the specified size.
If the operation succeeds, then the function returns a pointer to the beginning of the allocated memory block. Thereby, that pointer is suitably aligned for any object type with fundamental alignment. But, the content of the memory block is not initialized, remaining with indeterminate values.
Additionally, the reference count of the memory block is initialized with 1. Therefore, the calling thread of execution takes ownership of the memory block.
If the operation fails, then the function returns NULL
. This is either because the specified size is 0 or the allocator cannot find a memory block large enough.
ao_acquired
void ao_acquired(ao_acquired_t const * a);
Notifies the application of a call to ao_acquire()
.
ao_delete
#define ao_delete(ptr) \
( \
ao_release(ptr) \
)
Deallocates a memory block.
ao_new
#define ao_new(type) \
( \
(type *) \
ao_acquire \
( \
sizeof(type) \
) \
)
Allocates a memory block large enough for the specified type.
ao_release
bool ao_release(void * ptr);
Reliquinshes ownership of a memory block, which decrements its reference count. If the reference count reaches zero, then this function additionally deallocates the memory block, making it available for further allocations.
The behavior of this function is undefined, if the memory block has been deallocated previously. Therefore, ownership of a memory block should be relinquished only, if it has been taken previously by the same thread of execution by calling ao_acquire()
or ao_retain()
, respectively.
The return value indicates whether the operation has succeeded or failed. The latter happens, if the specified pointer is NULL
. Nevertheless, the functions’ behavior is well-defined in this case, that is, it simply does nothing but return.
ao_released
void ao_released(ao_released_t const * r);
Notifies the application of a call to ao_release()
.
ao_retain
bool ao_retain(void * ptr);
Increments the reference count of a memory block, which means, that the calling thread of execution (once again) takes ownership thereof.
The return value indicates whether the operation has succeeded or failed. The latter happens, if the specified pointer is NULL
. Nevertheless, the functions’ behavior is well-defined in this case, that is, it simply does nothing but return.
ao_retained
void ao_retained(ao_retained_t const * r);
Notifies the application of a call to ao_retain()
.