zephyr/doc/kernel_v2/memory/slabs.rst

146 lines
4.1 KiB
ReStructuredText

.. _memory_slabs_v2:
Memory slabs
############
A :dfn:`memory slab` is a kernel object that allows memory blocks
to be dynamically allocated from a designated memory region.
All memory blocks in a memory slab have a single fixed size,
allowing them to be allocated and released efficiently
and avoiding memory fragmentation concerns.
.. contents::
:local:
:depth: 2
Concepts
********
Any number of memory slabs can be defined. Each memory slab is referenced
by its memory address.
A memory slab has the following key properties:
* The **block size** of each block, measured in bytes.
It must be at least 4 bytes long.
* The **number of blocks** available for allocation.
It must be greater than zero.
* A **buffer** that provides the memory for the memory slab's blocks.
It must be at least "block size" times "number of blocks" bytes long.
A thread that needs to use a memory block simply allocates it from a memory
slab. When the thread finishes with a memory block,
it must release the block back to the memory slab so the block can be reused.
If all the blocks are currently in use, a thread can optionally wait
for one to become available.
Any number of threads may wait on an empty memory slab simultaneously;
when a memory block becomes available, it is given to the highest-priority
thread that has waited the longest.
Unlike a heap, more than one memory slab can be defined, if needed. This
allows for a memory slab with smaller blocks and others with larger-sized
blocks. Alternatively, a memory pool object may be used.
Internal Operation
==================
A memory slab's buffer is an array of fixed-size blocks,
with no wasted space between the blocks.
The memory slab keeps track of unallocated blocks using a linked list;
the first 4 bytes of each unused block provide the necessary linkage.
Implementation
**************
Defining a Memory Slab
======================
A memory slab is defined using a variable of type :c:type:`struct k_mem_slab`.
It must then be initialized by calling :cpp:func:`k_mem_slab_init()`.
The following code defines and initializes a memory slab that has 6 blocks
of 400 bytes each and is aligned to a 4-byte boundary..
.. code-block:: c
struct k_mem_slab my_slab;
char __aligned(4) my_slab_buffer[6 * 400];
k_mem_slab_init(&my_slab, my_slab_buffer, 400, 6);
Alternatively, a memory slab can be defined and initialized at compile time
by calling :c:macro:`K_MEM_SLAB_DEFINE()`.
The following code has the same effect as the code segment above. Observe
that the macro defines both the memory slab and its buffer.
.. code-block:: c
K_MEM_SLAB_DEFINE(my_slab, 400, 6, 4);
Allocating a Memory Block
=========================
A memory block is allocated by calling :cpp:func:`k_mem_slab_alloc()`.
The following code builds on the example above, and waits up to 100 milliseconds
for a memory block to become available, then fills it with zeroes.
A warning is printed if a suitable block is not obtained.
.. code-block:: c
char *block_ptr;
if (k_mem_slab_alloc(&my_slab, &block_ptr, 100) == 0)) {
memset(block_ptr, 0, 400);
...
} else {
printf("Memory allocation time-out");
}
Releasing a Memory Block
========================
A memory block is released by calling :cpp:func:`k_mem_slab_free()`.
The following code builds on the example above, and allocates a memory block,
then releases it once it is no longer needed.
.. code-block:: c
char *block_ptr;
k_mem_slab_alloc(&my_slab, &block_ptr, K_FOREVER);
... /* use memory block pointed at by block_ptr */
k_mem_slab_free(&my_slab, &block_ptr);
Suggested Uses
**************
Use a memory slab to allocate and free memory in fixed-size blocks.
Use memory slab blocks when sending large amounts of data from one thread
to another, to avoid unnecessary copying of the data.
Configuration Options
*********************
Related configuration options:
* None.
APIs
****
The following memory slab APIs are provided by :file:`kernel.h`:
* :cpp:func:`k_mem_slab_init()`
* :cpp:func:`k_mem_slab_alloc()`
* :cpp:func:`k_mem_slab_free()`
* :cpp:func:`k_mem_slab_num_used_get()`
* :cpp:func:`k_mem_slab_num_free_get()`